---
title: "Waves"
description: "Waves addresses decode to 26 bytes. The validator checks the mainnet byte and checksum."
canonical_url: "https://chains.agntn.dev/chains/waves"
---
# Waves

> Waves addresses decode to 26 bytes. The validator checks the mainnet byte and checksum.

<chain-facts chain="waves">



</chain-facts>

## Waves address format

What's under a Waves address? Base58 hides 26 bytes, using the Bitcoin alphabet.

- One entity type byte, set to `1`.
- One chain ID byte.
- A 20-byte account public key hash.
- A 4-byte checksum.

The public key hash is the first 20 bytes of Keccak256(Blake2b256(publicKey)). Waves uses original Keccak-256, not FIPS SHA3-256. The [address binary format](https://docs.waves.tech/en/blockchain/binary-format/address-binary-format) documents the layout.

The check decodes base58, with a limit of 36 characters. It checks the byte count, entity type, mainnet byte and checksum. It reports every broken rule together. A length window would be a fragile substitute.

It doesn't check whether the account exists. The address contains a public key hash, not the public key. Transaction recipients can also use aliases such as `alias:W:name`. Those aren't addresses and the check refuses them.

```ts
import { getChain } from "@agntn/chains";

const chain = getChain("waves");
chain.assertAddress("3PPbMwqLtwBGcJrTA5whqJfY95GqnNnFMDX"); // returned unchanged
chain.caip2; // "waves:087"
chain.bip44; // 5741564
```

That address is a documented Waves test vector. Its public key is `HBqhfdFASRQ5eBBpu2y6c6KKi1az6bMx8v1JxX4iW1Q8`. `decodeAddress` returns `{ kind: "account" }`.

Waves has 8 decimals. One WAVES is 100,000,000 wavelets.

## Why mainnet addresses start with 3P

Every mainnet address carries byte `87`, ASCII `W`. That makes every mainnet address start with `3P`.

Testnet uses byte `84`, ASCII `T`. Its addresses start with `3M` or `3N`. Stagenet uses byte `83`, ASCII `S`. Its addresses start with `3M`. Both networks are refused.

For example, `3N9Q2sdkkhAnbR4XCveuRaSMLiVtvebZ3wp` fails with `chain byte "T", Waves testnet, where mainnet writes "W"`.

The CAIP-2 ID is `waves:087`. The namespace writes the chain byte as a padded signed integer.

## Waves checksum and Base58Check

The checksum covers the first 22 bytes. It's the first four bytes of Keccak256(Blake2b256(first 22 bytes)). Two different hashes for four bytes. Fair enough.

This isn't Base58Check. Base58Check runs one hash twice. Waves stacks two different hashes once. The Waves class computes its checksum itself.

Change the last character and the checksum fails. The reason says `the checksum does not hold, so a character is wrong`.

## Identifying a Waves address

What about `3PBitcoinAVGJvpSe6jevepPbT3M8SoMZjb`? It's a real Waves mainnet sender. `identify` returns Waves alone, with the key `waves`. The Bitcoin validator refuses it. The name inside the address doesn't get a vote.

## Waves transaction IDs

Transaction IDs are base58 decoded to 32 or 64 bytes. Other widths fail.

A 32-byte ID is a hash, such as `kD9ahh6vk5AQKQnnAGW797Qxwadidzf6Jty6r4imDQX`.

Why accept 64 bytes? Genesis and payment transactions, the oldest kinds Waves has, still use their signatures as IDs. The first genesis transaction is `2DVtfgXjpMeFf2PQCqvwxAiaGbiDsxDjSdNQkc5JQ74eWxjWFYgwvqzC4dn7iB1AhuM32WxEiVi1SGijsBtYQwn8`. The node's `TransactionId` path reads exactly these two widths.

## Waves chain spellings

Use `waves` or `Waves` with `getChain`. Case doesn't matter. There are no other aliases.


## Sitemap

See the full [sitemap](https://chains.agntn.dev/sitemap.md) for all pages.
