Esempio n. 1
0
def test_receive_already_confirmed():
    txs = create_client().listtransactions("*", 100)
    tx = None
    for t in txs:
        if t['confirmations'] >= float(CFG.get('bitcoin', 'CONFS')) and t['category'] == 'receive':
            tx = t
            break

    if not tx:
        "skipping test_receive_already_confirmed"
        return
    user = create_user()
    assign_address(tx['address'], user)
    main(['transaction', tx['txid']])

    for i in range(0, 50):
        c = ses.query(models.Credit).filter(models.Credit.address == tx['address']).first()
        if c is not None:
            break
        else:
            time.sleep(0.1)
    assert c is not None
    assert c.address == tx['address']
    assert c.amount == int(float(tx['amount']) * 1e8)
    assert c.currency == CURRENCY
    assert c.network == NETWORK
    assert c.state == 'complete'
    assert c.user_id == user.id
    assert tx['txid'] in c.ref_id
    bal = ses.query(models.Balance).filter(models.Balance.user_id == user.id).filter(models.Balance.currency == CURRENCY).first()
    assert bal.total == int(float(tx['amount']) * 1e8)
    assert bal.available == int(float(tx['amount']) * 1e8)
Esempio n. 2
0
def process_receive(txid, details, confirmed=False):
    """
    Process an incoming transaction with the given txid and details.
    If valid and new, create a Credit and update the corresponding Balance.

    :param str txid: The txid for the transaction in question
    :param dict details: The transaction details as returned by rpc client.
    :param bool confirmed: Has this transaction received enough confirmations?
    """
    creds = ses.query(wm.Credit).filter(wm.Credit.ref_id == txid)
    if creds.count() > 0:
        logger.info("txid already known. returning.")
        return
    transaction_state = 'complete' if confirmed else 'unconfirmed'
    addy = ses.query(wm.Address)\
        .filter(wm.Address.address == details['address']).first()
    if not addy:
        logger.warning("address not known. returning.")
        return
    amount = Amount("%s %s" % (float(details['amount']), CURRENCIES[0]))
    logger.info("crediting txid %s" % txid)
    process_credit(amount=amount, address=details['address'],
                   currency=CURRENCIES[0], network=NETWORK, transaction_state=transaction_state,
                   reference='tx received', ref_id=txid,
                   user_id=addy.user_id)
    adjust_hw_balance(CURRENCIES[0], NETWORK, available=None, total=amount)
Esempio n. 3
0
def search_debit():
    """
    Get one to ten debit(s) for a single User.
    ---
    parameters:
      - name: searchcd
        in: body
        description: The Debit(s) you'd like to get.
        required: false
        schema:
          $ref: '#/definitions/SearchCD'
    responses:
      '200':
        description: the User's debit(s)
        schema:
          items:
            $ref: '#/definitions/Debit'
          type: array
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: searchDebits
    """
    sid = request.jws_payload['data'].get('id')
    address = request.jws_payload['data'].get('address')
    currency = request.jws_payload['data'].get('currency')
    network = request.jws_payload['data'].get('network')
    #reference = request.jws_payload['data'].get('reference')
    ref_id = request.jws_payload['data'].get('ref_id')
    page = request.jws_payload['data'].get('page') or 0

    debsq = ses.query(
        models.Debit).filter(models.Debit.user_id == current_user.id)
    if not debsq:
        return None

    if sid:
        debsq = debsq.filter(models.Debit.id == sid)
    if address:
        debsq = debsq.filter(models.Debit.address == address)
    if currency:
        debsq = debsq.filter(models.Debit.currency == currency)
    if network:
        debsq = debsq.filter(models.Debit.network == network)
    #if reference:
    #    debsq = debsq.filter(models.Debit.reference == reference)
    if ref_id:
        debsq = debsq.filter(models.Debit.ref_id == ref_id)
    debsq = debsq.order_by(models.Debit.time.desc()).limit(10)
    if page and isinstance(page, int):
        debsq = debsq.offset(page * 10)

    debits = [jsonify2(d, 'Debit') for d in debsq]
    response = current_app.bitjws.create_response(debits)
    return response
Esempio n. 4
0
def get_balance():
    """
    Get the latest balance(s) for a single User.
    Currently no search parameters are supported. All balances returned.
    ---
    responses:
      '200':
        description: the User's balance(s)
        schema:
          items:
            $ref: '#/definitions/Balance'
          type: array
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: getBalance
    """
    balsq = ses.query(
        models.Balance).filter(models.Balance.user_id == current_user.id)
    if not balsq:
        return None
    bals = [jsonify2(b, 'Balance') for b in balsq]
    response = current_app.bitjws.create_response(bals)
    return response
Esempio n. 5
0
def search_debit():
    """
    Get one to ten debit(s) for a single User.
    ---
    parameters:
      - name: searchcd
        in: body
        description: The Debit(s) you'd like to get.
        required: false
        schema:
          $ref: '#/definitions/SearchCD'
    responses:
      '200':
        description: the User's debit(s)
        schema:
          items:
            $ref: '#/definitions/Debit'
          type: array
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: searchDebits
    """
    sid = request.jws_payload['data'].get('id')
    address = request.jws_payload['data'].get('address')
    currency = request.jws_payload['data'].get('currency')
    network = request.jws_payload['data'].get('network')
    #reference = request.jws_payload['data'].get('reference')
    ref_id = request.jws_payload['data'].get('ref_id')
    page = request.jws_payload['data'].get('page') or 0

    debsq = ses.query(wm.Debit).filter(wm.Debit.user_id == current_user.id)
    if not debsq:
        return None

    if sid:
        debsq = debsq.filter(wm.Debit.id == sid)
    if address:
        debsq = debsq.filter(wm.Debit.address == address)
    if currency:
        debsq = debsq.filter(wm.Debit.currency == currency)
    if network:
        debsq = debsq.filter(wm.Debit.network == network)
    #if reference:
    #    debsq = debsq.filter(wm.Debit.reference == reference)
    if ref_id:
        debsq = debsq.filter(wm.Debit.ref_id == ref_id)
    debsq = debsq.order_by(wm.Debit.time.desc()).limit(10)
    if page and isinstance(page, int):
        debsq = debsq.offset(page * 10)

    debits = [json.loads(jsonify2(d, 'Debit')) for d in debsq]
    response = current_app.bitjws.create_response(debits)
    ses.close()
    return response
