atp-chain-utils

Crates.ioatp-chain-utils
lib.rsatp-chain-utils
version0.1.3
created_at2025-08-05 08:20:12.113744+00
updated_at2025-08-28 07:43:39.455021+00
descriptionChain utilities for ATP(Account Transfer Protocol)
homepage
repositoryhttps://github.com/mycel-labs/atp
max_upload_size
id1781708
size87,763
taryune (taryune)

documentation

README

Chain Utils

A Rust library for generating blockchain addresses from public keys obtained via ICP threshold signatures, with support for CAIP (Chain Agnostic Improvement Proposals) chain identifiers.

Features

  • Multi-chain support: Generate addresses for different blockchain networks
  • CAIP integration: Uses CAIP-2 chain identifiers for standardized chain specification
  • ICP threshold signature compatibility: Designed to work with public keys from ICP threshold ECDSA/Schnorr signatures
  • Comprehensive testing: Full test coverage with validation for multiple scenarios

Supported Chains

Namespace Chain Address Format Public Key Format
eip155 Ethereum & EVM chains 0x-prefixed hex (42 chars) SEC1-encoded hex string
solana Solana Base58-encoded (32-44 chars) 32-byte hex string
bip122 Bitcoin & Bitcoin-compatible P2PKH base58 (26-35 chars) SEC1-encoded hex string

Usage

Basic Address Generation

use atp_chain_utils::address::generate_address;
use atp_caip::chain_id::ChainId;

// Generate Ethereum address
let eth_pubkey = "04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235";
let eth_chain = ChainId::new("eip155", "1").unwrap(); // Ethereum mainnet
let eth_address = generate_address(eth_pubkey.to_string(), eth_chain)?;
println!("Ethereum address: {}", eth_address); // 0x1234...

// Generate Solana address  
let sol_pubkey = "e258d6e13adfb7b6eb771e0c9e8b1e3d4e3f1a2b3c4d5e6f7a8b9c0d1e2f3a4b";
let sol_chain = ChainId::new("solana", "mainnet").unwrap(); // Solana mainnet
let sol_address = generate_address(sol_pubkey.to_string(), sol_chain)?;
println!("Solana address: {}", sol_address); // Fe3d...

// Generate Bitcoin address, compressed by default
let btc_pubkey = "04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235";
let btc_chain = ChainId::new("bip122", "000000000019d6689c085ae165831e93").unwrap(); // Bitcoin mainnet
let btc_address = generate_address(btc_pubkey.to_string(), btc_chain)?;
println!("Bitcoin address: {}", btc_address); // 1ABC...

Chain-Specific Generation

use atp_chain_utils::eip155::address as eth;
use atp_chain_utils::solana::address as sol;
use atp_chain_utils::bip122::address as btc;

// Direct Ethereum address generation
let eth_addr = eth::generate_address(eth_pubkey.to_string())?;

// Direct Solana address generation  
let sol_addr = sol::generate_address(sol_pubkey.to_string())?;

// Direct Bitcoin address generation (compressed format recommended)
let btc_addr = btc::generate_p2pkh_address(btc_pubkey.to_string(), "000000000019d6689c085ae165831e93".to_string(), true)?;

Public Key Formats

Ethereum (EIP155)

Accepts SEC1-encoded public keys in hex format:

  • Uncompressed: 65 bytes starting with 04 (130 hex chars)
  • Compressed: 33 bytes starting with 02 or 03 (66 hex chars)
// Uncompressed (recommended for ICP threshold signatures)
let uncompressed = "04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235";

// Compressed
let compressed = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798";

Solana

Requires exactly 32-byte public keys in hex format (64 hex characters):

let solana_pubkey = "e258d6e13adfb7b6eb771e0c9e8b1e3d4e3f1a2b3c4d5e6f7a8b9c0d1e2f3a4b";

Bitcoin (BIP122)

Accepts SEC1-encoded public keys in hex format, similar to Ethereum:

  • Uncompressed: 65 bytes starting with 04 (130 hex chars)
  • Compressed: 33 bytes starting with 02 or 03 (66 hex chars)

The address type (mainnet/testnet) is determined by the chain reference:

  • 000000000019d6689c085ae165831e93 - Bitcoin mainnet (addresses start with 1)
  • 000000000933ea01ad0ee984209779ba - Bitcoin testnet (addresses start with m or n)
  • 0f9188f13cb7b2c71f2a335e3a4fc328 - Bitcoin regtest (addresses start with m or n)

Important: The compression flag affects the generated address:

  • use_compressed: true - Uses compressed public key format (recommended)
  • use_compressed: false - Uses uncompressed public key format (legacy)
let bitcoin_pubkey = "04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235";

// Compressed format (recommended)
let compressed_addr = btc::generate_p2pkh_address(bitcoin_pubkey.clone(), mainnet_ref, true)?;

// Uncompressed format (legacy)  
let uncompressed_addr = btc::generate_p2pkh_address(bitcoin_pubkey, mainnet_ref, false)?;

Error Handling

All functions return Result<String, String> with descriptive error messages:

match generate_address(pubkey, chain_id) {
    Ok(address) => println!("Generated address: {}", address),
    Err(error) => eprintln!("Failed to generate address: {}", error),
}

Common errors:

  • "Unsupported namespace: <namespace>" - Chain not supported

Testing

Run the test suite:

cargo test
Commit count: 126

cargo fmt