Skip to content

Commit

Permalink
Merge branch 'mrtnetwork:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
sandrocsimas authored Dec 3, 2024
2 parents 147ed34 + f9b8f24 commit eeb34b9
Show file tree
Hide file tree
Showing 48 changed files with 758 additions and 593 deletions.
7 changes: 7 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
# Uncomment the following section to specify additional rules.
linter:
rules:
- unnecessary_const
- prefer_const_declarations
- prefer_final_locals # Warns when a local variable could be final
- prefer_final_in_for_each # Warns when a forEach variable could be final
131 changes: 131 additions & 0 deletions example/lib/global/btc_examples_multisig_taproot_legacy_uncomp.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:example/services_examples/electrum/electrum_ssl_service.dart';

void main() async {
final one = ECPrivate.fromBytes(List<int>.filled(32, 12));
final two = ECPrivate.fromBytes(List<int>.filled(32, 13));
final three = ECPrivate.fromBytes(List<int>.filled(32, 14));
final four = ECPrivate.fromBytes(List<int>.filled(32, 15));
final five = ECPrivate.fromBytes(List<int>.filled(32, 16));
final six = ECPrivate.fromBytes(List<int>.filled(32, 17));
final seven = ECPrivate.fromBytes(List<int>.filled(32, 18));
final eight = ECPrivate.fromBytes(List<int>.filled(32, 19));
final Map<String, ECPrivate> keys = {
for (final i in [one, two, three, four, five, six, seven, eight])
i.getPublic().toHex(): i
};
final account = MultiSignatureAddress(threshold: 8, signers: [
MultiSignatureSigner(
publicKey: one.getPublic().toHex(compressed: false), weight: 1),
MultiSignatureSigner(publicKey: two.getPublic().toHex(), weight: 1),
MultiSignatureSigner(publicKey: three.getPublic().toHex(), weight: 1),
MultiSignatureSigner(
publicKey: four.getPublic().toHex(compressed: false), weight: 1),
MultiSignatureSigner(publicKey: five.getPublic().toHex(), weight: 1),
MultiSignatureSigner(publicKey: six.getPublic().toHex(), weight: 1),
MultiSignatureSigner(
publicKey: seven.getPublic().toHex(compressed: false), weight: 1),
MultiSignatureSigner(publicKey: eight.getPublic().toHex(), weight: 1),
]);

/// connect to electrum service with websocket
/// please see `services_examples` folder for how to create electrum websocket service
final service = await ElectrumSSLService.connect(
"testnet4-electrumx.wakiyamap.dev:51002");

/// create provider with service
final provider = ElectrumApiProvider(service);

final addrOne = one.getPublic().toP2pkAddress(compressed: false);

final addrTwo = two.getPublic().toAddress(compressed: false);

final addrThree = three.getPublic().toP2pkInP2sh(compressed: false);
final addrFour = four.getPublic().toP2pkhInP2sh(compressed: false);
final addrFive = four.getPublic().toSegwitAddress();
final addrSix = account.toP2shAddress();
final addr7 = eight.getPublic().toTaprootAddress();
final addr8 = eight.getPublic().toP2wshAddress();
final addr9 = eight.getPublic().toP2wshInP2sh();
final List<String> pubkys = [
one.getPublic().toHex(compressed: false),
two.getPublic().toHex(compressed: false),
three.getPublic().toHex(compressed: false),
four.getPublic().toHex(compressed: false),
four.getPublic().toHex(),
four.getPublic().toHex(),
eight.getPublic().toHex(),
eight.getPublic().toHex(),
eight.getPublic().toHex(),
eight.getPublic().toHex(),
];
final addresses = [
one.getPublic().toP2pkAddress(compressed: false),
two.getPublic().toAddress(compressed: false),
three.getPublic().toP2pkInP2sh(compressed: false),
four.getPublic().toP2pkhInP2sh(compressed: false),
four.getPublic().toSegwitAddress(),
four.getPublic().toP2wshInP2sh(),
addrSix,
addr7,
addr8,
addr9
];
List<UtxoWithAddress> utxos = [];
for (int i = 0; i < addresses.length; i++) {
final address = addresses[i];
final elctrumUtxos = await provider.request(ElectrumScriptHashListUnspent(
scriptHash: address.pubKeyHash(), includeTokens: false));
if (elctrumUtxos.isEmpty) continue;
if (i == 6) {
utxos.addAll(elctrumUtxos.map((e) => UtxoWithAddress(
utxo: e.toUtxo(address.type),
ownerDetails: UtxoAddressDetails.multiSigAddress(
multiSigAddress: account, address: address))));
continue;
}
utxos.addAll(elctrumUtxos
.map((e) => UtxoWithAddress(
utxo: e.toUtxo(address.type),
ownerDetails:
UtxoAddressDetails(publicKey: pubkys[i], address: address)))
.toList());
}

final sumOfUtxo = utxos.sumOfUtxosValue();

if (sumOfUtxo == BigInt.zero) {
return;
}
final change =
sumOfUtxo - (BigInt.from(1000) * BigInt.from(11) + BigInt.from(4295));
final bchTransaction = BitcoinTransactionBuilder(outPuts: [
/// change input (sumofutxos - spend)
BitcoinOutput(address: addrOne, value: change),
BitcoinOutput(address: addrOne, value: BigInt.from(1000)),
BitcoinOutput(address: addrTwo, value: BigInt.from(1000)),
BitcoinOutput(address: addrThree, value: BigInt.from(1000)),
BitcoinOutput(address: addrFour, value: BigInt.from(1000)),
BitcoinOutput(address: addrFour, value: BigInt.from(1000)),
BitcoinOutput(address: addrFive, value: BigInt.from(1000)),
BitcoinOutput(address: addrSix, value: BigInt.from(1000)),
BitcoinOutput(address: addrSix, value: BigInt.from(1000)),
BitcoinOutput(address: addr7, value: BigInt.from(1000)),
BitcoinOutput(address: addr8, value: BigInt.from(1000)),
BitcoinOutput(address: addr9, value: BigInt.from(1000)),
], fee: BigInt.from(4295), network: BitcoinNetwork.testnet, utxos: utxos);
final transaaction =
bchTransaction.buildTransaction((trDigest, utxo, publicKey, sighash) {
final pk = ECPublic.fromHex(publicKey);
if (utxo.utxo.isP2tr) {
return keys[pk.toHex()]!.signTapRoot(trDigest, sighash: sighash);
}
return keys[pk.toHex()]!.signInput(trDigest, sigHash: sighash);
});

final transactionRaw = transaaction.toHex();
await provider
.request(ElectrumBroadCastTransaction(transactionRaw: transactionRaw));
}

