Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions lib/bitcoin_flutter.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/// Support for doing something awesome.
///
/// More dartdocs go here.
library bitcoin_flutter;

export 'src/bitcoin_flutter_base.dart';
Expand All @@ -11,5 +8,7 @@ export 'src/transaction_builder.dart';
export 'src/ecpair.dart';
export 'src/payments/p2pkh.dart';
export 'src/payments/p2wpkh.dart';
export 'src/payments/p2sh.dart';
export 'src/payments/index.dart';
// TODO: Export any libraries intended for clients of this package.
export 'src/utils/magic_hash.dart';

55 changes: 35 additions & 20 deletions lib/src/address.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import 'dart:typed_data';
import 'package:defichain_bech32/defichain_bech32.dart';

import 'models/networks.dart';
import 'package:bs58check/bs58check.dart' as bs58check;
import 'package:bech32/bech32.dart';
// import 'package:bech32/bech32.dart';
import 'payments/index.dart' show PaymentData;
import 'payments/p2pkh.dart';
import 'payments/p2sh.dart';
import 'payments/p2wpkh.dart';

class Address {
static bool validateAddress(String address, [NetworkType nw]) {
static bool validateAddress(String address, [NetworkType? nw]) {
try {
addressToOutputScript(address, nw);
return true;
Expand All @@ -16,33 +19,45 @@ class Address {
}
}

static Uint8List addressToOutputScript(String address, [NetworkType nw]) {
NetworkType network = nw ?? bitcoin;
static Uint8List? addressToOutputScript(String address, [NetworkType? nw]) {
var network = nw ?? bitcoin;
var decodeBase58;
var decodeBech32;
try {
decodeBase58 = bs58check.decode(address);
} catch (err) {}
} catch (err) {
// Base58check decode fail
}
if (decodeBase58 != null) {
if (decodeBase58[0] != network.pubKeyHash)
throw new ArgumentError('Invalid version or Network mismatch');
P2PKH p2pkh =
new P2PKH(data: new PaymentData(address: address), network: network);
return p2pkh.data.output;
if (decodeBase58[0] == network.pubKeyHash) {
return P2PKH(data: PaymentData(address: address), network: network)
.data
.output;
}
if (decodeBase58[0] == network.scriptHash) {
return P2SH(data: PaymentData(address: address), network: network)
.data!
.output;
}
throw ArgumentError('Invalid version or Network mismatch');
} else {
try {
decodeBech32 = segwit.decode(address);
} catch (err) {}
decodeBech32 = segwit.decode(SegwitInput(network.bech32!, address));
} catch (err) {
// Bech32 decode fail
}
if (decodeBech32 != null) {
if (network.bech32 != decodeBech32.hrp)
throw new ArgumentError('Invalid prefix or Network mismatch');
if (decodeBech32.version != 0)
throw new ArgumentError('Invalid address version');
P2WPKH p2wpkh = new P2WPKH(
data: new PaymentData(address: address), network: network);
return p2wpkh.data.output;
if (network.bech32 != decodeBech32.hrp) {
throw ArgumentError('Invalid prefix or Network mismatch');
}
if (decodeBech32.version != 0) {
throw ArgumentError('Invalid address version');
}
var p2wpkh =
P2WPKH(data: PaymentData(address: address), network: network);
return p2wpkh.data!.output;
}
}
throw new ArgumentError(address + ' has no matching Script');
throw ArgumentError(address + ' has no matching Script');
}
}
60 changes: 30 additions & 30 deletions lib/src/bitcoin_flutter_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,65 +12,65 @@ import 'dart:convert';

/// Checks if you are awesome. Spoiler: you are.
class HDWallet {
bip32.BIP32 _bip32;
P2PKH _p2pkh;
String seed;
bip32.BIP32? _bip32;
P2PKH? _p2pkh;
String? seed;
NetworkType network;

String get privKey {
String? get privKey {
if (_bip32 == null) return null;
try {
return HEX.encode(_bip32.privateKey);
return HEX.encode(_bip32!.privateKey!);
} catch (_) {
return null;
}
}

String get pubKey => _bip32 != null ? HEX.encode(_bip32.publicKey) : null;
String? get pubKey => _bip32 != null ? HEX.encode(_bip32!.publicKey) : null;

String get base58Priv {
String? get base58Priv {
if (_bip32 == null) return null;
try {
return _bip32.toBase58();
return _bip32!.toBase58();
} catch (_) {
return null;
}
}

String get base58 => _bip32 != null ? _bip32.neutered().toBase58() : null;
String? get base58 => _bip32 != null ? _bip32!.neutered().toBase58() : null;

String get wif {
String? get wif {
if (_bip32 == null) return null;
try {
return _bip32.toWIF();
return _bip32!.toWIF();
} catch (_) {
return null;
}
}

String get address => _p2pkh != null ? _p2pkh.data.address : null;
String? get address => _p2pkh != null ? _p2pkh!.data.address : null;

HDWallet(
{@required bip32, @required p2pkh, @required this.network, this.seed}) {
{required bip32, required p2pkh, required this.network, this.seed}) {
this._bip32 = bip32;
this._p2pkh = p2pkh;
}

HDWallet derivePath(String path) {
final bip32 = _bip32.derivePath(path);
final bip32 = _bip32!.derivePath(path);
final p2pkh = new P2PKH(
data: new PaymentData(pubkey: bip32.publicKey), network: network);
return HDWallet(bip32: bip32, p2pkh: p2pkh, network: network);
}

HDWallet derive(int index) {
final bip32 = _bip32.derive(index);
final bip32 = _bip32!.derive(index);
final p2pkh = new P2PKH(
data: new PaymentData(pubkey: bip32.publicKey), network: network);
return HDWallet(bip32: bip32, p2pkh: p2pkh, network: network);
}

factory HDWallet.fromSeed(Uint8List seed, {NetworkType network}) {
factory HDWallet.fromSeed(Uint8List seed, {NetworkType? network}) {
network = network ?? bitcoin;
final seedHex = HEX.encode(seed);
final wallet = bip32.BIP32.fromSeed(
Expand All @@ -85,7 +85,7 @@ class HDWallet {
bip32: wallet, p2pkh: p2pkh, network: network, seed: seedHex);
}

factory HDWallet.fromBase58(String xpub, {NetworkType network}) {
factory HDWallet.fromBase58(String xpub, {NetworkType? network}) {
network = network ?? bitcoin;
final wallet = bip32.BIP32.fromBase58(
xpub,
Expand All @@ -98,42 +98,42 @@ class HDWallet {
return HDWallet(bip32: wallet, p2pkh: p2pkh, network: network, seed: null);
}

Uint8List sign(String message) {
Uint8List? sign(String message) {
Uint8List messageHash = magicHash(message, network);
return _bip32.sign(messageHash);
return _bip32!.sign(messageHash);
}

bool verify({String message, Uint8List signature}) {
bool? verify({required String message, required Uint8List signature}) {
Uint8List messageHash = magicHash(message);
return _bip32.verify(messageHash, signature);
return _bip32!.verify(messageHash, signature);
}
}

class Wallet {
ECPair _keyPair;
P2PKH _p2pkh;

String get privKey =>
_keyPair != null ? HEX.encode(_keyPair.privateKey) : null;
String? get privKey =>
_keyPair != null ? HEX.encode(_keyPair.privateKey!) : null;

String get pubKey => _keyPair != null ? HEX.encode(_keyPair.publicKey) : null;
String? get pubKey => _keyPair != null ? HEX.encode(_keyPair.publicKey!) : null;

String get wif => _keyPair != null ? _keyPair.toWIF() : null;
String? get wif => _keyPair != null ? _keyPair.toWIF() : null;

String get address => _p2pkh != null ? _p2pkh.data.address : null;
String? get address => _p2pkh != null ? _p2pkh.data.address : null;

NetworkType network;
NetworkType? network;

Wallet(this._keyPair, this._p2pkh, this.network);

factory Wallet.random([NetworkType network]) {
factory Wallet.random([NetworkType? network]) {
final _keyPair = ECPair.makeRandom(network: network);
final _p2pkh = new P2PKH(
data: new PaymentData(pubkey: _keyPair.publicKey), network: network);
return Wallet(_keyPair, _p2pkh, network);
}

factory Wallet.fromWIF(String wif, [NetworkType network]) {
factory Wallet.fromWIF(String wif, [NetworkType? network]) {
network = network ?? bitcoin;
final _keyPair = ECPair.fromWIF(wif, network: network);
final _p2pkh = new P2PKH(
Expand All @@ -146,7 +146,7 @@ class Wallet {
return _keyPair.sign(messageHash);
}

bool verify({String message, Uint8List signature}) {
bool verify({required String message, required Uint8List signature}) {
Uint8List messageHash = magicHash(message, network);
return _keyPair.verify(messageHash, signature);
}
Expand Down
22 changes: 14 additions & 8 deletions lib/src/classify.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import 'dart:typed_data';
import '../src/utils/script.dart' as bscript;
import 'templates/pubkeyhash.dart' as pubkeyhash;
import 'templates/pubkey.dart' as pubkey;
import 'templates/witnesspubkeyhash.dart' as witnessPubKeyHash;
import 'templates/scriptHash.dart' as scripthash;
import 'templates/witnesspubkeyhash.dart' as witness_pubkey_hash;

const SCRIPT_TYPES = {
'P2SM': 'multisig',
Expand All @@ -16,25 +17,30 @@ const SCRIPT_TYPES = {
'WITNESS_COMMITMENT': 'witnesscommitment'
};

String classifyOutput(Uint8List script) {
if (witnessPubKeyHash.outputCheck(script)) return SCRIPT_TYPES['P2WPKH'];
String? classifyOutput(Uint8List script) {
if (witness_pubkey_hash.outputCheck(script)) return SCRIPT_TYPES['P2WPKH'];
if (pubkeyhash.outputCheck(script)) return SCRIPT_TYPES['P2PKH'];
if (scripthash.outputCheck(script)) return SCRIPT_TYPES['P2SH'];
final chunks = bscript.decompile(script);
if (chunks == null) throw new ArgumentError('Invalid script');
if (chunks == null) throw ArgumentError('Invalid script');
return SCRIPT_TYPES['NONSTANDARD'];
}

String classifyInput(Uint8List script) {
String? classifyInput(Uint8List? script, bool allowIncomplete) {
final chunks = bscript.decompile(script);
if (chunks == null) throw new ArgumentError('Invalid script');
if (pubkeyhash.inputCheck(chunks)) return SCRIPT_TYPES['P2PKH'];
if (pubkey.inputCheck(chunks)) return SCRIPT_TYPES['P2PK'];
if (scripthash.inputCheck(chunks, allowIncomplete)) {
return SCRIPT_TYPES['P2SH'];
}
if (pubkey.inputCheck(chunks)) return SCRIPT_TYPES['P2PK'];
return SCRIPT_TYPES['NONSTANDARD'];
}

String classifyWitness(List<Uint8List> script) {
String? classifyWitness(List<Uint8List?>? script) {
final chunks = bscript.decompile(script);
if (chunks == null) throw new ArgumentError('Invalid script');
if (witnessPubKeyHash.inputCheck(chunks)) return SCRIPT_TYPES['P2WPKH'];
if (chunks == null) throw ArgumentError('Invalid script');
if (witness_pubkey_hash.inputCheck(chunks)) return SCRIPT_TYPES['P2WPKH'];
return SCRIPT_TYPES['NONSTANDARD'];
}
Loading