Esempio n. 6
0
def get_balance():
    """
    Get the latest balance(s) for a single User.
    Currently no search parameters are supported. All balances returned.
    ---
    responses:
      '200':
        description: the User's balance(s)
        schema:
          items:
            $ref: '#/definitions/Balance'
          type: array
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: getBalance
    """
    balsq = ses.query(wm.Balance).filter(wm.Balance.user_id == current_user.id)
    if not balsq:
        return None
    bals = [json.loads(jsonify2(b, 'Balance')) for b in balsq]
    print "returning bals %s" % bals
    response = current_app.bitjws.create_response(bals)
    ses.close()
    return response
Esempio n. 7
0
def mock_credit(address, amount):
    addyq = ses.query(models.Address)
    addy = addyq.filter(models.Address.address == address).first()
    if not addy:
        logger.warning("address not known. returning.")
        return
    return process_credit(amount, address, 'MCK', 'Mock', 'unconfirmed',
                          'mock credit', _gen_txid(), addy.user_id)
Esempio n. 8
0
def internal_credit(address, amount, currency='BTC'):
    addyq = ses.query(models.Address)
    addy = addyq.filter(models.Address.address == address).first()
    if not addy:
        logger.warning("address not known. returning.")
        return
    return process_credit(amount, address, currency, 'Internal', 'unconfirmed',
                          'internal credit', _gen_txid(), addy.user_id)
Esempio n. 9
0
def get_user_by_key(app, key):
    """
    An SQLAlchemy User getting function. Get a user by public key.

    :param str key: the public key the user belongs to
    """
    user = ses.query(um.User).join(um.UserKey).filter(um.UserKey.key==key).first()
    return user
Esempio n. 10
0
def internal_confirm_credit(txid):
    credq = ses.query(models.Credit)
    credit = credq.filter(models.Credit.ref_id == txid).first()
    if not credit:
        logger.warning("credit not known. returning.")
        return
    credit.state = 'complete'
    credit.ref_id = "%s:0" % txid
Esempio n. 11
0
def get_user_by_key(app, key):
    """
    An SQLAlchemy User getting function. Get a user by public key.

    :param str key: the public key the user belongs to
    """
    user = ses.query(SLM_User).join(UserKey).filter(UserKey.key == key).first()
    return user
Esempio n. 12
0
def internal_confirm_credit(txid):
    credq = ses.query(models.Credit)
    credit = credq.filter(models.Credit.ref_id == txid).first()
    if not credit:
        logger.warning("credit not known. returning.")
        return
    credit.state = 'complete'
    credit.ref_id = "%s:0" % txid
Esempio n. 13
0
def internal_credit(address, amount, currency='BTC'):
    addyq = ses.query(models.Address)
    addy = addyq.filter(models.Address.address == address).first()
    if not addy:
        logger.warning("address not known. returning.")
        return
    return process_credit(amount, address, currency, 'Internal', 'unconfirmed',
                          'internal credit', _gen_txid(), addy.user_id)
Esempio n. 14
0
def assign_address(address, user):
    dbaddy = ses.query(models.Address).filter(models.Address.address == address).first()
    if dbaddy is None:
        ses.add(models.Address(address, CURRENCY, NETWORK, 'active', user.id))
    elif dbaddy.user_id != user.id:
        dbaddy.user_id = user.id
        ses.add(dbaddy)
    else:
        return
    creds = ses.query(models.Credit).filter(models.Credit.address == address)
    for c in creds:
        ses.delete(c)
    try:
        ses.commit()
    except Exception as ie:
        ses.rollback()
        ses.flush()
Esempio n. 15
0
def main(sys_args=sys.argv[1:]):
    """
    The main CLI entry point. Reads the command line arguments which should
    be filled in by the calling wallet node. Handler for walletnotify and
    blocknotify.
    """
    global lastblock
    client = create_client()
    parser = argparse.ArgumentParser()
    parser.add_argument("type")
    parser.add_argument("data")
    args = parser.parse_args(sys_args)
    typ = args.type
    if typ == 'transaction' and args.data is not None:
        txid = args.data
        txd = client.gettransaction(txid)
        confirmed = txd['confirmations'] >= CONFS
        for p, put in enumerate(txd['details']):
            if put['category'] == 'send':
                confirm_send(put['address'], put['amount'],
                             ref_id="%s:%s" % (txid, p))
            elif put['category'] == 'receive':
                process_receive("%s:%s" % (txid, p), put, confirmed)

    elif typ == 'block':
        info = client.getinfo()
        if info['blocks'] <= lastblock:
            return
        lastblock = info['blocks']
        creds = ses.query(models.Credit)\
            .filter(models.Credit.state == 'unconfirmed')\
            .filter(models.Credit.network == NETWORK)
        for cred in creds:
            txid = cred.ref_id.split(':')[0] or cred.ref_id
            txd = client.gettransaction(txid)
            if txd['confirmations'] >= CONFS:
                cred.state = 'complete'
                for p, put in enumerate(txd['details']):
                    cred.ref_id = "%s:%s" % (txd['txid'], p)
                ses.add(cred)
        try:
            ses.commit()
        except Exception as e:
            logger.exception(e)
            ses.rollback()
            ses.flush()

        # update balances
        total = int(float(client.getbalance("*", 0)) * 1e8)
        avail = int(float(info['balance']) * 1e8)
        hwb = models.HWBalance(avail, total, CURRENCIES[0], NETWORK.lower())
        ses.add(hwb)
        try:
            ses.commit()
        except Exception as ie:
            ses.rollback()
            ses.flush()
Esempio n. 16
0
def get_balance():
    """
    Get the wallet's balance. Returns a dict with 'available' and 'total'
    balances, indicating what can be spent right now, and what is the total
    including unconfirmed funds.

    :rtype: dict
    """
    hwb = ses.query(wm.HWBalance).filter(wm.HWBalance.network == NETWORK).order_by(wm.HWBalance.time.desc()).first()
    return {'total': hwb.total, 'available': hwb.available}
Esempio n. 17
0
def test_confirm_credit_by_txid():
    username, address = create_username_address()
    user, userkey = create_user_and_key(username=username, address=address, last_nonce=time.time() * 1000,
                                        session=ses)
    caddress = wm.Address(_gen_txid(), "BTC", "Internal", "active", user.id)
    ses.add(caddress)
    ses.commit()
    credit = internal_credit(caddress.address, Amount("0.01 BTC"), session=ses)
    confirm_credit(txid=credit.ref_id, session=ses)
    bal2 = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal2.available == Amount("0.01 BTC")
    assert bal2.total == Amount("0.01 BTC")
Esempio n. 18
0
def test_process_internal_debit():
    username, address = create_username_address()
    user, userkey = create_user_and_key(username=username, address=address, last_nonce=time.time() * 1000,
                                        session=ses)
    caddress = wm.Address(_gen_txid(), "BTC", "Internal", "active", user.id)
    ses.add(caddress)
    username2, address2 = create_username_address()
    user2, userkey2 = create_user_and_key(username=username2, address=address2, last_nonce=time.time() * 1000,
                                          session=ses)
    caddress2 = wm.Address(_gen_txid(), "BTC", "Internal", "active", user2.id)
    ses.add(caddress2)
    ses.commit()
    internal_credit(caddress.address, Amount("0.01 BTC"), state='complete', session=ses)
    debit = create_debit(user, Amount("0.001 BTC"), "BTC", caddress2.address, 'Internal', "", session=ses)
    process_debit(debit, session=ses)
    credit = ses.query(wm.Credit).filter(wm.Credit.ref_id == str(debit.id)).first()
    assert credit.amount == Amount("0.001 BTC")
    assert credit.transaction_state == 'complete'
    dbdebit = ses.query(wm.Debit).filter(wm.Debit.id == debit.id).first()
    assert dbdebit.transaction_state == 'complete'
    assert dbdebit.ref_id == str(credit.id)
Esempio n. 19
0
def test_create_user_used_address():
    username, address = create_username_address()
    create_user_and_key(username=username, address=address, last_nonce=time.time() * 1000,
                                        session=ses)
    username2, address2 = create_username_address()
    try:
        create_user_and_key(username=username2, address=address, last_nonce=time.time() * 1000,
                                            session=ses)
        assert not "address was already used, but did not throw IOError as expected"
    except IOError:
        pass
    dbuser = ses.query(um.User).filter(um.User.username == username2).first()
    assert dbuser is None
Esempio n. 20
0
def test_process_unconfirmed_credit():
    username, address = create_username_address()
    user, userkey = create_user_and_key(username=username, address=address, last_nonce=time.time() * 1000,
                                        session=ses)
    caddress = wm.Address(_gen_txid(), "BTC", "Internal", "active", user.id)
    ses.add(caddress)
    ses.commit()
    # process_credit(Amount("0.01 BTC"), address, "BTC", 'Internal', 'unconfirmed', '', )
    credit = internal_credit(caddress.address, Amount("0.01 BTC"), session=ses)
    assert isinstance(credit, wm.Credit)
    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal.available == Amount("0 BTC")
    assert bal.total == Amount("0.01 BTC")
Esempio n. 21
0
def test_receive_then_confirm():
    txs = create_client().listtransactions("*", 100)
    tx = None
    for t in txs:
        if t['confirmations'] >= CONFS and t['category'] == 'receive':
            tx = t
            break

    if not tx:
        "skipping test_receive_already_confirmed"
        return
    user = create_user()
    assign_address(tx['address'], user)
    print "confirmed tx to credit: %s" % tx['txid']
    main(['transaction', tx['txid']])

    for i in range(0, 50):
        c = ses.query(models.Credit).filter(models.Credit.address == tx['address']).first()
        if c is not None:
            break
        else:
            time.sleep(0.1)
    assert c is not None
    c.state = 'unconfirmed'
    ses.add(c)
    ses.commit()

    main(['block', ""])
    assert c.address == tx['address']
    assert c.amount == int(float(tx['amount']) * 1e8)
    assert c.currency == CURRENCY
    assert c.network == NETWORK
    assert c.state == 'complete'
    assert c.user_id == user.id
    assert tx['txid'] in c.ref_id
    assert len(c.ref_id) > len(tx['txid'])
    bal = ses.query(models.Balance).filter(models.Balance.user_id == user.id).filter(models.Balance.currency == CURRENCY).first()
    assert bal.total == int(float(tx['amount']) * 1e8)
    assert bal.available == int(float(tx['amount']) * 1e8)
Esempio n. 22
0
def test_adjust_user_balance():
    username, address = create_username_address()
    user, userkey = create_user_and_key(username=username, address=address, last_nonce=time.time() * 1000,
                                        session=ses)
    adjust_user_balance(user.id, 'BTC', available=Amount("0 BTC"), total=Amount("0.01 BTC"), session=ses)
    ses.commit()
    bal2 = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal2.available == Amount("0 BTC")
    assert bal2.total == Amount("0.01 BTC")

    adjust_user_balance(user.id, 'BTC', available=Amount("0.01 BTC"), total=Amount("0 BTC"), session=ses)
    ses.commit()
    bal3 = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    bal3.load_commodities()
    assert bal3.available == Amount("0.01 BTC")
    assert bal3.total == Amount("0.01 BTC")

    adjust_user_balance(user.id, 'BTC', available=Amount("-0.01 BTC"), total=Amount("-0.01 BTC"), session=ses)
    ses.commit()
    bal4 = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    bal4.load_commodities()
    assert bal4.available == Amount("0 BTC")
    assert bal4.total == Amount("0 BTC")
Esempio n. 23
0
def test_receive():
    user = create_user()
    address = get_new_address()
    assign_address(address, user)

    txid = testclient.sendtoaddress(address, 0.01)

    for i in range(0, 600):
        c = ses.query(models.Credit).filter(models.Credit.address == address).first()
        if c is not None:
            break
        else:
            time.sleep(0.1)
    assert c is not None
    assert c.address == address
    assert c.amount == int(0.01 * 1e8)
    assert c.currency == CURRENCY
    assert c.network == NETWORK
    assert c.state == 'unconfirmed'
    assert c.user_id == user.id
    assert txid in c.ref_id
    bal = ses.query(models.Balance).filter(models.Balance.user_id == user.id).filter(models.Balance.currency == CURRENCY).first()
    assert bal.total == int(0.01 * 1e8)
    assert bal.available == 0
Esempio n. 24
0
def adjust_hwbalance(available=None, total=None):
    if available is None and total is None:
        return
    hwb = ses.query(models.HWBalance).filter(models.HWBalance.network == NETWORK.lower()).order_by(models.HWBalance.time.desc()).first()
    if available is not None:
        hwb.available += available
    if total is not None:
        hwb.total += total
    ses.add(hwb)
    try:
        ses.commit()
    except Exception as e:
        logger.exception(e)
        ses.rollback()
        ses.flush()
Esempio n. 25
0
def get_address():
    """
    Get one or more existing address(es) owned by your user.
    ---
    parameters:
      - name: address
        in: body
        description: The address you'd like to get info about.
        required: false
        schema:
          $ref: '#/definitions/Address'
    responses:
      '200':
        description: Your new address
        schema:
          items:
              $ref: '#/definitions/Address'
          type: array
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: getAddress
    """
    address = request.jws_payload['data'].get('address')
    currency = request.jws_payload['data'].get('currency')
    network = request.jws_payload['data'].get('network')
    addysq = ses.query(wm.Address).filter(wm.Address.user_id == current_user.id)
    if address:
        addysq = addysq.filter(wm.Address.address == address)
    elif currency:
        addysq = addysq.filter(wm.Address.currency == currency)
    elif network:
        addysq = addysq.filter(wm.Address.network == network)
    if addysq.count() == 0:
        return "Invalid Request", 400

    addys = [json.loads(jsonify2(a, 'Address')) for a in addysq]
    response = current_app.bitjws.create_response(addys)
    ses.close()
    return response
Esempio n. 26
0
def test_process_credit():
    username, address = create_username_address()
    user, userkey = create_user_and_key(username=username, address=address, last_nonce=time.time() * 1000,
                                        session=ses)
    caddress = wm.Address(_gen_txid(), "BTC", "Internal", "active", user.id)
    ses.add(caddress)
    ses.commit()
    # process_credit(Amount("0.01 BTC"), address, "BTC", 'Internal', 'unconfirmed', '', )
    credit = internal_credit(caddress.address, Amount("0.01 BTC"), state='complete', session=ses)
    assert isinstance(credit, wm.Credit)
    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal.available == Amount("0.01 BTC")
    assert bal.total == Amount("0.01 BTC")
    try:
        confirm_credit(credit=credit, session=ses)
        assert not "confirming complete credit, but did not throw ValueError as expected"
    except ValueError:
        pass
Esempio n. 27
0
def get_address():
    """
    Get one or more existing address(es) owned by your user.
    ---
    parameters:
      - name: address
        in: body
        description: The address you'd like to get info about.
        required: false
        schema:
          $ref: '#/definitions/Address'
    responses:
      '200':
        description: Your new address
        schema:
          items:
              $ref: '#/definitions/Address'
          type: array
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: getAddress
    """
    address = request.jws_payload['data'].get('address')
    currency = request.jws_payload['data'].get('currency')
    network = request.jws_payload['data'].get('network')
    addysq = ses.query(
        models.Address).filter(models.Address.user_id == current_user.id)
    if address:
        addysq = addysq.filter(models.Address.address == address)
    elif currency:
        addysq = addysq.filter(models.Address.currency == currency)
    elif network:
        addysq = addysq.filter(models.Address.network == network)
    if not addysq:
        return None
    addys = [jsonify2(a, 'Address') for a in addysq]
    response = current_app.bitjws.create_response(addys)
    return response
Esempio n. 28
0
def get_last_nonce(app, key, nonce):
    """
    Get the last_nonce used by the given key from the SQLAlchemy database.
    Update the last_nonce to nonce at the same time.

    :param str key: the public key the nonce belongs to
    :param int nonce: the last nonce used by this key
    """
    uk = ses.query(UserKey).filter(UserKey.key==key)\
            .filter(UserKey.last_nonce<nonce * 1000).first()
    if not uk:
        return None
    lastnonce = copy.copy(uk.last_nonce)
    # TODO Update DB record in same query as above, if possible
    uk.last_nonce = nonce * 1000
    try:
        ses.commit()
    except Exception as e:
        current_app.logger.exception(e)
        ses.rollback()
        ses.flush()
    return lastnonce
Esempio n. 29
0
def get_last_nonce(app, key, nonce):
    """
    Get the last_nonce used by the given key from the SQLAlchemy database.
    Update the last_nonce to nonce at the same time.

    :param str key: the public key the nonce belongs to
    :param int nonce: the last nonce used by this key
    """
    uk = ses.query(um.UserKey).filter(um.UserKey.key==key)\
            .filter(um.UserKey.last_nonce<nonce * 1000).first()
    if not uk:
        return None
    lastnonce = copy.copy(uk.last_nonce)
    # TODO Update DB record in same query as above, if possible
    uk.last_nonce = nonce * 1000
    try:
        ses.commit()
    except Exception as e:
        current_app.logger.exception(e)
        ses.rollback()
        ses.flush()
    return lastnonce
Esempio n. 30
0
def test_create_debit():
    username, address = create_username_address()
    user, userkey = create_user_and_key(username=username, address=address, last_nonce=time.time() * 1000,
                                        session=ses)
    caddress = wm.Address(_gen_txid(), "BTC", "Internal", "active", user.id)
    ses.add(caddress)
    username2, address2 = create_username_address()
    user2, userkey2 = create_user_and_key(username=username2, address=address2, last_nonce=time.time() * 1000,
                                          session=ses)
    caddress2 = wm.Address(_gen_txid(), "BTC", "Internal", "active", user2.id)
    ses.add(caddress2)
    ses.commit()
    internal_credit(caddress.address, Amount("0.01 BTC"), state='complete', session=ses)
    debit = create_debit(user, Amount("0.001 BTC"), "BTC", caddress2.address, 'Internal', "", session=ses)
    assert isinstance(debit, wm.Debit)
    assert debit.network == 'internal'
    assert debit.transaction_state == 'unconfirmed'
    txid = _gen_txid()
    cdebit = confirm_send(caddress2.address, 0.001, ref_id=txid, session=ses)
    assert cdebit.transaction_state == 'complete'
    assert cdebit.ref_id == txid
    dbdebit = ses.query(wm.Debit).filter(wm.Debit.id == debit.id).first()
    assert dbdebit.transaction_state == 'complete'
    assert dbdebit.ref_id == txid
Esempio n. 31
0
def test_get_debits():
    # generate a big credit
    addy = client.get_model('Address')(currency='BTC', network='Internal')
    address = client.address.createAddress(address=addy).result()
    c = internal_credit(address.address, Amount("1 BTC"))
    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    bal.available = bal.available + c.amount
    ses.add(bal)
    try:
        ses.commit()
    except Exception as e:
        ses.rollback()
        print "skipping test"
        return

    # send lots of debits
    by_id = None
    by_address = None
    for i in range(30):
        addy = client2.get_model('Address')(currency='BTC', network='Internal')
        address = client2.address.createAddress(address=addy).result()
        debit = client.debit.sendMoney(debit={'amount': 0.01,
                                        'fee': CFG.get('internal', 'FEE'),
                                       'address': address.address,
                                       'currency': 'BTC',
                                       'network': 'Internal',
                                       'state': 'unconfirmed',
                                       'reference': 'test get debits',
                                       'ref_id': ''}).result()
        if i == 1:
            by_id = debit.id
        elif i == 2:
            by_address = address.address

    time.sleep(0.2) # db write time... should really check to avoid race

    # find all
    debs = client.search.searchDebits().result()
    assert len(debs) >= 10


    # find second page
    debs2 = client.search.searchDebits(searchcd={'page': 1}).result()
    assert len(debs2) == 10
    # assure that there is no overlap
    for d2 in debs2:
        for d in debs:
            assert d.id != d2.id

    # find third page
    debs3 = client.search.searchDebits(searchcd={'page': 2}).result()
    assert len(debs3) == 10
    # assure that there is no overlap
    for d3 in debs3:
        for d in debs:
            assert d.id != d3.id
        for d2 in debs2:
            assert d2.id != d3.id

    # find by address
    debs = client.search.searchDebits(searchcd={'address': by_address}).result()
    assert len(debs) == 1
    assert debs[0].address == by_address

    # find by id
    debs = client.search.searchDebits(searchcd={'id': by_id}).result()
    assert len(debs) == 1
    assert debs[0].id == by_id
