stack_wallet/lib/models/coinlib/exp2pkh_address.dart
2024-06-25 14:46:36 -06:00

87 lines
2.2 KiB
Dart

import 'dart:typed_data';
import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib;
const OP_EXCHANGEADDR = 0xe0;
class EXP2PKHAddress implements coinlib.Address {
/// The 160bit public key or redeemScript hash for the base58 address
final Uint8List _hash;
/// The network and address type version of the address
final Uint8List version;
String? _encodedCache;
EXP2PKHAddress._(Uint8List hash, this.version) : _hash = hash {
if (version.length != 3) {
throw ArgumentError(
"version bytes length must be 3",
);
}
}
factory EXP2PKHAddress.fromString(String encoded, Uint8List versionBytes) {
if (versionBytes.length != 3) {
throw ArgumentError(
"version bytes length must be 3",
);
}
final data = coinlib.base58Decode(encoded);
if (data.length != 23) throw coinlib.InvalidAddress();
final version = data.sublist(0, 3);
for (int i = 0; i < 3; i++) {
if (version[i] != versionBytes[i]) {
throw Exception("EX address version bytes do not match");
}
}
final payload = data.sublist(3);
final addr = EXP2PKHAddress._(payload, version);
addr._encodedCache = encoded;
return addr;
}
@override
String toString() => _encodedCache.toString();
@override
coinlib.Program get program => EXP2PKH.fromHash(_hash);
}
class EXP2PKH implements coinlib.Program {
static const template =
"OP_EXCHANGEADDR OP_DUP OP_HASH160 <20-bytes> OP_EQUALVERIFY OP_CHECKSIG";
@override
final coinlib.Script script;
EXP2PKH.fromScript(this.script);
factory EXP2PKH.fromHash(Uint8List pkHash) {
final List<coinlib.ScriptOp> ops = [
coinlib.ScriptOpCode(OP_EXCHANGEADDR),
];
final parts = template.split(" ").sublist(1);
for (final name in parts) {
if (name.startsWith("OP_")) {
ops.add(
coinlib.ScriptOpCode(
coinlib.scriptOpNameToCode[name.substring(3)]!,
),
);
} else if (name == "<20-bytes>") {
ops.add(coinlib.ScriptPushData(pkHash));
} else {
throw Exception("Something went wrong in this hacked code");
}
}
return EXP2PKH.fromScript(coinlib.Script(ops));
}
}