Address Class
OP_NET provides the Address class to manage all address requirements. This class offers a comprehensive set of methods and properties for address generation, validation, conversion, and manipulation across all supported address types and networks.
Address Creation
The Address class can be instantiated using two methods:
- constructor: Creates an address from raw key data.
- 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.
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.
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.
// Special "dead" address (all zeros)
const deadAddress = Address.dead();
console.log('Dead address:', deadAddress.toHex());
// Output: 0x0000000000000000000000000000000000000000000000000000000000000000Address 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.
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
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
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
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.
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)); // falseOrdering
For ordering comparisons, use the lessThan() and greaterThan() methods. These methods enable sorting and ordering operations on address collections.
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.
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
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));