/// https://mempool.space/testnet4/tx/a7f08f07739de45a6a4f8871f8e6ad79e0aefbc940086df76571354ba22263fa
8 changes: 4 additions & 4 deletions example/lib/global/old_examples/bitcoin_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ void _spendFromP2pkhTo10DifferentType() async {
/// and sign the transaction digest to construct the unlocking script.
if (publicKey == examplePublicKey2.toHex()) {
if (utxo.utxo.isP2tr()) {
if (utxo.utxo.isP2tr) {
return examplePrivateKey.signTapRoot(trDigest);
}
return examplePrivateKey.signInput(trDigest, sigHash: sighash);
Expand Down Expand Up @@ -400,19 +400,19 @@ void _spendFrom10DifferentTypeToP2pkh() async {
/// For each input in the transaction, locate the corresponding private key
/// and sign the transaction digest to construct the unlocking script.
if (publicKey == childKey1PublicKey.toHex()) {
if (utxo.utxo.isP2tr()) {
if (utxo.utxo.isP2tr) {
return childKey1PrivateKey.signTapRoot(trDigest, sighash: sighash);
}
return childKey1PrivateKey.signInput(trDigest, sigHash: sighash);
}
if (publicKey == examplePublicKey.toHex()) {
if (utxo.utxo.isP2tr()) {
if (utxo.utxo.isP2tr) {
return childKey2PrivateKey.signTapRoot(trDigest, sighash: sighash);
}
return childKey2PrivateKey.signInput(trDigest, sigHash: sighash);
}
if (publicKey == examplePublicKey2.toHex()) {
if (utxo.utxo.isP2tr()) {
if (utxo.utxo.isP2tr) {
return examplePrivateKey.signTapRoot(trDigest, sighash: sighash);
}
return examplePrivateKey.signInput(trDigest, sigHash: sighash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ void main() async {

// Ok, now we have the private key, we need to check which method to use for signing
// We check whether the UTX corresponds to the P2TR address or not.
if (utxo.utxo.isP2tr()) {
if (utxo.utxo.isP2tr) {
// yes is p2tr utxo and now we use SignTaprootTransaction(Schnorr sign)
// for now this transaction builder support only tweak transaction
// If you want to spend a Taproot script-path spending, you must create your own transaction builder.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ void main() async {

// Ok, now we have the private key, we need to check which method to use for signing
// We check whether the UTX corresponds to the P2TR address or not.
if (utxo.utxo.isP2tr()) {
if (utxo.utxo.isP2tr) {
// yes is p2tr utxo and now we use SignTaprootTransaction(Schnorr sign)
// for now this transaction builder support only tweak transaction
// If you want to spend a Taproot script-path spending, you must create your own transaction builder.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void main() async {
/// create transaction and sign it
final transaction =
builder.buildTransaction((trDigest, utxo, publicKey, sighash) {
if (utxo.utxo.isP2tr()) {
if (utxo.utxo.isP2tr) {
return privateKey.signTapRoot(trDigest, sighash: sighash);
}
return privateKey.signInput(trDigest, sigHash: sighash);
Expand Down
2 changes: 1 addition & 1 deletion example/lib/global/transfer_to_8_account_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void main() async {
/// create transaction and sign it
final transaction =
builder.buildTransaction((trDigest, utxo, publicKey, sighash) {
if (utxo.utxo.isP2tr()) {
if (utxo.utxo.isP2tr) {
return examplePrivateKey2.signTapRoot(trDigest, sighash: sighash);
}
return examplePrivateKey2.signInput(trDigest, sigHash: sighash);
Expand Down
7 changes: 3 additions & 4 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ packages:
blockchain_utils:
dependency: "direct main"
description:
name: blockchain_utils
sha256: eebd06ff3709be5c660be72f0b0ee8f524fbb9e20752436f19f07f3be8ee6d1f
url: "https://pub.dev"
source: hosted
path: "../../blockchain_utils"
relative: true
source: path
version: "3.5.0"
boolean_selector:
dependency: transitive
Expand Down
6 changes: 3 additions & 3 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ dependencies:
cupertino_icons: ^1.0.2
bitcoin_base:
path: ../
# blockchain_utils:
# path: ../../blockchain_utils
blockchain_utils: ^3.5.0
blockchain_utils:
path: ../../../blockchain_utils
# blockchain_utils: ^3.5.0
http: ^1.2.0

dev_dependencies:
Expand Down
1 change: 0 additions & 1 deletion example/test/widget_test.dart

This file was deleted.

2 changes: 1 addition & 1 deletion lib/bitcoin_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/// including spending transactions, Bitcoin address management,
/// Bitcoin Schnorr signatures, BIP-39 mnemonic phrase generation,
/// hierarchical deterministic (HD) wallet derivation, and Web3 Secret Storage Definition.
library bitcoin_base;
library;

export 'package:bitcoin_base/src/bitcoin/address/address.dart';

Expand Down
2 changes: 1 addition & 1 deletion lib/src/bitcoin/address/address.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// - Utility functions for address manipulation.
// - encode/decode Segregated Witness (SegWit) address implementation.
// - Enhanced functionality for improved handling of addresses across diverse networks.
library bitcoin_base.address;
library;

import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:bitcoin_base/src/exception/exception.dart';
Expand Down
37 changes: 18 additions & 19 deletions lib/src/bitcoin/address/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ abstract class BitcoinAddressType implements Enumerate {
P2shAddressType.p2pkInP2shwt,
P2pkhAddressType.p2pkhwt
];
T cast<T extends BitcoinAddressType>() {
if (this is! T) {
throw DartBitcoinPluginException("BitcoinAddressType casting failed.",
details: {"excepted": "$T", "type": value});
}
return this as T;
}

@override
String toString() {
return "BitcoinAddressType.$value";
Expand All @@ -50,15 +58,14 @@ abstract class BitcoinBaseAddress {
String get addressProgram;
}

class PubKeyAddressType implements BitcoinAddressType {
const PubKeyAddressType._(this.value);
class PubKeyAddressType extends BitcoinAddressType {
const PubKeyAddressType._(super.value) : super._();
static const PubKeyAddressType p2pk = PubKeyAddressType._("P2PK");
@override
bool get isP2sh => false;
@override
bool get isSegwit => false;
@override
final String value;

@override
int get hashLength => 20;
@override
Expand All @@ -67,8 +74,8 @@ class PubKeyAddressType implements BitcoinAddressType {
}
}

class P2pkhAddressType implements BitcoinAddressType {
const P2pkhAddressType._(this.value);
class P2pkhAddressType extends BitcoinAddressType {
const P2pkhAddressType._(super.value) : super._();
static const P2pkhAddressType p2pkh = P2pkhAddressType._("P2PKH");
static const P2pkhAddressType p2pkhwt = P2pkhAddressType._("P2PKHWT");

Expand All @@ -77,9 +84,6 @@ class P2pkhAddressType implements BitcoinAddressType {
@override
bool get isSegwit => false;

@override
final String value;

@override
int get hashLength => 20;
@override
Expand All @@ -88,8 +92,9 @@ class P2pkhAddressType implements BitcoinAddressType {
}
}

class P2shAddressType implements BitcoinAddressType {
const P2shAddressType._(this.value, this.hashLength, this.withToken);
class P2shAddressType extends BitcoinAddressType {
const P2shAddressType._(super.value, this.hashLength, this.withToken)
: super._();
static const P2shAddressType p2wshInP2sh = P2shAddressType._(
"P2SH/P2WSH", _BitcoinAddressUtils.hash160DigestLength, false);
static const P2shAddressType p2wpkhInP2sh = P2shAddressType._(
Expand Down Expand Up @@ -131,17 +136,14 @@ class P2shAddressType implements BitcoinAddressType {
static const P2shAddressType p2pkInP2shwt = P2shAddressType._(
"P2SHWT/P2PK", _BitcoinAddressUtils.hash160DigestLength, true);

@override
final String value;

@override
String toString() {
return "P2shAddressType.$value";
}
}

class SegwitAddresType implements BitcoinAddressType {
const SegwitAddresType._(this.value);
class SegwitAddresType extends BitcoinAddressType {
const SegwitAddresType._(super.value) : super._();
static const SegwitAddresType p2wpkh = SegwitAddresType._("P2WPKH");
static const SegwitAddresType p2tr = SegwitAddresType._("P2TR");
static const SegwitAddresType p2wsh = SegwitAddresType._("P2WSH");
Expand All @@ -150,9 +152,6 @@ class SegwitAddresType implements BitcoinAddressType {
@override
bool get isSegwit => true;

@override
final String value;

@override
int get hashLength {
switch (this) {
Expand Down
20 changes: 10 additions & 10 deletions lib/src/bitcoin/address/legacy_address.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ abstract class LegacyAddress implements BitcoinBaseAddress {

class P2shAddress extends LegacyAddress {
P2shAddress.fromScript(
{required Script script, this.type = P2shAddressType.p2pkInP2sh})
: super.fromScript(script: script);
{required super.script, this.type = P2shAddressType.p2pkInP2sh})
: super.fromScript();

P2shAddress.fromAddress(
{required String address,
required BasedUtxoNetwork network,
{required super.address,
required super.network,
this.type = P2shAddressType.p2pkInP2sh})
: super.fromAddress(address: address, network: network);
: super.fromAddress();
P2shAddress.fromHash160(
{required String addrHash, this.type = P2shAddressType.p2pkInP2sh})
: super.fromHash160(addrHash, type);
Expand Down Expand Up @@ -81,13 +81,13 @@ class P2shAddress extends LegacyAddress {

class P2pkhAddress extends LegacyAddress {
P2pkhAddress.fromScript(
{required Script script, this.type = P2pkhAddressType.p2pkh})
: super.fromScript(script: script);
{required super.script, this.type = P2pkhAddressType.p2pkh})
: super.fromScript();
P2pkhAddress.fromAddress(
{required String address,
required BasedUtxoNetwork network,
{required super.address,
required super.network,
this.type = P2pkhAddressType.p2pkh})
: super.fromAddress(address: address, network: network);
: super.fromAddress();
P2pkhAddress.fromHash160(
{required String addrHash, this.type = P2pkhAddressType.p2pkh})
: super.fromHash160(addrHash, type);
Expand Down
Loading

0 comments on commit eeb34b9

Please sign in to comment.