def trade(order, etherAmount): global user_wallet_private_key, web3, addressEtherDelta, contractEtherDelta print("\nTrading " + str(etherAmount) + " ETH of tokens against this order: %.10f tokens @ %.10f ETH/token" % (float(order['ethAvailableVolume']), float(order['price']))) print("Details about order: " + str(order)) # Transaction info amount_to_buyWei = web3.toWei(etherAmount, 'ether') maxGas = 250000 gasPriceWei = 5000000000 # 1 Gwei # trade function arguments kwargs = { 'tokenGet': Web3.toChecksumAddress(order['tokenGet']), 'amountGet': int(float(order['amountGet'])), 'tokenGive': Web3.toChecksumAddress(order['tokenGive']), 'amountGive': int(float(order['amountGive'])), 'expires': int(order['expires']), 'nonce': int(order['nonce']), 'user': Web3.toChecksumAddress(order['user']), 'v': order['v'], 'r': web3.toBytes(hexstr=order['r']), 's': web3.toBytes(hexstr=order['s']), 'amount': int(amount_to_buyWei), } # Build binary representation of the function call with arguments abidata = contractEtherDelta.encodeABI('trade', kwargs=kwargs) nonce = web3.eth.getTransactionCount(userAccount) transaction = { 'to': addressEtherDelta, 'from': userAccount, 'gas': 250000, 'gasPrice': 100000000, 'data': abidata, 'nonce': nonce, 'chainId': 1 } if len(user_wallet_private_key) == 64: signed = web3.eth.account.signTransaction(transaction, user_wallet_private_key) result = web3.eth.sendRawTransaction(web3.toHex(signed.rawTransaction)) print("Transaction returned: " + str(result)) print( "\nDone! You should see the transaction show up at https://etherscan.io/tx/" + web3.toHex(result)) else: print( "WARNING: no valid private key found, user_wallet_private_key must be 64 characters long" ) ws.close()
def trade(self, order, etherAmount, user_wallet_private_key=''): global web3, addressRyxEx # Transaction info maxGas = 250000 gasPriceWei = 1000000000 # 1 Gwei if order['tokenGive'] == '0x0000000000000000000000000000000000000000': ordertype = 'buy' # it's a buy order so we are selling tokens for ETH amount = etherAmount / float(order['price']) else: ordertype = 'sell' # it's a sell order so we are buying tokens for ETH amount = etherAmount amount_in_wei = web3.toWei(amount, 'ether') print("\nTrading " + str(etherAmount) + " ETH of tokens (" + str(amount) + " tokens) against this " + ordertype + " order: %.10f tokens @ %.10f ETH/token" % (float(order['ethAvailableVolume']), float(order['price']))) print("Details about order: " + str(order)) # trade function arguments kwargs = { 'tokenGet' : Web3.toChecksumAddress(order['tokenGet']), 'amountGet' : int(float(order['amountGet'])), 'tokenGive' : Web3.toChecksumAddress(order['tokenGive']), 'amountGive' : int(float(order['amountGive'])), 'expires' : int(order['expires']), 'nonce' : int(order['nonce']), 'user' : Web3.toChecksumAddress(order['user']), 'v' : order['v'], 'r' : web3.toBytes(hexstr=order['r']), 's' : web3.toBytes(hexstr=order['s']), 'amount' : int(amount_in_wei), } # Bail if there's no private key if len(user_wallet_private_key) != 64: raise ValueError('WARNING: user_wallet_private_key must be a hexadecimal string of 64 characters long') # Build binary representation of the function call with arguments abidata = self.contractRyxEx.encodeABI('trade', kwargs=kwargs) print("abidata: " + str(abidata)) # Use the transaction count as the nonce nonce = web3.eth.getTransactionCount(self.userAccount) # Override to have same as other transaction: #nonce = 53 print("nonce: " + str(nonce)) transaction = { 'to': addressRyxEx, 'from': self.userAccount, 'gas': maxGas, 'gasPrice': gasPriceWei, 'data': abidata, 'nonce': nonce, 'chainId': 1} print(transaction) signed = web3.eth.account.signTransaction(transaction, user_wallet_private_key) print("signed: " + str(signed)) result = web3.eth.sendRawTransaction(web3.toHex(signed.rawTransaction)) print("Transaction returned: " + str(result)) print("\nDone! You should see the transaction show up at https://etherscan.io/tx/" + web3.toHex(result))
def to_32byte_hex(web3, val): """ :param web3: :param val: :return: """ return web3.toBytes(val).rjust(32, b'\0')
def convert_to_bytes(web3, data): """ :param web3: :param data: :return: """ return web3.toBytes(text=data)
def generateStatusFromDebt(debt_obj): # get the terms parameters terms_address = debt_obj["terms_address"] # build the terms contract terms_contract = web3.eth.contract(address=terms_address, abi=COLLATERALIZED_SIMPLE_TERMS_ABI) terms_parameters = debt_obj["terms_params"] # get the principal terms terms_parameters_list = terms_contract.functions.unpackParametersFromBytes( terms_parameters).call() principal_token_index = terms_parameters_list[0] principal_amount = terms_parameters_list[1] principal_interest_rate = terms_parameters_list[2] / 10000 amortizationUnitType = terms_parameters_list[3] termLengthInAmortizationUnits = terms_parameters_list[4] # get the contract registry contract_registry_address = terms_contract.functions.contractRegistry( ).call() contract_registry_contract = web3.eth.contract( address=contract_registry_address, abi=CONTRACT_REGISTRY_ABI) # get collateralizer registry collateralizer_address = contract_registry_contract.functions.collateralizer( ).call() collateralizer_contract = web3.eth.contract(address=collateralizer_address, abi=COLLATERALIZER_ABI) # get the token registry token_registry_address = contract_registry_contract.functions.tokenRegistry( ).call() token_registry_contract = web3.eth.contract(address=token_registry_address, abi=TOKEN_REGISTRY_ABI) # get the principal token attribuetes principal_token_attributes = token_registry_contract.functions.getTokenAttributesByIndex( principal_token_index).call() principal_token_symbol = principal_token_attributes[1] principal_decimals = principal_token_attributes[3] principal_amount = int(debt_obj["principal_amount"]) / math.pow( 10, principal_decimals) # get the collateral amount collateral_parameters = collateralizer_contract.functions.unpackCollateralParametersFromBytes( web3.toBytes(hexstr=terms_parameters)).call() collateral_token_index = collateral_parameters[0] collateral_token_amount = collateral_parameters[1] # get collateral token data collateral_token_attributes = token_registry_contract.functions.getTokenAttributesByIndex( collateral_token_index).call() collateral_token_symbol = collateral_token_attributes[1] collateral_token_decimals = collateral_token_attributes[3] # determine the APR apr_interest_rate = 0 if (amortizationUnitType == AMORTIZATION_HOUR): # Hours apr_interest_rate = ( 8760 / termLengthInAmortizationUnits) * principal_interest_rate elif (amortizationUnitType == AMORTIZATION_DAY): # Days apr_interest_rate = ( 365 / termLengthInAmortizationUnits) * principal_interest_rate elif (amortizationUnitType == AMORTIZATION_WEEK): # Weeks apr_interest_rate = ( 52 / termLengthInAmortizationUnits) * principal_interest_rate elif (amortizationUnitType == AMORTIZATION_MONTH): # Months apr_interest_rate = ( 12 / termLengthInAmortizationUnits) * principal_interest_rate elif (amortizationUnitType == AMORTIZATION_YEAR): # Years apr_interest_rate = ( 1 / termLengthInAmortizationUnits) * principal_interest_rate # determine the total repay amount apr_interest_rate = round(apr_interest_rate, 2) total_repay_amount = principal_amount + (principal_amount * (principal_interest_rate / 100)) principal_interest_rate = round(principal_interest_rate, 2) # check if principal token is same as collateral (ie WETH for WETH) No need to query price if (principal_token_symbol == collateral_token_symbol): collateral_price_rate = 1 else: # determine the symbols to use for querying prices (ie WETH -> ETH) if (principal_token_symbol == "WETH"): principal_token_symbol_to_query = "ETH" else: principal_token_symbol_to_query = principal_token_symbol if (collateral_token_symbol == "WETH"): collateral_token_symbol_to_query = "ETH" else: collateral_token_symbol_to_query = collateral_token_symbol url = "https://min-api.cryptocompare.com/data/price?fsym=" + principal_token_symbol_to_query + "&tsyms=" + collateral_token_symbol_to_query print(url) f = urllib.request.urlopen(url) priceData = json.loads(f.read().decode('utf-8')) print(priceData) collateral_price_rate = priceData[collateral_token_symbol_to_query] if (debt_obj["kind"] == KIND_LOAN_OFFER): # calculate the collateral required # first determine the collateral amount in terms of principal collateral_required_in_principal = (100.0 / debt_obj["ltv"]) * principal_amount # then find out the price for the collateral to principal collateral_required = round( collateral_required_in_principal * collateral_price_rate, 2) else: collateral_supplied = collateral_token_amount / math.pow( 10, collateral_token_decimals) # calculate the loan to value ratio collateral_supplied_in_principal = collateral_supplied / collateral_price_rate loan_to_value_ratio = round( principal_amount / collateral_supplied_in_principal * 100, 2) debt_obj["ltv"] = loan_to_value_ratio string_builder = [] if (debt_obj["kind"] == KIND_LOAN_OFFER): string_builder.append("🚨 Loan Offer:\n") else: string_builder.append("🤲 Borrow Request:\n") # principal string_builder.append("💸 ") string_builder.append(stripTrailingZerosFromDecimal(str(principal_amount))) string_builder.append(" $") string_builder.append(principal_token_symbol) string_builder.append("\n") # Duration string_builder.append("⏳ ") string_builder.append(str(termLengthInAmortizationUnits)) string_builder.append(" ") string_builder.append(AMORTIZATION_UNITS[amortizationUnitType]) if (termLengthInAmortizationUnits > 1): string_builder.append("s") string_builder.append("\n") # APR string_builder.append("📈 ") string_builder.append( stripTrailingZerosFromDecimal(str(principal_interest_rate))) string_builder.append("% interest (") string_builder.append(stripTrailingZerosFromDecimal( str(apr_interest_rate))) string_builder.append("% APR)") # AMORTIZATION_UNITS string_builder.append("\n\n") # Collateral if (debt_obj["kind"] == KIND_LOAN_OFFER): string_builder.append("Required Collateral:\n") string_builder.append("💎 ~") string_builder.append(str(collateral_required)) else: string_builder.append("Collateral Supplied:\n") string_builder.append("💎 ") string_builder.append( stripTrailingZerosFromDecimal(str(collateral_supplied))) # str(collateral_supplied)); string_builder.append(" $") string_builder.append(collateral_token_symbol) string_builder.append("\n") string_builder.append("⚖️ ") string_builder.append(stripTrailingZerosFromDecimal(str(debt_obj["ltv"]))) string_builder.append("% LTV\n\n") # Total Repay string_builder.append("Total Repay:\n") string_builder.append("💸 ") string_builder.append(str(total_repay_amount)) string_builder.append(" $") string_builder.append(principal_token_symbol) string_builder.append("\n\n🔗 ") # if (debt_obj["kind"] == KIND_LOAN_OFFER): # string_builder.append("https://app.bloqboard.com/borrow/"); # else: # string_builder.append("https://app.bloqboard.com/loan/"); # string_builder.append(debt_obj["id"]); # Can't link directly to the loan for compliance, check back when it's allowed string_builder.append("https://app.bloqboard.com/") status = str.join('', string_builder) return status