mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
Cw 679 add ledger litecoin support (#1565)
* Add Litecoin Hardware Wallet Creation * Add Litecoin Hardware Wallet Creation * Fix Bitcoin not sending on Ledger * Fixes to sending LTC using Ledger * CW-679 Fix merge conflicts * CW-679 Fix merge conflicts * CW-679 Minor fixes * CW-679 Add derivation Path of change address * ledger flutter plus refactoring * ledger flutter plus refactoring * ledger flutter plus refactoring * Ups :| * Ups :| I forgot USB * Handle BT Off * Fix Issue with A14 and USB * Small Ledger Quality of life improvements * Small Ledger Quality of life improvements * Small Ledger Quality of life improvements * Small Ledger Quality of life improvements * Small Ledger Quality of life improvements * Small Ledger Quality of life improvements * Small Ledger Quality of life improvements * Pls work * Pls work * Pls work * Pls work * Fix overpopulation * Fix ble device detection and support for Stax and Flex * clean up pubspec * clean up * MWeb merge fix * MWeb merge fix * Fix Merge conflicts * Fix Requested changes
This commit is contained in:
parent
e04185a7c1
commit
68926c0a33
45 changed files with 842 additions and 405 deletions
|
@ -5,30 +5,31 @@ import 'package:blockchain_utils/blockchain_utils.dart';
|
|||
import 'package:cw_bitcoin/utils.dart';
|
||||
import 'package:cw_core/hardware/hardware_account_data.dart';
|
||||
import 'package:ledger_bitcoin/ledger_bitcoin.dart';
|
||||
import 'package:ledger_flutter/ledger_flutter.dart';
|
||||
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
|
||||
|
||||
class BitcoinHardwareWalletService {
|
||||
BitcoinHardwareWalletService(this.ledger, this.device);
|
||||
BitcoinHardwareWalletService(this.ledgerConnection);
|
||||
|
||||
final Ledger ledger;
|
||||
final LedgerDevice device;
|
||||
final LedgerConnection ledgerConnection;
|
||||
|
||||
Future<List<HardwareAccountData>> getAvailableAccounts({int index = 0, int limit = 5}) async {
|
||||
final bitcoinLedgerApp = BitcoinLedgerApp(ledger);
|
||||
Future<List<HardwareAccountData>> getAvailableAccounts(
|
||||
{int index = 0, int limit = 5}) async {
|
||||
final bitcoinLedgerApp = BitcoinLedgerApp(ledgerConnection);
|
||||
|
||||
final masterFp = await bitcoinLedgerApp.getMasterFingerprint(device);
|
||||
print(masterFp);
|
||||
final masterFp = await bitcoinLedgerApp.getMasterFingerprint();
|
||||
|
||||
final accounts = <HardwareAccountData>[];
|
||||
final indexRange = List.generate(limit, (i) => i + index);
|
||||
|
||||
for (final i in indexRange) {
|
||||
final derivationPath = "m/84'/0'/$i'";
|
||||
final xpub = await bitcoinLedgerApp.getXPubKey(device, derivationPath: derivationPath);
|
||||
final xpub =
|
||||
await bitcoinLedgerApp.getXPubKey(derivationPath: derivationPath);
|
||||
Bip32Slip10Secp256k1 hd =
|
||||
Bip32Slip10Secp256k1.fromExtendedKey(xpub).childKey(Bip32KeyIndex(0));
|
||||
|
||||
final address = generateP2WPKHAddress(hd: hd, index: 0, network: BitcoinNetwork.mainnet);
|
||||
final address = generateP2WPKHAddress(
|
||||
hd: hd, index: 0, network: BitcoinNetwork.mainnet);
|
||||
|
||||
accounts.add(HardwareAccountData(
|
||||
address: address,
|
||||
|
|
|
@ -5,13 +5,13 @@ import 'package:bitcoin_base/bitcoin_base.dart';
|
|||
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||
import 'package:cw_bitcoin/psbt_transaction_builder.dart';
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
import 'package:cw_bitcoin/electrum_derivations.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
|
||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
|
||||
import 'package:cw_bitcoin/psbt_transaction_builder.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
|
@ -19,7 +19,7 @@ import 'package:cw_core/wallet_keys_file.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:ledger_bitcoin/ledger_bitcoin.dart';
|
||||
import 'package:ledger_flutter/ledger_flutter.dart';
|
||||
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'bitcoin_wallet.g.dart';
|
||||
|
@ -61,8 +61,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
initialBalance: initialBalance,
|
||||
seedBytes: seedBytes,
|
||||
encryptionFileUtils: encryptionFileUtils,
|
||||
currency:
|
||||
networkParam == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc,
|
||||
currency: networkParam == BitcoinNetwork.testnet
|
||||
? CryptoCurrency.tbtc
|
||||
: CryptoCurrency.btc,
|
||||
alwaysScan: alwaysScan,
|
||||
) {
|
||||
// in a standard BIP44 wallet, mainHd derivation path = m/84'/0'/0'/0 (account 0, index unspecified here)
|
||||
|
@ -80,11 +81,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
mainHd: hd,
|
||||
sideHd: accountHD.childKey(Bip32KeyIndex(1)),
|
||||
network: networkParam ?? network,
|
||||
masterHd: seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null,
|
||||
masterHd:
|
||||
seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null,
|
||||
isHardwareWallet: walletInfo.isHardwareWallet,
|
||||
);
|
||||
|
||||
autorun((_) {
|
||||
this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
|
||||
this.walletAddresses.isEnabledAutoGenerateSubaddress =
|
||||
this.isEnabledAutoGenerateSubaddress;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -185,8 +189,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
walletInfo.derivationInfo ??= DerivationInfo();
|
||||
|
||||
// set the default if not present:
|
||||
walletInfo.derivationInfo!.derivationPath ??= snp?.derivationPath ?? electrum_path;
|
||||
walletInfo.derivationInfo!.derivationType ??= snp?.derivationType ?? DerivationType.electrum;
|
||||
walletInfo.derivationInfo!.derivationPath ??=
|
||||
snp?.derivationPath ?? electrum_path;
|
||||
walletInfo.derivationInfo!.derivationType ??=
|
||||
snp?.derivationType ?? DerivationType.electrum;
|
||||
|
||||
Uint8List? seedBytes = null;
|
||||
final mnemonic = keysData.mnemonic;
|
||||
|
@ -228,15 +234,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
);
|
||||
}
|
||||
|
||||
Ledger? _ledger;
|
||||
LedgerDevice? _ledgerDevice;
|
||||
LedgerConnection? _ledgerConnection;
|
||||
BitcoinLedgerApp? _bitcoinLedgerApp;
|
||||
|
||||
void setLedger(Ledger setLedger, LedgerDevice setLedgerDevice) {
|
||||
_ledger = setLedger;
|
||||
_ledgerDevice = setLedgerDevice;
|
||||
_bitcoinLedgerApp =
|
||||
BitcoinLedgerApp(_ledger!, derivationPath: walletInfo.derivationInfo!.derivationPath!);
|
||||
@override
|
||||
void setLedgerConnection(LedgerConnection connection) {
|
||||
_ledgerConnection = connection;
|
||||
_bitcoinLedgerApp = BitcoinLedgerApp(_ledgerConnection!,
|
||||
derivationPath: walletInfo.derivationInfo!.derivationPath!);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -251,12 +256,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
BitcoinOrdering inputOrdering = BitcoinOrdering.bip69,
|
||||
BitcoinOrdering outputOrdering = BitcoinOrdering.bip69,
|
||||
}) async {
|
||||
final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint(_ledgerDevice!);
|
||||
final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint();
|
||||
|
||||
final psbtReadyInputs = <PSBTReadyUtxoWithAddress>[];
|
||||
for (final utxo in utxos) {
|
||||
final rawTx = await electrumClient.getTransactionHex(hash: utxo.utxo.txHash);
|
||||
final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
|
||||
final rawTx =
|
||||
await electrumClient.getTransactionHex(hash: utxo.utxo.txHash);
|
||||
final publicKeyAndDerivationPath =
|
||||
publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
|
||||
|
||||
psbtReadyInputs.add(PSBTReadyUtxoWithAddress(
|
||||
utxo: utxo.utxo,
|
||||
|
@ -268,10 +275,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
));
|
||||
}
|
||||
|
||||
final psbt =
|
||||
PSBTTransactionBuild(inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF);
|
||||
final psbt = PSBTTransactionBuild(
|
||||
inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF);
|
||||
|
||||
final rawHex = await _bitcoinLedgerApp!.signPsbt(_ledgerDevice!, psbt: psbt.psbt);
|
||||
final rawHex = await _bitcoinLedgerApp!.signPsbt(psbt: psbt.psbt);
|
||||
return BtcTransaction.fromRaw(BytesUtils.toHexString(rawHex));
|
||||
}
|
||||
|
||||
|
@ -279,14 +286,16 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
Future<String> signMessage(String message, {String? address = null}) async {
|
||||
if (walletInfo.isHardwareWallet) {
|
||||
final addressEntry = address != null
|
||||
? walletAddresses.allAddresses.firstWhere((element) => element.address == address)
|
||||
? walletAddresses.allAddresses
|
||||
.firstWhere((element) => element.address == address)
|
||||
: null;
|
||||
final index = addressEntry?.index ?? 0;
|
||||
final isChange = addressEntry?.isHidden == true ? 1 : 0;
|
||||
final accountPath = walletInfo.derivationInfo?.derivationPath;
|
||||
final derivationPath = accountPath != null ? "$accountPath/$isChange/$index" : null;
|
||||
final derivationPath =
|
||||
accountPath != null ? "$accountPath/$isChange/$index" : null;
|
||||
|
||||
final signature = await _bitcoinLedgerApp!.signMessage(_ledgerDevice!,
|
||||
final signature = await _bitcoinLedgerApp!.signMessage(
|
||||
message: ascii.encode(message), signDerivationPath: derivationPath);
|
||||
return base64Encode(signature);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
|
|||
required super.mainHd,
|
||||
required super.sideHd,
|
||||
required super.network,
|
||||
required super.isHardwareWallet,
|
||||
super.initialAddresses,
|
||||
super.initialRegularAddressIndex,
|
||||
super.initialChangeAddressIndex,
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'dart:isolate';
|
|||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:cw_bitcoin/address_from_output.dart';
|
||||
|
@ -26,6 +25,8 @@ import 'package:cw_bitcoin/exceptions.dart';
|
|||
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
|
||||
import 'package:cw_bitcoin/utils.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
import 'package:cw_core/get_height_by_date.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/pending_transaction.dart';
|
||||
|
@ -37,10 +38,10 @@ import 'package:cw_core/wallet_base.dart';
|
|||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_keys_file.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_core/get_height_by_date.dart';
|
||||
import 'package:cw_core/unspent_coin_type.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as ledger;
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:rxdart/subjects.dart';
|
||||
import 'package:sp_scanner/sp_scanner.dart';
|
||||
|
@ -51,9 +52,10 @@ part 'electrum_wallet.g.dart';
|
|||
|
||||
class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet;
|
||||
|
||||
abstract class ElectrumWalletBase
|
||||
extends WalletBase<ElectrumBalance, ElectrumTransactionHistory, ElectrumTransactionInfo>
|
||||
with Store, WalletKeysFile {
|
||||
abstract class ElectrumWalletBase extends WalletBase<
|
||||
ElectrumBalance,
|
||||
ElectrumTransactionHistory,
|
||||
ElectrumTransactionInfo> with Store, WalletKeysFile {
|
||||
ElectrumWalletBase({
|
||||
required String password,
|
||||
required WalletInfo walletInfo,
|
||||
|
@ -69,8 +71,8 @@ abstract class ElectrumWalletBase
|
|||
ElectrumBalance? initialBalance,
|
||||
CryptoCurrency? currency,
|
||||
this.alwaysScan,
|
||||
}) : accountHD =
|
||||
getAccountHDWallet(currency, network, seedBytes, xpub, walletInfo.derivationInfo),
|
||||
}) : accountHD = getAccountHDWallet(
|
||||
currency, network, seedBytes, xpub, walletInfo.derivationInfo),
|
||||
syncStatus = NotConnectedSyncStatus(),
|
||||
_password = password,
|
||||
_feeRates = <int>[],
|
||||
|
@ -105,8 +107,12 @@ abstract class ElectrumWalletBase
|
|||
sharedPrefs.complete(SharedPreferences.getInstance());
|
||||
}
|
||||
|
||||
static Bip32Slip10Secp256k1 getAccountHDWallet(CryptoCurrency? currency, BasedUtxoNetwork network,
|
||||
Uint8List? seedBytes, String? xpub, DerivationInfo? derivationInfo) {
|
||||
static Bip32Slip10Secp256k1 getAccountHDWallet(
|
||||
CryptoCurrency? currency,
|
||||
BasedUtxoNetwork network,
|
||||
Uint8List? seedBytes,
|
||||
String? xpub,
|
||||
DerivationInfo? derivationInfo) {
|
||||
if (seedBytes == null && xpub == null) {
|
||||
throw Exception(
|
||||
"To create a Wallet you need either a seed or an xpub. This should not happen");
|
||||
|
@ -117,8 +123,9 @@ abstract class ElectrumWalletBase
|
|||
case CryptoCurrency.btc:
|
||||
case CryptoCurrency.ltc:
|
||||
case CryptoCurrency.tbtc:
|
||||
return Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath(
|
||||
_hardenedDerivationPath(derivationInfo?.derivationPath ?? electrum_path))
|
||||
return Bip32Slip10Secp256k1.fromSeed(seedBytes, getKeyNetVersion(network))
|
||||
.derivePath(_hardenedDerivationPath(
|
||||
derivationInfo?.derivationPath ?? electrum_path))
|
||||
as Bip32Slip10Secp256k1;
|
||||
case CryptoCurrency.bch:
|
||||
return bitcoinCashHDWallet(seedBytes);
|
||||
|
@ -127,15 +134,26 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
}
|
||||
|
||||
return Bip32Slip10Secp256k1.fromExtendedKey(xpub!);
|
||||
return Bip32Slip10Secp256k1.fromExtendedKey(
|
||||
xpub!, getKeyNetVersion(network));
|
||||
}
|
||||
|
||||
static Bip32Slip10Secp256k1 bitcoinCashHDWallet(Uint8List seedBytes) =>
|
||||
Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'") as Bip32Slip10Secp256k1;
|
||||
Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'")
|
||||
as Bip32Slip10Secp256k1;
|
||||
|
||||
static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
|
||||
inputsCount * 68 + outputsCounts * 34 + 10;
|
||||
|
||||
static Bip32KeyNetVersions? getKeyNetVersion(BasedUtxoNetwork network) {
|
||||
switch (network) {
|
||||
case LitecoinNetwork.mainnet:
|
||||
return Bip44Conf.litecoinMainNet.altKeyNetVer;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool? alwaysScan;
|
||||
|
||||
final Bip32Slip10Secp256k1 accountHD;
|
||||
|
@ -634,8 +652,9 @@ abstract class ElectrumWalletBase
|
|||
ECPrivate? privkey;
|
||||
bool? isSilentPayment = false;
|
||||
|
||||
final hd =
|
||||
utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd;
|
||||
final hd = utx.bitcoinAddressRecord.isHidden
|
||||
? walletAddresses.sideHd
|
||||
: walletAddresses.mainHd;
|
||||
|
||||
if (utx.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) {
|
||||
final unspentAddress = utx.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
|
||||
|
@ -833,7 +852,7 @@ abstract class ElectrumWalletBase
|
|||
inputs: utxoDetails.availableInputs,
|
||||
outputs: updatedOutputs,
|
||||
);
|
||||
final address = RegexUtils.addressTypeFromStr(changeAddress, network);
|
||||
final address = RegexUtils.addressTypeFromStr(changeAddress.address, network);
|
||||
updatedOutputs.add(BitcoinOutput(
|
||||
address: address,
|
||||
value: BigInt.from(amountLeftForChangeAndFee),
|
||||
|
@ -845,6 +864,14 @@ abstract class ElectrumWalletBase
|
|||
isChange: true,
|
||||
));
|
||||
|
||||
// Get Derivation path for change Address since it is needed in Litecoin and BitcoinCash hardware Wallets
|
||||
final changeDerivationPath =
|
||||
"${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? "m/0'")}"
|
||||
"/${changeAddress.isHidden ? "1" : "0"}"
|
||||
"/${changeAddress.index}";
|
||||
utxoDetails.publicKeys[address.pubKeyHash()] =
|
||||
PublicKeyWithDerivationPath('', changeDerivationPath);
|
||||
|
||||
// calcFee updates the silent payment outputs to calculate the tx size accounting
|
||||
// for taproot addresses, but if more inputs are needed to make up for fees,
|
||||
// the silent payment outputs need to be recalculated for the new inputs
|
||||
|
@ -1206,6 +1233,9 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
}
|
||||
|
||||
void setLedgerConnection(ledger.LedgerConnection connection) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
Future<BtcTransaction> buildHardwareWalletTransaction({
|
||||
required List<BitcoinBaseOutput> outputs,
|
||||
required BigInt fee,
|
||||
|
@ -1563,7 +1593,9 @@ abstract class ElectrumWalletBase
|
|||
|
||||
final btcAddress = RegexUtils.addressTypeFromStr(addressRecord.address, network);
|
||||
final privkey = generateECPrivate(
|
||||
hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd,
|
||||
hd: addressRecord.isHidden
|
||||
? walletAddresses.sideHd
|
||||
: walletAddresses.mainHd,
|
||||
index: addressRecord.index,
|
||||
network: network);
|
||||
|
||||
|
@ -1745,7 +1777,8 @@ abstract class ElectrumWalletBase
|
|||
|
||||
if (height != null) {
|
||||
if (time == null && height > 0) {
|
||||
time = (getDateByBitcoinHeight(height).millisecondsSinceEpoch / 1000).round();
|
||||
time = (getDateByBitcoinHeight(height).millisecondsSinceEpoch / 1000)
|
||||
.round();
|
||||
}
|
||||
|
||||
if (confirmations == null) {
|
||||
|
|
|
@ -36,6 +36,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
required this.mainHd,
|
||||
required this.sideHd,
|
||||
required this.network,
|
||||
required this.isHardwareWallet,
|
||||
List<BitcoinAddressRecord>? initialAddresses,
|
||||
Map<String, int>? initialRegularAddressIndex,
|
||||
Map<String, int>? initialChangeAddressIndex,
|
||||
|
@ -44,6 +45,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
List<BitcoinAddressRecord>? initialMwebAddresses,
|
||||
Bip32Slip10Secp256k1? masterHd,
|
||||
BitcoinAddressType? initialAddressPageType,
|
||||
|
||||
}) : _addresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? []).toSet()),
|
||||
addressesByReceiveType =
|
||||
ObservableList<BaseBitcoinAddressRecord>.of((<BitcoinAddressRecord>[]).toSet()),
|
||||
|
@ -112,6 +114,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
final BasedUtxoNetwork network;
|
||||
final Bip32Slip10Secp256k1 mainHd;
|
||||
final Bip32Slip10Secp256k1 sideHd;
|
||||
final bool isHardwareWallet;
|
||||
|
||||
@observable
|
||||
SilentPaymentOwner? silentAddress;
|
||||
|
@ -240,15 +243,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||
} else if (walletInfo.type == WalletType.litecoin) {
|
||||
await _generateInitialAddresses(type: SegwitAddresType.p2wpkh);
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
if ((Platform.isAndroid || Platform.isIOS) && !isHardwareWallet) {
|
||||
await _generateInitialAddresses(type: SegwitAddresType.mweb);
|
||||
}
|
||||
} else if (walletInfo.type == WalletType.bitcoin) {
|
||||
await _generateInitialAddresses();
|
||||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||
await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
|
||||
await _generateInitialAddresses(type: SegwitAddresType.p2tr);
|
||||
await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
|
||||
if (!isHardwareWallet) {
|
||||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||
await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
|
||||
await _generateInitialAddresses(type: SegwitAddresType.p2tr);
|
||||
await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
|
||||
}
|
||||
}
|
||||
|
||||
updateAddressesByMatch();
|
||||
|
@ -267,7 +272,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
}
|
||||
|
||||
@action
|
||||
Future<String> getChangeAddress({List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
|
||||
Future<BitcoinAddressRecord> getChangeAddress({List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
|
||||
updateChangeAddresses();
|
||||
|
||||
if (changeAddresses.isEmpty) {
|
||||
|
@ -282,7 +287,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
}
|
||||
|
||||
updateChangeAddresses();
|
||||
final address = changeAddresses[currentChangeAddressIndex].address;
|
||||
final address = changeAddresses[currentChangeAddressIndex];
|
||||
currentChangeAddressIndex += 1;
|
||||
return address;
|
||||
}
|
||||
|
@ -670,7 +675,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
}
|
||||
|
||||
Bip32Slip10Secp256k1 _getHd(bool isHidden) => isHidden ? sideHd : mainHd;
|
||||
|
||||
bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) => addr.type == type;
|
||||
|
||||
bool _isUnusedReceiveAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) =>
|
||||
!addr.isHidden && !addr.isUsed && addr.type == type;
|
||||
|
||||
|
|
46
cw_bitcoin/lib/litecoin_hardware_wallet_service.dart
Normal file
46
cw_bitcoin/lib/litecoin_hardware_wallet_service.dart
Normal file
|
@ -0,0 +1,46 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||
import 'package:cw_bitcoin/utils.dart';
|
||||
import 'package:cw_core/hardware/hardware_account_data.dart';
|
||||
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
|
||||
import 'package:ledger_litecoin/ledger_litecoin.dart';
|
||||
|
||||
class LitecoinHardwareWalletService {
|
||||
LitecoinHardwareWalletService(this.ledgerConnection);
|
||||
|
||||
final LedgerConnection ledgerConnection;
|
||||
|
||||
Future<List<HardwareAccountData>> getAvailableAccounts(
|
||||
{int index = 0, int limit = 5}) async {
|
||||
final litecoinLedgerApp = LitecoinLedgerApp(ledgerConnection);
|
||||
|
||||
await litecoinLedgerApp.getVersion();
|
||||
|
||||
final accounts = <HardwareAccountData>[];
|
||||
final indexRange = List.generate(limit, (i) => i + index);
|
||||
final xpubVersion = Bip44Conf.litecoinMainNet.altKeyNetVer;
|
||||
|
||||
for (final i in indexRange) {
|
||||
final derivationPath = "m/84'/2'/$i'";
|
||||
final xpub = await litecoinLedgerApp.getXPubKey(
|
||||
accountsDerivationPath: derivationPath,
|
||||
xPubVersion: int.parse(hex.encode(xpubVersion.public), radix: 16));
|
||||
final hd = Bip32Slip10Secp256k1.fromExtendedKey(xpub, xpubVersion)
|
||||
.childKey(Bip32KeyIndex(0));
|
||||
|
||||
final address = generateP2WPKHAddress(
|
||||
hd: hd, index: 0, network: LitecoinNetwork.mainnet);
|
||||
|
||||
accounts.add(HardwareAccountData(
|
||||
address: address,
|
||||
accountIndex: i,
|
||||
derivationPath: derivationPath,
|
||||
xpub: xpub,
|
||||
));
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:convert/convert.dart' as convert;
|
||||
import 'dart:math';
|
||||
import 'package:collection/collection.dart';
|
||||
|
@ -37,6 +39,8 @@ import 'package:cw_core/wallet_keys_file.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
|
||||
import 'package:ledger_litecoin/ledger_litecoin.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_mweb/cw_mweb.dart';
|
||||
|
@ -50,12 +54,13 @@ class LitecoinWallet = LitecoinWalletBase with _$LitecoinWallet;
|
|||
|
||||
abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||
LitecoinWalletBase({
|
||||
required String mnemonic,
|
||||
required String password,
|
||||
required WalletInfo walletInfo,
|
||||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||
required Uint8List seedBytes,
|
||||
required EncryptionFileUtils encryptionFileUtils,
|
||||
Uint8List? seedBytes,
|
||||
String? mnemonic,
|
||||
String? xpub,
|
||||
String? passphrase,
|
||||
String? addressPageType,
|
||||
List<BitcoinAddressRecord>? initialAddresses,
|
||||
|
@ -68,6 +73,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
}) : super(
|
||||
mnemonic: mnemonic,
|
||||
password: password,
|
||||
xpub: xpub,
|
||||
walletInfo: walletInfo,
|
||||
unspentCoinsInfo: unspentCoinsInfo,
|
||||
network: LitecoinNetwork.mainnet,
|
||||
|
@ -78,8 +84,14 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
currency: CryptoCurrency.ltc,
|
||||
alwaysScan: alwaysScan,
|
||||
) {
|
||||
mwebHd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/1000'") as Bip32Slip10Secp256k1;
|
||||
mwebEnabled = alwaysScan ?? false;
|
||||
if (seedBytes != null) {
|
||||
mwebHd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath(
|
||||
"m/1000'") as Bip32Slip10Secp256k1;
|
||||
mwebEnabled = alwaysScan ?? false;
|
||||
} else {
|
||||
mwebHd = null;
|
||||
mwebEnabled = false;
|
||||
}
|
||||
walletAddresses = LitecoinWalletAddresses(
|
||||
walletInfo,
|
||||
initialAddresses: initialAddresses,
|
||||
|
@ -91,6 +103,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
network: network,
|
||||
mwebHd: mwebHd,
|
||||
mwebEnabled: mwebEnabled,
|
||||
isHardwareWallet: walletInfo.isHardwareWallet,
|
||||
);
|
||||
autorun((_) {
|
||||
this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
|
||||
|
@ -126,7 +139,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
}
|
||||
});
|
||||
}
|
||||
late final Bip32Slip10Secp256k1 mwebHd;
|
||||
late final Bip32Slip10Secp256k1? mwebHd;
|
||||
late final Box<MwebUtxo> mwebUtxosBox;
|
||||
Timer? _syncTimer;
|
||||
Timer? _feeRatesTimer;
|
||||
|
@ -138,8 +151,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
@observable
|
||||
SyncStatus mwebSyncStatus = NotConnectedSyncStatus();
|
||||
|
||||
List<int> get scanSecret => mwebHd.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
|
||||
List<int> get spendSecret => mwebHd.childKey(Bip32KeyIndex(0x80000001)).privateKey.privKey.raw;
|
||||
List<int> get scanSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
|
||||
List<int> get spendSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000001)).privateKey.privKey.raw;
|
||||
|
||||
static Future<LitecoinWallet> create(
|
||||
{required String mnemonic,
|
||||
|
@ -249,14 +262,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
}
|
||||
|
||||
return LitecoinWallet(
|
||||
mnemonic: keysData.mnemonic!,
|
||||
mnemonic: keysData.mnemonic,
|
||||
xpub: keysData.xPub,
|
||||
password: password,
|
||||
walletInfo: walletInfo,
|
||||
unspentCoinsInfo: unspentCoinsInfo,
|
||||
initialAddresses: snp?.addresses,
|
||||
initialMwebAddresses: snp?.mwebAddresses,
|
||||
initialBalance: snp?.balance,
|
||||
seedBytes: seedBytes!,
|
||||
seedBytes: seedBytes,
|
||||
passphrase: passphrase,
|
||||
encryptionFileUtils: encryptionFileUtils,
|
||||
initialRegularAddressIndex: snp?.regularAddressIndex,
|
||||
|
@ -935,7 +949,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
|
||||
if (!mwebEnabled) {
|
||||
tx.changeAddressOverride =
|
||||
await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(isPegIn: false);
|
||||
(await (walletAddresses as LitecoinWalletAddresses)
|
||||
.getChangeAddress(isPegIn: false))
|
||||
.address;
|
||||
return tx;
|
||||
}
|
||||
await waitForMwebAddresses();
|
||||
|
@ -974,8 +990,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
|
||||
bool isPegIn = !hasMwebInput && hasMwebOutput;
|
||||
bool isRegular = !hasMwebInput && !hasMwebOutput;
|
||||
tx.changeAddressOverride = await (walletAddresses as LitecoinWalletAddresses)
|
||||
.getChangeAddress(isPegIn: isPegIn || isRegular);
|
||||
tx.changeAddressOverride =
|
||||
(await (walletAddresses as LitecoinWalletAddresses)
|
||||
.getChangeAddress(isPegIn: isPegIn || isRegular))
|
||||
.address;
|
||||
if (!hasMwebInput && !hasMwebOutput) {
|
||||
tx.isMweb = false;
|
||||
return tx;
|
||||
|
@ -1215,4 +1233,64 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
LedgerConnection? _ledgerConnection;
|
||||
LitecoinLedgerApp? _litecoinLedgerApp;
|
||||
|
||||
@override
|
||||
void setLedgerConnection(LedgerConnection connection) {
|
||||
_ledgerConnection = connection;
|
||||
_litecoinLedgerApp =
|
||||
LitecoinLedgerApp(_ledgerConnection!, derivationPath: walletInfo.derivationInfo!.derivationPath!);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BtcTransaction> buildHardwareWalletTransaction({
|
||||
required List<BitcoinBaseOutput> outputs,
|
||||
required BigInt fee,
|
||||
required BasedUtxoNetwork network,
|
||||
required List<UtxoWithAddress> utxos,
|
||||
required Map<String, PublicKeyWithDerivationPath> publicKeys,
|
||||
String? memo,
|
||||
bool enableRBF = false,
|
||||
BitcoinOrdering inputOrdering = BitcoinOrdering.bip69,
|
||||
BitcoinOrdering outputOrdering = BitcoinOrdering.bip69,
|
||||
}) async {
|
||||
final readyInputs = <LedgerTransaction>[];
|
||||
for (final utxo in utxos) {
|
||||
final rawTx = await electrumClient.getTransactionHex(hash: utxo.utxo.txHash);
|
||||
final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
|
||||
|
||||
readyInputs.add(LedgerTransaction(
|
||||
rawTx: rawTx,
|
||||
outputIndex: utxo.utxo.vout,
|
||||
ownerPublicKey: Uint8List.fromList(hex.decode(publicKeyAndDerivationPath.publicKey)),
|
||||
ownerDerivationPath: publicKeyAndDerivationPath.derivationPath,
|
||||
// sequence: enableRBF ? 0x1 : 0xffffffff,
|
||||
sequence: 0xffffffff,
|
||||
));
|
||||
}
|
||||
|
||||
String? changePath;
|
||||
for (final output in outputs) {
|
||||
final maybeChangePath = publicKeys[(output as BitcoinOutput).address.pubKeyHash()];
|
||||
if (maybeChangePath != null) changePath ??= maybeChangePath.derivationPath;
|
||||
}
|
||||
|
||||
|
||||
final rawHex = await _litecoinLedgerApp!.createTransaction(
|
||||
inputs: readyInputs,
|
||||
outputs: outputs
|
||||
.map((e) => TransactionOutput.fromBigInt(
|
||||
(e as BitcoinOutput).value, Uint8List.fromList(e.address.toScriptPubKey().toBytes())))
|
||||
.toList(),
|
||||
changePath: changePath,
|
||||
sigHashType: 0x01,
|
||||
additionals: ["bech32"],
|
||||
isSegWit: true,
|
||||
useTrustedInputForSegwit: true
|
||||
);
|
||||
|
||||
return BtcTransaction.fromRaw(rawHex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,17 @@ import 'package:mobx/mobx.dart';
|
|||
|
||||
part 'litecoin_wallet_addresses.g.dart';
|
||||
|
||||
class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses;
|
||||
class LitecoinWalletAddresses = LitecoinWalletAddressesBase
|
||||
with _$LitecoinWalletAddresses;
|
||||
|
||||
abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
|
||||
abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses
|
||||
with Store {
|
||||
LitecoinWalletAddressesBase(
|
||||
WalletInfo walletInfo, {
|
||||
required super.mainHd,
|
||||
required super.sideHd,
|
||||
required super.network,
|
||||
required super.isHardwareWallet,
|
||||
required this.mwebHd,
|
||||
required this.mwebEnabled,
|
||||
super.initialAddresses,
|
||||
|
@ -37,20 +40,20 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
print("initialized with ${mwebAddrs.length} mweb addresses");
|
||||
}
|
||||
|
||||
final Bip32Slip10Secp256k1 mwebHd;
|
||||
final Bip32Slip10Secp256k1? mwebHd;
|
||||
bool mwebEnabled;
|
||||
int mwebTopUpIndex = 1000;
|
||||
List<String> mwebAddrs = [];
|
||||
bool generating = false;
|
||||
|
||||
List<int> get scanSecret => mwebHd.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
|
||||
|
||||
List<int> get scanSecret =>
|
||||
mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
|
||||
List<int> get spendPubkey =>
|
||||
mwebHd.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
|
||||
mwebHd!.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
|
||||
|
||||
@override
|
||||
Future<void> init() async {
|
||||
await initMwebAddresses();
|
||||
if (!isHardwareWallet) await initMwebAddresses();
|
||||
await super.init();
|
||||
}
|
||||
|
||||
|
@ -94,6 +97,9 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
print("Done generating MWEB addresses len: ${mwebAddrs.length}");
|
||||
|
||||
// ensure mweb addresses are up to date:
|
||||
// This is the Case if the Litecoin Wallet is a hardware Wallet
|
||||
if (mwebHd == null) return;
|
||||
|
||||
if (mwebAddresses.length < mwebAddrs.length) {
|
||||
List<BitcoinAddressRecord> addressRecords = mwebAddrs
|
||||
.asMap()
|
||||
|
@ -143,7 +149,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
|
||||
@action
|
||||
@override
|
||||
Future<String> getChangeAddress(
|
||||
Future<BitcoinAddressRecord> getChangeAddress(
|
||||
{List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
|
||||
// use regular change address on peg in, otherwise use mweb for change address:
|
||||
|
||||
|
@ -187,7 +193,12 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
|
||||
if (mwebEnabled) {
|
||||
await ensureMwebAddressUpToIndexExists(1);
|
||||
return mwebAddrs[0];
|
||||
return BitcoinAddressRecord(
|
||||
mwebAddrs[0],
|
||||
index: 0,
|
||||
type: SegwitAddresType.mweb,
|
||||
network: network,
|
||||
);
|
||||
}
|
||||
|
||||
return super.getChangeAddress();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:io';
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
|
||||
import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
|
@ -20,7 +21,7 @@ class LitecoinWalletService extends WalletService<
|
|||
BitcoinNewWalletCredentials,
|
||||
BitcoinRestoreWalletFromSeedCredentials,
|
||||
BitcoinRestoreWalletFromWIFCredentials,
|
||||
BitcoinNewWalletCredentials> {
|
||||
BitcoinRestoreWalletFromHardware> {
|
||||
LitecoinWalletService(
|
||||
this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan, this.isDirect);
|
||||
|
||||
|
@ -147,9 +148,23 @@ class LitecoinWalletService extends WalletService<
|
|||
}
|
||||
|
||||
@override
|
||||
Future<LitecoinWallet> restoreFromHardwareWallet(BitcoinNewWalletCredentials credentials) {
|
||||
throw UnimplementedError(
|
||||
"Restoring a Litecoin wallet from a hardware wallet is not yet supported!");
|
||||
Future<LitecoinWallet> restoreFromHardwareWallet(BitcoinRestoreWalletFromHardware credentials,
|
||||
{bool? isTestnet}) async {
|
||||
final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
|
||||
credentials.walletInfo?.network = network.value;
|
||||
credentials.walletInfo?.derivationInfo?.derivationPath =
|
||||
credentials.hwAccountData.derivationPath;
|
||||
|
||||
final wallet = await LitecoinWallet(
|
||||
password: credentials.password!,
|
||||
xpub: credentials.hwAccountData.xpub,
|
||||
walletInfo: credentials.walletInfo!,
|
||||
unspentCoinsInfo: unspentCoinsInfoSource,
|
||||
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
||||
);
|
||||
await wallet.save();
|
||||
await wallet.init();
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -16,10 +16,6 @@ class PSBTTransactionBuild {
|
|||
for (var i = 0; i < inputs.length; i++) {
|
||||
final input = inputs[i];
|
||||
|
||||
print(input.utxo.isP2tr());
|
||||
print(input.utxo.isSegwit());
|
||||
print(input.utxo.isP2shSegwit());
|
||||
|
||||
psbt.setInputPreviousTxId(i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList()));
|
||||
psbt.setInputOutputIndex(i, input.utxo.vout);
|
||||
psbt.setInputSequence(i, enableRBF ? 0x1 : 0xffffffff);
|
||||
|
|
|
@ -101,6 +101,14 @@ packages:
|
|||
url: "https://github.com/cake-tech/blockchain_utils"
|
||||
source: git
|
||||
version: "3.3.0"
|
||||
bluez:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bluez
|
||||
sha256: "203a1924e818a9dd74af2b2c7a8f375ab8e5edf0e486bba8f90a0d8a17ed9fce"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.2"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -300,6 +308,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
dbus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dbus
|
||||
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.10"
|
||||
encrypt:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -361,19 +377,19 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1+1"
|
||||
flutter_reactive_ble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_reactive_ble
|
||||
sha256: "247e2efa76de203d1ba11335c13754b5b9d0504b5423e5b0c93a600f016b24e0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.3.1"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_bluetooth:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_web_bluetooth
|
||||
sha256: "52ce64f65d7321c4bf6abfe9dac02fb888731339a5e0ad6de59fb916c20c9f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.3"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -387,14 +403,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
functional_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: functional_data
|
||||
sha256: "76d17dc707c40e552014f5a49c0afcc3f1e3f05e800cd6b7872940bfe41a5039"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -550,29 +558,37 @@ packages:
|
|||
ledger_bitcoin:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
path: "packages/ledger-bitcoin"
|
||||
ref: HEAD
|
||||
resolved-ref: f819d37e235e239c315e93856abbf5e5d3b71dab
|
||||
url: "https://github.com/cake-tech/ledger-bitcoin"
|
||||
resolved-ref: dbb5c4956949dc734af3fc8febdbabed89da72aa
|
||||
url: "https://github.com/cake-tech/ledger-flutter-plus-plugins"
|
||||
source: git
|
||||
version: "0.0.2"
|
||||
ledger_flutter:
|
||||
version: "0.0.3"
|
||||
ledger_flutter_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: cake-v3
|
||||
resolved-ref: "66469ff9dffe2417c70ae7287c9d76d2fe7157a4"
|
||||
url: "https://github.com/cake-tech/ledger-flutter.git"
|
||||
source: git
|
||||
version: "1.0.2"
|
||||
ledger_usb:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ledger_usb
|
||||
sha256: "52c92d03a4cffe06c82921c8e2f79f3cdad6e1cf78e1e9ca35444196ff8f14c2"
|
||||
name: ledger_flutter_plus
|
||||
sha256: ea3ed586e1697776dacf42ac979095f1ca3bd143bf007cbe5c78e09cb6943f42
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.2.5"
|
||||
ledger_litecoin:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "packages/ledger-litecoin"
|
||||
ref: HEAD
|
||||
resolved-ref: dbb5c4956949dc734af3fc8febdbabed89da72aa
|
||||
url: "https://github.com/cake-tech/ledger-flutter-plus-plugins"
|
||||
source: git
|
||||
version: "0.0.2"
|
||||
ledger_usb_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ledger_usb_plus
|
||||
sha256: "21cc5d976cf7edb3518bd2a0c4164139cbb0817d2e4f2054707fc4edfdf9ce87"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -701,6 +717,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.2"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -773,30 +797,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
reactive_ble_mobile:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: reactive_ble_mobile
|
||||
sha256: "9ec2b4c9c725e439950838d551579750060258fbccd5536d0543b4d07d225798"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.3.1"
|
||||
reactive_ble_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: reactive_ble_platform_interface
|
||||
sha256: "632c92401a2d69c9b94bd48f8fd47488a7013f3d1f9b291884350291a4a81813"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.3.1"
|
||||
rxdart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: rxdart
|
||||
sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
|
||||
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.27.7"
|
||||
version: "0.28.0"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -987,6 +995,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
universal_ble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_ble
|
||||
sha256: "0dfbd6b64bff3ad61ed7a895c232530d9614e9b01ab261a74433a43267edb7f3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.0"
|
||||
universal_platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_platform
|
||||
sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
unorm_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1043,6 +1067,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -24,16 +24,12 @@ dependencies:
|
|||
git:
|
||||
url: https://github.com/cake-tech/bitbox-flutter.git
|
||||
ref: Add-Support-For-OP-Return-data
|
||||
rxdart: ^0.27.5
|
||||
rxdart: ^0.28.0
|
||||
cryptography: ^2.0.5
|
||||
blockchain_utils:
|
||||
git:
|
||||
url: https://github.com/cake-tech/blockchain_utils
|
||||
ref: cake-update-v2
|
||||
ledger_flutter: ^1.0.1
|
||||
ledger_bitcoin:
|
||||
git:
|
||||
url: https://github.com/cake-tech/ledger-bitcoin
|
||||
cw_mweb:
|
||||
path: ../cw_mweb
|
||||
grpc: ^3.2.4
|
||||
|
@ -44,6 +40,15 @@ dependencies:
|
|||
bech32:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bech32.git
|
||||
ledger_flutter_plus: ^1.4.1
|
||||
ledger_bitcoin:
|
||||
git:
|
||||
url: https://github.com/cake-tech/ledger-flutter-plus-plugins
|
||||
path: packages/ledger-bitcoin
|
||||
ledger_litecoin:
|
||||
git:
|
||||
url: https://github.com/cake-tech/ledger-flutter-plus-plugins
|
||||
path: packages/ledger-litecoin
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -54,10 +59,6 @@ dev_dependencies:
|
|||
hive_generator: ^1.1.3
|
||||
|
||||
dependency_overrides:
|
||||
ledger_flutter:
|
||||
git:
|
||||
url: https://github.com/cake-tech/ledger-flutter.git
|
||||
ref: cake-v3
|
||||
watcher: ^1.1.0
|
||||
protobuf: ^3.1.0
|
||||
bitcoin_base:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue