I have a smart contract I am interacting with but I cannot seem to form a proper JSON object using these variables. I have been able to pull the data and log it, I've even been able to pull other data in other functions without issue but these numbers are returning an error when attempting to respond using these values.
As expected this code works:
app.get('/stats', async (req, res) => {
try {
res.json({'maxSupply':1});
} catch (error) {
// Handle any errors that occur during the stats
res.status(500).send("500 Error:");
}
And this code works:
app.get('/stats', async (req, res) => {
try {
const totalSupply = await contract.methods.totalSupply().call();
console.log("Total Supply: ",totalSupply)
const remainingSupply = await contract.methods.remainingSupply().call();
console.log("Remaining Supply: ",remainingSupply)
// Create the high-level response object
const responseObj = {
totalSupply: Number(totalSupply),
remainingSupply: Number(remainingSupply)
};
// Forward the response data to the client
console.log("JSON", responseObj);
and the resulting output is:
Server running on port 8080
Total Supply: 189880000000000000n
Remaining Supply: 810120000000000000n
JSON {
totalSupply: 189880000000000000,
remainingSupply: 810120000000000000
}
When I add the json response line in like this I get a 500 error.
// Forward the response data to the client
res.json({'totalSupply':totalSupply});
and
res.json(responseObj)
both fail. What am I missing here?
You're going to get issues serializing large numbers like this with JSON, specifically ones that exceed the IEEE754 floating point safe-decimal amount [1].
In this case, in Javascript:
> 189880000000000000 > Number.MAX_SAFE_INTEGER
true
The n
at the end of the number indicates that it is a native BigInt value. [2]. These are integer-only numbers of arbitrary size.
You cannot natively serialize BigInt with JSON.
JSON.stringify({ a: 1n })
Uncaught TypeError: Do not know how to serialize a BigInt
JSON can only use the IEEE standard for serializing numbers.
You can serialize the number as a string (String(18988n)
) and then coerce it from a string to a BigInt with BigInt(s)
.
Another option is to use a different encoding from JSON e.g. CBOR [3].
In addition to the inability to serialize, with IEEE floating point numbers you also cannot guarantee that the amounts will perform arithmetic correctly i.e. for fractions (but there are also whole-integer-cases when using numbers above MAX_SAFE_INTEGER
)
> 0.1 + 0.2
0.30000000000000004
so you may generally wish to prefer BigInt, if your numbers are indeed guaranteed to be integers.