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
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'])
def create_client(): """ Create an RPC client. :rtype: AuthServiceProxy """ return AuthServiceProxy(CFG.get(NETWORK.lower(), 'RPCURL'))
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
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()
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()
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
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
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
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)
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.
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
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)
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)
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
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
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")
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
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)
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: