0

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}&timestamp={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}'
 
 #&quoteAmount={quant_de_cpt}
 query_string = f'baseAsset={de}&quoteAsset={para}&limitPrice={preco_limite}&baseAmount={quantidade}&side={lado}&expiredType=1_H&recvWindow=60000&timestamp={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&timestamp={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()

Show Url value

asked Apr 25, 2024 at 6:26

2 Answers 2

1

As for your second question, you can see in the documentation that quoteAmount should be a decimal, i.e. a number. You are however providing a string, specifically a formatted string. If you simple pass in the value as a number it should work.

Considering the first error, have you read through the FAQ to confirm that your order is valid? The error code seems unusual, are you sure that you aren't getting any of the documented error codes?

answered Apr 25, 2024 at 7:10
Sign up to request clarification or add additional context in comments.

4 Comments

about the quoteAmount I'm just fixing the same amount of decimal precision as I usually see with 15 decimal units. But I just fix it now reducing to 8 like this quant_de_cpt = float(f'{quantidade_de_crypto:.8f}'). But it's not the string formatting because it should be passed as string in the query_string, isn't? But now with only 8 digits the malformat error is gone.
about the main issue I'm using 100 USDT to convert to ETH so it's not the value I guess, and the position I'm creting the order is technically the same as we see in the Spot so it's a valid limitPrice. All the values in the string is pretty well defined and valid. I'm not creating more then one orders at same time. so the query_string is like 'baseAsset=USDT&quoteAsset=ETH&limitPrice=3150.99&baseAmount=100&quoteAmount=0.03168172&side=BUY&expiredType=1_H&recvWindow=60000&timestamp=1714060059458'
@JoaoVictor using float(f'{...}') is pointless because the additional zeroes are only for display purposes - just use the original number straight away.
if you aren't getting one of the usual error codes I would contact their API support to clarify what the error means. Otherwise we can only guess.
0

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}&quoteAsset={para}&limitPrice={preco_limite}&quoteAmount={quantidade}&side={lado}&walletType={tipo_carteira}&expiredType=1_D&recvWindow=60000&timestamp={timestamp}'
 else:
 query_string = f'baseAsset={para}&quoteAsset={de}&limitPrice={preco_limite}&baseAmount={quantidade_de_crypto}&side={lado}&walletType={tipo_carteira}&expiredType=1_D&recvWindow=60000&timestamp={timestamp}'
 signature = self._generate_signature(query_string)
answered May 8, 2024 at 18:58

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.