Jump to content

Binance API UDF


andybiochem
 Share

Recommended Posts

Hi All,

Firstly, I accept no responsibility for how you use the following UDF, use at your own risk!

 

Below is a very basic UDF that will allow communication with Binance's API (binance.com, not the US version).

There is no error handling - add this yourself if you are concerned. If you are going to use this UDF in any meaningful way, carefully check the return of every single call, to make sure there is no error in the data you are receiving back from Binance. e.g. if you are pulling ticker prices, and suddenly you get $NULL returned, this could affect how you go on to place orders etc.

 

I have very intentionally not provided an example of how to place orders using the UDF. If you are technically minded enough to use the UDF and understand how to construct the POST data, this should not be an issue. If you are struggling to work out how to place orders with this, please stop - no good can come from not fully understanding  Binance's API and trying to automate it. In any event, please start with POSTing to "/api/v3/order/test" before commiting to your live account!

 

The whole UDF calls directly on winhttp.dll, this was the only method I could find that gave a decent reliability, TCP / INET functions I found quite unreliable.

 

Every UDF return gives you the HTTP Code and API Weight pulled out of the http header. Monitor these carefully if you're making heavy/lots of calls to the API; it's very easy to make a mistake and spam Binance's server, which will lead in a ban.

 

Lastly, if you get "Timestamp for this request is outside of the recvwindow" errors back from Binance, it is because your computer clock is not synced with an NTP properly. Sync your clock, and the error should go away, try rebooting too - BUT, the error will probably return after a few days/weeks as the sync drops. Monitor for this error, and keep on top of it if you can!

 

;----- API Keys -----
Global $sAPI_Key_Access = "enter your access key"
Global $sAPI_Key_Secret = "enter your secret key"

;----- Prepare DLL -----
Global $hDll_WinHTTP = DllOpen("winhttp.dll")


;########## EXAMPLE API CALLS ##########

;----- Ping Binance -----
Global $sRet = _BINANCE_API_Call("api/v3/ping")
ConsoleWrite($sRet & @CRLF & @CRLF)

;----- Get Binance's Server Time -----
$sRet = _BINANCE_API_Call("api/v3/time")
ConsoleWrite($sRet & @CRLF & @CRLF)

;----- Get BTC/USDT Average Price -----
$sRet = _BINANCE_API_Call("api/v3/avgPrice","symbol=BTCUSDT")
ConsoleWrite($sRet & @CRLF & @CRLF)

;----- Get ETH/BTC Live Ticker Price -----
For $i = 1 To 5
    Sleep(100)
    $sRet = _BINANCE_API_Call("api/v3/ticker/price", "symbol=ETHBTC")
    ConsoleWrite($sRet & @CRLF)
Next
ConsoleWrite(@CRLF)

;----- Get Last 10 ETH/BTC Trades -----
$sRet = _BINANCE_API_Call("api/v3/trades", "symbol=ETHBTC&limit=10")
ConsoleWrite($sRet & @CRLF & @CRLF)

;----- Get Your Account Data -----
$sRet = _BINANCE_API_Call("api/v3/account")
ConsoleWrite($sRet & @CRLF & @CRLF)






Func _BINANCE_API_Call($sEndPoint, $sParameters = "")
    ;**************************************************
    ; Performs Binance API Call Via Native WinHTTP dll
    ;**************************************************

    ;----- Vars -----
    ; Presume GET, assign POST if needed in switch
    Local $sGETorPOST = "GET"

    ;----- Check Endpoint Required -----
    ; Some endpoints require signing, other endpoints can be
    ; added as new cases.
    Switch $sEndPoint
        Case "api/v3/account"
            $sParameters &= "&timestamp=" & _TimeStamp()
            $sParameters &= "&signature=" & _HMAC($sParameters, $sAPI_Key_Secret)
        Case "api/v3/order"
            $sGETorPOST = "POST"
            $sParameters &= "&timestamp=" & _TimeStamp()
            $sParameters &= "&signature=" & _HMAC($sParameters, $sAPI_Key_Secret)
        Case "api/v3/myTrades"
            $sParameters &= "&timestamp=" & _TimeStamp()
            $sParameters &= "&signature=" & _HMAC($sParameters, $sAPI_Key_Secret)
    EndSwitch

    ;----- Start Session -----
    Local $hHTTP_Session = DllCall($hDll_WinHTTP, "handle", "WinHttpOpen", "wstr", "Mozilla/4.0", "dword", 0, "wstr", "", "wstr", "", "dword", 0)[0]
    ;----- Connect To Binance Server -----
    Local $hHTTP_Connection = DllCall($hDll_WinHTTP, "handle", "WinHttpConnect", "handle", $hHTTP_Session, "wstr", "api.binance.com", "dword", 443, "dword", 0)[0]
    ;----- Prepare Request Data -----
    If $sParameters <> "" Then $sParameters = "?" & $sParameters
    Local $hHTTP_Request = DllCall($hDll_WinHTTP, "handle", "WinHttpOpenRequest", "handle", $hHTTP_Connection, "wstr", $sGETorPOST, "wstr", $sEndPoint & $sParameters, "wstr", "HTTP/1.1", "wstr", "", "ptr", 0, "dword", 0x00800000)[0]
    ;----- Add Request Header -----
    ; Adds API key to header even if not specifically needed, inconsequential
    DllCall($hDll_WinHTTP, "bool", "WinHttpAddRequestHeaders", "handle", $hHTTP_Request, "wstr", "X-MBX-APIKEY: " & $sAPI_Key_Access, "dword", -1, "dword", 0x10000000)
    ;----- Send Request To Server -----
    DllCall($hDll_WinHTTP, "bool", "WinHttpSendRequest", "handle", $hHTTP_Request, "wstr", "", "dword", 0, "ptr", 0, "dword", 0, "dword", 0, "dword_ptr", 0)
    ;----- Recieve Response -----
    DllCall($hDll_WinHTTP, "bool", "WinHttpReceiveResponse", "handle", $hHTTP_Request, "ptr", 0)
    ;----- Recieve Headers -----
    ; Extract HTTP return code and API weight
    Local $sHeaders = DllCall($hDll_WinHTTP, "bool", "WinHttpQueryHeaders", "handle", $hHTTP_Request, "dword", 22, "wstr", "", "wstr", "", "dword*", 65536, "dword*", 0)[4]
    Local $sHTTP_ReturnCode = StringMid($sHeaders, StringInStr($sHeaders, "HTTP/1.1 ") + 9, StringInStr($sHeaders, @CR, 0, 1, StringInStr($sHeaders, "HTTP/1.1 ") + 9) - (StringInStr($sHeaders, "HTTP/1.1 ") + 9))
    Local $sAPI_Weight = StringMid($sHeaders, StringInStr($sHeaders, "x-mbx-used-weight: ") + 19, StringInStr($sHeaders, @CR, 0, 1, StringInStr($sHeaders, "x-mbx-used-weight: ") + 19) - (StringInStr($sHeaders, "x-mbx-used-weight: ") + 19))
    Local $sAPI_IPBan_RetryAfter_Sec = StringInStr($sHeaders, "Retry-After: ") = 0 ? "" : StringMid($sHeaders, StringInStr($sHeaders, "Retry-After: ") + 13, StringInStr($sHeaders, @CR, 0, 1, StringInStr($sHeaders, "Retry-After: ") + 13) - (StringInStr($sHeaders, "Retry-After: ") + 13))
    ;----- Get Data -----
    Local $sData = ""
    Local $iBytesToRead, $hBuffer_Data
    While 1
        ;- Get Bytes To Read In This Loop -
        $iBytesToRead = DllCall($hDll_WinHTTP, "bool", "WinHttpQueryDataAvailable", "handle", $hHTTP_Request, "dword*", 0)[2]
        ;- Check If No More Data To Read -
        If $iBytesToRead <= 0 Then ExitLoop
        ;- Prep Data Buffer -
        $hBuffer_Data = DllStructCreate("char[" & $iBytesToRead & "]")
        ;- Read Data To Buffer -
        DllCall($hDll_WinHTTP, "bool", "WinHttpReadData", "handle", $hHTTP_Request, "struct*", $hBuffer_Data, "dword", $iBytesToRead, "dword*", 0)
        ;- Get Data From Buffer -
        $sData &= DllStructGetData($hBuffer_Data, 1)
        ;- Release -
        $hBuffer_Data = ""
    WEnd
    ;----- Close Handles -----
    DllCall($hDll_WinHTTP, "bool", "WinHttpCloseHandle", "handle", $hHTTP_Request)
    DllCall($hDll_WinHTTP, "bool", "WinHttpCloseHandle", "handle", $hHTTP_Connection)
    DllCall($hDll_WinHTTP, "bool", "WinHttpCloseHandle", "handle", $hHTTP_Session)

    ;----- Return Data -----
    ; Include HTTP Code and API Weight to check for overuse, and retry period if banned
    ; HTTP CODES : 429=over request limit, 418=IP banned due to overuse
    ; API WEIGHT : over 1200 will lead to ban
    Return '{"HTTPCode":"' & $sHTTP_ReturnCode & '","APIWeight":"' & $sAPI_Weight & ($sAPI_IPBan_RetryAfter_Sec = "" ? "" : '","Retry-After":"' & $sAPI_IPBan_RetryAfter_Sec) & '"}' & $sData

