Question: does anyone know how to make a post request from Coinspot API? The information of how to put the API key, secret and nonce is not very clear

---

All requests to the POST API requests will need to include the following security data.

Headers key - Your API key generated from the settings page sign - The POST data is to be signed using your secret key according to HMAC-SHA512 method. Post Params nonce - Any integer value which must always be greater than the previous requests nonce value.

---

I am trying to create a REST API, but I am getting a 401 request error. Not sure what I am doing wrong?

```html
const axios = require("axios");
var n = require("nonce")();
const crypto = require("crypto");

const api_key = process.env.COINSPOT_KEY;
const api_secret = process.env.COINSPOT_SECRET;

let nonce = n();
let postdata = { nonce: nonce };

function getSecurePassword(password, salt, algo) {
  const algoFormatted = algo.toLowerCase().replace("-", "");
  const hash = crypto.createHmac(algoFormatted, salt);
  hash.update(password);
  const res = hash.digest("hex");
  return res;
}

exports.orderHistory = async (req, res) => {
  let sign = getSecurePassword(api_secret, JSON.stringify(postdata), "SHA-512");
  try {
    await axios({
      baseURL: "https://www.coinspot.com.au/api/v2/ro",
      url: "my/orders/completed",
      port: 443,
      method: "post",
      data: postdata,
      headers: { key: api_key, sign: sign },
    }).then(function (response) {
      res.json(response);
    });
  } catch (error) {
    res.json(error);
  }
};
```

Answer: 
As the [documentation](https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-expandenvironmentstringsa) explains:

> 
> `lpDst`
> 
> 
> A pointer to a buffer that receives the result of expanding the environment variable strings in the *lpSrc* buffer.
> 
> 
> 

The buffer needs to be supplied by the caller, while the code simply passes an uninitialized pointer, alongside tricking the system into believing that it points at memory with a size of 1024 bytes.

A simple fix would be:

```cpp
void expandWindowsString(const std::string &input, std::string &output)
{
    const char* in = input.c_str();
    char out[1024];
    ExpandEnvironmentStrings(in, out, 1024);
    output = out;
}

```

There's lots of room for improvement, e.g.

* Using the [Unicode version](https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-expandenvironmentstringsw)
* Handling errors (as explained in the documentation)
* Repeatedly growing the output buffer in case the API call returns a value larger than the provided buffer length
* Constructing a `std::string` using the [pointer and length](https://en.cppreference.com/w/cpp/string/basic_string/basic_string)
* Returning a value rather than using an out parameter

As for why it fails when being called a second time: That's a meaningless question. The code exhibits undefined behavior by writing through an uninitialized pointer. With that, **any** outcome is possible, including the code appearing to work as expected.
ExpandEnvironmentStrings expects a buffer already allocated. You can determine the size of the buffer if [you pass a buffer with a size too small to hold the string](https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-expandenvironmentstringsa#return-value), like 0.

So, here are two versions, UNICODE and ANSI, that will compute the size dynamically:

```
std::wstring expandWindowsString(const std::wstring& input)
{
    std::wstring output;
    do
    {
        auto size = ExpandEnvironmentStringsW(input.c_str(), (LPWSTR)output.c_str(), output.size());
        if (!size || size <= output.size())
            break;

        output.resize(size);
    } while (true);
    output = output.c_str();
    return output;
}

std::string expandWindowsString(const std::string& input)
{
    std::string output;
    do
    {
        auto size = ExpandEnvironmentStringsA(input.c_str(), (LPSTR)output.c_str(), output.size());
        if (!size || size <= output.size())
            break;

        output.resize(size);
    } while (true);
    output = output.c_str();
    return output;
}

```