Exemple #1
0
def network_info(network):
    """
    Get information about the transaction network indicated.
    Returned info is: enabled/disabled, available hot wallet balance,
    & the transaction fee.
    ---
    description: Get information about the transaction network indicated.
    operationId: getinfo
    produces:
      - application/json
    parameters:
      - name: network
        in: path
        type: string
        required: true
        description: The network name i.e. Bitcoin, Dash
    responses:
      '200':
        description: the network information
        schema:
          $ref: '#/definitions/NetworkInfo'
      default:
        description: an error
        schema:
          $ref: '#/definitions/errorModel'
    """
    lnet = network.lower()
    isenabled = lnet in ps
    fee = float(CFG.get(lnet, 'FEE'))
    roughAvail = str(int(ps[lnet].get_balance()['available'].to_double()))
    available = float(10 ** (len(roughAvail) - 1))
    response = json.dumps({'isenabled': isenabled, 'fee': fee,
                           'available': available})
    ses.close()
    return response
Exemple #2
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(wm.Credit).filter(wm.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 == Amount("%s BTC" % tx['amount'])
    assert c.currency == CURRENCY
    assert c.network == NETWORK
    assert c.transaction_state == 'complete'
    assert c.user_id == user.id
    assert tx['txid'] in c.ref_id
    bal = ses.query(wm.Balance).filter(wm.Balance.user_id == user.id).filter(wm.Balance.currency == CURRENCY).first()
    assert bal.total == Amount("%s BTC" % tx['amount'])
    assert bal.available == Amount("%s BTC" % tx['amount'])
Exemple #3
0
def create_client():
    """
    Create an RPC client.

    :rtype: AuthServiceProxy
    """
    return AuthServiceProxy(CFG.get(NETWORK.lower(), 'RPCURL'))
Exemple #4
0
def load_plugins():
    plugins = {}
    for section in CFG.sections():
        if section not in ['db', 'bitjws', 'log', 'test', 'internal']:
            # assume section refers to a plugin module
            pname = "desw_%s" % section
            plugins[section] = importlib.import_module(pname)
    plugins['internal'] = InternalPlugin()
    return plugins
Exemple #5
0
def load_plugins():
    plugins = {}
    for section in CFG.sections():
        if section not in ['db', 'bitjws', 'log', 'test', 'internal']:
            # assume section refers to a plugin module
            pname = "desw_%s" % section
            plugins[section] = importlib.import_module(pname)
    plugins['internal'] = InternalPlugin()
    return plugins
Exemple #6
0
 def __init__(self, session=ses):
     for cur in json.loads(CFG.get('internal', 'CURRENCIES')):
         #TODO set this to maximum transaction sizes for each currency
         hwb = wm.HWBalance(Amount("1000 %s" % cur), Amount("1000 %s" % cur), cur, 'internal')
         session.add(hwb)
         try:
             session.commit()
         except Exception as ie:
             session.rollback()
             session.flush()
Exemple #7
0
 def __init__(self):
     for cur in json.loads(CFG.get('internal', 'CURRENCIES')):
         #TODO set this to maximum transaction sizes for each currency
         hwb = models.HWBalance(100000000000, 100000000000, cur, 'internal')
         ses.add(hwb)
         try:
             ses.commit()
         except Exception as ie:
             ses.rollback()
             ses.flush()
Exemple #8
0
 def __init__(self):
     for cur in json.loads(CFG.get('internal', 'CURRENCIES')):
         #TODO set this to maximum transaction sizes for each currency
         hwb = models.HWBalance(100000000000, 100000000000, cur, 'internal')
         ses.add(hwb)
         try:
             ses.commit()
         except Exception as ie:
             ses.rollback()
             ses.flush()
Exemple #9
0
def load_plugins():
    plugins = {}
    for section in CFG.sections():
        if section not in ['db', 'bitjws', 'log', 'test']:
            # assume section refers to a plugin module unless it is 'mock'
            if section == 'mock':
                plugins[section] = MockPlugin()
            else:
                pname = "desw_%s" % section
                plugins[section] = importlib.import_module(pname)
    return plugins
Exemple #10
0
def create_debit(user, amount, currency, address, network, reference, state='unconfirmed', plugins=None, session=ses):
    if plugins is None:
        plugins = load_plugins()
    if network.lower() not in plugins:
        raise ValueError("Plugin %s not active" % network)

    dbaddy = session.query(wm.Address)\
        .filter(wm.Address.address == address)\
        .filter(wm.Address.currency == currency).first()
    if dbaddy is not None and dbaddy.address == address:
        network = 'internal'
    elif network == 'internal' and dbaddy is None:
        raise ValueError("internal address %s not found" % address)
    fee = Amount("%s %s" % (CFG.get(network.lower(), 'FEE'), currency))

    txid = 'TBD'
    debit = wm.Debit(amount, fee, address,
                     currency, network, state, reference, txid,
                     user.id, datetime.datetime.utcnow())
    session.add(debit)

    bal = session.query(wm.Balance)\
        .filter(wm.Balance.user_id == user.id)\
        .filter(wm.Balance.currency == currency)\
        .order_by(wm.Balance.time.desc()).first()
    if not bal or bal.available < amount + fee:
        session.rollback()
        session.flush()
        raise ValueError("not enough funds")
    else:
        bal.total = bal.total - (amount + fee)
        bal.available = bal.available - (amount + fee)
        bal.time = datetime.datetime.utcnow()
        bal.reference = "debit: %s" % txid
        session.add(bal)
        logger.info("updating balance %s" % jsonify2(bal, 'Balance'))
    try:
        session.commit()
    except Exception as ie:
        logger.exception(ie)
        session.rollback()
        session.flush()
        raise IOError("unable to send funds")
    return debit
Exemple #11
0
def network_info(network):
    """
    Get information about the transaction network indicated.
    Returned info is: enabled/disabled, available hot wallet balance,
    & the transaction fee.
    ---
    description: Get information about the transaction network indicated.
    operationId: getinfo
    produces:
      - application/json
    parameters:
      - name: network
        in: path
        type: string
        required: true
        description: The network name i.e. Bitcoin, Dash
    responses:
      '200':
        description: the network information
        schema:
          $ref: '#/definitions/NetworkInfo'
      default:
        description: an error
        schema:
          $ref: '#/definitions/errorModel'
    """
    lnet = network.lower()
    isenabled = lnet in ps
    fee = int(CFG.get(lnet, 'FEE'))
    roughAvail = str(int(ps[lnet].get_balance()['available']))
    available = int(float("1" + "0" * (len(roughAvail) - 1)) * 1e8)
    response = json.dumps({
        'isenabled': isenabled,
        'fee': fee,
        'available': available
    })
    return response
Exemple #12
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)
Exemple #13
0
import json
import sys

