Ejemplo n.º 1
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 plug in ps:
        ses.add(models.Balance(total=0, available=0, currency=ps[plug].CURRENCY, 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)
Ejemplo n.º 2
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()
Ejemplo n.º 3
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()
Ejemplo n.º 4
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()
Ejemplo n.º 5
0
def create_address():
    """
    Create a new address owned by your user.
    ---
    parameters:
      - name: address
        in: body
        description: The pseudo-address you would like to create. i.e. currency and network
        required: true
        schema:
          $ref: '#/definitions/Address'
    responses:
      '200':
        description: Your new address
        schema:
          $ref: '#/definitions/Address'
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: createAddress
    """
    currency = request.jws_payload['data'].get('currency')
    network = request.jws_payload['data'].get('network')
    state = 'active'
    if network.lower() in ps:
        try:
            addy = ps[network.lower()].get_new_address()
        except Exception as e:
            print type(e)
            print e
            current_app.logger.error(e)
            return 'wallet temporarily unavailable', 500
    else:
        return 'Invalid network', 400
    address = wm.Address(addy, currency, network, state, current_user.id)
    ses.add(address)
    try:
        ses.commit()
    except Exception as ie:
        ses.rollback()
        ses.flush()
        return 'Could not save address', 500
    newaddy = json.loads(jsonify2(address, 'Address'))
    current_app.logger.info("created new address %s" % newaddy)
    ses.close()
    return current_app.bitjws.create_response(newaddy)
Ejemplo n.º 6
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
    """
    currency = request.jws_payload['data'].get('currency')
    amount = Amount("%s %s" % (request.jws_payload['data'].get('amount'),
                               currency))
    address = request.jws_payload['data'].get('address')
    network = request.jws_payload['data'].get('network')
    reference = request.jws_payload['data'].get('reference')
    state = 'unconfirmed'
    try:
        debit = plugin.create_debit(current_user, amount, currency, address, network, reference, state='unconfirmed',
                                    plugins=ps, session=ses)
        plugin.process_debit(debit, plugins=ps, session=ses)
    except (IOError, ValueError) as e:
        current_app.logger.exception(e)
        ses.rollback()
        ses.flush()
        return "Unable to send money", 400
    except Exception as e:
        current_app.logger.exception(e)
        ses.rollback()
        ses.flush()
        return "Unable to send money", 500
    result = json.loads(jsonify2(debit, 'Debit'))
    current_app.logger.info("created new debit %s" % result)
    ses.close()
    return current_app.bitjws.create_response(result)
Ejemplo n.º 7
0
def create_address():
    """
    Create a new address owned by your user.
    ---
    parameters:
      - name: address
        in: body
        description: The pseudo-address you would like to create. i.e. currency and network
        required: true
        schema:
          $ref: '#/definitions/Address'
    responses:
      '200':
        description: Your new address
        schema:
          $ref: '#/definitions/Address'
      default:
        description: unexpected error
        schema:
          $ref: '#/definitions/errorModel'
    security:
      - kid: []
      - typ: []
      - alg: []
    operationId: createAddress
    """
    currency = request.jws_payload['data'].get('currency')
    network = request.jws_payload['data'].get('network')
    state = 'active'
    if network.lower() in ps:
        try:
            addy = ps[network.lower()].get_new_address()
        except Exception as e:
            print type(e)
            print e
            current_app.logger.error(e)
            return 'wallet temporarily unavailable', 500
    else:
        return 'Invalid network', 400
    address = models.Address(addy, currency, network, state, current_user.id)
    ses.add(address)
    try:
        ses.commit()
    except Exception as ie:
        ses.rollback()
        ses.flush()
        return 'Could not save address', 500
    newaddy = jsonify2(address, 'Address')
    current_app.logger.info("created new address %s" % newaddy)
    return current_app.bitjws.create_response(newaddy)
Ejemplo n.º 8
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()
Ejemplo n.º 9
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()
Ejemplo n.º 10
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']
    last_nonce = request.jws_payload['iat']*1000
    try:
        user, userkey = create_user_and_key(username=username, address=address, last_nonce=last_nonce, session=ses)
    except IOError:
        ses.rollback()
        ses.flush()
        return 'username or key taken', 400
    jresult = json.loads(jsonify2(userkey, 'UserKey'))
    current_app.logger.info("registered user %s with key %s" % (user.id, userkey.key))
    ses.close()
    return current_app.bitjws.create_response(jresult)
Ejemplo n.º 11
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
Ejemplo n.º 12
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
Ejemplo n.º 13
0
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 = models.User(username=username)
    ses.add(user)
    try:
        ses.commit()
    except Exception as ie:
        print ie
        ses.rollback()
        ses.flush()
    userkey = models.UserKey(key=my_address, keytype='public', user_id=user.id,
                      last_nonce=0)
    ses.add(userkey)
    ses.add(models.Balance(total=0, available=0, currency=CURRENCY, reference='open account', user_id=user.id))
    try:
        ses.commit()
    except Exception as ie:
        print ie
        ses.rollback()
        ses.flush()
    return user
Ejemplo n.º 14
0
from desw import ses
from sqlalchemy_models import wallet as wm

hwb = wm.HWBalance(0, 0, 'DASH', 'dash')
ses.add(hwb)
try:
    ses.commit()
except Exception as ie:
    ses.rollback()
    ses.flush()
Ejemplo n.º 15
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)
Ejemplo n.º 16
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)
Ejemplo n.º 17
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)
Ejemplo n.º 18
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()