Esempio n. 32
0
def create_debit():
    """
    Create a new debit, sending tokens out of your User's account.
    ---
    parameters:
      - name: debit
        in: body
        description: The debit you would like to create.
        required: true
        schema:
          $ref: '#/definitions/Debit'
    responses:
      '200':
        description: The Debit record
        schema:
          $ref: '#/definitions/Debit'
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: sendMoney
    """
    amount = request.jws_payload['data'].get('amount')
    address = request.jws_payload['data'].get('address')
    currency = request.jws_payload['data'].get('currency')
    network = request.jws_payload['data'].get('network')
    reference = request.jws_payload['data'].get('reference')
    state = 'unconfirmed'
    if network.lower() not in ps:
        return 'Invalid network', 400

    dbaddy = ses.query(models.Address)\
        .filter(models.Address.address == address)\
        .filter(models.Address.currency == currency).first()
    if dbaddy is not None and dbaddy.address == address:
        network = 'internal'
    elif network == 'internal' and dbaddy is None:
        return "internal address not found", 400

    txid = 'TBD'
    debit = models.Debit(amount, address, currency, network, state, reference, txid, current_user.id)
    ses.add(debit)

    bal = ses.query(models.Balance)\
        .filter(models.Balance.user_id == current_user.id)\
        .filter(models.Balance.currency == currency)\
        .order_by(models.Balance.time.desc()).first()
    if not bal or bal.available < amount:
        return "not enough funds", 400
    else:
        bal.total -= amount
        bal.available -= amount
        ses.add(bal)
        current_app.logger.info("updating balance %s" % jsonify2(bal, 'Balance'))
    try:
        ses.commit()
    except Exception as ie:
        current_app.logger.exception(ie)
        ses.rollback()
        ses.flush()
        return "unable to send funds", 500

    if network == 'internal':
        bal2 = ses.query(models.Balance)\
            .filter(models.Balance.user_id == dbaddy.user_id)\
            .filter(models.Balance.currency == currency)\
            .order_by(models.Balance.time.desc()).first()
        bal2.available += amount
        bal2.total += amount
        credit = models.Credit(amount, address, currency, network, 'complete', reference, debit.id, dbaddy.user_id)
        ses.add(bal2)
        ses.add(credit)
        current_app.logger.info("updating balance %s" % jsonify2(bal2, 'Balance'))
        current_app.logger.info("created new credit %s" % jsonify2(credit, 'Credit'))
        try:
            ses.commit()
            debit.ref_id = str(credit.id)
        except Exception as ie:
            ses.rollback()
            ses.flush()
            return "unable to send funds", 500
    else:
        try:
            debit.ref_id = ps[network.lower()].send_to_address(address, float(amount) / 1e8)
        except Exception as e:
            print type(e)
            print e
            current_app.logger.error(e)
            return 'wallet temporarily unavailable', 500

    debit.state = 'complete'
    try:
        ses.commit()
    except Exception as ie:
        current_app.logger.exception(ie)
        ses.rollback()
        ses.flush()
        return "Sent but unconfirmed... check again soon", 200

    result = jsonify2(debit, 'Debit')
    current_app.logger.info("created new debit %s" % result)
    return current_app.bitjws.create_response(result)
Esempio n. 33
0
 def get_balance(self):
     hwb = ses.query(models.HWBalance).filter(models.HWBalance.network == self.NETWORK.lower()).order_by(models.HWBalance.time.desc()).first()
     return {'total': hwb.total, 'available': hwb.available}
Esempio n. 34
0
def create_debit():
    """
    Create a new debit, sending tokens out of your User's account.
    ---
    parameters:
      - name: debit
        in: body
        description: The debit you would like to create.
        required: true
        schema:
          $ref: '#/definitions/Debit'
    responses:
      '200':
        description: The Debit record
        schema:
          $ref: '#/definitions/Debit'
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: sendMoney
    """
    amount = request.jws_payload['data'].get('amount')
    address = request.jws_payload['data'].get('address')
    currency = request.jws_payload['data'].get('currency')
    network = request.jws_payload['data'].get('network')
    reference = request.jws_payload['data'].get('reference')
    state = 'unconfirmed'
    if network.lower() not in ps:
        return 'Invalid network', 400

    dbaddy = ses.query(models.Address)\
        .filter(models.Address.address == address)\
        .filter(models.Address.currency == currency).first()
    if dbaddy is not None and dbaddy.address == address:
        network = 'internal'
    elif network == 'internal' and dbaddy is None:
        return "internal address not found", 400
    fee = int(CFG.get(network.lower(), 'FEE'))

    txid = 'TBD'
    debit = models.Debit(amount, fee, address, currency, network, state,
                         reference, txid, current_user.id)
    ses.add(debit)

    bal = ses.query(models.Balance)\
        .filter(models.Balance.user_id == current_user.id)\
        .filter(models.Balance.currency == currency)\
        .order_by(models.Balance.time.desc()).first()
    if not bal or bal.available < amount + fee:
        return "not enough funds", 400
    else:
        bal.total -= amount + fee
        bal.available -= amount + fee
        ses.add(bal)
        current_app.logger.info("updating balance %s" %
                                jsonify2(bal, 'Balance'))
    try:
        ses.commit()
    except Exception as ie:
        current_app.logger.exception(ie)
        ses.rollback()
        ses.flush()
        return "unable to send funds", 500

    if network == 'internal':
        bal2 = ses.query(models.Balance)\
            .filter(models.Balance.user_id == dbaddy.user_id)\
            .filter(models.Balance.currency == currency)\
            .order_by(models.Balance.time.desc()).first()
        bal2.available += amount
        bal2.total += amount
        credit = models.Credit(amount, address, currency, network, 'complete',
                               reference, debit.id, dbaddy.user_id)
        ses.add(bal2)
        ses.add(credit)
        current_app.logger.info("updating balance %s" %
                                jsonify2(bal2, 'Balance'))
        current_app.logger.info("created new credit %s" %
                                jsonify2(credit, 'Credit'))
        try:
            ses.commit()
            debit.ref_id = str(credit.id)
        except Exception as ie:
            ses.rollback()
            ses.flush()
            return "unable to send funds", 500
    else:
        try:
            debit.ref_id = ps[network.lower()].send_to_address(
                address,
                float(amount) / 1e8)
        except Exception as e:
            print type(e)
            print e
            current_app.logger.error(e)
            return 'wallet temporarily unavailable', 500

    debit.state = 'complete'
    try:
        ses.commit()
    except Exception as ie:
        current_app.logger.exception(ie)
        ses.rollback()
        ses.flush()
        return "Sent but unconfirmed... check again soon", 200

    result = jsonify2(debit, 'Debit')
    current_app.logger.info("created new debit %s" % result)
    return current_app.bitjws.create_response(result)