from ledger import Amount

import datetime

from desw.plugin import confirm_credit
from pycoin.key.validate import is_address_valid
from desw import CFG, ses, logger, process_credit, confirm_send, adjust_hw_balance
from sqlalchemy_models import wallet as wm

from bitcoinrpc.authproxy import AuthServiceProxy
NETCODES = ['DASH', 'tDASH']
NETWORK = 'dash'
CURRENCIES = json.loads(CFG.get(NETWORK.lower(), 'CURRENCIES'))
CONFS = int(CFG.get(NETWORK.lower(), 'CONFS'))


def create_client():
    """
    Create an RPC client.

    :rtype: AuthServiceProxy
    """
    return AuthServiceProxy(CFG.get(NETWORK.lower(), 'RPCURL'))


def get_new_address():
    """
    Get a new address from the client.
Exemple #14
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
Exemple #15
0
import time
from ledger import Amount

import bitjws
from bitcoinrpc.authproxy import AuthServiceProxy
from desw import CFG
from sqlalchemy_models import wallet as wm, user as um

from desw_bitcoin import get_new_address, get_balance, send_to_address, validate_address, create_client, CONFS, main,\
    ses

CURRENCY = 'BTC'
NETWORK = 'bitcoin'
ADDYFIRSTCHARS = '123mn'

testclient = AuthServiceProxy(CFG.get('test', NETWORK))


def check_balances():
    info = testclient.getinfo()
    if info['balance'] <= 0.1:
        print "low balance, please deposit to %s" % testclient.getnewaddress()


def create_user():
    privkey = bitjws.PrivateKey()
    my_pubkey = privkey.pubkey.serialize()
    my_address = bitjws.pubkey_to_addr(my_pubkey)
    username = str(my_address)[0:8]
    user = um.User(username=username)
    ses.add(user)
Exemple #16
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

# Setup flask app and FlaskBitjws
app = Flask(__name__)
app._static_folder = "%s/static" % os.path.realpath(os.path.dirname(__file__))

FlaskBitjws(app, privkey=CFG.get('bitjws', 'PRIV_KEY'), get_last_nonce=get_last_nonce,
            get_user_by_key=get_user_by_key, basepath=CFG.get('bitjws', 'BASEPATH'))

CORS(app)


@app.route('/balance', methods=['GET'])
@login_required
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)
Exemple #17
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
Exemple #18
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
Exemple #19
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")
Exemple #20
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
Exemple #21
0
def add_user():
    """
    Register a new User.
    Create a User and a UserKey based on the JWS header and payload.
    ---
    operationId:
      addUser
    parameters:
      - name: user
        in: body
        description: A new User to add
        required: true
        schema:
          $ref: '#/definitions/User'
    responses:
      '200':
        description: "user's new key"
        schema:
          $ref: '#/definitions/UserKey'
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    """
    load_jws_from_request(request)
    if not hasattr(request, 'jws_header') or request.jws_header is None:
        return "Invalid Payload", 401
    username = request.jws_payload['data'].get('username')
    address = request.jws_header['kid']
    user = SLM_User(username=username)
    ses.add(user)
    try:
        ses.commit()
    except Exception as ie:
        current_app.logger.exception(ie)
        ses.rollback()
        ses.flush()
        return 'username taken', 400
    userkey = UserKey(key=address,
                      keytype='public',
                      user_id=user.id,
                      last_nonce=request.jws_payload['iat'] * 1000)
    ses.add(userkey)
    for cur in json.loads(CFG.get('internal', 'CURRENCIES')):
        ses.add(
            models.Balance(total=0,
                           available=0,
                           currency=cur,
                           reference='open account',
                           user_id=user.id))
    try:
        ses.commit()
    except Exception as ie:
        current_app.logger.exception(ie)
        ses.rollback()
        ses.flush()
        #ses.delete(user)
        #ses.commit()
        return 'username taken', 400
    jresult = jsonify2(userkey, 'UserKey')
    current_app.logger.info("registered user %s with key %s" %
                            (user.id, userkey.key))

    return current_app.bitjws.create_response(jresult)
Exemple #22
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


# Setup flask app and FlaskBitjws
app = Flask(__name__)
app._static_folder = "%s/static" % os.path.realpath(os.path.dirname(__file__))

FlaskBitjws(app,
            privkey=CFG.get('bitjws', 'PRIV_KEY'),
            get_last_nonce=get_last_nonce,
            get_user_by_key=get_user_by_key,
            basepath=CFG.get('bitjws', 'BASEPATH'))

CORS(app)


@app.route('/balance', methods=['GET'])
@login_required
def get_balance():
    """
    Get the latest balance(s) for a single User.
    Currently no search parameters are supported. All balances returned.
    ---
    responses: