Skip to main content

Base58 Class

software.sava.core.encoding.Base58 Provides Base58 encoding and decoding for Solana public keys and signatures.

Encoding Methods

Encode to String

static String encode(byte[] input)
input
byte[]
required
Bytes to encode
return
String
Base58-encoded string
static String encode(byte[] input, int offset, int to)
offset
int
required
Starting offset in input array
to
int
required
Ending index (exclusive)

Encode to Char Array

static int encode(byte[] input, char[] output)
output
char[]
required
Destination char array (must be at least input.length * 2)
return
int
Starting index of encoded data in output array
static int encode(byte[] input, int offset, int to, char[] output)

Decoding Methods

static byte[] decode(String input)
input
String
required
Base58-encoded string
return
byte[]
Decoded bytes
Throws IllegalArgumentException if input contains invalid Base58 characters.
static byte[] decode(char[] input)
static byte[] decode(char[] input, int from, int len)
from
int
required
Starting index
len
int
required
Length to decode

Validation Methods

static boolean isBase58(char c)
c
char
required
Character to check
return
boolean
True if character is valid Base58
static boolean isBase58(String str)
str
String
required
String to validate
return
boolean
True if all characters are valid Base58
static int nonBase58(String str)
return
int
Index of first invalid character, or -1 if all valid

Example Usage

import software.sava.core.encoding.Base58;

// Encode bytes to Base58
byte[] publicKey = new byte[32];
String encoded = Base58.encode(publicKey);
System.out.println(encoded); // "11111111111111111111111111111111"

// Decode Base58 string
String address = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
byte[] decoded = Base58.decode(address);

// Validate Base58 string
if (Base58.isBase58(address)) {
    System.out.println("Valid address");
}

// Find invalid character
String invalid = "invalid-address-0OIl";
int pos = Base58.nonBase58(invalid);
if (pos >= 0) {
    System.out.println("Invalid at position: " + pos);
}

ByteUtil Class

software.sava.core.encoding.ByteUtil Utilities for reading and writing integers in little-endian format.

Write Methods

Integers

static void putInt16LE(byte[] b, int off, int val)
static void putInt16LE(byte[] b, int off, short val)
b
byte[]
required
Destination byte array
off
int
required
Offset in array
val
int | short
required
Value to write (16-bit)
static void putInt32LE(byte[] b, int off, int val)
static void putInt64LE(byte[] b, int off, long val)

Floating Point

static void putFloat32LE(byte[] b, int off, float val)
static void putFloat32LE(byte[] b, int off, double val)
static void putFloat64LE(byte[] b, int off, double val)

Big Integers

static int putInt128LE(byte[] data, int offset, BigInteger val)
static int putInt256LE(byte[] data, int offset, BigInteger val)
return
int
Number of bytes written (16 or 32)

Read Methods

Integers

static int getInt8LE(byte[] b, int off)
return
int
Unsigned 8-bit value (0-255)
static short getInt16LE(byte[] b, int off)
static int getInt32LE(byte[] b, int off)
static long getInt64LE(byte[] b, int off)
b
byte[]
required
Source byte array
off
int
required
Offset in array

Floating Point

static float getFloat32LE(byte[] b, int off)
static double getFloat64LE(byte[] b, int off)

Big Integers

static BigInteger getInt128LE(byte[] data, int offset)
static BigInteger getUInt128LE(byte[] data, int offset)
static BigInteger getInt256LE(byte[] data, int offset)
static BigInteger getUInt256LE(byte[] data, int offset)

Utility Methods

Reverse Bytes

static byte[] reverse(byte[] bytes)
static byte[] reverse(byte[] bytes, int len)
static byte[] reverse(byte[] bytes, int offset, int len)
return
byte[]
New array with reversed bytes

Fixed Length Arrays

static byte[] fixedLength(byte[] bytes, int length)
bytes
byte[]
required
Input bytes
length
int
required
Desired length
return
byte[]
Array padded with zeros to specified length
Throws IllegalArgumentException if input exceeds desired length.
static byte[] fixedLength(String val, int length)
static byte[] fixedLength(String val, int length, Charset charset)
static int indexOf(byte[] data, byte[] sub)
data
byte[]
required
Array to search
sub
byte[]
required
Subsequence to find
return
int
Index of first occurrence, or -1 if not found
static int indexOf(byte[] data, int start, byte[] sub)
static int indexOf(byte[] data, int start, int end, byte[] sub, int subStart, int subEnd)

Example Usage

import software.sava.core.encoding.ByteUtil;
import java.math.BigInteger;

// Write integers
byte[] buffer = new byte[16];
ByteUtil.putInt32LE(buffer, 0, 12345);
ByteUtil.putInt64LE(buffer, 4, 9876543210L);

// Read integers
int value32 = ByteUtil.getInt32LE(buffer, 0);
long value64 = ByteUtil.getInt64LE(buffer, 4);

// Work with 128-bit integers
var bigInt = new BigInteger("340282366920938463463374607431768211455");
ByteUtil.putInt128LE(buffer, 0, bigInt);
var retrieved = ByteUtil.getUInt128LE(buffer, 0);

// Reverse bytes
byte[] original = {1, 2, 3, 4, 5};
byte[] reversed = ByteUtil.reverse(original);
// reversed = {5, 4, 3, 2, 1}

// Fixed length string
String seed = "vault";
byte[] fixedSeed = ByteUtil.fixedLength(seed, 32);
// Padded to 32 bytes with zeros

CompactU16Encoding Class

software.sava.core.encoding.CompactU16Encoding Encodes integers (0 to 262,143) in compact variable-length format.

Format

  • 0-127: 1 byte
  • 128-16,383: 2 bytes
  • 16,384-262,143: 3 bytes

Encoding Methods

static byte[] encodeLength(int len)
len
int
required
Value to encode (0 to 262,143)
return
byte[]
Encoded bytes (1-3 bytes)
static int encodeLength(byte[] out, int off, int len)
out
byte[]
required
Destination array
off
int
required
Offset in destination
return
int
Number of bytes written (1, 2, or 3)

Decoding Methods

static int decode(byte[] out, int off)
out
byte[]
required
Source array
off
int
required
Offset to read from
return
int
Decoded integer value

Utility Methods

static int getByteLen(int len)
len
int
required
Value to encode
return
int
Number of bytes required (1, 2, or 3)
static int getByteLen(byte[] data, int offset)
data
byte[]
required
Encoded data
return
int
Number of bytes in encoded value
static boolean signedByte(int bite)
bite
int
required
Byte value to check
return
boolean
True if byte has high bit set (multi-byte encoding)

Example Usage

import software.sava.core.encoding.CompactU16Encoding;

// Encode values
byte[] encoded1 = CompactU16Encoding.encodeLength(100);
// 1 byte: [100]

byte[] encoded2 = CompactU16Encoding.encodeLength(1000);
// 2 bytes: [0xe8, 0x07]

byte[] encoded3 = CompactU16Encoding.encodeLength(100000);
// 3 bytes

// Encode into buffer
byte[] buffer = new byte[10];
int written = CompactU16Encoding.encodeLength(buffer, 0, 5000);
System.out.println("Bytes written: " + written); // 2

// Decode
int value = CompactU16Encoding.decode(buffer, 0);
System.out.println("Decoded: " + value); // 5000

// Get byte length
int byteLen = CompactU16Encoding.getByteLen(100000);
System.out.println("Byte length: " + byteLen); // 3

// Check if multi-byte
boolean isMultiByte = CompactU16Encoding.signedByte(buffer[0]);

Use Cases

  • Transaction Encoding: Account and instruction counts
  • Lookup Tables: Address counts
  • Vector Lengths: Borsh serialization
  • Compact Indexing: Space-efficient indices

Encoding Details

1-byte encoding (values 0-127):
0xxxxxxx
2-byte encoding (values 128-16,383):
1xxxxxxx 0xxxxxxx
3-byte encoding (values 16,384-262,143):
1xxxxxxx 1xxxxxxx 000000xx
The high bit (0x80) indicates continuation to the next byte.

Build docs developers (and LLMs) love