Esempio n. 35
0
 def get_balance(self):
     hwb = ses.query(models.HWBalance).filter(
         models.HWBalance.network == self.NETWORK.lower()).order_by(
             models.HWBalance.time.desc()).first()
     return {'total': hwb.total, 'available': hwb.available}
Esempio n. 36
0
def test_money_cycle():
    fee = int(CFG.get('internal', 'FEE'))
    # Receive Internal to user
    addy = client.get_model('Address')(currency='BTC', network='Internal')
    address = client.address.createAddress(address=addy).result()
    internal_credit(address.address, int(0.01 * 1e8) + fee)

    for i in range(0, 60):
        c = ses.query(models.Credit).filter(
            models.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.address == address.address
    assert c.amount == int(0.01 * 1e8) + fee
    assert c.currency == 'BTC'
    assert c.network == 'Internal'
    assert len(c.ref_id) > 0

    bal = ses.query(
        models.Balance).filter(models.Balance.user_id == user.id).filter(
            models.Balance.currency == 'BTC').first()
    assert bal.total > 0
    assert bal.available == 0
    bal.available += c.amount
    ses.add(bal)
    try:
        ses.commit()
    except Exception as e:
        ses.rollback()
        print "skipping test"
        return

    # send Internal internally to user 2
    addy = client2.get_model('Address')(currency='BTC', network='Internal')
    address = client2.address.createAddress(address=addy).result()

    debit = client.debit.sendMoney(
        debit={
            'amount': int(0.01 * 1e8),
            'fee': fee,
            'address': address.address,
            'currency': 'BTC',
            'network': 'Internal',
            'state': 'unconfirmed',
            'reference': 'test send money internal internal',
            'ref_id': ''
        }).result()
    assert debit.state == 'complete'
    assert debit.amount == int(0.01 * 1e8)
    assert debit.reference == 'test send money internal internal'
    assert debit.network == 'internal'

    for i in range(0, 60):
        c = ses.query(models.Credit).filter(
            models.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.state == 'complete'
    assert c.amount == int(0.01 * 1e8)
    assert c.reference == 'test send money internal internal'
    assert c.network == 'internal'
    assert int(debit.ref_id) == c.id
    assert int(c.ref_id) == debit.id
    bal = ses.query(
        models.Balance).filter(models.Balance.user_id == user.id).filter(
            models.Balance.currency == 'BTC').first()
    assert bal.total == 0
    assert bal.available == 0

    bal = ses.query(
        models.Balance).filter(models.Balance.user_id == user2.id).filter(
            models.Balance.currency == 'BTC').first()
    assert bal.total == int(0.01 * 1e8)
    assert bal.available == int(0.01 * 1e8)

    # send BTC internally to user 2
    addy = client2.get_model('Address')(currency='BTC', network='Internal')
    address = client2.address.createAddress(address=addy).result()

    debit = client2.debit.sendMoney(
        debit={
            'amount': int(0.0099 * 1e8),
            'fee': CFG.get('internal', 'FEE'),
            'address': address.address,
            'currency': 'BTC',
            'network': 'Internal',
            'state': 'unconfirmed',
            'reference': 'test send money internal internal',
            'ref_id': ''
        }).result()
    assert debit.state == 'complete'
    assert debit.amount == int(0.0099 * 1e8)
    assert debit.reference == 'test send money internal internal'
    assert debit.network == 'internal'

    for i in range(0, 60):
        c = ses.query(models.Credit).filter(
            models.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.state == 'complete'
    assert c.amount == int(0.0099 * 1e8)
    assert c.reference == 'test send money internal internal'
    assert c.network == 'internal'
    assert int(debit.ref_id) == c.id
    assert int(c.ref_id) == debit.id
    bal = ses.query(
        models.Balance).filter(models.Balance.user_id == user.id).filter(
            models.Balance.currency == 'BTC').first()
    assert bal.total == 0
    assert bal.available == 0

    bal = ses.query(
        models.Balance).filter(models.Balance.user_id == user2.id).filter(
            models.Balance.currency == 'BTC').first()
    assert bal.total == int(0.0099 * 1e8)
    assert bal.available == int(0.0099 * 1e8)

    # Send Internal from user2
    addy = internal_address()
    debit = client2.debit.sendMoney(
        debit={
            'amount': int(0.0098 * 1e8),
            'fee': CFG.get('internal', 'FEE'),
            'address': addy,
            'currency': 'BTC',
            'network': 'Internal',
            'state': 'unconfirmed',
            'reference': 'test send money internal',
            'ref_id': ''
        }).result()
    time.sleep(0.1)
    for i in range(0, 60):
        d = ses.query(
            models.Debit).filter(models.Debit.address == addy).first()
        if d is not None:
            break
        else:
            time.sleep(1)
    assert d is not None

    assert d.address == addy
    assert d.amount == int(0.0098 * 1e8)
    bal = ses.query(
        models.Balance).filter(models.Balance.user_id == user2.id).filter(
            models.Balance.currency == 'BTC')
    assert bal.first().total == 0
    assert bal.first().available == 0
Esempio n. 37
0
def test_get_debits():
    # generate a big credit
    addy = client.get_model('Address')(currency='BTC', network='Internal')
    address = client.address.createAddress(address=addy).result()
    c = internal_credit(address.address, int(1 * 1e8))
    bal = ses.query(
        models.Balance).filter(models.Balance.user_id == user.id).filter(
            models.Balance.currency == 'BTC').first()
    bal.available += c.amount
    ses.add(bal)
    try:
        ses.commit()
    except Exception as e:
        ses.rollback()
        print "skipping test"
        return

    # send lots of debits
    by_id = None
    by_address = None
    for i in range(30):
        addy = client2.get_model('Address')(currency='BTC', network='Internal')
        address = client2.address.createAddress(address=addy).result()
        debit = client.debit.sendMoney(
            debit={
                'amount': int(0.01 * 1e8),
                'fee': CFG.get('internal', 'FEE'),
                'address': address.address,
                'currency': 'BTC',
                'network': 'Internal',
                'state': 'unconfirmed',
                'reference': 'test get debits',
                'ref_id': ''
            }).result()
        if i == 1:
            by_id = debit.id
        elif i == 2:
            by_address = address.address

    time.sleep(0.2)  # db write time... should really check to avoid race

    # find all
    debs = client.search.searchDebits().result()
    assert len(debs) >= 10

    # find second page
    debs2 = client.search.searchDebits(searchcd={'page': 1}).result()
    assert len(debs2) == 10
    # assure that there is no overlap
    for d2 in debs2:
        for d in debs:
            assert d.id != d2.id

    # find third page
    debs3 = client.search.searchDebits(searchcd={'page': 2}).result()
    assert len(debs3) == 10
    # assure that there is no overlap
    for d3 in debs3:
        for d in debs:
            assert d.id != d3.id
        for d2 in debs2:
            assert d2.id != d3.id

    # find by address
    debs = client.search.searchDebits(searchcd={
        'address': by_address
    }).result()
    assert len(debs) == 1
    assert debs[0].address == by_address

    # find by id
    debs = client.search.searchDebits(searchcd={'id': by_id}).result()
    assert len(debs) == 1
    assert debs[0].id == by_id
Esempio n. 38
0
def test_money_cycle():
    fee = Amount("%s BTC" % CFG.get('internal', 'FEE'))
    amount = Amount("%s BTC" % 0.01)
    # Receive Internal to user
    addy = client.get_model('Address')(currency='BTC', network='Internal')
    address = client.address.createAddress(address=addy).result()
    internal_credit(address.address, amount + fee, session=ses)

    for i in range(0, 60):
        c = ses.query(wm.Credit).filter(wm.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.address == address.address
    assert c.amount == amount + fee
    assert c.currency == 'BTC'
    assert c.network == 'Internal'
    assert len(c.ref_id) > 0
    # ses.close()
    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal.total > Amount("0 BTC")
    assert bal.available == Amount("0 BTC")
    bal.available = bal.available + c.amount
    ses.add(bal)
    try:
        ses.commit()
    except Exception as e:
        ses.rollback()
        print "skipping test"
        return
    ses.close()
    # send Internal internally to user 2
    addy = client2.get_model('Address')(currency='BTC', network='Internal')
    address = client2.address.createAddress(address=addy).result()

    debit = client.debit.sendMoney(debit={'amount': 0.01,
                                  'fee': fee.to_double(),
                                  'address': address.address,
                                  'currency': 'BTC',
                                  'network': 'Internal',
                                  'state': 'unconfirmed',
                                  'reference': 'test send money internal internal',
                                  'ref_id': ''}).result()
    assert debit.transaction_state == 'complete'
    assert debit.amount == 0.01
    assert debit.reference == 'test send money internal internal'
    assert debit.network == 'internal'

    for i in range(0, 60):
        c = ses.query(wm.Credit).filter(wm.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.transaction_state == 'complete'
    assert c.amount == Amount("0.01 BTC")
    assert c.reference == 'test send money internal internal'
    assert c.network == 'internal'
    assert int(debit.ref_id) == c.id
    assert int(c.ref_id) == debit.id
    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal.total == Amount("0 BTC")
    assert bal.available == Amount("0 BTC")

    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user2.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal.total == Amount("0.01 BTC")
    assert bal.available == Amount("0.01 BTC")
    ses.close()
    # send BTC internally to user 2
    addy = client2.get_model('Address')(currency='BTC', network='Internal')
    address = client2.address.createAddress(address=addy).result()

    debit = client2.debit.sendMoney(debit={'amount': 0.0099,
                                  'fee': CFG.get('internal', 'FEE'),
                                  'address': address.address,
                                  'currency': 'BTC',
                                  'network': 'Internal',
                                  'state': 'unconfirmed',
                                  'reference': 'test send money internal internal',
                                  'ref_id': ''}).result()
    assert debit.transaction_state == 'complete'
    assert debit.amount == 0.0099
    assert debit.reference == 'test send money internal internal'
    assert debit.network == 'internal'

    for i in range(0, 60):
        c = ses.query(wm.Credit).filter(wm.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.transaction_state == 'complete'
    assert c.amount == Amount("0.0099 BTC")
    assert c.reference == 'test send money internal internal'
    assert c.network == 'internal'
    assert int(debit.ref_id) == c.id
    assert int(c.ref_id) == debit.id
    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal.total == Amount("0 BTC")
    assert bal.available == Amount("0 BTC")

    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user2.id).filter(wm.Balance.currency == 'BTC').first()
    assert bal.total == Amount("0.0099 BTC")
    assert bal.available == Amount("0.0099 BTC")
    ses.close()
    # Send Internal from user2
    addy = internal_address()
    debit = client2.debit.sendMoney(debit={'amount': 0.0098,
                                   'fee': CFG.get('internal', 'FEE'),
                                  'address': addy,
                                  'currency': 'BTC',
                                  'network': 'Internal',
                                  'state': 'unconfirmed',
                                  'reference': 'test send money internal',
                                  'ref_id': ''}).result()
    time.sleep(0.1)
    for i in range(0, 60):
        d = ses.query(wm.Debit).filter(wm.Debit.address == addy).first()
        if d is not None:
            break
        else:
            time.sleep(1)
    assert d is not None

    assert d.address == addy
    assert d.amount == Amount("0.0098 BTC")
    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user2.id).filter(wm.Balance.currency == 'BTC')
    assert bal.first().total == Amount("0 BTC")
    assert bal.first().available == Amount("0 BTC")
Esempio n. 39
0
def test_money_cycle():
    fee = int(CFG.get('internal', 'FEE'))
    # Receive Internal to user
    addy = client.get_model('Address')(currency='BTC', network='Internal')
    address = client.address.createAddress(address=addy).result()
    internal_credit(address.address, int(0.01 * 1e8) + fee)

    for i in range(0, 60):
        c = ses.query(models.Credit).filter(models.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.address == address.address
    assert c.amount == int(0.01 * 1e8) + fee
    assert c.currency == 'BTC'
    assert c.network == 'Internal'
    assert len(c.ref_id) > 0

    bal = ses.query(models.Balance).filter(models.Balance.user_id == user.id).filter(models.Balance.currency == 'BTC').first()
    assert bal.total > 0
    assert bal.available == 0
    bal.available += c.amount
    ses.add(bal)
    try:
        ses.commit()
    except Exception as e:
        ses.rollback()
        print "skipping test"
        return

    # send Internal internally to user 2
    addy = client2.get_model('Address')(currency='BTC', network='Internal')
    address = client2.address.createAddress(address=addy).result()

    debit = client.debit.sendMoney(debit={'amount': int(0.01 * 1e8),
                                  'fee': fee,
                                  'address': address.address,
                                  'currency': 'BTC',
                                  'network': 'Internal',
                                  'state': 'unconfirmed',
                                  'reference': 'test send money internal internal',
                                  'ref_id': ''}).result()
    assert debit.state == 'complete'
    assert debit.amount == int(0.01 * 1e8)
    assert debit.reference == 'test send money internal internal'
    assert debit.network == 'internal'

    for i in range(0, 60):
        c = ses.query(models.Credit).filter(models.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.state == 'complete'
    assert c.amount == int(0.01 * 1e8)
    assert c.reference == 'test send money internal internal'
    assert c.network == 'internal'
    assert int(debit.ref_id) == c.id
    assert int(c.ref_id) == debit.id
    bal = ses.query(models.Balance).filter(models.Balance.user_id == user.id).filter(models.Balance.currency == 'BTC').first()
    assert bal.total == 0
    assert bal.available == 0

    bal = ses.query(models.Balance).filter(models.Balance.user_id == user2.id).filter(models.Balance.currency == 'BTC').first()
    assert bal.total == int(0.01 * 1e8)
    assert bal.available == int(0.01 * 1e8)

    # send BTC internally to user 2
    addy = client2.get_model('Address')(currency='BTC', network='Internal')
    address = client2.address.createAddress(address=addy).result()

    debit = client2.debit.sendMoney(debit={'amount': int(0.0099 * 1e8),
                                  'fee': CFG.get('internal', 'FEE'),
                                  'address': address.address,
                                  'currency': 'BTC',
                                  'network': 'Internal',
                                  'state': 'unconfirmed',
                                  'reference': 'test send money internal internal',
                                  'ref_id': ''}).result()
    assert debit.state == 'complete'
    assert debit.amount == int(0.0099 * 1e8)
    assert debit.reference == 'test send money internal internal'
    assert debit.network == 'internal'

    for i in range(0, 60):
        c = ses.query(models.Credit).filter(models.Credit.address == address.address).first()
        if c is not None:
            break
        else:
            time.sleep(1)
    assert c is not None
    assert c.state == 'complete'
    assert c.amount == int(0.0099 * 1e8)
    assert c.reference == 'test send money internal internal'
    assert c.network == 'internal'
    assert int(debit.ref_id) == c.id
    assert int(c.ref_id) == debit.id
    bal = ses.query(models.Balance).filter(models.Balance.user_id == user.id).filter(models.Balance.currency == 'BTC').first()
    assert bal.total == 0
    assert bal.available == 0

    bal = ses.query(models.Balance).filter(models.Balance.user_id == user2.id).filter(models.Balance.currency == 'BTC').first()
    assert bal.total == int(0.0099 * 1e8)
    assert bal.available == int(0.0099 * 1e8)

    # Send Internal from user2
    addy = internal_address()
    debit = client2.debit.sendMoney(debit={'amount': int(0.0098 * 1e8),
                                   'fee': CFG.get('internal', 'FEE'),
                                  'address': addy,
                                  'currency': 'BTC',
                                  'network': 'Internal',
                                  'state': 'unconfirmed',
                                  'reference': 'test send money internal',
                                  'ref_id': ''}).result()
    time.sleep(0.1)
    for i in range(0, 60):
        d = ses.query(models.Debit).filter(models.Debit.address == addy).first()
        if d is not None:
            break
        else:
            time.sleep(1)
    assert d is not None

    assert d.address == addy
    assert d.amount == int(0.0098 * 1e8)
    bal = ses.query(models.Balance).filter(models.Balance.user_id == user2.id).filter(models.Balance.currency == 'BTC')
    assert bal.first().total == 0
    assert bal.first().available == 0
Esempio n. 40
0
def main(sys_args=sys.argv[1:]):
    """
    The main CLI entry point. Reads the command line arguments which should
    be filled in by the calling wallet node. Handler for walletnotify and
    blocknotify.
    """
    global lastblock
    client = create_client()
    parser = argparse.ArgumentParser()
    parser.add_argument("type")
    parser.add_argument("data")
    args = parser.parse_args(sys_args)
    typ = args.type
    if typ == 'transaction' and args.data is not None:
        txid = args.data
        txd = client.gettransaction(txid)
        confirmed = txd['confirmations'] >= CONFS
        for p, put in enumerate(txd['details']):
            if put['category'] == 'send':
                try:
                    confirm_send(put['address'], put['amount'],
                                 ref_id=txid)
                except ValueError as ve:
                    logger.info(str(ve))
            elif put['category'] == 'receive':
                try:
                    process_receive(txid, put, confirmed)
                except ValueError as ve:
                    logger.info(str(ve))

    elif typ == 'block':
        info = client.getinfo()
        if info['blocks'] <= lastblock:
            return
        lastblock = info['blocks']
        creds = ses.query(wm.Credit)\
            .filter(wm.Credit.transaction_state == 'unconfirmed')\
            .filter(wm.Credit.network == NETWORK)
        modified = False
        for cred in creds:
            txid = cred.ref_id.split(':')[0] or cred.ref_id
            txd = client.gettransaction(txid)
            if txd['confirmations'] >= CONFS or \
                    txd['bcconfirmations'] >= CONFS:
                cred.load_commodities()
                confirm_credit(credit=cred, txid=txd['txid'], session=ses)
                # cred.transaction_state = 'complete'
                # for p, put in enumerate(txd['details']):
                #     cred.ref_id = "%s:%s" % (txd['txid'], p)
                # ses.add(cred)
                modified = True

        if modified:
            try:
                ses.commit()
            except Exception as e:
                logger.exception(e)
                ses.rollback()
                ses.flush()

        # update balances
        total = Amount("%s %s" % (client.getbalance("*", 0), CURRENCIES[0]))
        avail = Amount("%s %s" % (info['balance'], CURRENCIES[0]))
        hwb = wm.HWBalance(avail, total, CURRENCIES[0], NETWORK)
        ses.add(hwb)
        try:
            ses.commit()
        except Exception as ie:
            ses.rollback()
            ses.flush()
    ses.close()