feat: Start with signing txs

This commit is contained in:
Nathan Woodburn 2024-06-04 17:08:25 +10:00
parent 3bd61ae1ee
commit 7ca9c5f735
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
4 changed files with 169 additions and 3 deletions

75
lib/hns.dart Normal file
View File

@ -0,0 +1,75 @@
import 'package:flutter/services.dart';
import 'package:flutter_bitcoin/flutter_bitcoin.dart' as bitcoin;
import 'dart:typed_data';
import 'package:hex/hex.dart';
import 'package:crypto/crypto.dart';
import 'package:bip39/bip39.dart' as bip39;
import 'package:bip32/bip32.dart' as bip32;
final bip32.NetworkType hnsMainnet = bip32.NetworkType(
bip32: bip32.Bip32Type(public: 0x0488b21e, private: 0x0488ade4),
wif: 0x80,
);
final bitcoin.NetworkType hnsMainnetBitcoin = bitcoin.NetworkType(
messagePrefix: '\x18Handshake Signed Message:\n',
bech32: 'hs',
bip32: bitcoin.Bip32Type(public: 0x0488b21e, private: 0x0488ade4),
pubKeyHash: 0x00,
scriptHash: 0x05,
wif: 0x80);
String getXpub(String seedPhrase) {
List<int> seedints = bip39.mnemonicToSeed(seedPhrase);
Uint8List seed = Uint8List.fromList(seedints);
bip32.BIP32 master = bip32.BIP32.fromSeed(seed, hnsMainnet);
return master.derivePath("m/44'/5353'/0'").neutered().toBase58();
}
Future<String> signTX(String seedPhrase, Map<String, dynamic> txData) async {
final seed = bip39.mnemonicToSeed(seedPhrase);
final master = bip32.BIP32.fromSeed(seed, hnsMainnet);
final txb = bitcoin.TransactionBuilder(
network: hnsMainnetBitcoin,
);
// for (var input in txData['inputs']) {
// final prevout = input['prevout'];
// final vin = input['vin'];
// if (vin != null && vin is int) {
// final hash = prevout['hash'];
// final index = prevout['index'];
// bitcoin.ECPair keyPair = bitcoin.ECPair.fromPrivateKey(
// master.derivePath("m/44'/5353'/0'/0/$vin").privateKey!,
// network: hnsMainnetBitcoin);
// txb.addInput(hash, index);
// txb.sign(vin: vin, keyPair: keyPair);
// } else {
// print('vin is not an int');
// print(input);
// }
// }
for (var input in txData['inputs']) {
final prevout = input['prevout'];
final coin = input['coin'];
final index = prevout['index'];
final hash = prevout['hash'];
final vin = coin['height'];
print(input);
bitcoin.ECPair keyPair = bitcoin.ECPair.fromPrivateKey(
master.derivePath("m/44'/5353'/0'/0/$vin").privateKey!,
network: hnsMainnetBitcoin,
);
txb.addInput(hash, index);
txb.sign(vin: int.parse(vin.toString()), keyPair: keyPair);
}
for (var output in txData['outputs']) {
txb.addOutput(output['address'], output['value']);
}
return txb.build().toHex();
}

View File

@ -4,7 +4,12 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'dart:convert'; import 'dart:convert';
import 'package:qr_flutter/qr_flutter.dart'; import 'package:flutter_bitcoin/flutter_bitcoin.dart';
import 'package:bip39/bip39.dart' as bip39;
import 'package:bip32/bip32.dart' as bip32;
import 'package:crypto/crypto.dart';
import 'dart:typed_data';
import 'package:firewallet/hns.dart' as hns;
class SendPage extends StatefulWidget { class SendPage extends StatefulWidget {
SendPage({Key? key, required this.uuid, required this.wallet}) SendPage({Key? key, required this.uuid, required this.wallet})
@ -168,8 +173,16 @@ class _SendPageState extends State<SendPage> {
content: Text('Sent $amount HNS to $toAddress'), content: Text('Sent $amount HNS to $toAddress'),
), ),
); );
String seedPhrase = 'abandon abandon abandon abandon abandon abandon ' +
'abandon abandon abandon abandon abandon about';
print(hns.getXpub(seedPhrase));
hns.signTX(seedPhrase, data).then((tx) {
print(tx);
});
if (sendMax) { if (sendMax) {
amountController.text = ''; // amountController.text = '';
} else { } else {
amountController.text = amountController.text =
min(amount, walletBalance - 0.02).toStringAsFixed(2); min(amount, walletBalance - 0.02).toStringAsFixed(2);

View File

@ -25,6 +25,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.0" version: "2.11.0"
bech32:
dependency: transitive
description:
name: bech32
sha256: "156cbace936f7720c79a79d16a03efad343b1ef17106716e04b8b8e39f99f7f7"
url: "https://pub.dev"
source: hosted
version: "0.2.2"
bip32:
dependency: "direct main"
description:
name: bip32
sha256: "54787cd7a111e9d37394aabbf53d1fc5e2e0e0af2cd01c459147a97c0e3f8a97"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
bip39:
dependency: "direct main"
description:
name: bip39
sha256: de1ee27ebe7d96b84bb3a04a4132a0a3007dcdd5ad27dd14aa87a29d97c45edc
url: "https://pub.dev"
source: hosted
version: "1.0.6"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -33,6 +57,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
bs58check:
dependency: transitive
description:
name: bs58check
sha256: c4a164d42b25c2f6bc88a8beccb9fc7d01440f3c60ba23663a20a70faf484ea9
url: "https://pub.dev"
source: hosted
version: "1.0.2"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -73,8 +105,16 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.18.0" version: "1.18.0"
crypto: convert:
dependency: transitive dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
crypto:
dependency: "direct main"
description: description:
name: crypto name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
@ -118,6 +158,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_bitcoin:
dependency: "direct main"
description:
name: flutter_bitcoin
sha256: "1a783c4d80f83b1ba5dedb4f18ebf522c90dd99e6fa0224b5228f68aa29b3442"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
flutter_launcher_icons: flutter_launcher_icons:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -144,6 +192,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
hex:
dependency: "direct main"
description:
name: hex
sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
@ -168,6 +224,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.0" version: "4.2.0"
js:
dependency: transitive
description:
name: js
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
version: "0.7.1"
json_annotation: json_annotation:
dependency: transitive dependency: transitive
description: description:
@ -288,6 +352,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.8" version: "2.1.8"
pointycastle:
dependency: "direct main"
description:
name: pointycastle
sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
url: "https://pub.dev"
source: hosted
version: "3.9.1"
qr: qr:
dependency: transitive dependency: transitive
description: description:

View File

@ -39,6 +39,12 @@ dependencies:
http: ^1.2.1 http: ^1.2.1
url_launcher: ^6.2.6 url_launcher: ^6.2.6
qr_flutter: ^4.1.0 qr_flutter: ^4.1.0
flutter_bitcoin: ^1.0.1
crypto: ^3.0.3
pointycastle: ^3.9.1
bip39: ^1.0.6
bip32: ^2.0.0
hex: ^0.2.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: