Api

BigInt Methods

Methods for serializing and deserializing arbitrary-precision integers using JavaScript's native BigInt type.

Sia supports arbitrary-precision integers through JavaScript's native BigInt type. This is useful for values that exceed the 53-bit safe integer limit of Number, such as cryptographic values, blockchain amounts, or large counters. Available as both class methods and standalone functions:

// Class API
import { Sia } from "@timeleap/sia";

// Functional API (tree-shakeable)
import { Buffer, addBigInt, readBigInt } from "@timeleap/sia";

addBigInt(n) / readBigInt()

Writes or reads a BigInt value. The value is encoded as a variable-length big-endian byte array with an 8-bit length prefix.

addBigInt(n: bigint): Sia
readBigInt(): bigint
ParameterTypeDescription
nbigintThe BigInt value to serialize

Returns (add): this (for chaining)

Returns (read): bigint

Throws: "BigInt too large for this simple implementation" if the encoded byte representation exceeds 255 bytes.

Encoding Format

BigInt values are encoded using the following steps:

  1. The BigInt is converted to a hexadecimal string
  2. The hex string is padded to even length if needed
  3. Each pair of hex digits becomes one byte (big-endian order)
  4. The byte array is written using addByteArray8, which prepends a 1-byte length prefix

The wire format is:

[1 byte: length] [N bytes: big-endian value]

For example, the value 123456789012345678901234567890 encodes as:

[13] [05 8D 15 E1 76 28 0F 09 AA CE 7B 22 52]
  ^    ^--- 13 bytes of big-endian data ----^
  |
  length prefix
The encoding uses big-endian byte order for the value itself (most significant byte first), which differs from the little-endian order used by integer methods. This matches Go's big.Int.Bytes() encoding for cross-language compatibility.

Limitations

  • Maximum encoded size is 255 bytes (limited by the 8-bit length prefix from addByteArray8). This supports integers up to 2^2040 - 1, which is sufficient for most practical use cases.
  • Only non-negative values are supported. The encoding does not include a sign bit.
  • The value 0n encodes as a zero-length byte array (1 byte total for the prefix).
If you need to serialize signed BigInt values, handle the sign separately:
const value = -123456789n;
sia.addBool(value < 0n).addBigInt(value < 0n ? -value : value);

Example

import { Sia } from "@timeleap/sia";

// A value too large for Number
const largeValue = BigInt("123456789012345678901234567890");

const sia = new Sia();
sia.addBigInt(largeValue);

sia.seek(0);
const result = sia.readBigInt();

console.log(result === largeValue); // true
console.log(result.toString()); // "123456789012345678901234567890"

Use Cases

Cryptographic Values

import { Sia } from "@timeleap/sia";

// 256-bit cryptographic hash as BigInt
const hash = BigInt(
  "0xd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
);

const sia = new Sia();
sia.addBigInt(hash);
const bytes = sia.toUint8Array();

console.log(bytes.length); // 33 bytes (1 prefix + 32 value)

Token Amounts

import { Sia } from "@timeleap/sia";

// ERC-20 token amounts often exceed Number.MAX_SAFE_INTEGER
const amount = BigInt("1000000000000000000"); // 1 token with 18 decimals

const sia = new Sia();
sia.addAscii8("TRANSFER").addBigInt(amount).addByteArrayN(new Uint8Array(20)); // recipient address

const bytes = sia.toUint8Array();

// Deserialize
const reader = new Sia(bytes);
const action = reader.readAscii8();
const tokenAmount = reader.readBigInt();
const recipient = reader.readByteArrayN(20);

console.log(action); // "TRANSFER"
console.log(tokenAmount.toString()); // "1000000000000000000"

Comparison with Integer Methods

MethodTypeRangeBytes
addUInt64number0 to 2^53 - 18 (fixed)
addInt64number-(2^53 - 1) to 2^53 - 18 (fixed)
addBigIntbigint0 to 2^2040 - 11 + N (variable)

Use addUInt64/addInt64 when your values fit within the safe integer range for better performance and fixed-size encoding. Use addBigInt when you need arbitrary precision.