BitVavo API benadering via .NET

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Mijn vraag

Ik probeer via C#.NET de API van BitVavo te benaderen. Er bestaan, zover ik weet, geen .NET clients voor deze API, dus ik moest zelf aan de slag.

Sommige functies kan ik benaderen. Maar zodra ik een request in wil schieten met parameters (b.v. de Orders-request met parameter "market", dan houdt het op.

Als ik hun docs interpreteer (o.a. https://docs.bitvavo.com/#tag/Orders/paths/~1orders/get en https://docs.bitvavo.com/#section/Signing-REST-requests) dan dien ik de request-paremters in de body op te nemen. Echter een body met een HTTP-GET-request levert een protocol-exceptie op (het mag ook niet volgens RFC2616).

Heeft iemand hier ervaring mee? Weet iemand hoe ik een request juist en correct opbouw?

Alle reacties


Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 10:16

Haan

dotnetter

Ik zie 7 verschillende order requests die je zou kunnen doen, welke heb je het precies over? En het zou handig zijn om een stukje code te delen zodat we kunnen zien wat je precies aan het doen bent.

Tip: gebruik eerst even een tool als Postman om je requests te testen.

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

  • Groentjuh
  • Registratie: September 2011
  • Laatst online: 10-09 15:16
GET-requests kunnen prima HEADERs hebben; Headers zijn anders dan een request-body.

[ Voor 3% gewijzigd door Groentjuh op 11-06-2021 15:42 ]


Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Groentjuh schreef op vrijdag 11 juni 2021 @ 15:40:
GET-requests kunnen prima HEADERs hebben; Headers zijn anders dan een request-body.
Dat weet ik. Die moet ik sowieso toevoegen ivm versleuteling. Het gaat nu om de interpretatie van hun docs-pagina en wat ik als gevolg moet doen.

Acties:
  • +1 Henk 'm!

  • barellron
  • Registratie: April 2012
  • Laatst online: 10:30
Je moet de market als querystring meesturen en de authenticatie in de headers.
De request verder is GET.

Het handigst is het eerst werkende te krijgen in Postman, zoals eerder aangegeven. Je zou zelfs de C# code vanuit daar kunnen exporteren op basis van de request.

[ Voor 44% gewijzigd door barellron op 11-06-2021 16:13 ]


Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Haan schreef op vrijdag 11 juni 2021 @ 15:40:
Ik zie 7 verschillende order requests die je zou kunnen doen, welke heb je het precies over? En het zou handig zijn om een stukje code te delen zodat we kunnen zien wat je precies aan het doen bent.

Tip: gebruik eerst even een tool als Postman om je requests te testen.
Het gaat mij nu even om "Orders" (zie mijn eerste link). En het gaat mij er niet om of mijn code correct is, maar hoe ik het correct moet vullen. Op basis van de documentatie kom ik er niet uit. Daarom vraag ik er naar van iemand die er ervaring mee heeft.

Ik moet verplicht een json-entiteit meegeven met daarin "market". Dat zal zoiets worden als {market="BTC-EUR"} (gebaseerd op hun voorbeeld bij authenticatie).

De vraag is: Waar plaats ik dit stukje json? In de body? Als header? Als querystring?

Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
barellron schreef op vrijdag 11 juni 2021 @ 16:11:
Je moet de market als querystring meesturen en de authenticatie in de headers.
De request verder is GET.

Het handigst is het eerst werkende te krijgen in Postman, zoals eerder aangegeven. Je zou zelfs de C# code vanuit daar kunnen exporteren op basis van de request.
Ik ga postman zo proberen.

Ik denk dat mijn verwarring zit in dat ze de URL anders opbouwen dan de "tekst" die ze gebruiken voor de signature. Deze laatste is wel beschreven en daarin wordt een json-entiteit meegegeven. Ik vermoed steeds meer dat deze entiteit helemaal niet meegegeven moet worden als zodanig in het request. De inhoud wel, maar de entiteit zelf niet.

Acties:
  • 0 Henk 'm!

  • barellron
  • Registratie: April 2012
  • Laatst online: 10:30
muldermartin schreef op vrijdag 11 juni 2021 @ 16:28:
[...]


Ik ga postman zo proberen.

Ik denk dat mijn verwarring zit in dat ze de URL anders opbouwen dan de "tekst" die ze gebruiken voor de signature. Deze laatste is wel beschreven en daarin wordt een json-entiteit meegegeven. Ik vermoed steeds meer dat deze entiteit helemaal niet meegegeven moet worden als zodanig in het request. De inhoud wel, maar de entiteit zelf niet.
Ik snap het, het staat er wel alleen op een minder duidelijke manier:
Afbeeldingslocatie: https://i.ibb.co/HFSS4kf/Capture.png

Querystring moet het komen.

Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Ik heb nu het volgende geprobeerd:

Adres: https://api.bitvavo.com/v2/orders?market=BTC-EUR

Signature is gebaseerd op deze tekst: 1623422161038GET/v2/orders{"market":"BTC-EUR"}

Ik blijf de foutmelding krijgen: 309 = "The signature is invalid."

Dus ik doe duidelijk iets niet correct.

Met postman gaat het ook niet lukken. Ik maar daar, tijdens het invullen van alles dezelfde "interpretatiefout". Tevens moet de signature elke 30 seconden opnieuw berekend worden. Geen idee of postman dat automatisch kan, maar dat is een andere vraag.

Acties:
  • +1 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Ik denk het ik het gevonden heb. Hun voorbeeld betreft een POST. In hun voorbeeld gebruiken ze een json-entiteit als body. Zowel in de body als in de signature berekening.

Ik moet een GET doen. Ik ging uit van een json die ik ERGENS moest gebruiken, of in de berekening, dan wel in de request. Niets is minder waar. De zoekparameters moesten onderdeel zijn van de query-string en de deze URL (althans, een gedeelte) moest weer gebruikt worden voor de signature.

Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Laatst online: 10:16

Haan

dotnetter

Het staat nochtans vrij duidelijk uitgelegd, met voorbeeld requests en alles er bij in diverse talen .
Voor de goede orde: je probeert een nieuwe order te plaatsen dmv een POST? Want als je een order wilt opvragen moet je wel een GET doen, maar moet je ook een order id meesturen geen orderId nodig als je meerdere orders wilt opvragen.

Maar sowieso moet je dus altijd een aantal headers ook meesturen zoals staat uitgelegd, anders zal het sowieso nooit gaan werken. Aangezien je die moet genereren zal dat met Postman wat lastiger gaan (kan volgens mij wel, maar dan moet je er echt verstand van hebben)

[ Voor 5% gewijzigd door Haan op 11-06-2021 17:14 ]

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

  • barellron
  • Registratie: April 2012
  • Laatst online: 10:30
muldermartin schreef op vrijdag 11 juni 2021 @ 16:43:
Ik heb nu het volgende geprobeerd:

Adres: https://api.bitvavo.com/v2/orders?market=BTC-EUR

Signature is gebaseerd op deze tekst: 1623422161038GET/v2/orders{"market":"BTC-EUR"}

Ik blijf de foutmelding krijgen: 309 = "The signature is invalid."

Dus ik doe duidelijk iets niet correct.

Met postman gaat het ook niet lukken. Ik maar daar, tijdens het invullen van alles dezelfde "interpretatiefout". Tevens moet de signature elke 30 seconden opnieuw berekend worden. Geen idee of postman dat automatisch kan, maar dat is een andere vraag.
A signature is generated by creating a SHA256 HMAC hex digest of timestamp + method + url + body. Please note that timestamp is the same timestamp used in the header. The url is with the /v2/ prefix. Body may be empty (e.g. GET requests), otherwise this is a string representation of the body.

verder staat er bij: https://docs.bitvavo.com/ bij "Introduction" een button Run with postman.

met een collectie met alle requests en voorbeelden.

Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Haan schreef op vrijdag 11 juni 2021 @ 17:10:
Het staat nochtans vrij duidelijk uitgelegd, met voorbeeld requests en alles er bij in diverse talen .
Voor de goede orde: je probeert een nieuwe order te plaatsen dmv een POST? Want als je een order wilt opvragen moet je wel een GET doen, maar moet je ook een order id meesturen geen orderId nodig als je meerdere orders wilt opvragen.

Maar sowieso moet je dus altijd een aantal headers ook meesturen zoals staat uitgelegd, anders zal het sowieso nooit gaan werken. Aangezien je die moet genereren zal dat met Postman wat lastiger gaan (kan volgens mij wel, maar dan moet je er echt verstand van hebben)
Het staat mogelijk uitgelegd in diverse talen, en met bijhorende diverse clients. Echter... er bestaat geen .NET-client, dus alle voorbeelden zijn voor mij nutteloos. Dat gene wat ik dus wil maken is al opgelost in die clients die zij als voorbeeld gebruiken.

En ja, ik stuur mijn headers mee zoals gedefinieerd. En ik probeerde mijn orders uit het verleden op te halen. Maar zoals beschreven is mijn probleem opgelost.

Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
barellron schreef op vrijdag 11 juni 2021 @ 17:19:
[...]


A signature is generated by creating a SHA256 HMAC hex digest of timestamp + method + url + body. Please note that timestamp is the same timestamp used in the header. The url is with the /v2/ prefix. Body may be empty (e.g. GET requests), otherwise this is a string representation of the body.

verder staat er bij: https://docs.bitvavo.com/ bij "Introduction" een button Run with postman.

met een collectie met alle requests en voorbeelden.
Heb ik allemaal al gelezen. Maar dat zegt weinig over mijn probleem. Ook die postman-button lost niets op. Het opent slechts postman met die URL, that is it. Dus het gaf geen antwoord op de vraag: Waar en hoe voel ik die market-parameter in in zowel de het request als in de signature.

Acties:
  • 0 Henk 'm!

  • barellron
  • Registratie: April 2012
  • Laatst online: 10:30
muldermartin schreef op vrijdag 11 juni 2021 @ 17:40:
[...]


Heb ik allemaal al gelezen. Maar dat zegt weinig over mijn probleem. Ook die postman-button lost niets op. Het opent slechts postman met die URL, that is it. Dus het gaf geen antwoord op de vraag: Waar en hoe voel ik die market-parameter in in zowel de het request als in de signature.
Postman link laad een collectie, die je bij Collections kan zien in postman.

Als samenvatting:
market gaat in querystring
authentication in headers
voor de signature is de body leeg als de request GET is.

Acties:
  • +2 Henk 'm!

  • roberts
  • Registratie: December 2001
  • Laatst online: 10-09 10:04
Ik gebruikt zelf RestSharp, misschien heeft iemand hier iets aan.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
     public static List<TickerPrice> GetTickerPrices()
        {
            var command = "/v2/ticker/price";
            var url = string.Concat(endpointUrl + command);
            var client = new RestClient(url){Timeout = -1};
            var request = new RestRequest(Method.GET){ RequestFormat = DataFormat.Json };

            var time = GetTime();
            var signatureString = time + "GET" + command;
            var signature = signatureString.HmacSha256Digest(secret);
            request.AddHeader("Bitvavo-Access-Key", key);
            request.AddHeader("Bitvavo-Access-Signature", signature);
            request.AddHeader("Bitvavo-Access-Timestamp", time);
            request.AddHeader("Bitvavo-Access-Window", "4000");
            request.AddHeader("Content-Type", "application/json");
            IRestResponse response = client.Execute(request);
            var result = DeserializeResponse.TickerPrice(response.Content.ToString());
            return result;
        }

        public static string GetTime()
        {
            var clientTime = new RestClient(string.Concat(endpointUrl, "/v2/time"));
            var requestTime = new RestRequest(Method.GET);
            IRestResponse response_time = clientTime.Execute(requestTime);
            var jsonData = JObject.Parse(response_time.Content.ToString());
            return jsonData["time"].ToString();

        }



C#:
1
2
3
4
5
6
7
8
9
10
11
12
  public static class Extension
    {
        public static string HmacSha256Digest(this string signature, string secret)
        {
            ASCIIEncoding encoding = new();
            byte[] keyBytes = encoding.GetBytes(secret);
            byte[] messageBytes = encoding.GetBytes(signature);
            System.Security.Cryptography.HMACSHA256 cryptographer = new(keyBytes);
            byte[] bytes = cryptographer.ComputeHash(messageBytes);
            return BitConverter.ToString(bytes).Replace("-", "").ToLower();
        }
}

Acties:
  • 0 Henk 'm!

  • anddam
  • Registratie: Augustus 2021
  • Laatst online: 22-12-2024
Zou iemand hier misschien een voorbeeld hebben van hoe het opgelost kan worden? Mij is namelijk uit eerdere posts niet duidelijk wat de oplossing is voor dit probleem. Ik ben bezig met een side project in C# maar om een of andere reden elke keer als ik een private request maak is de signature invalid.

  • Ludi.Kuyper
  • Registratie: September 2021
  • Laatst online: 06-05 20:35
Het heeft me nogal wat moeite gekost om lid te worden en te kunnen reageren op dit bericht.
Ik weet dat de laatste reactie meer dan 2 weken geleden is.

Ik wil Bitvavo ook benaderen via .Net.

Ik hoop niet dat ik te laat ben en zou het fijn vinden als we hier gezamenlijk tot een oplossing kunnen komen.

Acties:
  • +1 Henk 'm!

  • Rheptor
  • Registratie: Augustus 2001
  • Laatst online: 08-09 16:01
Ik heb hier vandaag ook mee lopen stoeien. Het is lastig voor iemand zonder parate kennis van het programmeren van API's om met de handleiding aan de slag te gaan. Maar met goed lezen ben ik er toch uit gekomen.

@Ludi.Kuyper & @anddam, wellicht hebben jullie hier iets aan.

Waar ik mee bezig was is in Filemaker een connectie maken met Bitvavo via een aanroep via URL met cURL parameters. Hiervoor heb ik deze gegevens / formules gebruikt:

Een aanroep naar "https://api.bitvavo.com/v2/time" voor het ophalen van de tijd op de Bitvavo server.
Resultaat = 12345678910 (Kun je ook zien wanneer je direct naar de webpagina gaat)

Daarna een aantal variabelen gedefinieerd (als tekst):
time_value = 12345678910
url_method = GET
url_suffix = /account
url_query = ""
url_body = ""
auth_string = time_value + url_method + "/v2" + url_suffix + url_body, wordt dan: "12345678910GET/v2/account"

Deze berekening is in het geval van Filemaker, https://fmhelp.filemaker....P_Help/cryptauthcode.html, moet je omzetten naar eigen platform;
auth = Lower ( HexEncode ( CryptAuthCode ( auth_string ; "SHA256" ; [[Plaats hier je Bitvavo API secret]] ), dit resulteert in een hexadecimale code van 64 karakters, zoals ook uitgelegd in de Bitvavo API handleiding bij Authorisatie.

Daarmee kun je de url aanroep inrichten en de headers opbouwen: (in mijn geval zit het er zo uit, let op de escapes voor de quotes.

"--header \"Content-Type: application/json\"
--header \"Bitvavo-Access-Signature: " & $$auth & "\"
--header \"Bitvavo-Access-Timestamp: " & $$time_value & "\"
--header \"Bitvavo-Access-Window: 60000\"
--header \"Bitvavo-Access-Key: [[Plaats hier je Bitvavo API key]]\""

Waar ik zelf op vastliep is de volgende stap, die @muldermartin ook al aanhaalde.

Wanneer je een GET doet op bijvoorbeeld je /account pagina, dan moet je het body en query deel leeg laten, dus ook geen {""} oid.
Daarmee wordt dan de basis voor je auth, de auth_string, 12345678910GET/v2/account en moet je URL https://api.bitvavo.com/v2/account zijn.

In het geval van een GET op /trades of /orders, dan moet je 2 zaken regelen. Dit voorkomt dat je een E203 "Market parameter is required" foutmelding krijgt.
1. Als url_query aan de URL toevoegen "?market=BTC-EUR"
2. Als body in je auth_string toevoegen "{\"market\":\"BTC-EUR\"}"

Misschien wat veel details, maar wie weet heeft er iemand iets aan. Dit heeft mij vandaag in ieder geval al 3 uur gekost ;)

Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Excuses voor mijn late reactie. Ik heb de boel inmiddels werkend middels C#. Als ik iemand een stapje verder kan helpen, dan hoor ik het graag.

Acties:
  • 0 Henk 'm!

  • Ludi.Kuyper
  • Registratie: September 2021
  • Laatst online: 06-05 20:35
Ik zou prijs stellen als je me iets verder zou kunnen helpen.

Ik werk dan wel met vb.Net maar het verschil tussen vb.Net en C# is nihiel.
Maar voor de connectie naar BtVavo staats ik volledig in het duister.

Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Ik heb praktisch alles wat ik wil up-and-running. Dus ik ga er vanuit dat ik je kan helpen. Wat is op dit moment datgene waar je tegen aan loopt?

Acties:
  • 0 Henk 'm!

  • Bloemy
  • Registratie: December 2019
  • Laatst online: 11-07 14:17
Iemand toevallig ook een idee hoe ik een connectie leg tussn Bitvavo en PowerBi?

Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
Bloemy schreef op maandag 25 oktober 2021 @ 19:41:
Iemand toevallig ook een idee hoe ik een connectie leg tussn Bitvavo en PowerBi?
Helaas, ik heb geen ervaring met PowerBI.

Acties:
  • 0 Henk 'm!

  • heigo
  • Registratie: Januari 2022
  • Laatst online: 03-01-2022
@muldermartin Ik heb de koppeling vanuit C# met Bitvavo werkend voor bijvoorbeeld ophalen van de timestamp of ophalen van het account. Waar het bij mij nu nog misgaat is dat als ik bijvoorbeeld trades opvraag, ik elke keer deze fout krijg:

{"errorCode":309,"error":"The signature is invalid."}

Ik heb allerlei variaties geprobeerd. Ik sign het volgende:

1641126669964GET/v2/trades{"market":"BTC-EUR"}

Als ik ditzelfde doe voor account, dan gaat het wel goed. Verschil is dat daar niet het stukje JSON in meegenomen is. Ik heb de REST-client geïnitialiseerd met de volgende varianten:

client = new RestClient(string.Concat("https://api.bitvavo.com", "/v2/trades));
client = new RestClient(string.Concat("https://api.bitvavo.com", "/v2/trades?market=BTC-EUR"));

Beide hielpen niet. Gevoelsmatig zit het probleem bij het opbouwen van de signature, met name in het stukje body (market=BTC-EUR) die ik erin moet meenemen. Zou jij een voorbeeld kunnen geven van de input van jouw signature? De versleuteling die ik heb zou wel moeten werken, omdat het voor account ook werkt.

Acties:
  • +1 Henk 'm!

  • ftpfreak
  • Registratie: November 2002
  • Laatst online: 08:55
heigo schreef op zondag 2 januari 2022 @ 13:39:
@muldermartin Ik heb de koppeling vanuit C# met Bitvavo werkend voor bijvoorbeeld ophalen van de timestamp of ophalen van het account. Waar het bij mij nu nog misgaat is dat als ik bijvoorbeeld trades opvraag, ik elke keer deze fout krijg:

{"errorCode":309,"error":"The signature is invalid."}

Ik heb allerlei variaties geprobeerd. Ik sign het volgende:

1641126669964GET/v2/trades{"market":"BTC-EUR"}

Als ik ditzelfde doe voor account, dan gaat het wel goed. Verschil is dat daar niet het stukje JSON in meegenomen is. Ik heb de REST-client geïnitialiseerd met de volgende varianten:

client = new RestClient(string.Concat("https://api.bitvavo.com", "/v2/trades));
client = new RestClient(string.Concat("https://api.bitvavo.com", "/v2/trades?market=BTC-EUR"));

Beide hielpen niet. Gevoelsmatig zit het probleem bij het opbouwen van de signature, met name in het stukje body (market=BTC-EUR) die ik erin moet meenemen. Zou jij een voorbeeld kunnen geven van de input van jouw signature? De versleuteling die ik heb zou wel moeten werken, omdat het voor account ook werkt.
Ik liep toevallig net tegen hetzelfde probleem aan, bij mij werkt het met de volgende aanpassing:
Ik sign nu: 1641126669964GET/v2/trades?market=BTC-EUR ipv 1641126669964GET/v2/trades{"market":"BTC-EUR"} en dan werkt het prima.

Acties:
  • +1 Henk 'm!

  • heigo
  • Registratie: Januari 2022
  • Laatst online: 03-01-2022
@ftpfreak jouw voorgestelde aanpassing works like a charm. Dank voor je hulp! Ik kan nu inderdaad ook de BTC-EUR trades ophalen, via de API.

Acties:
  • 0 Henk 'm!

  • muldermartin
  • Registratie: Maart 2020
  • Laatst online: 24-03 16:33
roberts schreef op woensdag 7 juli 2021 @ 11:39:
Ik gebruikt zelf RestSharp, misschien heeft iemand hier iets aan.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
     public static List<TickerPrice> GetTickerPrices()
        {
            var command = "/v2/ticker/price";
            var url = string.Concat(endpointUrl + command);
            var client = new RestClient(url){Timeout = -1};
            var request = new RestRequest(Method.GET){ RequestFormat = DataFormat.Json };

            var time = GetTime();
            var signatureString = time + "GET" + command;
            var signature = signatureString.HmacSha256Digest(secret);
            request.AddHeader("Bitvavo-Access-Key", key);
            request.AddHeader("Bitvavo-Access-Signature", signature);
            request.AddHeader("Bitvavo-Access-Timestamp", time);
            request.AddHeader("Bitvavo-Access-Window", "4000");
            request.AddHeader("Content-Type", "application/json");
            IRestResponse response = client.Execute(request);
            var result = DeserializeResponse.TickerPrice(response.Content.ToString());
            return result;
        }

        public static string GetTime()
        {
            var clientTime = new RestClient(string.Concat(endpointUrl, "/v2/time"));
            var requestTime = new RestRequest(Method.GET);
            IRestResponse response_time = clientTime.Execute(requestTime);
            var jsonData = JObject.Parse(response_time.Content.ToString());
            return jsonData["time"].ToString();

        }



C#:
1
2
3
4
5
6
7
8
9
10
11
12
  public static class Extension
    {
        public static string HmacSha256Digest(this string signature, string secret)
        {
            ASCIIEncoding encoding = new();
            byte[] keyBytes = encoding.GetBytes(secret);
            byte[] messageBytes = encoding.GetBytes(signature);
            System.Security.Cryptography.HMACSHA256 cryptographer = new(keyBytes);
            byte[] bytes = cryptographer.ComputeHash(messageBytes);
            return BitConverter.ToString(bytes).Replace("-", "").ToLower();
        }
}
Beste Roberts,

Deze code komt redelijk overeen met de mijne. Toch levert mijn code niet altijd, maar soms wel, een 309 = "The signature is invalid."

Het enigeverschil tussen jou en mijn code is dat jouw code per call een extra call doet om de servertijd van Bitvavo op te halen. Ik gebruik deze functie slechts 1x om het tijdsverschil tussen mijn machine en die van Bitvavo te bepalen. Dat zou toch voldoende moeten zijn? Ik vind per call een 2e call uitvoeren nogal "duur".

Heeft iemand al een werkende versie met slechts één een call?

PS: Als ik kijk naar andere libraries zie ik vaak ook dat er een tijdverschil wordt uitgerekend, en niet een call per call. Het zou dus echt wel moeten kunnen.

Acties:
  • 0 Henk 'm!

  • mannowlahn
  • Registratie: Mei 2009
  • Laatst online: 10:28
Jullie vergeten dan transport time. Zorg dat je voordat je de call naar bitvavo zelf een time stamp bij houdt en die dan vergelijkt met wat je terug krijgt. Dan heb je de echte tijd. Dat kan je 309 verklaren. Vanaf dat moment kan je deze tijd idd gaan bewaren. Maar ook dan hou rekening hoe je dat doet en besef dat zaken in je code soms tijd kosten. Ik weet niet wat de tolerantie van bitvavo is maar als die onder de seconde ligt en jij hebt een server less app die uit een koude start komt, dan gaat dit echt wel in de secondes zitten.

Acties:
  • 0 Henk 'm!

  • roberts
  • Registratie: December 2001
  • Laatst online: 10-09 10:04
@muldermartin Ik haal altijd de tijd op om die signaturestring op te bouwen.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 private static IRestResponse DoRequest(string command, Dictionary<string, string> parameters = null)
        {
            var url = string.Concat(endpointUrl + command);
            RestClient client = new(url) { Timeout = -1 };
            var request = new RestRequest(Method.GET);
            var responseTime = GetTime();
            if (!responseTime.IsSuccessful)
            {
                Console.WriteLine("Could not get time from API");
                return responseTime;
            }
            var paramString = string.Empty;
            if (parameters != null)
            {
                foreach (KeyValuePair<string, string> ele2 in parameters)
                {
                    var ParamValue = parameters.TryGetValue(ele2.Key, out var value) ? value : "";
                    if (!string.IsNullOrWhiteSpace(ParamValue))
                    {
                        request.AddParameter(ele2.Key, ele2.Value.ToUpper());
                        paramString = "?" + ele2.Key + "=" + ele2.Value.ToUpper();
                    }
                }
            }

            var signatureString = $"{responseTime.Content}GET{command}{paramString}";
            var signature = signatureString.HmacSha256Digest(secret);
            request.AddHeader("Bitvavo-Access-Key", key);
            request.AddHeader("Bitvavo-Access-Signature", signature);
            request.AddHeader("Bitvavo-Access-Timestamp", responseTime.Content);
            request.AddHeader("Bitvavo-Access-Window", "4000");
            request.AddHeader("Content-Type", "application/json");
            IRestResponse response = client.Execute(request);
            return response;
        }

Acties:
  • +1 Henk 'm!

  • mstreutker
  • Registratie: Augustus 2012
  • Laatst online: 27-01 13:56
Ik heb niet de hele thread gelezen, maar kwam toevallig hier vanwege de '309' fout.
Een klein beetje achtergrond, in mijn python-app probeer ik een order te plaatsen (buy of sell) en daarbij gaven sommige currencies consistent een 309 error, terwijl andere orders voor andere currencies succesvol geplaatst konden worden.
Bij python bleek dit te liggen aan het 'amount'; Als de minimal order quantity b.v. 0.01 is, dan moet het amount een float zijn.
Als de minimal order quantity b.v. 3 is, dan moet het amount een integer zijn. Het plaatsen van b.v. 3.0 resulteert in een 309 error.
Om het in python aan de praat te krijgen, haal ik dus eerst de market-data op om te bepalen welk datatype het amount moet zijn.
Geen idee of dit bij .NET ook zo is, maar wellicht hebben jullie hier iets aan :)

Acties:
  • 0 Henk 'm!

  • Bloemy
  • Registratie: December 2019
  • Laatst online: 11-07 14:17
Hi allen,

Ik ben ook met Postman aan de gang gegaan om informatie te trekken uit Bitvavo met name "Get/balance". Echter blijf ik ook hangen in die Signature. Ik heb echt van alles geprobeerd om die 64 Karakters lange signature naar boven te toveren maar het lukt me niet.


"errorCode": 309,
"error": "The signature is invalid."

Moet ik dan een pre-request script code maken of iets anders? Iemand die mij nog kan helpen?


Note: Ik ben echt een noob in API's, maar probeer het enigzins te leren.

Acties:
  • 0 Henk 'm!

  • erwinwernars
  • Registratie: April 2014
  • Laatst online: 02-09 22:21
Aangezien ik op dit topic uit kwam met googlen wil ik toch even een update geven hoe mensen kunnen connecten met bitvavo in postman. Ik heb het net werkend met postman met deels hulp uit het topic om de signature goed te krijgen.

Deze vaste headers heb ik nu staan:
Bitvavo-Access-Key: <Bitvavo-Api-Key>
Bitvavo-Access-Window: 30000
Content-Type: application/json

daarnaast heb ik een pre-request script toegevoegd en daar kan je dit script inzetten:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var time = '1673992630516'; //haal dit uit https://api.bitvavo.com/v2/time
var secret = <Bitvavo-Secret-Key>;
var signBytes = CryptoJS.HmacSHA256(
    time + 
    'GET/v2/orders?market=BTC-EUR', 
    secret
);
var signHex = CryptoJS.enc.Hex.stringify(signBytes);
pm.request.headers.add(
    {
        key: "Bitvavo-Access-Signature",
        value: signHex
    }
);
pm.request.headers.add(
    {
        key: "Bitvavo-Access-Timestamp",
        value: time
    }
);


nu hoef je alleen de tijd dus op te halen en deze aan te passen in de variable in pre-request script. Dit kun je natuurlijk verder optimaliseren, maar mij ging het even om dat ik het werkend kon krijgen met postman.

Hopelijk helpt dit mensen, voor in de toekomst!

[ Voor 9% gewijzigd door erwinwernars op 17-01-2023 23:16 ]


Acties:
  • 0 Henk 'm!

  • sig69
  • Registratie: Mei 2002
  • Laatst online: 11:52
Er zijn inmiddels twee bitvavo nuget packages te vinden, eentje lijkt redelijk dood maat deze is twee maanden geleden nog bijgewerkt: https://www.nuget.org/packages/BitvavoTrader.Api. Geen idee wat er allemaal wel en niet geïmplementeerd is maar wellicht het bekijken waard.

Roomba E5 te koop


Acties:
  • 0 Henk 'm!

  • Collen
  • Registratie: Mei 2002
  • Laatst online: 24-04 12:28

Collen

Dude..

Heren, Dank jullie wel...

Ik ben al een dag aan het klooien om de api van bitvavo aan de gang te krijgen onder Curl..
Dankzij dit draadje is het eindelijk gelukt..
gelukkig ben ik niet de enigste lees ik...

Thx

Acties:
  • 0 Henk 'm!

  • jawiko
  • Registratie: April 2023
  • Laatst online: 09-04-2023
heigo schreef op zondag 2 januari 2022 @ 13:39:
@muldermartin Ik heb de koppeling vanuit C# met Bitvavo werkend voor bijvoorbeeld ophalen van de timestamp of ophalen van het account. Waar het bij mij nu nog misgaat is dat als ik bijvoorbeeld trades opvraag, ik elke keer deze fout krijg:

{"errorCode":309,"error":"The signature is invalid."}

Ik heb allerlei variaties geprobeerd. Ik sign het volgende:

1641126669964GET/v2/trades{"market":"BTC-EUR"}

Als ik ditzelfde doe voor account, dan gaat het wel goed. Verschil is dat daar niet het stukje JSON in meegenomen is. Ik heb de REST-client geïnitialiseerd met de volgende varianten:

client = new RestClient(string.Concat("https://api.bitvavo.com", "/v2/trades));
client = new RestClient(string.Concat("https://api.bitvavo.com", "/v2/trades?market=BTC-EUR"));

Beide hielpen niet. Gevoelsmatig zit het probleem bij het opbouwen van de signature, met name in het stukje body (market=BTC-EUR) die ik erin moet meenemen. Zou jij een voorbeeld kunnen geven van de input van jouw signature? De versleuteling die ik heb zou wel moeten werken, omdat het voor account ook werkt.
Ik heb exact hetzelfde probleem en de suggestie in de andere post heeft me niet geholpen. Het werkt prima met account, maar niet met trades

Account werkt wel (krijg netjes fees te zien zonder foutmelding):
url = https://api.bitvavo.com/v2/account
query = 1681056449706GET/v2/account

trades werkt niet
url = https://api.bitvavo.com/v2/trades
query = 1681056849043GET/v2/trades?market=BTC-EUR

>> "errorCode":309,"error":"The signature is invalid."

Acties:
  • +1 Henk 'm!

  • ymoona
  • Registratie: Januari 2004
  • Laatst online: 12:07
Dit is een heel handig topic gebleken voor mij. Dank voor alle input.
@jawiko
Je moet zo wel op de url als in de signature de query string toevoegen.
Dus de input van je signature moet zijn:1702036126125GET/v2/trades?market=BTC-EUR
en je endpoint is dan: https://api.bitvavo.com/v2/trades?market=BTC-EUR

https://f1nerd.nl


Acties:
  • +1 Henk 'm!

  • Crome
  • Registratie: Juni 2024
  • Laatst online: 06-09-2024
muldermartin schreef op vrijdag 11 juni 2021 @ 16:52:
Ik denk het ik het gevonden heb. Hun voorbeeld betreft een POST. In hun voorbeeld gebruiken ze een json-entiteit als body. Zowel in de body als in de signature berekening.

Ik moet een GET doen. Ik ging uit van een json die ik ERGENS moest gebruiken, of in de berekening, dan wel in de request. Niets is minder waar. De zoekparameters moesten onderdeel zijn van de query-string en de deze URL (althans, een gedeelte) moest weer gebruikt worden voor de signature.
Omdat deze topic mij heeft geholpen de boel draaiende te krijgen, wil ik toch even reageren. Bovenstaande is het juiste antwoord op deze topic. Dank hiervoor.

Van belang is om te weten dat de opbouw van de signature overeen moet komen met de request zelf. Bij een GET worden alle parameters aan de URL meegeven zonder body. De signature bevat dus ook alleen de URL (inclusief parameters) en geen body.

Bij een POST dien je wel een body mee te sturen, dus deze dien je ook aan de signature toe te voegen. De parameters worden in dit geval niet aan de URL meegegeven.

Als je met dit in het achterhoofd de documentatie erbij pakt, is alles een stuk duidelijker.

Overigens raad ik aan om bij alle GET requests authenticatie te gebruiken ondanks dat dit niet altijd nodig is. Je wordt namelijk langer geblokkeerd als je de rate limit hebt bereikt zonder authenticatie.

Cheers

Acties:
  • 0 Henk 'm!

  • 8x4
  • Registratie: Oktober 2009
  • Niet online

8x4

nvm

(admin, verwijder deze post)

[ Voor 102% gewijzigd door 8x4 op 29-07-2024 00:20 ]

Pagina: 1