def post(self): """ Return the balance for a given wallet. The bitcoin balance is only available when the wallet has a server-controlled cosigner. Parameters required from the client: * id [text] - wallet ID """ wallet_id = g.payload.get('id', '').encode('ascii') if not wallet_id: return current_app.encode_error(Errors.MissingArguments) # Get the cosigner for this wallet for this user. record = current_app.session.query(db.CosignerWallet).filter( db.CosignerWallet.user_id == current_user.id, db.CosignerWallet.wallet_id == wallet_id).one_or_none() if record is None: return current_app.encode_error(Errors.CosignerNotFound) # Send the request to the cosigning server. logging.info('still here') resp = current_app.cosigner('/balance', wallet=record.wallet) logging.info('result %s', resp) if 'balance' in resp: data = {'btc': resp['balance']} result = current_app.encode_success(data) else: logging.error(resp) result = current_app.encode_error(Errors.CosignerError) return result
def put(self): # XXX not implemented in the client yet. """ Update an existing blob for this user. Parameters required from the client: * id [text] - blob UUID * blob [text] - blob to replace the one previously stored Returns: the new blob """ blob = g.payload.get('blob', '').encode('ascii') blob_id = g.payload.get('id', '').encode('ascii') if not blob or not blob_id: # No blob specified. return current_app.encode_error(Errors.MissingArguments) elif len(blob) > MAX_BLOBLEN: # Blob size is too big. return current_app.encode_error(Errors.BlobTooLong) # Update the blob that belongs to this user only if this new one # is greater (in size) than the current one. record = current_app.session.query(db.WalletBlob).filter( db.WalletBlob.user_id == current_user.id, db.WalletBlob.updates_left > 0, db.func.char_length(db.WalletBlob.blob) < len(blob)).update({ 'updates_left': db.WalletBlob.updates_left - 1, 'blob': blob }) result = format_blob(record).next() return current_app.encode_success(result)
def get(self): """ Return the salt and iteration count (for PBKDF2) for this user. Parameters required from the client: * username [text] * check [text] - 6 hexadecimal digits Returns: * salt [text] - hexadecimal digits * iterations [integer] """ username = request.args.get('username').encode('utf8') bcheck = request.args.get('check').encode('ascii') if not username or len(bcheck) != 6: return current_app.encode_error(Errors.MissingArguments) user = current_app.session.query(db.User).filter( db.User.username == username, db.User.user_check == bcheck).one_or_none() if user is None: return current_app.encode_error(Errors.UserNotFound) result = {'salt': user.salt, 'iterations': user.itercount} return current_app.encode_success(result)
def put(self): # XXX not implemented in the client yet. """ Update an existing blob for this user. Parameters required from the client: * id [text] - blob UUID * blob [text] - blob to replace the one previously stored Returns: the new blob """ blob = g.payload.get('blob', '').encode('ascii') blob_id = g.payload.get('id', '').encode('ascii') if not blob or not blob_id: # No blob specified. return current_app.encode_error(Errors.MissingArguments) elif len(blob) > MAX_BLOBLEN: # Blob size is too big. return current_app.encode_error(Errors.BlobTooLong) # Update the blob that belongs to this user only if this new one # is greater (in size) than the current one. record = current_app.session.query(db.WalletBlob).filter( db.WalletBlob.user_id == current_user.id, db.WalletBlob.updates_left > 0, db.func.char_length(db.WalletBlob.blob) < len(blob)).update({ 'updates_left': db.WalletBlob.updates_left - 1, 'blob': blob}) result = format_blob(record).next() return current_app.encode_success(result)
def post(self): """ Create new address(es). This only available when the wallet has a server-controlled cosigner. Parameters required from the client: * id [text] - wallet ID Optional parameters: * num [number] - number of addresses to obtain (max: 100, default: 1) """ num = int(g.payload.get('num', 1)) wallet_id = g.payload.get('id', '').encode('ascii') if not wallet_id: return current_app.encode_error(Errors.MissingArguments) if num <= 0 or num > MAX_NEWADDRESS: return current_app.encode_error(Errors.InvalidAddressCount) # Get the cosigner for this wallet for this user. record = current_app.session.query(db.CosignerWallet).filter( db.CosignerWallet.user_id == current_user.id, db.CosignerWallet.wallet_id == wallet_id).one_or_none() if record is None: return current_app.encode_error(Errors.CosignerNotFound) # Send the request to the cosigning server. resp = current_app.cosigner('/address/new', num=num, wallet=record.wallet) if 'address' in resp: keys = ['address', 'path', 'createdOn'] if isinstance(resp['address'], dict): # Single address derived. keys.append('walletId') data = {key: resp['address'][key] for key in keys} else: # Multiple addresses. data = { 'walletId': resp['address'][0]['walletId'], 'result': None } data['result'] = [{key: entry[key] for key in keys} for entry in resp['address']] result = current_app.encode_success(data) else: logging.error(resp) result = current_app.encode_error(Errors.CosignerError) return result
def insert(record): session = current_app.session session.add(record) try: session.commit() return current_app.encode_success() except Exception: logging.exception("Failed to commit cowallet record") session.rollback() resp = current_app.encode_error(Errors.GenericError) return resp finally: session.close()
def post(self): """ Create new address(es). This only available when the wallet has a server-controlled cosigner. Parameters required from the client: * id [text] - wallet ID Optional parameters: * num [number] - number of addresses to obtain (max: 100, default: 1) """ num = int(g.payload.get('num', 1)) wallet_id = g.payload.get('id', '').encode('ascii') if not wallet_id: return current_app.encode_error(Errors.MissingArguments) if num <= 0 or num > MAX_NEWADDRESS: return current_app.encode_error(Errors.InvalidAddressCount) # Get the cosigner for this wallet for this user. record = current_app.session.query(db.CosignerWallet).filter( db.CosignerWallet.user_id == current_user.id, db.CosignerWallet.wallet_id == wallet_id).one_or_none() if record is None: return current_app.encode_error(Errors.CosignerNotFound) # Send the request to the cosigning server. resp = current_app.cosigner( '/address/new', num=num, wallet=record.wallet) if 'address' in resp: keys = ['address', 'path', 'createdOn'] if isinstance(resp['address'], dict): # Single address derived. keys.append('walletId') data = {key: resp['address'][key] for key in keys} else: # Multiple addresses. data = { 'walletId': resp['address'][0]['walletId'], 'result': None } data['result'] = [{key: entry[key] for key in keys} for entry in resp['address']] result = current_app.encode_success(data) else: logging.error(resp) result = current_app.encode_error(Errors.CosignerError) return result
def post(self): """Return the blobs stored for this user.""" only_count = int(g.payload.get('count', 0)) blobs = current_app.session.query( db.WalletBlob).filter(db.WalletBlob.user_id == current_user.id) if only_count: # Return the number of blobs stored. result = {'num': blobs.count()} else: # Return the actual blobs. result = list(format_blob(*blobs)) return current_app.encode_success(result)
def post(self): """Return the blobs stored for this user.""" only_count = int(g.payload.get('count', 0)) blobs = current_app.session.query(db.WalletBlob).filter( db.WalletBlob.user_id == current_user.id) if only_count: # Return the number of blobs stored. result = {'num': blobs.count()} else: # Return the actual blobs. result = list(format_blob(*blobs)) return current_app.encode_success(result)
def post(self): # XXX blob update not implemented yet. """ Store or update a blob for this user. Parameters required from the client: * id [text] - an UUID (assumed to be a wallet ID) * blob [text] - blob to be stored Optional parameters: * maxchanges [integer] - maximum number of changes accepted for this blob, no more than 32 Returns: * id [text] - id for the blob stored * blob [text] - the blob stored * created_at [integer] - creation time as a unix timestamp """ maxchanges = min(int(g.payload.get('maxchanges', '32')), 32) blob = g.payload.get('blob', '').encode('ascii') # Blob ID is used internally as a reference to the Wallet record # stored in the MongoDB by bitcore-wallet-service. # The default client implementation passes that UUID as this id, # but it is not enforced. blob_id = g.payload.get('id', '').encode('ascii') if not blob or not blob_id or len(blob_id) != 36: # No blob specified. return current_app.encode_error(Errors.MissingArguments) elif len(blob) > MAX_BLOBLEN: # Blob size is too big. return current_app.encode_error(Errors.BlobTooLong) blob_count = current_app.session.query(db.WalletBlob).filter( db.WalletBlob.user_id == current_user.id).count() if blob_count >= MAX_BLOBCOUNT: # This user has stored too many blobs already. return current_app.encode_error(Errors.TooManyBlobs) record = db.WalletBlob(id=blob_id, user_id=current_user.id, updates_left=maxchanges, blob=blob) current_app.session.add(record) current_app.session.commit() result = format_blob(record).next() return current_app.encode_success(result)
def signup_insert(records): session = current_app.session session.add_all(records) try: session.commit() return current_app.encode_success() except Exception as err: logging.exception("Failed to commit user records") session.rollback() if (isinstance(err, db.IntegrityError) and 'username' in err.orig.message): # Username already in use resp = current_app.encode_error(Errors.InvalidUsername) else: resp = current_app.encode_error(Errors.GenericError) return resp finally: session.close()