def deploy(_deploy_data, _token_id, _exchange_contract_id, _creating_org_id=None): smart_token_result = bt.deploy_smart_token(**_deploy_data) address = smart_token_result['smart_token_address'] subexchange_address = smart_token_result['subexchange_address'] _token = Token.query.get(_token_id) _token.address = address _exchange_contract = ExchangeContract.query.get(_exchange_contract_id) _exchange_contract.add_token(_token, subexchange_address, reserve_ratio_ppm) if _creating_org_id: _creating_org = Organisation.query.get(_creating_org_id) _creating_org.bind_token(_token) _creating_org.org_level_transfer_account.set_balance_offset( int(_deploy_data['issue_amount_wei'] / 1e16)) bal = bt.get_wallet_balance( _creating_org.primary_blockchain_address, _token) print(f'Balance is {bal}') db.session.commit()
def cached_funds_available(allowed_cache_age_seconds=60): """ IF refreshing cash THEN: return: [current blockchain balance] - [all transfers with blockchain state pending or unknown] save to cache: [funds available], [ID of highest transfer used in cache], [cache creation datetime] ELSE return: [funds available at last cache] - [all non-failed transfers since last cache] Max Txn ID is a simple way to determine whether txn was used in cache or not, and thus needs to be accounted for :param allowed_cache_age_seconds: how long between checking the blockchain for external funds added or removed :return: amount of funds available """ token = g.active_organisation.org_level_transfer_account.token balance_wei = bt.get_wallet_balance( g.active_organisation.org_level_transfer_account.blockchain_address, token) return token.token_amount_to_system(balance_wei) refresh_cache = False funds_available_cache = red.get('funds_available_cache') try: parsed_cache = json.loads(funds_available_cache) last_updated_datetime = datetime.datetime.fromtimestamp( float(parsed_cache['last_updated'])) earliest_allowed = datetime.datetime.utcnow() - datetime.timedelta( seconds=allowed_cache_age_seconds) if last_updated_datetime < earliest_allowed: refresh_cache = True except Exception as e: refresh_cache = True if refresh_cache: master_wallet_balance = bt.get_wallet_balance() highest_transfer_id_checked = 0 required_blockchain_statuses = ['PENDING', 'UNKNOWN'] else: cached_funds_available = parsed_cache['cached_funds_available'] highest_transfer_id_checked = parsed_cache[ 'highest_transfer_id_checked'] required_blockchain_statuses = ['PENDING', 'UNKNOWN', 'COMPLETE'] new_dibursements = (CreditTransfer.query.filter( CreditTransfer.transfer_type == TransferTypeEnum.PAYMENT).filter( CreditTransfer.transfer_subtype == TransferSubTypeEnum.DISBURSEMENT ).filter(CreditTransfer.transfer_status == TransferStatusEnum.COMPLETE).filter( CreditTransfer.id > highest_transfer_id_checked).filter( CreditTransfer.created > datetime.datetime.utcnow() - datetime.timedelta(hours=36)).all()) local_disbursement_value = 0 for disbursement in new_dibursements: status = disbursement.blockchain_status if status in required_blockchain_statuses: local_disbursement_value += disbursement.transfer_amount if refresh_cache: balance = master_wallet_balance - local_disbursement_value if len(new_dibursements) > 0: highest_transfer_id_checked = new_dibursements[-1].id else: all_transfers = CreditTransfer.query.all() if len(all_transfers) > 0: highest_transfer_id_checked = all_transfers[-1].id else: highest_transfer_id_checked = 0 cache_data = { 'cached_funds_available': balance, 'highest_transfer_id_checked': highest_transfer_id_checked, 'last_updated': datetime.datetime.utcnow().timestamp() } red.set('funds_available_cache', json.dumps(cache_data)) balance = master_wallet_balance - local_disbursement_value return balance else: balance = cached_funds_available - local_disbursement_value return balance
def deploy_cic_token(post_data, creating_org=None): name = post_data['name'] symbol = post_data['symbol'] decimals = post_data.get('decimals', 18) issue_amount_wei = int(post_data['issue_amount_wei']) reserve_deposit_wei = int(post_data['reserve_deposit_wei']) exchange_contract_id = post_data['exchange_contract_id'] reserve_ratio_ppm = post_data.get('reserve_ratio_ppm', 250000) if creating_org: deploying_address = creating_org.primary_blockchain_address else: deploying_address = g.user.primary_blockchain_address if not exchange_contract_id: response_object = { 'message': 'Must supply exchange contract id if deploying smart token contract' } return response_object, 400 exchange_contract = ExchangeContract.query.get(exchange_contract_id) if not exchange_contract: response_object = { 'message': 'Exchange contract not found for id {}'.format(exchange_contract_id) } return response_object, 400 balance_wei = bt.get_wallet_balance(deploying_address, exchange_contract.reserve_token) if balance_wei < reserve_deposit_wei: load_amount = int((reserve_deposit_wei - balance_wei) / 1e16) master_org = Organisation.master_organisation() print(f'Insufficient reserve funds (balance in wei: {balance_wei}), loading') if master_org.org_level_transfer_account.balance < load_amount: response_object = { 'message': f'Insufficient reserve funds for both deploying account ({balance_wei} wei), ' f'and master ({master_org.org_level_transfer_account.balance * 1e16} wei)' } return response_object, 400 load_task_uuid = bt.make_token_transfer( signing_address=master_org.primary_blockchain_address, token=exchange_contract.reserve_token, from_address=master_org.primary_blockchain_address, to_address=deploying_address, amount=load_amount ) try: bt.await_task_success(load_task_uuid) except TimeoutError: response_object = { 'message': f'Insufficient reserve funds (balance in wei: {balance_wei}), and could not load from master' } return response_object, 400 master_org.org_level_transfer_account.balance -= load_amount token = Token(name=name, symbol=symbol, token_type=TokenType.LIQUID) db.session.add(token) db.session.flush() deploy_data = dict( deploying_address=deploying_address, name=name, symbol=symbol, decimals=decimals, reserve_deposit_wei=reserve_deposit_wei, issue_amount_wei=issue_amount_wei, contract_registry_address=exchange_contract.contract_registry_blockchain_address, reserve_token_address=exchange_contract.reserve_token.address, reserve_ratio_ppm=reserve_ratio_ppm ) @copy_current_request_context def deploy(_deploy_data, _token_id, _exchange_contract_id, _creating_org_id=None): smart_token_result = bt.deploy_smart_token(**_deploy_data) address = smart_token_result['smart_token_address'] subexchange_address = smart_token_result['subexchange_address'] _token = Token.query.get(_token_id) _token.address = address _exchange_contract = ExchangeContract.query.get(_exchange_contract_id) _exchange_contract.add_token(_token, subexchange_address, reserve_ratio_ppm) if _creating_org_id: _creating_org = Organisation.query.get(_creating_org_id) _creating_org.bind_token(_token) _creating_org.org_level_transfer_account.balance = int(_deploy_data['issue_amount_wei'] / 1e16) bal = bt.get_wallet_balance(_creating_org.primary_blockchain_address, _token) print(f'Balance is {bal}') db.session.commit() if creating_org: creating_org_id = creating_org.id else: creating_org_id = None t = threading.Thread(target=deploy, args=(deploy_data, token.id, exchange_contract_id, creating_org_id)) t.daemon = True t.start() response_object = { 'message': 'success', 'data': { 'token_id': token.id } } return response_object, 201