EndFunc   ;==>_BINANCE_API_Call

Func _HMAC($bData, $bKey)
    ;**************************************************
    ; Create HMAC SHA256 Signature
    ;**************************************************
    Local $oHMAC = ObjCreate("System.Security.Cryptography.HMAC" & "SHA256")
    $oHMAC.key = Binary($bKey)
    Local $bHash = $oHMAC.ComputeHash_2(Binary($bData))
    Return StringLower(StringMid($bHash, 3))
EndFunc   ;==>_HMAC

Func _TimeStamp()
    ;**************************************************
    ; Create UNIX-style TimeStamp
    ;**************************************************
    ; This is 'unix time', aka UTC time in milliseconds
    Local $aTimeStamp = DllCall("msvcrt.dll", "int:cdecl", "time", "int", 0)
    Return ($aTimeStamp[0] * 1000) + @MSEC ;convert to miliseconds
EndFunc   ;==>_TimeStamp

 

An example return would be:

{"HTTPCode":"200 OK","APIWeight":"4"}{"symbol":"ETHBTC","price":"0.07152900"}

 

The first {} block is the HTTP code and API weight, the second {} block is the full Binance JSON reply.

The JSON can be queried with a JSON UDF (do a search on the forum), or can be split with regexp.

 

 

Again, please use with caution! :)

 

Feel free to donate if you find this useful!:

NANO

nano_1161rm7egfzwgbtckwe8aoicee55897bbgc8apzrp1s3fzyyn7zqobbtkmfh

 

 

Edited by andybiochem
- Table UDF - create simple data tables - Line Graph UDF GDI+ - quickly create simple line graphs with x and y axes (uses GDI+ with double buffer) - Line Graph UDF - quickly create simple line graphs with x and y axes (uses AI native graphic control) - Barcode Generator Code 128 B C - Create the 1/0 code for barcodes. - WebCam as BarCode Reader - use your webcam to read barcodes - Stereograms!!! - make your own stereograms in AutoIT - Ziggurat Gaussian Distribution RNG - generate random numbers based on normal/gaussian distribution - Box-Muller Gaussian Distribution RNG - generate random numbers based on normal/gaussian distribution - Elastic Radio Buttons - faux-gravity effects in AutoIT (from javascript)- Morse Code Generator - Generate morse code by tapping your spacebar!
Link to comment
Share on other sites

  • 5 months later...
  • 2 years later...
On 10/3/2021 at 2:01 AM, andybiochem said:

Hi All,

Firstly, I accept no responsibility for how you use the following UDF, use at your own risk!

 

Below is a very basic UDF that will allow communication with Binance's API (binance.com, not the US version).

There is no error handling - add this yourself if you are concerned. If you are going to use this UDF in any meaningful way, carefully check the return of every single call, to make sure there is no error in the data you are receiving back from Binance. e.g. if you are pulling ticker prices, and suddenly you get $NULL returned, this could affect how you go on to place orders etc.

 

I have very intentionally not provided an example of how to place orders using the UDF. If you are technically minded enough to use the UDF and understand how to construct the POST data, this should not be an issue. If you are struggling to work out how to place orders with this, please stop - no good can come from not fully understanding  Binance's API and trying to automate it. In any event, please start with POSTing to "/api/v3/order/test" before commiting to your live account!

 

The whole UDF calls directly on winhttp.dll, this was the only method I could find that gave a decent reliability, TCP / INET functions I found quite unreliable.

 

Every UDF return gives you the HTTP Code and API Weight pulled out of the http header. Monitor these carefully if you're making heavy/lots of calls to the API; it's very easy to make a mistake and spam Binance's server, which will lead in a ban.

 

Lastly, if you get "Timestamp for this request is outside of the recvwindow" errors back from Binance, it is because your computer clock is not synced with an NTP properly. Sync your clock, and the error should go away, try rebooting too - BUT, the error will probably return after a few days/weeks as the sync drops. Monitor for this error, and keep on top of it if you can!

 

;----- API Keys -----
Global $sAPI_Key_Access = "enter your access key"
Global $sAPI_Key_Secret = "enter your secret key"

;----- Prepare DLL -----
Global $hDll_WinHTTP = DllOpen("winhttp.dll")


;########## EXAMPLE API CALLS ##########

