Address Class

OP_NET provides the Address class as the unified representation for all address operations throughout the library. This class offers methods and properties for creating addresses from various input formats, validating address correctness, converting between address types and extracting the underlying public key data, all while enforcing network-specific encoding rules.

Address Creation

The Address class provides two ways to create an instance, depending on the input format available:

  • constructor(): Creates an address directly from raw public key bytes
  • fromString(): Parses an address from its hexadecimal string representation.

Using constructor()

The Address constructor accepts two optional parameters:

  • mldsaPublicKey: The quantum-resistant ML-DSA public key.
  • publicKeyOrTweak: The classical public key or tweak value. Valid lengths are 32, 33, or 65 bytes.

If no parameters are provided, an empty address instance is created. If only mldsaPublicKey is provided, the address is initialized with quantum-resistant key data only.

typescript
How to create an address using its constructor
import { Address } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

// From ML-DSA public key hash and classical public key
const mldsaHash = Buffer.alloc(32, 0x01);         // SHA256 of ML-DSA public key
const classicalKey = Buffer.from('02...', 'hex'); // 33-bytes compressed key

const address = new Address(mldsaHash, classicalKey);

// Generate addresses
const p2op = address.p2op(networks.bitcoin);
const p2tr = address.p2tr(networks.bitcoin);

Using fromString()

The static fromString() method creates an Address instance from hexadecimal strings. It accepts the ML-DSA public key as the first parameter and an optional classical public key as the second. Both parameters must be in hexadecimal format. The 0x prefix is automatically stripped if present.

typescript
How to Create an address from a hex string
import { Address } from '@btc-vision/transaction';

// Create address from hex strings
const address = Address.fromString(
    '0xabcdef1234567890...',  // ML-DSA public key hash (32 bytes hex)
    '0x02...'                 // Classical public key (33 bytes hex)
);

Dead Address

The dead address is a special address for which no private key exists. The Address class provides the dead() method to retrieve the standard dead address.

typescript
How to get the dead address
// Special "dead" address (all zeros)
const deadAddress = Address.dead();
console.log('Dead address:', deadAddress.toHex());
// Output: 0x0000000000000000000000000000000000000000000000000000000000000000

Address Methods and Properties

The Address class exposes multiple methods and properties such as mldsaPublicKey for accessing the quantum-resistant public key and originalPublicKey for the classical public key. It also provides utility methods including toHex() for hexadecimal representation and toBuffer() for binary conversion, among others.

See Address.ts source code for the Address class definition.

typescript
How to use some methods and properties
const address = wallet.address;

// Quantum address (SHA-256 hash of ML-DSA public key) - Universal public key
console.log('Quantum address:', address.toHex());
console.log('Quantum address buffer:', address.toBuffer());

// Classical public key
console.log('Classical key (hex):', address.tweakedToHex());
console.log('Classical key (buffer):', address.tweakedPublicKeyToBuffer());

// Original keys
console.log('Full ML-DSA public key:', address.mldsaPublicKey);  // 1312-2592 bytes
console.log('Original classical key:', address.originalPublicKey);

Network Support

Remember, address formats vary depending on the network. The following examples demonstrate how to specify a network when working with the Address class.

Mainnet

typescript
How to use address with mainnet
import { Mnemonic, Address } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

const mnemonic = Mnemonic.generate();

const wallet = mnemonic.derive(0);

// All mainnet addresses
console.log('P2OP:', wallet.address.p2op(networks.bitcoin));      // bc1s...
console.log('P2TR:', wallet.address.p2tr(networks.bitcoin));      // bc1p...
console.log('P2WPKH:', wallet.address.p2wpkh(networks.bitcoin));  // bc1q...
console.log('P2PKH:', wallet.address.p2pkh(networks.bitcoin));    // 1...
        

Testnet

typescript
How to use address with testnet
import { Mnemonic, MLDSASecurityLevel, Address } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

// Testnet with different prefixes
const mnemonic = Mnemonic.generate(
    undefined,                            // Default strength (24 words)
    '',                                   // No passphrase
    networks.testnet,                     // Testnet network
    MLDSASecurityLevel.LEVEL2             // Security level
);

const wallet = mnemonic.derive(0);

console.log('P2OP:', wallet.address.p2op(networks.testnet));      // tb1s...
console.log('P2TR:', wallet.address.p2tr(networks.testnet));      // tb1p...
console.log('P2WPKH:', wallet.address.p2wpkh(networks.testnet));  // tb1q...
console.log('P2PKH:', wallet.address.p2pkh(networks.testnet));    // m... or n...
        

Regtest

typescript
How to use address with regtest
import { Mnemonic, MLDSASecurityLevel, Address } from '@btc-vision/transaction';

// Regtest for local development
const regtestMnemonic = Mnemonic.generate(
    undefined,                            // Default strength (24 words)
    '',                                   // No passphrase
    networks.regtest,                     // Regtest network
    MLDSASecurityLevel.LEVEL2             // Security level
);

const wallet = regtestMnemonic.derive(0);

console.log('P2OP:', wallet.address.p2op(networks.regtest));      // bcrt1s...
console.log('P2TR:', wallet.address.p2tr(networks.regtest));      // bcrt1p...
        

Address Comparison

Equality

To compare two Address instances, use the equals() method. This method performs a proper comparison of the underlying address data and returns true if both addresses are identical.

typescript
How to compare 2 addresses
import { Mnemonic, MLDSASecurityLevel } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

const wallet1 = mnemonic.derive(0);
const wallet2 = mnemonic.derive(0);
const wallet3 = mnemonic.derive(1);

const addr1 = wallet1.address;
const addr2 = wallet2.address;
const addr3 = wallet3.address;

// Same derivation index = same address
console.log(addr1.equals(addr2));  // true

// Different index = different address
console.log(addr1.equals(addr3));  // false

Ordering

For ordering comparisons, use the lessThan() and greaterThan() methods. These methods enable sorting and ordering operations on address collections.

typescript
How to sort addresses
import { Mnemonic, MLDSASecurityLevel } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

// Generate wallet with ML-DSA support
const mnemonic = Mnemonic.generate(
    undefined,                            // Default strength (24 words)
    '',                                   // No passphrase
    networks.bitcoin,                     // Mainnet
    MLDSASecurityLevel.LEVEL2             // Security level
);

const wallet = mnemonic.derive(0);
const addresses = [
    mnemonic.derive(5).address,
    mnemonic.derive(2).address,
    mnemonic.derive(8).address,
    mnemonic.derive(1).address,
];

// Less than comparison
console.log(addresses[0].lessThan(addresses[1]));

// Greater than comparison
console.log(addresses[0].greaterThan(addresses[1]));

// Sort addresses
addresses.sort((a, b) => {
    if (a.lessThan(b)) return -1;
    if (a.greaterThan(b)) return 1;
    return 0;
});

Time-Locked Addresses (CSV)

CSV (CheckSequenceVerify) addresses enable time-locked transactions where funds can only be spent after a specified number of blocks have passed. Use the toCSV() method to generate a CSV address from an existing Address instance. This method accepts two parameters: the the lock duration in blocks and network configuration.

typescript
How to use the CSV feature
import { Mnemonic, MLDSASecurityLevel } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

// Generate wallet with ML-DSA support
const mnemonic = Mnemonic.generate(
    undefined,                            // Default strength (24 words)
    '',                                   // No passphrase
    networks.bitcoin,                     // Mainnet
    MLDSASecurityLevel.LEVEL2            // Security level
);

const wallet = mnemonic.derive(0);

// Create time-locked address (100 blocks)
const duration = 100;
const csvAddress = wallet.address.toCSV(duration, networks.bitcoin);

console.log('CSV Address (100 blocks):', csvAddress);

// Different durations
const addr1Day = wallet.address.toCSV(144, networks.bitcoin);    // ~1 day
const addr1Week = wallet.address.toCSV(1008, networks.bitcoin);  // ~1 week
const addr1Month = wallet.address.toCSV(4320, networks.bitcoin); // ~1 month

// Valid range: 1 to 65535 blocks
const minLock = wallet.address.toCSV(1, networks.bitcoin);
const maxLock = wallet.address.toCSV(65535, networks.bitcoin);

Complete Example

typescript
How to get all supported address types
import { Mnemonic, MLDSASecurityLevel } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';

// Generate wallet with ML-DSA support
const mnemonic = Mnemonic.generate(
    undefined,                            // Default strength (24 words)
    '',                                   // No passphrase
    networks.bitcoin,                     // Mainnet
    MLDSASecurityLevel.LEVEL2             // Security level
);

const wallet = mnemonic.derive(0);
const address = wallet.address;

console.log('=== Universal Public Key (Quantum Address) ===');
console.log('Quantum Address:', address.toHex());  // SHA-256 hash of ML-DSA public key
console.log('ML-DSA Key Size:', address.mldsaPublicKey?.length, 'bytes');

console.log('\n=== P2OP Address (Contract Address) ===');
console.log('P2OP:', address.p2op(networks.bitcoin));  // Encoded form of quantum address

console.log('\n=== Classical Addresses ===');
console.log('P2TR (Taproot):', address.p2tr(networks.bitcoin));
console.log('P2WPKH (SegWit):', address.p2wpkh(networks.bitcoin));
console.log('P2PKH (Legacy):', address.p2pkh(networks.bitcoin));
console.log('P2SH-P2WPKH:', address.p2shp2wpkh(networks.bitcoin));

console.log('\n=== Testnet Addresses ===');
console.log('P2OP:', address.p2op(networks.testnet));
console.log('P2TR:', address.p2tr(networks.testnet));

console.log('\n=== Time-Locked Address ===');
console.log('CSV (100 blocks):', address.toCSV(100, networks.bitcoin));