Using the REST API

Hi all,

Is it possible to make REST API calls without having a local node [fully synced] on my machine?

In other words, would it be possible to get the same functionality of the Algorand block explorer for my python app, but without the need to depend on a local node; which I fear may become an issue in regards to taking up too much space.

Thanks!

1 Like

Dave, yes. Just sign up and use purestake api. https://www.purestake.com/technology/algorand-api/

1 Like

Hi Dave,

AlgoExplorer has a full API. We will release it publicly very soon but if you want to start playing with it you can get full documentation here:
https://api.algoexplorer.io/v1/doc/swagger.yml, you can open this file with https://editor.swagger.io/ to read it fully formatted.

Get 10 latest transactions of Binance hot wallet:
https://api.algoexplorer.io/v1/account/SP745JJR4KPRQEXJZHVIEN736LYTL2T2DFMG3OIIFJBV66K73PHNMDCZVM/transactions/latest/10

Get transactions of block 2783757:
https://api.algoexplorer.io/v1/block/2783757/transactions

Get block count on Testnet:
https://api.testnet.algoexplorer.io/v1/block/count

It supports Mainnet / Testnet / Betanet.

Best,
Pablo

3 Likes

Hey Dave - Sorry for the delay here. As Visybl said, you can just sign up for an account on PureStake.com We’ve got a few different levels depending on what you’re looking for. Feel free to reach out if you need a hand nateATpurestakeDOTcom

1 Like

Hi, @NHamilton!
How can the PureStake POST API used?
Namely, in what binary format shoud be the transaction?
After using base 64 encoding, the result is:

Error: Bad Request

can't parse JSON. Raw result: msgpack decode error [pos 1]: only encoded map or array can be decoded into a struct

Can you give a specific example of using the POST API?

At present time, the POST transaction requires an additional header containing the content-type of application/x-binary and in JavaScript in particular one client for the GETs and one for the POST.

PureStake is working with Algorand to try to bake the header directly into the SDK’s for this call and barring that a simplified version where only a single client is created - but for now here is a complete example at https://github.com/PureStake/api-examples/blob/master/javascript-examples/submit_tx.js

PureStake has examples in all the SDK supported languages here - https://github.com/PureStake/api-examples

2 Likes

To @NHamilton

Using PureStake API with cURL, post signed transaction (on Testnet):

$ curl -X POST "https://testnet-algorand.api.purestake.io/ps1/v1/transactions" -H  "accept: application/json" -H  "Content-Type: application/x-binary" -H  "x-api-key: (api_key)" --data-binary @tx1.tx
{"txId":"BLNQO3NTHPW3GPXHGI3P7OXDFJED2PJ4J6XVZAZJ7T5ITCXDWHFQ"}

Note, that the signed transation can be included in the POST request with

--data-binary @filename

Note also, that fv (firstvalid) in the transaction must be less equal that that the actual block number.

1 Like

Great to see. Let us know if you need a hand with anything.

Hello Maugli, can you please show me what’s inside of the tx1.tx file? I am trying to run the same curl you posted but I am always getting this error message:

msgpack decode error [pos 1]: only encoded map or array can be decoded into a struct

Thanks

Did you try to generate the transaction following this tutorial?

https://developer.algorand.org/docs/build-apps/hello_world/

Yes, I have no issues getting the proper response using JavaScript, but it is failing when I try to do the same using cUrl or PureStake.

Thanks

How are you generating the file? From the developer site, creating and signing using goal looks like:

$ goal clerk send --from=<my-account> --to=GD64YIY3TWGDMCNPP553DZPPR6LDUSFQOIJVFDPPXWEG3FVOJCCDBBHU5A --fee=1000 --amount=1000000 --note="Hello World" --out="hello-world.txn"

$ goal clerk sign --infile="hello-world.txn" --outfile="hello-world.stxn"

Also, in the cUrl, note the inclusion of the header object denoting the ‘Content-type’ as ‘application/x-binary’ - this carries over in the JavaScript w/PureStake as a requirement to include the content type with the transaction submission.

I have a similar issue. Note that some of links above are broken. I read and applied the fixes myself. I also went into the js-algorand-sdk to look at what the SDK does and even following that I get a 400 malformed request error.

I want to send a transaction to the algoexplorer endpoint for broadcast. Specifically: first an opt-in transaction, and then normal transactions to move assets.

@pipaman, that file contains no POST request for the /v2/transactions or even the /transactions endpoint whereas you can find the /v2/transaction endpoint here: AlgoExplorer API v2

I am building an application that will go live soon, I’d appreciate if the community can help me sort this out in a timely manner. Thank you.

@NHamilton, I need some help. :slight_smile:

Sample code:



>`// Get the mainnet recommended parameters for transactions
  const algoApiParams = axios.create({baseURL: "https://algoexplorerapi.io/",
    timeout: 1000,
    headers: {"accept": "application/json"},
  });

  return algoApiParams.get( "v2/transactions/params" )
      .then( (parms: any) => {
        const assetID = 123456789;  //Just a dummy assetID for posting here
        const params = parms.data;
        
        const parameters = {
          "fee": 1000,
          "flatFee": true,
          "genesisHash": params["genesis-hash"],
          "lastRound": params["last-round"] + 10,
          "genesisID": params["genesis-id"],
          "firstRound": params["last-round"] - 10,
        };

        const sender    = wallet;
        const recipient = wallet;
        const revocationTarget = undefined;
        const closeRemainderTo = undefined;
        const amount = 0;
        const note   = undefined;

        const opttxn = algosdk.makeAssetTransferTxnWithSuggestedParams(
            sender,
            recipient,
            closeRemainderTo,
            revocationTarget,
            amount,
            note,
            assetID,
            parameters);

        const rawSignedTxn =  algosdk.signTransaction( opttxn,  pkey );
        
        // Send the transaction
        const algoApiBroadcastTxn = axios.create({baseURL: "https://algoexplorerapi.io/",
          timeout: 1000,
          headers: { 'accept': 'application/json',
          "Content-Type": "application/x-binary"},
        });

        return algoApiBroadcastTxn.post("v2/transactions/",
        rawSignedTxn.blob )
            .then( (res2) => {
              console.log(res2);
              return res2;
            })
            .catch( (err) =>{
              console.log("POST error message: ", err);
              return err;
            });
      }).catch( (err) => {
        console.log(err);
        return  err ;
      });

`
Error Message:


POST error message:  Error: Request failed with status code 400
config: {
    transitional: {
      silentJSONParsing: true,
      forcedJSONParsing: true,
      clarifyTimeoutError: false
    },
    adapter: [Function: httpAdapter],
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 1000,
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    maxBodyLength: -1,
    validateStatus: [Function: validateStatus],
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/x-binary',
      'User-Agent': 'axios/0.23.0',
      'Content-Length': 251
    },
    baseURL: 'https://algoexplorerapi.io/',
    method: 'post',
    url: 'v2/transactions/',
    data: ArrayBuffer {
      [Uint8Contents]: <82 a3 73 69 67 c4 40 d7 99 d5 1b 22 bf 2f 15 04 ad 6d b1 5c 92 a4 ce 32 ef c0 63 6f 10 24 dd 4f 64 8c 9b 04 0c 1c 88 75 22 85 5c fa c5 e4 75 22 35 2d 92 13 db ee fb 79 08 78 cb a7 a5 5e c2 4d d2 dc 11 31 c9 8c 05 a3 74 78 6e 89 a4 61 72 63 76 c4 20 74 97 9c 73 de 18 35 f6 85 8a cf d2 de 86 67 ca 7c ... 151 more bytes>,
      byteLength: 251
    }
  }

data: {
      message: 'TransactionPool.Remember: transaction T5WT3L576AOZO6OIN4MDP3M7H6XI5J5CK4BFZNOUDJESWGAYQ4MA: overspend (account OSLZY466DA27NBMKZ7JN5BTHZJ6NY652WYTA4EHYXQ4TMFSMBJGYRO5RIE, data {_struct:{} Status:Offline MicroAlgos:{Raw:0} RewardsBase:0 RewardedMicroAlgos:{Raw:0} VoteID:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] SelectionID:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] VoteFirstValid:0 VoteLastValid:0 VoteKeyDilution:0 AssetParams:map[] Assets:map[] AuthAddr:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ AppLocalStates:map[] AppParams:map[] TotalAppSchema:{_struct:{} NumUint:0 NumByteSlice:0} TotalExtraAppPages:0}, tried to spend {1000})'
    }

I omitted part of the error response as it is not relevant.

Firstly, it’s highly recommended to use the SDK (algosdk) instead of manually making REST queries. The SDK takes care of all encoding issues.

Regarding your specific issue, the error is:

TransactionPool.Remember: transaction T5WT3L576AOZO6OIN4MDP3M7H6XI5J5CK4BFZNOUDJESWGAYQ4MA: overspend (account OSLZY466DA27NBMKZ7JN5BTHZJ6NY652WYTA4EHYXQ4TMFSMBJGYRO5RIE, data {_struct:{} Status:Offline MicroAlgos:{Raw:0} RewardsBase:0 RewardedMicroAlgos:{Raw:0} VoteID:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] SelectionID:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] VoteFirstValid:0 VoteLastValid:0 VoteKeyDilution:0 AssetParams:map[] Assets:map[] AuthAddr:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ AppLocalStates:map[] AppParams:map[] TotalAppSchema:{_struct:{} NumUint:0 NumByteSlice:0} TotalExtraAppPages:0}, tried to spend {1000})

From the error message you see that the issue is that the account OSLZY466DA27NBMKZ7JN5BTHZJ6NY652WYTA4EHYXQ4TMFSMBJGYRO5RIE is empty (i.e., does not have Algos).
You need Algos to pay transaction fees.

On MainNet (what you are using), you need to buy Algos on an exchange.
If you switch to TestNet, you may use the dispenser: TestNet - Algorand Developer Portal

Thank you.

I’ve had great difficulty using the js-Algorand-SDK directly. So much so that it was faster and easier to just do it myself directly. The algo explorer requires no tokens for the headers, the SDK’s automatically add this header API-token thing that is not needed, and there is all sorts of head aches from there.

If I can get one working example each in code for the algoexplorer V2 REST API, for both python and js as I use both of them, then I will use them. Until then, this is easier for me.

Now the next hurdle is atomic transactions. How do I perform atomic transactions using the algo explorer REST API. Getting all my transactions signed and the groupID is easy, getting the encoding so that algo explorer will accept my post request seems impossible. One transaction? Piece of cake. A group of them as an atomic unit? How cow how do people do this!! I have tried everything and I even looked and did the exact same thing that the js-algorand-sdk did. I have my signed Txns as Uint8 arrays; I flatten them using the exact same function the js-sdk has; and then I do Buffer.from( flattenedTxns ) and send it away. Still I get the 400 HTTP error.

I would very much like to get a group transaction posted to the algoexplorer REST API as soon as possible.

Thank you.

@fabrice

To submit group transactions, you just need to concatenate the encoding of all the transactions in the group.

Can you show the exact error you got?

Actually, you are right!! I had a typo in my concat function, so it wan’t concatenating every byte in the right place. I fixed that and now it works.

I do wonder, on the topic of the official algorand-SDKs and the algoexplorer free public API. Could you please create examples for that specific use case? That way people don’t have to REST API directly making the request and parsing the data directly.

You can use any example in the documentation, just changing the algodToken/algodServer/algodPort accordingly:

const algosdk = require('algosdk');

(async function() {
    const algodToken = '';
    const algodServer = 'https://testnet.algoexplorerapi.io';
    const algodPort = '';
    const algodClient = new algosdk.Algodv2(algodToken, algodServer, algodPort);

    const status = await algodClient.status().do();

    console.log(JSON.stringify(status, null, 2));
})();
1 Like