;----- Ping Binance -----
Global $sRet = _BINANCE_API_Call("api/v3/ping")
ConsoleWrite($sRet & @CRLF & @CRLF)

;----- Get Binance's Server Time -----
$sRet = _BINANCE_API_Call("api/v3/time")
ConsoleWrite($sRet & @CRLF & @CRLF)

;----- Get BTC/USDT Average Price -----
$sRet = _BINANCE_API_Call("api/v3/avgPrice","symbol=BTCUSDT")
ConsoleWrite($sRet & @CRLF & @CRLF)

;----- Get ETH/BTC Live Ticker Price -----
For $i = 1 To 5
    Sleep(100)
    $sRet = _BINANCE_API_Call("api/v3/ticker/price", "symbol=ETHBTC")
    ConsoleWrite($sRet & @CRLF)
Next
ConsoleWrite(@CRLF)

;----- Get Last 10 ETH/BTC Trades -----
$sRet = _BINANCE_API_Call("api/v3/trades", "symbol=ETHBTC&limit=10")
ConsoleWrite($sRet & @CRLF & @CRLF)

;----- Get Your Account Data -----
$sRet = _BINANCE_API_Call("api/v3/account")
ConsoleWrite($sRet & @CRLF & @CRLF)






Func _BINANCE_API_Call($sEndPoint, $sParameters = "")
    ;**************************************************
    ; Performs Binance API Call Via Native WinHTTP dll
    ;**************************************************

    ;----- Vars -----
    ; Presume GET, assign POST if needed in switch
    Local $sGETorPOST = "GET"

    ;----- Check Endpoint Required -----
    ; Some endpoints require signing, other endpoints can be
    ; added as new cases.
    Switch $sEndPoint
        Case "api/v3/account"
            $sParameters &= "&timestamp=" & _TimeStamp()
            $sParameters &= "&signature=" & _HMAC($sParameters, $sAPI_Key_Secret)
        Case "api/v3/order"
            $sGETorPOST = "POST"
            $sParameters &= "&timestamp=" & _TimeStamp()
            $sParameters &= "&signature=" & _HMAC($sParameters, $sAPI_Key_Secret)
        Case "api/v3/myTrades"
            $sParameters &= "&timestamp=" & _TimeStamp()
            $sParameters &= "&signature=" & _HMAC($sParameters, $sAPI_Key_Secret)
    EndSwitch

    ;----- Start Session -----
    Local $hHTTP_Session = DllCall($hDll_WinHTTP, "handle", "WinHttpOpen", "wstr", "Mozilla/4.0", "dword", 0, "wstr", "", "wstr", "", "dword", 0)[0]
    ;----- Connect To Binance Server -----
    Local $hHTTP_Connection = DllCall($hDll_WinHTTP, "handle", "WinHttpConnect", "handle", $hHTTP_Session, "wstr", "api.binance.com", "dword", 443, "dword", 0)[0]
    ;----- Prepare Request Data -----
    If $sParameters <> "" Then $sParameters = "?" & $sParameters
    Local $hHTTP_Request = DllCall($hDll_WinHTTP, "handle", "WinHttpOpenRequest", "handle", $hHTTP_Connection, "wstr", $sGETorPOST, "wstr", $sEndPoint & $sParameters, "wstr", "HTTP/1.1", "wstr", "", "ptr", 0, "dword", 0x00800000)[0]
    ;----- Add Request Header -----
    ; Adds API key to header even if not specifically needed, inconsequential
    DllCall($hDll_WinHTTP, "bool", "WinHttpAddRequestHeaders", "handle", $hHTTP_Request, "wstr", "X-MBX-APIKEY: " & $sAPI_Key_Access, "dword", -1, "dword", 0x10000000)
    ;----- Send Request To Server -----
    DllCall($hDll_WinHTTP, "bool", "WinHttpSendRequest", "handle", $hHTTP_Request, "wstr", "", "dword", 0, "ptr", 0, "dword", 0, "dword", 0, "dword_ptr", 0)
    ;----- Recieve Response -----
    DllCall($hDll_WinHTTP, "bool", "WinHttpReceiveResponse", "handle", $hHTTP_Request, "ptr", 0)
    ;----- Recieve Headers -----
    ; Extract HTTP return code and API weight
    Local $sHeaders = DllCall($hDll_WinHTTP, "bool", "WinHttpQueryHeaders", "handle", $hHTTP_Request, "dword", 22, "wstr", "", "wstr", "", "dword*", 65536, "dword*", 0)[4]
    Local $sHTTP_ReturnCode = StringMid($sHeaders, StringInStr($sHeaders, "HTTP/1.1 ") + 9, StringInStr($sHeaders, @CR, 0, 1, StringInStr($sHeaders, "HTTP/1.1 ") + 9) - (StringInStr($sHeaders, "HTTP/1.1 ") + 9))
    Local $sAPI_Weight = StringMid($sHeaders, StringInStr($sHeaders, "x-mbx-used-weight: ") + 19, StringInStr($sHeaders, @CR, 0, 1, StringInStr($sHeaders, "x-mbx-used-weight: ") + 19) - (StringInStr($sHeaders, "x-mbx-used-weight: ") + 19))
    Local $sAPI_IPBan_RetryAfter_Sec = StringInStr($sHeaders, "Retry-After: ") = 0 ? "" : StringMid($sHeaders, StringInStr($sHeaders, "Retry-After: ") + 13, StringInStr($sHeaders, @CR, 0, 1, StringInStr($sHeaders, "Retry-After: ") + 13) - (StringInStr($sHeaders, "Retry-After: ") + 13))
    ;----- Get Data -----
    Local $sData = ""
    Local $iBytesToRead, $hBuffer_Data
    While 1
        ;- Get Bytes To Read In This Loop -
        $iBytesToRead = DllCall($hDll_WinHTTP, "bool", "WinHttpQueryDataAvailable", "handle", $hHTTP_Request, "dword*", 0)[2]
        ;- Check If No More Data To Read -
        If $iBytesToRead <= 0 Then ExitLoop
        ;- Prep Data Buffer -
        $hBuffer_Data = DllStructCreate("char[" & $iBytesToRead & "]")
        ;- Read Data To Buffer -
        DllCall($hDll_WinHTTP, "bool", "WinHttpReadData", "handle", $hHTTP_Request, "struct*", $hBuffer_Data, "dword", $iBytesToRead, "dword*", 0)
        ;- Get Data From Buffer -
        $sData &= DllStructGetData($hBuffer_Data, 1)
        ;- Release -
        $hBuffer_Data = ""
    WEnd
    ;----- Close Handles -----
    DllCall($hDll_WinHTTP, "bool", "WinHttpCloseHandle", "handle", $hHTTP_Request)
    DllCall($hDll_WinHTTP, "bool", "WinHttpCloseHandle", "handle", $hHTTP_Connection)
    DllCall($hDll_WinHTTP, "bool", "WinHttpCloseHandle", "handle", $hHTTP_Session)

    ;----- Return Data -----
    ; Include HTTP Code and API Weight to check for overuse, and retry period if banned
    ; HTTP CODES : 429=over request limit, 418=IP banned due to overuse
    ; API WEIGHT : over 1200 will lead to ban
    Return '{"HTTPCode":"' & $sHTTP_ReturnCode & '","APIWeight":"' & $sAPI_Weight & ($sAPI_IPBan_RetryAfter_Sec = "" ? "" : '","Retry-After":"' & $sAPI_IPBan_RetryAfter_Sec) & '"}' & $sData

