LCOV - code coverage report
Current view: top level - crypto/utxo/utils - pubkey_to_address.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 96.6 % 88 85
Test Date: 2025-01-30 01:10:00 Functions: - 0 0

            Line data    Source code
       1              : import 'dart:typed_data';
       2              : import 'package:dart_bech32/dart_bech32.dart';
       3              : import 'package:pointycastle/digests/ripemd160.dart';
       4              : import 'package:pointycastle/digests/sha256.dart';
       5              : import 'package:walletkit_dart/src/utils/base32.dart';
       6              : import 'package:convert/convert.dart' show hex;
       7              : import 'package:bs58check/bs58check.dart' as bs58check;
       8              : import 'package:walletkit_dart/src/utils/base58.dart';
       9              : import 'package:walletkit_dart/walletkit_dart.dart';
      10              : 
      11            3 : String pubKeyHexToAddress(
      12              :   String pubKeyHex,
      13              :   AddressType addressType,
      14              :   UTXONetworkType networkType,
      15              : ) {
      16            6 :   final pubKey = Uint8List.fromList(hex.decode(pubKeyHex));
      17            3 :   return pubKeyToAddress(pubKey, addressType, networkType);
      18              : }
      19              : 
      20           10 : String pubKeyToAddress(
      21              :   Uint8List pubKey,
      22              :   AddressType addressType,
      23              :   UTXONetworkType networkType,
      24              : ) {
      25           10 :   final pubKeyHash = ripmed160Sha256Hash(pubKey);
      26              : 
      27              :   return switch (addressType) {
      28           16 :     AddressType.segwit => pubKeyHashToSegwitAddress(
      29              :         pubKeyHash,
      30            6 :         networkType.bech32,
      31            6 :         networkType.pubKeyHashPrefix,
      32              :       ),
      33           11 :     AddressType.compatibility => pubKeyHashToP2SHAddress(
      34              :         pubKey,
      35            1 :         networkType.scriptHashPrefix,
      36              :       ),
      37           18 :     AddressType.legacy => pubKeyHashToLegacyAddress(
      38              :         pubKeyHash,
      39            9 :         networkType.pubKeyHashPrefix,
      40              :       ),
      41            6 :     AddressType.cashaddr => bchAddrEncode(
      42            3 :         hrp: networkType.bech32,
      43              :         data: pubKeyHash,
      44            3 :         witnessVersion: networkType.pubKeyHashPrefix,
      45              :       ),
      46            0 :     _ => throw UnsupportedError("Address type not supported: $addressType")
      47              :   };
      48              : }
      49              : 
      50            8 : String pubKeyHashToAddress(
      51              :   Uint8List pubKeyHash,
      52              :   AddressType addressType,
      53              :   UTXONetworkType networkType,
      54              : ) {
      55              :   return switch (addressType) {
      56           12 :     AddressType.segwit => pubKeyHashToSegwitAddress(
      57              :         pubKeyHash,
      58            4 :         networkType.bech32,
      59            4 :         networkType.pubKeyHashPrefix,
      60              :       ),
      61           16 :     AddressType.legacy => pubKeyHashToLegacyAddress(
      62              :         pubKeyHash,
      63            8 :         networkType.pubKeyHashPrefix,
      64              :       ),
      65            6 :     AddressType.cashaddr => bchAddrEncode(
      66            3 :         hrp: networkType.bech32,
      67              :         data: pubKeyHash,
      68            3 :         witnessVersion: networkType.pubKeyHashPrefix,
      69              :       ),
      70            0 :     _ => throw UnsupportedError("Address type not supported: $addressType")
      71              :   };
      72              : }
      73              : 
      74              : ///
      75              : /// Legacy Address (Base58)
      76              : ///
      77            9 : String pubKeyHashToLegacyAddress(Uint8List pubKeyHash, int witnessVersion) {
      78           27 :   final data = Uint8List.fromList([witnessVersion, ...pubKeyHash]);
      79              : 
      80            9 :   return bs58check.encode(data);
      81              : }
      82              : 
      83              : ///
      84              : /// Segwit Address (Bech32)
      85              : ///
      86            6 : String pubKeyHashToSegwitAddress(
      87              :   Uint8List pubKeyHash,
      88              :   String bech32Prefix,
      89              :   int witnessVersion,
      90              : ) {
      91            6 :   final words = bech32.toWords(pubKeyHash);
      92              : 
      93           18 :   final wordsWithVersion = Uint8List.fromList([0, ...words]);
      94              : 
      95            6 :   final decoded = Decoded(prefix: bech32Prefix, words: wordsWithVersion);
      96              : 
      97              :   try {
      98            6 :     bech32.encode(decoded);
      99              :   } catch (e) {
     100            0 :     print(e);
     101              :   }
     102              : 
     103            6 :   return bech32.encode(decoded);
     104              : }
     105              : 
     106              : ///
     107              : /// P2SH Address (Base58)
     108              : ///
     109            5 : String pubKeyHashToP2SHAddress(Uint8List pubKeyHash, int scriptHashPrefix) {
     110           15 :   final prefixedHash = Uint8List.fromList([scriptHashPrefix, ...pubKeyHash]);
     111              : 
     112           10 :   final checkSum = sha256Sha256Hash(prefixedHash).sublist(0, 4);
     113              : 
     114            5 :   final prefixedHashWithChecksum = Uint8List.fromList(
     115           10 :     [...prefixedHash, ...checkSum],
     116              :   );
     117              : 
     118            5 :   return base58Encode(prefixedHashWithChecksum);
     119              : }
     120              : 
     121              : ///
     122              : /// Ripmed160 Hash of Sha256 Hash
     123              : ///
     124           10 : Uint8List ripmed160Sha256Hash(Uint8List buffer) {
     125           10 :   final ripmed160 = RIPEMD160Digest();
     126           10 :   final sha256 = SHA256Digest();
     127           20 :   return ripmed160.process(sha256.process(buffer));
     128              : }
     129              : 
     130              : ///
     131              : /// Sha256 Hash of Sha256 Hash
     132              : ///
     133            8 : Uint8List sha256Sha256Hash(Uint8List buffer) {
     134            8 :   final sha256 = SHA256Digest();
     135           16 :   return sha256.process(sha256.process(buffer));
     136              : }
     137              : 
     138              : ///
     139              : /// Sha256 Hash
     140              : ///
     141           12 : Uint8List sha256Hash(Uint8List buffer) {
     142           12 :   final sha256 = SHA256Digest();
     143           12 :   return sha256.process(buffer);
     144              : }
     145              : 
     146              : ///
     147              : /// BCH CashAddr
     148              : ///
     149              : 
     150            3 : BigInt _polymod(List<int> data) {
     151            3 :   List<BigInt> GENERATOR = [
     152            3 :     BigInt.from(0x98f2bc8e61),
     153            3 :     BigInt.from(0x79b76d99e2),
     154            3 :     BigInt.from(0xf33e5fb3c4),
     155            3 :     BigInt.from(0xae2eabe2a8),
     156            3 :     BigInt.from(0x1e4f43e470),
     157              :   ];
     158              : 
     159            3 :   BigInt checksum = BigInt.from(1);
     160              : 
     161            9 :   for (int i = 0; i < data.length; ++i) {
     162            3 :     int value = data[i];
     163            3 :     BigInt topBits = checksum >> 35;
     164              :     checksum =
     165           15 :         ((checksum & BigInt.from(0x07ffffffff)) << 5) ^ BigInt.from(value);
     166              : 
     167            9 :     for (int j = 0; j < GENERATOR.length; ++j) {
     168           15 :       if ((topBits >> j) & BigInt.from(1) == BigInt.from(1)) {
     169            6 :         checksum = checksum ^ GENERATOR[j];
     170              :       }
     171              :     }
     172              :   }
     173              : 
     174            6 :   return checksum ^ BigInt.from(1);
     175              : }
     176              : 
     177            3 : String bchAddrEncode({
     178              :   required String hrp,
     179              :   required int witnessVersion,
     180              :   required List<int> data,
     181              : }) {
     182           12 :   final prefixData = [..._prefixToUint5Array(hrp), 0].toUint8List;
     183              : 
     184           12 :   final payloadData = bech32.toWords([witnessVersion, ...data].toUint8List);
     185              : 
     186            3 :   final checksumData = [
     187              :     ...prefixData,
     188            3 :     ...payloadData,
     189            3 :     ...[0, 0, 0, 0, 0, 0, 0, 0]
     190            3 :   ].toUint8List;
     191              : 
     192              :   final checksumUint5List =
     193            9 :       _checksumToUint5List(_polymod(checksumData).toInt());
     194              : 
     195            9 :   final payload = [...payloadData, ...checksumUint5List].toUint8List;
     196              : 
     197            6 :   final base32Encoded = Base32().encode(payload);
     198              : 
     199            3 :   return "$hrp:$base32Encoded";
     200              : }
     201              : 
     202            3 : Uint8List _checksumToUint5List(int checksum) {
     203            3 :   final result = Uint8List(8);
     204            6 :   for (var i = 0; i < 8; ++i) {
     205            9 :     result[7 - i] = checksum & 31;
     206            3 :     checksum = checksum >> 5;
     207              :   }
     208              :   return result;
     209              : }
     210              : 
     211            3 : Uint8List _prefixToUint5Array(String prefix) {
     212            6 :   var result = new Uint8List(prefix.length);
     213            9 :   for (var i = 0; i < prefix.length; ++i) {
     214           12 :     result[i] = prefix[i].codeUnitAt(0) & 31;
     215              :   }
     216              :   return result;
     217              : }
        

Generated by: LCOV version 2.0-1