I'm trying to make a limit order of convert using binance api. The Postman doc tell us that should be pass as parameter in the POST like we do with user_saldo
that works just fine.
The error returned content: b'{"code":345214,"msg":"Placing a limit order has failed. Please try again later. Error code: 345124"}'
so the methods conversao
don't work. I also tried to ajust the limitePrice value when it is a BUY and increase it when it's a SELL to avoid open a dead limit order, still same error.
Fixed using only 8 decimal units instead of 15 Another issue that give a diffent error is when I try to pass the quant_de_cpt
it says this value is malformed.
What I'm doing wrong?
#!/usr/bin/env python
import os
import requests
import time
import hmac
import hashlib
class OperadorBinanceClient:
def __init__(self, api_key=None, api_secret=None):
self.api_key = api_key or os.environ.get('binance_api_key')
self.api_secret = api_secret or os.environ.get('binance_api_secret')
self.recv_window = 60000 # Valor em milissegundos
self.base_url = 'https://api.binance.com'
self.user_endpoint = '/sapi/v3/asset/getUserAsset'
self.conversao_endpoint = '/sapi/v1/convert/limit/placeOrder'
self.conversao_status_endpoint = '/sapi/v1/convert/orderStatus'
def _get_timestamp(self):
return str(int(time.time() * 1000))
def _generate_signature(self, query_string:str):
signature = hmac.new(self.api_secret.encode('utf-8'), query_string.encode('utf-8'), hashlib.sha256).hexdigest()
return signature
def user_saldo(self, coin='BRL'):
timestamp = self._get_timestamp()
query_string = f'recvWindow={self.recv_window}×tamp={timestamp}'
signature = self._generate_signature(query_string)
url = f'{self.base_url}{self.user_endpoint}?{query_string}&signature={signature}'
headers = {'X-MBX-APIKEY': self.api_key}
response = requests.post(url, headers=headers)
all_balances = response.json()
if coin == '':
return all_balances
filtered_balance = [item for item in all_balances if item['asset'] == coin]
# empty list coin not exist
return filtered_balance if len(filtered_balance) > 0 else None
def conversao2(self, de='BRL', para='ETH', quantidade=1, quantidade_de_crypto=0.1, preco_limite=None, lado='BUY', tipo_carteira='SPOT'):
timestamp = self._get_timestamp()
quant_de_cpt = f'{quantidade_de_crypto:.15f}'
data = {
'baseAsset': de,
'quoteAsset': para,
'limitPrice': preco_limite or '',
'baseAmount': quantidade,
'quoteAmount': quant_de_cpt,
'side': lado,
'expiredType': '1_H',
'recvWindow': 60000,
'timestamp': timestamp
}
signature = self._generate_signature('&'.join([f'{key}={data[key]}' for key in data]))
data['signature'] = signature
url = f'{self.base_url}{self.conversao_endpoint}'
headers = {'X-MBX-APIKEY': self.api_key, 'Content-Type': 'application/json'}
response = requests.post(url, headers=headers, data=data)
return response.json()
def conversao(self, de= 'BRL', para='ETH', quantidade=1, quantidade_de_crypto=0.1,preco_limite=None, lado='BUY', tipo_carteira='SPOT'):
timestamp = self._get_timestamp()
quant_de_cpt = f'{quantidade_de_crypto:.15f}'
#"eAmount={quant_de_cpt}
query_string = f'baseAsset={de}"eAsset={para}&limitPrice={preco_limite}&baseAmount={quantidade}&side={lado}&expiredType=1_H&recvWindow=60000×tamp={timestamp}'
signature = self._generate_signature(query_string)
url = f'{self.base_url}{self.conversao_endpoint}?{query_string}&signature={signature}'
headers = {'X-MBX-APIKEY': self.api_key, 'Content-Type': 'application/json'}
response = requests.post(url, headers=headers)
return response.json()
def conversao_status(self, id_conversao):
timestamp = self._get_timestamp()
query_string = f'orderId={id_conversao}&recvWindow=60000×tamp={timestamp}'
signature = self._generate_signature(query_string)
url = f'{self.base_url}{self.conversao_status_endpoint}?{query_string}&signature={signature}'
headers = {'X-MBX-APIKEY': self.api_key}
response = requests.get(url, headers=headers)
return response.json()
The issue was that the baseAmount should be what return the exchangeInfo endpoint '/sapi/v1/convert/exchangeInfo'
when you define the baseAsset it should be the asset valid as base like this
exchange_info=self.exchange_info(from_asset=de, to_asset=para)
if exchange_info[0]['fromIsBase']:
query_string = f'baseAsset={de}"eAsset={para}&limitPrice={preco_limite}"eAmount={quantidade}&side={lado}&walletType={tipo_carteira}&expiredType=1_D&recvWindow=60000×tamp={timestamp}'
else:
query_string = f'baseAsset={para}"eAsset={de}&limitPrice={preco_limite}&baseAmount={quantidade_de_crypto}&side={lado}&walletType={tipo_carteira}&expiredType=1_D&recvWindow=60000×tamp={timestamp}'
signature = self._generate_signature(query_string)