EndFunc   ;==>_BINANCE_API_Call

Func _HMAC($bData, $bKey)
    ;**************************************************
    ; Create HMAC SHA256 Signature
    ;**************************************************
    Local $oHMAC = ObjCreate("System.Security.Cryptography.HMAC" & "SHA256")
    $oHMAC.key = Binary($bKey)
    Local $bHash = $oHMAC.ComputeHash_2(Binary($bData))
    Return StringLower(StringMid($bHash, 3))
EndFunc   ;==>_HMAC

Func _TimeStamp()
    ;**************************************************
    ; Create UNIX-style TimeStamp
    ;**************************************************
    ; This is 'unix time', aka UTC time in milliseconds
    Local $aTimeStamp = DllCall("msvcrt.dll", "int:cdecl", "time", "int", 0)
    Return ($aTimeStamp[0] * 1000) + @MSEC ;convert to miliseconds
EndFunc   ;==>_TimeStamp

 

An example return would be:

{"HTTPCode":"200 OK","APIWeight":"4"}{"symbol":"ETHBTC","price":"0.07152900"}

 

The first {} block is the HTTP code and API weight, the second {} block is the full Binance JSON reply.

The JSON can be queried with a JSON UDF (do a search on the forum), or can be split with regexp.

 

 

Again, please use with caution! :)

 

Feel free to donate if you find this useful!:

NANO

nano_1161rm7egfzwgbtckwe8aoicee55897bbgc8apzrp1s3fzyyn7zqobbtkmfh

 

 

Amazzing , you are a lifesaver , thank you very much for sharing this ...

AutoFox, A Modern, Simple, No dependency, Noob friendly yet powerful Firefox UDF !

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...