frank1 has asked for the wisdom of the Perl Monks concerning the following question:

am trying to parse bitstamp api

but am getting this error

Error: {"status": "error", "reason": "Invalid nonce", "code": "API0004"}

API documentation https://www.bitstamp.net/api/

#!/usr/bin/perl use strict; use warnings; use URI qw(); use Time::HiRes qw(gettimeofday); use Digest::SHA qw(hmac_sha256_hex); use LWP::UserAgent; my $uri = URI->new(); my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 }, ); $ua->agent("MyApp/0.1"); my $apiKey = 'Jp'; my $apiSecret = '2ULKB1'; my $urlcb = "https://www.bitstamp.net/api/v2/usdt_withdrawal/"; my $url = URI->new($urlcb); my $urlpath = $url->path(); my $timestamp = int (gettimeofday * 1000); my $nonce = int(rand(1000000)); my %params = $uri->query_form( 'currency' => "USDT", 'network' => "ethereum", 'address' => "", 'amount' => "4", ); my $signature = hmac_sha256_hex($nonce.'POST'.$urlpath.%params, $apiSe +cret); my %payload = ( "X-Auth" => $apiKey, "X-Auth-Signature" => $signature, "X-Auth-Nonce" => $nonce, "X-Auth-Timestamp" => $timestamp, "X-Auth-Version" => 'v2', "Content-Type" => 'application/x-www-form-urlencoded' ); my $req = HTTP::Request->new(POST=>$url); $req->header(%payload); $req->content(%params); my $resp = $ua->request($req); if($resp->is_success){ print $resp->content ."\n"; } else{ print "Error: " . $resp->content; }

Replies are listed 'Best First'.
Re: Invalid nonce
by marto (Cardinal) on Jul 19, 2024 at 13:54 UTC

    Your nonce doesn't meet the criteria specified in the documentation:

    Client generated random nonce: lowercase, 36 char string, each nonce can be used only once within a timeframe of 150 seconds +.

      thanks i have been able to fix this problem by generating nonce like this

      my @Char = ('a'..'z'); my $Leng = 36; my $RandomChar = ''; for (1..$Leng) { $RandomChar .= $Char[int rand @Char]; }

        but Corion told you not to use rand(). because it is likely (in the case of 36char strings actually quite unlikely) that nonce will be the same. Why introduce bugs in your code? You can start with a nonce and keep incrementing it perhaps? my $startnonce = 'a' x 36; print $startnonce++."\n" for 1..10; (note that this will expand to invalid nonce of 37 characters long after some 26**36 nonces). Or append Time::HiRes::time() into a constant nonce part in order to complete 36 chars my $nonce = substr Time::HiRes::time().("a" x 36), 0, 36. This will fail if your two requests happen in the same nanosecond.

        minor edits after a few minutes

        am just having this error confusing me

        Error: {"status": "error", "reason": "Content-Type header should not be present", "code": "API0020"}

        and API says

        Content-Type header should not be present Please make sure you're not sending any body in the request.

        and when i remove "Content-Type" => 'application/x-www-form-urlencoded'

        am getting this error Error: {"status": "error", "reason": "Invalid signature", "code": "API0005"}

      That's odd, a nonce is usually a monotonically increasing number. The higher the refinement of said number using epoch in nanoseconds (e.g.), the better. So rather than generating the nonce randomly, use the current timestamp (in nanoseconds), then maybe hash it or tr/[0-9]/[a-j]/. That it restricts you to the same one every 150 seconds is also weird.
Re: Invalid nonce
by Corion (Patriarch) on Jul 19, 2024 at 13:40 UTC

    The documentation for that error number says:

    Check your nonce value. It must be different than last nonce used in the last 150 seconds.

    Have you checked your nonce against all other nonces sent within the last three minutes? If you use rand there is a possibility to get a repeat value.

    I recommend using a counter, or a linear sequence that is long enough to not repeat within three minutes of your program making requests.