mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-03-24 08:09:19 +00:00
Merge branch 'mweb' of https://github.com/ltcmweb/cake_wallet into mweb
This commit is contained in:
commit
77142e3700
44 changed files with 2013 additions and 98 deletions
cw_bitcoin
lib
bitcoin_receive_page_option.dartelectrum.dartelectrum_transaction_info.dartelectrum_wallet.dartelectrum_wallet_addresses.dartlitecoin_wallet.dartlitecoin_wallet_addresses.dartpending_bitcoin_transaction.dart
pubspec.lockpubspec.yamlcw_bitcoin_cash
cw_haven/android
cw_monero/android
cw_mweb
.gitignore.metadataCHANGELOG.mdLICENSEREADME.mdanalysis_options.yaml
android
ios
lib
cw_mweb.dartcw_mweb_method_channel.dartcw_mweb_platform_interface.dartmwebd.pb.dartmwebd.pbgrpc.dart
macos
pubspec.yamllib
macos/Flutter
|
@ -7,6 +7,7 @@ class BitcoinReceivePageOption implements ReceivePageOption {
|
|||
static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)');
|
||||
static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)');
|
||||
static const p2pkh = BitcoinReceivePageOption._('Legacy (P2PKH)');
|
||||
static const mweb = BitcoinReceivePageOption._('MWEB');
|
||||
|
||||
const BitcoinReceivePageOption._(this.value);
|
||||
|
||||
|
@ -24,12 +25,19 @@ class BitcoinReceivePageOption implements ReceivePageOption {
|
|||
BitcoinReceivePageOption.p2pkh
|
||||
];
|
||||
|
||||
static const allLitecoin = [
|
||||
BitcoinReceivePageOption.p2wpkh,
|
||||
BitcoinReceivePageOption.mweb
|
||||
];
|
||||
|
||||
factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) {
|
||||
switch (type) {
|
||||
case SegwitAddresType.p2tr:
|
||||
return BitcoinReceivePageOption.p2tr;
|
||||
case SegwitAddresType.p2wsh:
|
||||
return BitcoinReceivePageOption.p2wsh;
|
||||
case SegwitAddresType.mweb:
|
||||
return BitcoinReceivePageOption.mweb;
|
||||
case P2pkhAddressType.p2pkh:
|
||||
return BitcoinReceivePageOption.p2pkh;
|
||||
case P2shAddressType.p2wpkhInP2sh:
|
||||
|
|
|
@ -331,14 +331,19 @@ class ElectrumClient {
|
|||
// "height": 520481,
|
||||
// "hex": "00000020890208a0ae3a3892aa047c5468725846577cfcd9b512b50000000000000000005dc2b02f2d297a9064ee103036c14d678f9afc7e3d9409cf53fd58b82e938e8ecbeca05a2d2103188ce804c4"
|
||||
// }
|
||||
Future<int?> getCurrentBlockChainTip() =>
|
||||
call(method: 'blockchain.headers.subscribe').then((result) {
|
||||
if (result is Map<String, dynamic>) {
|
||||
return result["height"] as int;
|
||||
}
|
||||
BehaviorSubject<Map<String, dynamic>>? tipListener;
|
||||
int? currentTip;
|
||||
|
||||
return null;
|
||||
});
|
||||
Future<int?> getCurrentBlockChainTip() async {
|
||||
final method = 'blockchain.headers.subscribe';
|
||||
final cb = (result) => currentTip = result['height'] as int;
|
||||
if (tipListener == null) {
|
||||
tipListener = subscribe(id: method, method: method);
|
||||
tipListener?.listen(cb);
|
||||
cb(await call(method: method));
|
||||
}
|
||||
return currentTip;
|
||||
}
|
||||
|
||||
BehaviorSubject<Object>? scripthashUpdate(String scripthash) {
|
||||
_id += 1;
|
||||
|
@ -424,6 +429,12 @@ class ElectrumClient {
|
|||
|
||||
void _methodHandler({required String method, required Map<String, dynamic> request}) {
|
||||
switch (method) {
|
||||
case 'blockchain.headers.subscribe':
|
||||
final params = request['params'] as List<dynamic>;
|
||||
final id = 'blockchain.headers.subscribe';
|
||||
|
||||
_tasks[id]?.subject?.add(params.last);
|
||||
break;
|
||||
case 'blockchain.scripthash.subscribe':
|
||||
final params = request['params'] as List<dynamic>;
|
||||
final scripthash = params.first as String?;
|
||||
|
|
|
@ -196,8 +196,8 @@ class ElectrumTransactionInfo extends TransactionInfo {
|
|||
direction: parseTransactionDirectionFromInt(data['direction'] as int),
|
||||
date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int),
|
||||
isPending: data['isPending'] as bool,
|
||||
inputAddresses: data['inputAddresses'] as List<String>,
|
||||
outputAddresses: data['outputAddresses'] as List<String>,
|
||||
inputAddresses: List<String>.from(data['inputAddresses'] as List),
|
||||
outputAddresses: List<String>.from(data['outputAddresses'] as List),
|
||||
confirmations: data['confirmations'] as int);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
|||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_bitcoin/exceptions.dart';
|
||||
import 'package:cw_bitcoin/litecoin_network.dart';
|
||||
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
||||
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
|
||||
import 'package:cw_bitcoin/script_hash.dart';
|
||||
import 'package:cw_bitcoin/utils.dart';
|
||||
|
@ -138,11 +139,13 @@ abstract class ElectrumWalletBase
|
|||
SyncStatus syncStatus;
|
||||
|
||||
List<String> get scriptHashes => walletAddresses.addressesByReceiveType
|
||||
.where((addr) => addressTypeFromStr(addr.address, network) is! MwebAddress)
|
||||
.map((addr) => scriptHash(addr.address, network: network))
|
||||
.toList();
|
||||
|
||||
List<String> get publicScriptHashes => walletAddresses.allAddresses
|
||||
.where((addr) => !addr.isHidden)
|
||||
.where((addr) => addressTypeFromStr(addr.address, network) is! MwebAddress)
|
||||
.map((addr) => scriptHash(addr.address, network: network))
|
||||
.toList();
|
||||
|
||||
|
@ -182,8 +185,10 @@ abstract class ElectrumWalletBase
|
|||
syncStatus = AttemptingSyncStatus();
|
||||
await updateTransactions();
|
||||
_subscribeForUpdates();
|
||||
await updateUnspent();
|
||||
await updateBalance();
|
||||
if (this is! LitecoinWallet) {
|
||||
await updateUnspent();
|
||||
await updateBalance();
|
||||
}
|
||||
_feeRates = await electrumClient.feeRates(network: network);
|
||||
|
||||
Timer.periodic(
|
||||
|
@ -280,24 +285,13 @@ abstract class ElectrumWalletBase
|
|||
throw BitcoinTransactionNoInputsException();
|
||||
}
|
||||
|
||||
int estimatedSize;
|
||||
if (network is BitcoinCashNetwork) {
|
||||
estimatedSize = ForkedTransactionBuilder.estimateTransactionSize(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
network: network as BitcoinCashNetwork,
|
||||
memo: memo,
|
||||
);
|
||||
} else {
|
||||
estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
network: network,
|
||||
memo: memo,
|
||||
);
|
||||
}
|
||||
|
||||
int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize);
|
||||
int fee = await calcFee(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
network: network,
|
||||
memo: memo,
|
||||
feeRate: feeRate,
|
||||
);
|
||||
|
||||
if (fee == 0) {
|
||||
throw BitcoinTransactionNoFeeException();
|
||||
|
@ -441,24 +435,13 @@ abstract class ElectrumWalletBase
|
|||
value: BigInt.from(amountLeftForChangeAndFee),
|
||||
));
|
||||
|
||||
int estimatedSize;
|
||||
if (network is BitcoinCashNetwork) {
|
||||
estimatedSize = ForkedTransactionBuilder.estimateTransactionSize(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
network: network as BitcoinCashNetwork,
|
||||
memo: memo,
|
||||
);
|
||||
} else {
|
||||
estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
network: network,
|
||||
memo: memo,
|
||||
);
|
||||
}
|
||||
|
||||
int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize);
|
||||
int fee = await calcFee(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
network: network,
|
||||
memo: memo,
|
||||
feeRate: feeRate,
|
||||
);
|
||||
|
||||
if (fee == 0) {
|
||||
throw BitcoinTransactionNoFeeException();
|
||||
|
@ -549,6 +532,33 @@ abstract class ElectrumWalletBase
|
|||
);
|
||||
}
|
||||
|
||||
Future<int> calcFee({
|
||||
required List<UtxoWithAddress> utxos,
|
||||
required List<BitcoinBaseOutput> outputs,
|
||||
required BasedUtxoNetwork network,
|
||||
String? memo,
|
||||
required int feeRate}) async {
|
||||
|
||||
int estimatedSize;
|
||||
if (network is BitcoinCashNetwork) {
|
||||
estimatedSize = ForkedTransactionBuilder.estimateTransactionSize(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
network: network,
|
||||
memo: memo,
|
||||
);
|
||||
} else {
|
||||
estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
network: network,
|
||||
memo: memo,
|
||||
);
|
||||
}
|
||||
|
||||
return feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||
try {
|
||||
|
@ -839,7 +849,7 @@ abstract class ElectrumWalletBase
|
|||
|
||||
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
|
||||
|
||||
Future<void> updateUnspent() async {
|
||||
Future<void> updateUnspentCoins() async {
|
||||
List<BitcoinUnspent> updatedUnspentCoins = [];
|
||||
|
||||
final addressesSet = walletAddresses.allAddresses.map((addr) => addr.address).toSet();
|
||||
|
@ -858,6 +868,10 @@ abstract class ElectrumWalletBase
|
|||
}))));
|
||||
|
||||
unspentCoins = updatedUnspentCoins;
|
||||
}
|
||||
|
||||
Future<void> updateUnspent() async {
|
||||
await updateUnspentCoins();
|
||||
|
||||
if (unspentCoinsInfo.isEmpty) {
|
||||
unspentCoins.forEach((coin) => _addCoinInfo(coin));
|
||||
|
@ -877,7 +891,6 @@ abstract class ElectrumWalletBase
|
|||
coin.isFrozen = coinInfo.isFrozen;
|
||||
coin.isSending = coinInfo.isSending;
|
||||
coin.note = coinInfo.note;
|
||||
coin.bitcoinAddressRecord.balance += coinInfo.value;
|
||||
} else {
|
||||
_addCoinInfo(coin);
|
||||
}
|
||||
|
@ -1291,8 +1304,9 @@ abstract class ElectrumWalletBase
|
|||
});
|
||||
}
|
||||
|
||||
Future<ElectrumBalance> _fetchBalances() async {
|
||||
final addresses = walletAddresses.allAddresses.toList();
|
||||
Future<ElectrumBalance> fetchBalances() async {
|
||||
final addresses = walletAddresses.allAddresses.where((address) =>
|
||||
addressTypeFromStr(address.address, network) is! MwebAddress).toList();
|
||||
final balanceFutures = <Future<Map<String, dynamic>>>[];
|
||||
for (var i = 0; i < addresses.length; i++) {
|
||||
final addressRecord = addresses[i];
|
||||
|
@ -1326,6 +1340,7 @@ abstract class ElectrumWalletBase
|
|||
totalConfirmed += confirmed;
|
||||
totalUnconfirmed += unconfirmed;
|
||||
|
||||
addressRecord.balance = confirmed + unconfirmed;
|
||||
if (confirmed > 0 || unconfirmed > 0) {
|
||||
addressRecord.setAsUsed();
|
||||
}
|
||||
|
@ -1336,7 +1351,7 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
|
||||
Future<void> updateBalance() async {
|
||||
balance[currency] = await _fetchBalances();
|
||||
balance[currency] = await fetchBalances();
|
||||
await save();
|
||||
}
|
||||
|
||||
|
@ -1448,6 +1463,8 @@ BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network)
|
|||
return P2wshAddress.fromAddress(address: address, network: network);
|
||||
} else if (P2trAddress.regex.hasMatch(address)) {
|
||||
return P2trAddress.fromAddress(address: address, network: network);
|
||||
} else if (MwebAddress.regex.hasMatch(address)) {
|
||||
return MwebAddress.fromAddress(address: address, network: network);
|
||||
} else {
|
||||
return P2wpkhAddress.fromAddress(address: address, network: network);
|
||||
}
|
||||
|
@ -1462,6 +1479,8 @@ BitcoinAddressType _getScriptType(BitcoinBaseAddress type) {
|
|||
return SegwitAddresType.p2wsh;
|
||||
} else if (type is P2trAddress) {
|
||||
return SegwitAddresType.p2tr;
|
||||
} else if (type is MwebAddress) {
|
||||
return SegwitAddresType.mweb;
|
||||
} else {
|
||||
return SegwitAddresType.p2wpkh;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ const List<BitcoinAddressType> ADDRESS_TYPES = [
|
|||
P2pkhAddressType.p2pkh,
|
||||
SegwitAddresType.p2tr,
|
||||
SegwitAddresType.p2wsh,
|
||||
SegwitAddresType.mweb,
|
||||
P2shAddressType.p2wpkhInP2sh,
|
||||
];
|
||||
|
||||
|
@ -154,6 +155,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||
} else if (walletInfo.type == WalletType.litecoin) {
|
||||
await _generateInitialAddresses();
|
||||
await _generateInitialAddresses(type: SegwitAddresType.mweb);
|
||||
} else if (walletInfo.type == WalletType.bitcoin) {
|
||||
await _generateInitialAddresses();
|
||||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||
|
@ -217,6 +219,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
{required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) =>
|
||||
'';
|
||||
|
||||
Future<String> getAddressAsync(
|
||||
{required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) async =>
|
||||
getAddress(index: index, hd: hd, addressType: addressType);
|
||||
|
||||
@override
|
||||
Future<void> updateAddressesInBox() async {
|
||||
try {
|
||||
|
@ -328,7 +334,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
|
||||
for (var i = startIndex; i < count + startIndex; i++) {
|
||||
final address = BitcoinAddressRecord(
|
||||
getAddress(index: i, hd: _getHd(isHidden), addressType: type ?? addressPageType),
|
||||
await getAddressAsync(index: i, hd: _getHd(isHidden), addressType: type ?? addressPageType),
|
||||
index: i,
|
||||
isHidden: isHidden,
|
||||
type: type ?? addressPageType,
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:fixnum/fixnum.dart';
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
||||
import 'package:cw_bitcoin/electrum_transaction_info.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/pending_transaction.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:cw_core/transaction_direction.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
|
@ -9,11 +22,14 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||
import 'package:cw_bitcoin/litecoin_network.dart';
|
||||
import 'package:cw_mweb/cw_mweb.dart';
|
||||
import 'package:cw_mweb/mwebd.pb.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
|
||||
|
@ -33,7 +49,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
ElectrumBalance? initialBalance,
|
||||
Map<String, int>? initialRegularAddressIndex,
|
||||
Map<String, int>? initialChangeAddressIndex,
|
||||
}) : super(
|
||||
}) : mwebHd = bitcoin.HDWallet.fromSeed(seedBytes,
|
||||
network: litecoinNetwork).derivePath("m/1000'"),
|
||||
super(
|
||||
mnemonic: mnemonic,
|
||||
password: password,
|
||||
walletInfo: walletInfo,
|
||||
|
@ -52,12 +70,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
mainHd: hd,
|
||||
sideHd: accountHD.derive(1),
|
||||
network: network,
|
||||
mwebHd: mwebHd,
|
||||
);
|
||||
autorun((_) {
|
||||
this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
|
||||
});
|
||||
}
|
||||
|
||||
final bitcoin.HDWallet mwebHd;
|
||||
|
||||
static Future<LitecoinWallet> create(
|
||||
{required String mnemonic,
|
||||
required String password,
|
||||
|
@ -119,6 +140,209 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
);
|
||||
}
|
||||
|
||||
int mwebUtxosHeight = 0;
|
||||
|
||||
@action
|
||||
@override
|
||||
Future<void> startSync() async {
|
||||
await super.startSync();
|
||||
final stub = await CwMweb.stub();
|
||||
Timer.periodic(
|
||||
const Duration(milliseconds: 1500), (timer) async {
|
||||
if (syncStatus is FailedSyncStatus) return;
|
||||
final height = await electrumClient.getCurrentBlockChainTip() ?? 0;
|
||||
final resp = await stub.status(StatusRequest());
|
||||
if (resp.blockHeaderHeight < height) {
|
||||
int h = resp.blockHeaderHeight;
|
||||
syncStatus = SyncingSyncStatus(height - h, h / height);
|
||||
} else if (resp.mwebHeaderHeight < height) {
|
||||
int h = resp.mwebHeaderHeight;
|
||||
syncStatus = SyncingSyncStatus(height - h, h / height);
|
||||
} else if (resp.mwebUtxosHeight < height) {
|
||||
syncStatus = SyncingSyncStatus(1, 0.999);
|
||||
} else {
|
||||
syncStatus = SyncedSyncStatus();
|
||||
if (resp.mwebUtxosHeight > mwebUtxosHeight) {
|
||||
mwebUtxosHeight = resp.mwebUtxosHeight;
|
||||
await checkMwebUtxosSpent();
|
||||
for (final transaction in transactionHistory.transactions.values) {
|
||||
if (transaction.isPending) continue;
|
||||
final confirmations = mwebUtxosHeight - transaction.height + 1;
|
||||
if (transaction.confirmations == confirmations) continue;
|
||||
transaction.confirmations = confirmations;
|
||||
transactionHistory.addOne(transaction);
|
||||
}
|
||||
await transactionHistory.save();
|
||||
}
|
||||
}
|
||||
});
|
||||
processMwebUtxos();
|
||||
}
|
||||
|
||||
final Map<String, Utxo> mwebUtxos = {};
|
||||
|
||||
Future<void> processMwebUtxos() async {
|
||||
final stub = await CwMweb.stub();
|
||||
final scanSecret = mwebHd.derive(0x80000000).privKey!;
|
||||
final req = UtxosRequest(scanSecret: hex.decode(scanSecret));
|
||||
var initDone = false;
|
||||
await for (var utxo in stub.utxos(req)) {
|
||||
if (utxo.address.isEmpty) {
|
||||
await updateUnspent();
|
||||
await updateBalance();
|
||||
initDone = true;
|
||||
}
|
||||
final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
|
||||
if (!mwebAddrs.contains(utxo.address)) continue;
|
||||
mwebUtxos[utxo.outputId] = utxo;
|
||||
|
||||
final status = await stub.status(StatusRequest());
|
||||
var date = DateTime.now();
|
||||
var confirmations = 0;
|
||||
if (utxo.height > 0) {
|
||||
date = DateTime.fromMillisecondsSinceEpoch(utxo.blockTime * 1000);
|
||||
confirmations = status.blockHeaderHeight - utxo.height + 1;
|
||||
}
|
||||
var tx = transactionHistory.transactions.values.firstWhereOrNull(
|
||||
(tx) => tx.outputAddresses?.contains(utxo.outputId) ?? false);
|
||||
if (tx == null)
|
||||
tx = ElectrumTransactionInfo(WalletType.litecoin,
|
||||
id: utxo.outputId, height: utxo.height,
|
||||
amount: utxo.value.toInt(), fee: 0,
|
||||
direction: TransactionDirection.incoming,
|
||||
isPending: utxo.height == 0,
|
||||
date: date, confirmations: confirmations,
|
||||
inputAddresses: [], outputAddresses: [utxo.outputId]);
|
||||
tx.height = utxo.height;
|
||||
tx.isPending = utxo.height == 0;
|
||||
tx.confirmations = confirmations;
|
||||
var isNew = transactionHistory.transactions[tx.id] == null;
|
||||
if (!(tx.outputAddresses?.contains(utxo.address) ?? false)) {
|
||||
tx.outputAddresses?.add(utxo.address);
|
||||
isNew = true;
|
||||
}
|
||||
if (isNew) {
|
||||
final addressRecord = walletAddresses.allAddresses.firstWhere(
|
||||
(addressRecord) => addressRecord.address == utxo.address);
|
||||
if (!(tx.inputAddresses?.contains(utxo.address) ?? false))
|
||||
addressRecord.txCount++;
|
||||
addressRecord.balance += utxo.value.toInt();
|
||||
addressRecord.setAsUsed();
|
||||
}
|
||||
transactionHistory.addOne(tx);
|
||||
if (initDone) {
|
||||
await updateUnspent();
|
||||
await updateBalance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> checkMwebUtxosSpent() async {
|
||||
while ((await Future.wait(transactionHistory.transactions.values
|
||||
.where((tx) => tx.direction == TransactionDirection.outgoing && tx.isPending)
|
||||
.map(checkPendingTransaction))).any((x) => x));
|
||||
final outputIds = mwebUtxos.values
|
||||
.where((utxo) => utxo.height > 0)
|
||||
.map((utxo) => utxo.outputId).toList();
|
||||
final stub = await CwMweb.stub();
|
||||
final resp = await stub.spent(SpentRequest(outputId: outputIds));
|
||||
final spent = resp.outputId;
|
||||
if (spent.isEmpty) return;
|
||||
final status = await stub.status(StatusRequest());
|
||||
final height = await electrumClient.getCurrentBlockChainTip();
|
||||
if (height == null || status.blockHeaderHeight != height) return;
|
||||
if (status.mwebUtxosHeight != height) return;
|
||||
int amount = 0;
|
||||
Set<String> inputAddresses = {};
|
||||
var output = AccumulatorSink<Digest>();
|
||||
var input = sha256.startChunkedConversion(output);
|
||||
for (final outputId in spent) {
|
||||
final utxo = mwebUtxos[outputId];
|
||||
if (utxo == null) continue;
|
||||
final addressRecord = walletAddresses.allAddresses.firstWhere(
|
||||
(addressRecord) => addressRecord.address == utxo.address);
|
||||
if (!inputAddresses.contains(utxo.address))
|
||||
addressRecord.txCount++;
|
||||
addressRecord.balance -= utxo.value.toInt();
|
||||
amount += utxo.value.toInt();
|
||||
inputAddresses.add(utxo.address);
|
||||
mwebUtxos.remove(outputId);
|
||||
input.add(hex.decode(outputId));
|
||||
}
|
||||
if (inputAddresses.isEmpty) return;
|
||||
input.close();
|
||||
var digest = output.events.single;
|
||||
final tx = ElectrumTransactionInfo(WalletType.litecoin,
|
||||
id: digest.toString(), height: height,
|
||||
amount: amount, fee: 0,
|
||||
direction: TransactionDirection.outgoing,
|
||||
isPending: false,
|
||||
date: DateTime.fromMillisecondsSinceEpoch(status.blockTime * 1000),
|
||||
confirmations: 1,
|
||||
inputAddresses: inputAddresses.toList(),
|
||||
outputAddresses: []);
|
||||
transactionHistory.addOne(tx);
|
||||
await transactionHistory.save();
|
||||
}
|
||||
|
||||
Future<bool> checkPendingTransaction(ElectrumTransactionInfo tx) async {
|
||||
if (!tx.isPending) return false;
|
||||
final outputId = <String>[], target = <String>{};
|
||||
final isHash = RegExp(r'^[a-f0-9]{64}$').hasMatch;
|
||||
final spendingOutputIds = tx.inputAddresses?.where(isHash) ?? [];
|
||||
final payingToOutputIds = tx.outputAddresses?.where(isHash) ?? [];
|
||||
outputId.addAll(spendingOutputIds);
|
||||
outputId.addAll(payingToOutputIds);
|
||||
target.addAll(spendingOutputIds);
|
||||
for (final outputId in payingToOutputIds) {
|
||||
final spendingTx = transactionHistory.transactions.values.firstWhereOrNull(
|
||||
(tx) => tx.inputAddresses?.contains(outputId) ?? false);
|
||||
if (spendingTx != null && !spendingTx.isPending)
|
||||
target.add(outputId);
|
||||
}
|
||||
if (outputId.isEmpty) return false;
|
||||
final stub = await CwMweb.stub();
|
||||
final resp = await stub.spent(SpentRequest(outputId: outputId));
|
||||
if (!setEquals(resp.outputId.toSet(), target)) return false;
|
||||
final status = await stub.status(StatusRequest());
|
||||
if (!tx.isPending) return false;
|
||||
tx.height = status.mwebUtxosHeight;
|
||||
tx.confirmations = 1;
|
||||
tx.isPending = false;
|
||||
await transactionHistory.save();
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateUnspentCoins() async {
|
||||
await super.updateUnspentCoins();
|
||||
await checkMwebUtxosSpent();
|
||||
final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
|
||||
mwebUtxos.forEach((outputId, utxo) {
|
||||
final addressRecord = walletAddresses.allAddresses.firstWhere(
|
||||
(addressRecord) => addressRecord.address == utxo.address);
|
||||
final unspent = BitcoinUnspent(addressRecord, outputId,
|
||||
utxo.value.toInt(), mwebAddrs.indexOf(utxo.address));
|
||||
if (unspent.vout == 0) unspent.isChange = true;
|
||||
unspentCoins.add(unspent);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ElectrumBalance> fetchBalances() async {
|
||||
final balance = await super.fetchBalances();
|
||||
var confirmed = balance.confirmed;
|
||||
var unconfirmed = balance.unconfirmed;
|
||||
mwebUtxos.values.forEach((utxo) {
|
||||
if (utxo.height > 0)
|
||||
confirmed += utxo.value.toInt();
|
||||
else
|
||||
unconfirmed += utxo.value.toInt();
|
||||
});
|
||||
return ElectrumBalance(confirmed: confirmed,
|
||||
unconfirmed: unconfirmed, frozen: balance.frozen);
|
||||
}
|
||||
|
||||
@override
|
||||
int feeRate(TransactionPriority priority) {
|
||||
if (priority is LitecoinTransactionPriority) {
|
||||
|
@ -134,4 +358,93 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> calcFee({
|
||||
required List<UtxoWithAddress> utxos,
|
||||
required List<BitcoinBaseOutput> outputs,
|
||||
required BasedUtxoNetwork network,
|
||||
String? memo,
|
||||
required int feeRate}) async {
|
||||
|
||||
final spendsMweb = utxos.any((utxo) => utxo.utxo.scriptType == SegwitAddresType.mweb);
|
||||
final paysToMweb = outputs.any((output) =>
|
||||
output.toOutput.scriptPubKey.getAddressType() == SegwitAddresType.mweb);
|
||||
if (!spendsMweb && !paysToMweb) {
|
||||
return await super.calcFee(utxos: utxos, outputs: outputs,
|
||||
network: network, memo: memo, feeRate: feeRate);
|
||||
}
|
||||
if (outputs.length == 1 && outputs[0].toOutput.amount == BigInt.zero) {
|
||||
outputs = [BitcoinScriptOutput(
|
||||
script: outputs[0].toOutput.scriptPubKey,
|
||||
value: utxos.sumOfUtxosValue())];
|
||||
}
|
||||
final preOutputSum = outputs.fold<BigInt>(BigInt.zero,
|
||||
(acc, output) => acc + output.toOutput.amount);
|
||||
final fee = utxos.sumOfUtxosValue() - preOutputSum;
|
||||
final txb = BitcoinTransactionBuilder(utxos: utxos,
|
||||
outputs: outputs, fee: fee, network: network);
|
||||
final stub = await CwMweb.stub();
|
||||
final resp = await stub.create(CreateRequest(
|
||||
rawTx: txb.buildTransaction((a, b, c, d) => '').toBytes(),
|
||||
scanSecret: hex.decode(mwebHd.derive(0x80000000).privKey!),
|
||||
spendSecret: hex.decode(mwebHd.derive(0x80000001).privKey!),
|
||||
feeRatePerKb: Int64(feeRate * 1000),
|
||||
dryRun: true));
|
||||
final tx = BtcTransaction.fromRaw(hex.encode(resp.rawTx));
|
||||
final posUtxos = utxos.where((utxo) => tx.inputs.any((input) =>
|
||||
input.txId == utxo.utxo.txHash && input.txIndex == utxo.utxo.vout)).toList();
|
||||
final posOutputSum = tx.outputs.fold<int>(0, (acc, output) => acc + output.amount.toInt());
|
||||
final mwebInputSum = utxos.sumOfUtxosValue() - posUtxos.sumOfUtxosValue();
|
||||
final expectedPegin = max(0, (preOutputSum - mwebInputSum).toInt());
|
||||
var feeIncrease = posOutputSum - expectedPegin;
|
||||
if (expectedPegin > 0 && fee == BigInt.zero) {
|
||||
feeIncrease += await super.calcFee(utxos: posUtxos, outputs: tx.outputs.map((output) =>
|
||||
BitcoinScriptOutput(script: output.scriptPubKey, value: output.amount)).toList(),
|
||||
network: network, memo: memo, feeRate: feeRate) + feeRate * 41;
|
||||
}
|
||||
return fee.toInt() + feeIncrease;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||
final tx = await super.createTransaction(credentials) as PendingBitcoinTransaction;
|
||||
final stub = await CwMweb.stub();
|
||||
final resp = await stub.create(CreateRequest(
|
||||
rawTx: hex.decode(tx.hex),
|
||||
scanSecret: hex.decode(mwebHd.derive(0x80000000).privKey!),
|
||||
spendSecret: hex.decode(mwebHd.derive(0x80000001).privKey!),
|
||||
feeRatePerKb: Int64.parseInt(tx.feeRate) * 1000));
|
||||
final tx2 = BtcTransaction.fromRaw(hex.encode(resp.rawTx));
|
||||
tx.hexOverride = tx2.copyWith(witnesses: tx2.inputs.asMap().entries.map((e) {
|
||||
final utxo = unspentCoins.firstWhere((utxo) =>
|
||||
utxo.hash == e.value.txId && utxo.vout == e.value.txIndex);
|
||||
final key = generateECPrivate(hd: utxo.bitcoinAddressRecord.isHidden ?
|
||||
walletAddresses.sideHd : walletAddresses.mainHd,
|
||||
index: utxo.bitcoinAddressRecord.index, network: network);
|
||||
final digest = tx2.getTransactionSegwitDigit(txInIndex: e.key,
|
||||
script: key.getPublic().toP2pkhAddress().toScriptPubKey(),
|
||||
amount: BigInt.from(utxo.value));
|
||||
return TxWitnessInput(stack: [key.signInput(digest), key.getPublic().toHex()]);
|
||||
}).toList()).toHex();
|
||||
tx.outputs = resp.outputId;
|
||||
return tx..addListener((transaction) async {
|
||||
final addresses = <String>{};
|
||||
transaction.inputAddresses?.forEach((id) {
|
||||
final utxo = mwebUtxos.remove(id);
|
||||
if (utxo == null) return;
|
||||
final addressRecord = walletAddresses.allAddresses.firstWhere(
|
||||
(addressRecord) => addressRecord.address == utxo.address);
|
||||
if (!addresses.contains(utxo.address)) {
|
||||
addressRecord.txCount++;
|
||||
addresses.add(utxo.address);
|
||||
}
|
||||
addressRecord.balance -= utxo.value.toInt();
|
||||
});
|
||||
transaction.inputAddresses?.addAll(addresses);
|
||||
transactionHistory.addOne(transaction);
|
||||
await updateUnspent();
|
||||
await updateBalance();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import 'package:convert/convert.dart';
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart';
|
||||
import 'package:cw_bitcoin/utils.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_mweb/cw_mweb.dart';
|
||||
import 'package:cw_mweb/mwebd.pb.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'litecoin_wallet_addresses.g.dart';
|
||||
|
@ -14,6 +17,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
WalletInfo walletInfo, {
|
||||
required super.mainHd,
|
||||
required super.sideHd,
|
||||
required this.mwebHd,
|
||||
required super.network,
|
||||
required super.electrumClient,
|
||||
super.initialAddresses,
|
||||
|
@ -21,8 +25,48 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
super.initialChangeAddressIndex,
|
||||
}) : super(walletInfo);
|
||||
|
||||
final HDWallet mwebHd;
|
||||
List<String> mwebAddrs = [];
|
||||
|
||||
Future<void> topUpMweb(int index) async {
|
||||
while (mwebAddrs.length - index < 1000) {
|
||||
final length = mwebAddrs.length;
|
||||
final scanSecret = mwebHd.derive(0x80000000).privKey!;
|
||||
final spendPubkey = mwebHd.derive(0x80000001).pubKey!;
|
||||
final stub = await CwMweb.stub();
|
||||
final resp = await stub.addresses(AddressRequest(
|
||||
fromIndex: length,
|
||||
toIndex: index + 1000,
|
||||
scanSecret: hex.decode(scanSecret),
|
||||
spendPubkey: hex.decode(spendPubkey),
|
||||
));
|
||||
if (mwebAddrs.length == length) {
|
||||
mwebAddrs.addAll(resp.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String getAddress(
|
||||
{required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) =>
|
||||
generateP2WPKHAddress(hd: hd, index: index, network: network);
|
||||
String getAddress({required int index, required HDWallet hd, BitcoinAddressType? addressType}) {
|
||||
if (addressType == SegwitAddresType.mweb) {
|
||||
topUpMweb(index);
|
||||
return hd == sideHd ? mwebAddrs[0] : mwebAddrs[index+1];
|
||||
}
|
||||
return generateP2WPKHAddress(hd: hd, index: index, network: network);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> getAddressAsync({required int index, required HDWallet hd, BitcoinAddressType? addressType}) async {
|
||||
if (addressType == SegwitAddresType.mweb) {
|
||||
await topUpMweb(index);
|
||||
}
|
||||
return getAddress(index: index, hd: hd, addressType: addressType);
|
||||
}
|
||||
|
||||
@action
|
||||
@override
|
||||
Future<String> getChangeAddress() async {
|
||||
await topUpMweb(0);
|
||||
return mwebAddrs[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import 'package:grpc/grpc.dart';
|
||||
import 'package:cw_bitcoin/exceptions.dart';
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||
import 'package:cw_core/pending_transaction.dart';
|
||||
import 'package:cw_bitcoin/electrum.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_amount_format.dart';
|
||||
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
||||
import 'package:cw_core/transaction_direction.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_mweb/cw_mweb.dart';
|
||||
import 'package:cw_mweb/mwebd.pb.dart';
|
||||
|
||||
class PendingBitcoinTransaction with PendingTransaction {
|
||||
PendingBitcoinTransaction(
|
||||
|
@ -31,12 +35,15 @@ class PendingBitcoinTransaction with PendingTransaction {
|
|||
final bool hasChange;
|
||||
final bool isSendAll;
|
||||
final bool hasTaprootInputs;
|
||||
String? idOverride;
|
||||
String? hexOverride;
|
||||
List<String>? outputs;
|
||||
|
||||
@override
|
||||
String get id => _tx.txId();
|
||||
String get id => idOverride ?? _tx.txId();
|
||||
|
||||
@override
|
||||
String get hex => _tx.serialize();
|
||||
String get hex => hexOverride ?? _tx.serialize();
|
||||
|
||||
@override
|
||||
String get amountFormatted => bitcoinAmountToString(amount: amount);
|
||||
|
@ -49,8 +56,7 @@ class PendingBitcoinTransaction with PendingTransaction {
|
|||
|
||||
final List<void Function(ElectrumTransactionInfo transaction)> _listeners;
|
||||
|
||||
@override
|
||||
Future<void> commit() async {
|
||||
Future<void> _commit() async {
|
||||
int? callId;
|
||||
|
||||
final result = await electrumClient.broadcastTransaction(
|
||||
|
@ -78,6 +84,19 @@ class PendingBitcoinTransaction with PendingTransaction {
|
|||
|
||||
throw BitcoinTransactionCommitFailed();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> commit() async {
|
||||
if (network is LitecoinNetwork) try {
|
||||
final stub = await CwMweb.stub();
|
||||
final resp = await stub.broadcast(BroadcastRequest(rawTx: BytesUtils.fromHexString(hex)));
|
||||
idOverride = resp.txid;
|
||||
} on GrpcError catch (e) {
|
||||
throw BitcoinTransactionCommitFailed(errorMessage: e.message);
|
||||
} else {
|
||||
await _commit();
|
||||
}
|
||||
|
||||
_listeners.forEach((listener) => listener(transactionInfo()));
|
||||
}
|
||||
|
@ -93,5 +112,7 @@ class PendingBitcoinTransaction with PendingTransaction {
|
|||
date: DateTime.now(),
|
||||
isPending: true,
|
||||
confirmations: 0,
|
||||
inputAddresses: _tx.inputs.map((input) => input.txId).toList(),
|
||||
outputAddresses: outputs,
|
||||
fee: fee);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.7.0"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.10"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -78,11 +86,9 @@ packages:
|
|||
bitcoin_base:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: cake-update-v2
|
||||
resolved-ref: "01d844a5f5a520a31df5254e34169af4664aa769"
|
||||
url: "https://github.com/cake-tech/bitcoin_base.git"
|
||||
source: git
|
||||
path: "../../bitcoin_base"
|
||||
relative: true
|
||||
source: path
|
||||
version: "4.2.0"
|
||||
bitcoin_flutter:
|
||||
dependency: "direct main"
|
||||
|
@ -252,6 +258,13 @@ packages:
|
|||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
cw_mweb:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../cw_mweb"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -358,6 +371,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
googleapis_auth:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: googleapis_auth
|
||||
sha256: af7c3a3edf9d0de2e1e0a77e994fae0a581c525fa7012af4fa0d4a52ed9484da
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -366,6 +387,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
grpc:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: grpc
|
||||
sha256: e93ee3bce45c134bf44e9728119102358c7cd69de7832d9a874e2e74eb8cab40
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.4"
|
||||
hex:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -398,6 +427,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
http2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http2
|
||||
sha256: "9ced024a160b77aba8fb8674e38f70875e321d319e6f303ec18e87bd5a4b0c1d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -659,10 +696,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: protobuf
|
||||
sha256: "01dd9bd0fa02548bf2ceee13545d4a0ec6046459d847b6b061d8a27237108a08"
|
||||
sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "3.1.0"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -31,14 +31,15 @@ dependencies:
|
|||
unorm_dart: ^0.2.0
|
||||
cryptography: ^2.0.5
|
||||
bitcoin_base:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bitcoin_base.git
|
||||
ref: cake-update-v2
|
||||
path: ../../bitcoin_base
|
||||
blockchain_utils: ^2.1.1
|
||||
ledger_flutter: ^1.0.1
|
||||
ledger_bitcoin:
|
||||
git:
|
||||
url: https://github.com/cake-tech/ledger-bitcoin.git
|
||||
cw_mweb:
|
||||
path: ../cw_mweb
|
||||
grpc: ^3.2.4
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -30,9 +30,7 @@ dependencies:
|
|||
url: https://github.com/cake-tech/bitbox-flutter.git
|
||||
ref: Add-Support-For-OP-Return-data
|
||||
bitcoin_base:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bitcoin_base.git
|
||||
ref: cake-update-v2
|
||||
path: ../../bitcoin_base
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ android {
|
|||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ android {
|
|||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ class CwMoneroPlugin: MethodCallHandler {
|
|||
val main = Handler(Looper.getMainLooper());
|
||||
|
||||
init {
|
||||
System.loadLibrary("cw_monero")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
|
30
cw_mweb/.gitignore
vendored
Normal file
30
cw_mweb/.gitignore
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.packages
|
||||
build/
|
36
cw_mweb/.metadata
Normal file
36
cw_mweb/.metadata
Normal file
|
@ -0,0 +1,36 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
channel: stable
|
||||
|
||||
project_type: plugin
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
- platform: android
|
||||
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
- platform: ios
|
||||
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
- platform: macos
|
||||
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
3
cw_mweb/CHANGELOG.md
Normal file
3
cw_mweb/CHANGELOG.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
1
cw_mweb/LICENSE
Normal file
1
cw_mweb/LICENSE
Normal file
|
@ -0,0 +1 @@
|
|||
TODO: Add your license here.
|
15
cw_mweb/README.md
Normal file
15
cw_mweb/README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# cw_mweb
|
||||
|
||||
A new Flutter plugin project.
|
||||
|
||||
## Getting Started
|
||||
|
||||
This project is a starting point for a Flutter
|
||||
[plug-in package](https://flutter.dev/developing-packages/),
|
||||
a specialized package that includes platform-specific implementation code for
|
||||
Android and/or iOS.
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
|
4
cw_mweb/analysis_options.yaml
Normal file
4
cw_mweb/analysis_options.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
10
cw_mweb/android/.gitignore
vendored
Normal file
10
cw_mweb/android/.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
/libs
|
||||
.cxx
|
76
cw_mweb/android/build.gradle
Normal file
76
cw_mweb/android/build.gradle
Normal file
|
@ -0,0 +1,76 @@
|
|||
group 'com.cakewallet.mweb'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.7.10'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.allprojects {
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs project(':cw_mweb').file('libs')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
test.java.srcDirs += 'src/test/kotlin'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-test'
|
||||
testImplementation 'org.mockito:mockito-core:5.0.0'
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests.all {
|
||||
useJUnitPlatform()
|
||||
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed", "standardOut", "standardError"
|
||||
outputs.upToDateWhen {false}
|
||||
showStandardStreams = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation (name: 'mwebd', ext: 'aar')
|
||||
}
|
1
cw_mweb/android/settings.gradle
Normal file
1
cw_mweb/android/settings.gradle
Normal file
|
@ -0,0 +1 @@
|
|||
rootProject.name = 'cw_mweb'
|
3
cw_mweb/android/src/main/AndroidManifest.xml
Normal file
3
cw_mweb/android/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.cakewallet.mweb">
|
||||
</manifest>
|
|
@ -0,0 +1,44 @@
|
|||
package com.cakewallet.mweb
|
||||
|
||||
import androidx.annotation.NonNull
|
||||
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||
import io.flutter.plugin.common.MethodChannel.Result
|
||||
|
||||
import mwebd.Mwebd
|
||||
import mwebd.Server
|
||||
|
||||
/** CwMwebPlugin */
|
||||
class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
|
||||
/// The MethodChannel that will the communication between Flutter and native Android
|
||||
///
|
||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
||||
/// when the Flutter Engine is detached from the Activity
|
||||
private lateinit var channel : MethodChannel
|
||||
private var server: Server? = null
|
||||
private var port: Long? = null
|
||||
|
||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cw_mweb")
|
||||
channel.setMethodCallHandler(this)
|
||||
}
|
||||
|
||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||
if (call.method == "start") {
|
||||
val dataDir = call.argument("dataDir") ?: ""
|
||||
server = server ?: Mwebd.newServer("", dataDir, "")
|
||||
port = port ?: server?.start(0)
|
||||
result.success(port)
|
||||
} else {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel.setMethodCallHandler(null)
|
||||
server?.stop()
|
||||
}
|
||||
}
|
38
cw_mweb/ios/.gitignore
vendored
Normal file
38
cw_mweb/ios/.gitignore
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
.idea/
|
||||
.vagrant/
|
||||
.sconsign.dblite
|
||||
.svn/
|
||||
|
||||
.DS_Store
|
||||
*.swp
|
||||
profile
|
||||
|
||||
DerivedData/
|
||||
build/
|
||||
GeneratedPluginRegistrant.h
|
||||
GeneratedPluginRegistrant.m
|
||||
|
||||
.generated/
|
||||
|
||||
*.pbxuser
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.perspectivev3
|
||||
|
||||
!default.pbxuser
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.perspectivev3
|
||||
|
||||
xcuserdata
|
||||
|
||||
*.moved-aside
|
||||
|
||||
*.pyc
|
||||
*sync/
|
||||
Icon?
|
||||
.tags*
|
||||
|
||||
/Flutter/Generated.xcconfig
|
||||
/Flutter/ephemeral/
|
||||
/Flutter/flutter_export_environment.sh
|
0
cw_mweb/ios/Assets/.gitkeep
Normal file
0
cw_mweb/ios/Assets/.gitkeep
Normal file
19
cw_mweb/ios/Classes/CwMwebPlugin.swift
Normal file
19
cw_mweb/ios/Classes/CwMwebPlugin.swift
Normal file
|
@ -0,0 +1,19 @@
|
|||
import Flutter
|
||||
import UIKit
|
||||
|
||||
public class CwMwebPlugin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let channel = FlutterMethodChannel(name: "cw_mweb", binaryMessenger: registrar.messenger())
|
||||
let instance = CwMwebPlugin()
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
switch call.method {
|
||||
case "getPlatformVersion":
|
||||
result("iOS " + UIDevice.current.systemVersion)
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
23
cw_mweb/ios/cw_mweb.podspec
Normal file
23
cw_mweb/ios/cw_mweb.podspec
Normal file
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint cw_mweb.podspec` to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'cw_mweb'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'A new Flutter plugin project.'
|
||||
s.description = <<-DESC
|
||||
A new Flutter plugin project.
|
||||
DESC
|
||||
s.homepage = 'http://example.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Your Company' => 'email@example.com' }
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.dependency 'Flutter'
|
||||
s.platform = :ios, '11.0'
|
||||
|
||||
# Flutter.framework does not contain a i386 slice.
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
|
||||
s.swift_version = '5.0'
|
||||
end
|
14
cw_mweb/lib/cw_mweb.dart
Normal file
14
cw_mweb/lib/cw_mweb.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
import 'package:grpc/grpc.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'cw_mweb_platform_interface.dart';
|
||||
import 'mwebd.pbgrpc.dart';
|
||||
|
||||
class CwMweb {
|
||||
static Future<RpcClient> stub() async {
|
||||
final appDir = await getApplicationSupportDirectory();
|
||||
return RpcClient(ClientChannel('127.0.0.1',
|
||||
port: await CwMwebPlatform.instance.start(appDir.path) ?? 0,
|
||||
options: const ChannelOptions(
|
||||
credentials: ChannelCredentials.insecure())));
|
||||
}
|
||||
}
|
17
cw_mweb/lib/cw_mweb_method_channel.dart
Normal file
17
cw_mweb/lib/cw_mweb_method_channel.dart
Normal file
|
@ -0,0 +1,17 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'cw_mweb_platform_interface.dart';
|
||||
|
||||
/// An implementation of [CwMwebPlatform] that uses method channels.
|
||||
class MethodChannelCwMweb extends CwMwebPlatform {
|
||||
/// The method channel used to interact with the native platform.
|
||||
@visibleForTesting
|
||||
final methodChannel = const MethodChannel('cw_mweb');
|
||||
|
||||
@override
|
||||
Future<int?> start(String dataDir) async {
|
||||
final result = await methodChannel.invokeMethod<int>('start', {'dataDir': dataDir});
|
||||
return result;
|
||||
}
|
||||
}
|
29
cw_mweb/lib/cw_mweb_platform_interface.dart
Normal file
29
cw_mweb/lib/cw_mweb_platform_interface.dart
Normal file
|
@ -0,0 +1,29 @@
|
|||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
|
||||
import 'cw_mweb_method_channel.dart';
|
||||
|
||||
abstract class CwMwebPlatform extends PlatformInterface {
|
||||
/// Constructs a CwMwebPlatform.
|
||||
CwMwebPlatform() : super(token: _token);
|
||||
|
||||
static final Object _token = Object();
|
||||
|
||||
static CwMwebPlatform _instance = MethodChannelCwMweb();
|
||||
|
||||
/// The default instance of [CwMwebPlatform] to use.
|
||||
///
|
||||
/// Defaults to [MethodChannelCwMweb].
|
||||
static CwMwebPlatform get instance => _instance;
|
||||
|
||||
/// Platform-specific implementations should set this with their own
|
||||
/// platform-specific class that extends [CwMwebPlatform] when
|
||||
/// they register themselves.
|
||||
static set instance(CwMwebPlatform instance) {
|
||||
PlatformInterface.verifyToken(instance, _token);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
Future<int?> start(String dataDir) {
|
||||
throw UnimplementedError('start() has not been implemented.');
|
||||
}
|
||||
}
|
801
cw_mweb/lib/mwebd.pb.dart
Normal file
801
cw_mweb/lib/mwebd.pb.dart
Normal file
|
@ -0,0 +1,801 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: mwebd.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:core' as $core;
|
||||
|
||||
import 'package:fixnum/fixnum.dart' as $fixnum;
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
class StatusRequest extends $pb.GeneratedMessage {
|
||||
factory StatusRequest() => create();
|
||||
StatusRequest._() : super();
|
||||
factory StatusRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory StatusRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'StatusRequest', createEmptyInstance: create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
StatusRequest clone() => StatusRequest()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
StatusRequest copyWith(void Function(StatusRequest) updates) => super.copyWith((message) => updates(message as StatusRequest)) as StatusRequest;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static StatusRequest create() => StatusRequest._();
|
||||
StatusRequest createEmptyInstance() => create();
|
||||
static $pb.PbList<StatusRequest> createRepeated() => $pb.PbList<StatusRequest>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static StatusRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StatusRequest>(create);
|
||||
static StatusRequest? _defaultInstance;
|
||||
}
|
||||
|
||||
class StatusResponse extends $pb.GeneratedMessage {
|
||||
factory StatusResponse({
|
||||
$core.int? blockHeaderHeight,
|
||||
$core.int? mwebHeaderHeight,
|
||||
$core.int? mwebUtxosHeight,
|
||||
$core.int? blockTime,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (blockHeaderHeight != null) {
|
||||
$result.blockHeaderHeight = blockHeaderHeight;
|
||||
}
|
||||
if (mwebHeaderHeight != null) {
|
||||
$result.mwebHeaderHeight = mwebHeaderHeight;
|
||||
}
|
||||
if (mwebUtxosHeight != null) {
|
||||
$result.mwebUtxosHeight = mwebUtxosHeight;
|
||||
}
|
||||
if (blockTime != null) {
|
||||
$result.blockTime = blockTime;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
StatusResponse._() : super();
|
||||
factory StatusResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory StatusResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'StatusResponse', createEmptyInstance: create)
|
||||
..a<$core.int>(1, _omitFieldNames ? '' : 'blockHeaderHeight', $pb.PbFieldType.O3)
|
||||
..a<$core.int>(2, _omitFieldNames ? '' : 'mwebHeaderHeight', $pb.PbFieldType.O3)
|
||||
..a<$core.int>(3, _omitFieldNames ? '' : 'mwebUtxosHeight', $pb.PbFieldType.O3)
|
||||
..a<$core.int>(4, _omitFieldNames ? '' : 'blockTime', $pb.PbFieldType.OU3)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
StatusResponse clone() => StatusResponse()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
StatusResponse copyWith(void Function(StatusResponse) updates) => super.copyWith((message) => updates(message as StatusResponse)) as StatusResponse;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static StatusResponse create() => StatusResponse._();
|
||||
StatusResponse createEmptyInstance() => create();
|
||||
static $pb.PbList<StatusResponse> createRepeated() => $pb.PbList<StatusResponse>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static StatusResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StatusResponse>(create);
|
||||
static StatusResponse? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.int get blockHeaderHeight => $_getIZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set blockHeaderHeight($core.int v) { $_setSignedInt32(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasBlockHeaderHeight() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearBlockHeaderHeight() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.int get mwebHeaderHeight => $_getIZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set mwebHeaderHeight($core.int v) { $_setSignedInt32(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasMwebHeaderHeight() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearMwebHeaderHeight() => clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.int get mwebUtxosHeight => $_getIZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set mwebUtxosHeight($core.int v) { $_setSignedInt32(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasMwebUtxosHeight() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearMwebUtxosHeight() => clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.int get blockTime => $_getIZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set blockTime($core.int v) { $_setUnsignedInt32(3, v); }
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasBlockTime() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearBlockTime() => clearField(4);
|
||||
}
|
||||
|
||||
class UtxosRequest extends $pb.GeneratedMessage {
|
||||
factory UtxosRequest({
|
||||
$core.int? fromHeight,
|
||||
$core.List<$core.int>? scanSecret,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (fromHeight != null) {
|
||||
$result.fromHeight = fromHeight;
|
||||
}
|
||||
if (scanSecret != null) {
|
||||
$result.scanSecret = scanSecret;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
UtxosRequest._() : super();
|
||||
factory UtxosRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory UtxosRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'UtxosRequest', createEmptyInstance: create)
|
||||
..a<$core.int>(1, _omitFieldNames ? '' : 'fromHeight', $pb.PbFieldType.O3)
|
||||
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'scanSecret', $pb.PbFieldType.OY)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
UtxosRequest clone() => UtxosRequest()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
UtxosRequest copyWith(void Function(UtxosRequest) updates) => super.copyWith((message) => updates(message as UtxosRequest)) as UtxosRequest;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static UtxosRequest create() => UtxosRequest._();
|
||||
UtxosRequest createEmptyInstance() => create();
|
||||
static $pb.PbList<UtxosRequest> createRepeated() => $pb.PbList<UtxosRequest>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static UtxosRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UtxosRequest>(create);
|
||||
static UtxosRequest? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.int get fromHeight => $_getIZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set fromHeight($core.int v) { $_setSignedInt32(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasFromHeight() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearFromHeight() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.List<$core.int> get scanSecret => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set scanSecret($core.List<$core.int> v) { $_setBytes(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasScanSecret() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearScanSecret() => clearField(2);
|
||||
}
|
||||
|
||||
class Utxo extends $pb.GeneratedMessage {
|
||||
factory Utxo({
|
||||
$core.int? height,
|
||||
$fixnum.Int64? value,
|
||||
$core.String? address,
|
||||
$core.String? outputId,
|
||||
$core.int? blockTime,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (height != null) {
|
||||
$result.height = height;
|
||||
}
|
||||
if (value != null) {
|
||||
$result.value = value;
|
||||
}
|
||||
if (address != null) {
|
||||
$result.address = address;
|
||||
}
|
||||
if (outputId != null) {
|
||||
$result.outputId = outputId;
|
||||
}
|
||||
if (blockTime != null) {
|
||||
$result.blockTime = blockTime;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
Utxo._() : super();
|
||||
factory Utxo.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory Utxo.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Utxo', createEmptyInstance: create)
|
||||
..a<$core.int>(1, _omitFieldNames ? '' : 'height', $pb.PbFieldType.O3)
|
||||
..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO)
|
||||
..aOS(3, _omitFieldNames ? '' : 'address')
|
||||
..aOS(4, _omitFieldNames ? '' : 'outputId')
|
||||
..a<$core.int>(5, _omitFieldNames ? '' : 'blockTime', $pb.PbFieldType.OU3)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
Utxo clone() => Utxo()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
Utxo copyWith(void Function(Utxo) updates) => super.copyWith((message) => updates(message as Utxo)) as Utxo;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Utxo create() => Utxo._();
|
||||
Utxo createEmptyInstance() => create();
|
||||
static $pb.PbList<Utxo> createRepeated() => $pb.PbList<Utxo>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Utxo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Utxo>(create);
|
||||
static Utxo? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.int get height => $_getIZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set height($core.int v) { $_setSignedInt32(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasHeight() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearHeight() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$fixnum.Int64 get value => $_getI64(1);
|
||||
@$pb.TagNumber(2)
|
||||
set value($fixnum.Int64 v) { $_setInt64(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasValue() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearValue() => clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.String get address => $_getSZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set address($core.String v) { $_setString(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasAddress() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearAddress() => clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.String get outputId => $_getSZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set outputId($core.String v) { $_setString(3, v); }
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasOutputId() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearOutputId() => clearField(4);
|
||||
|
||||
@$pb.TagNumber(5)
|
||||
$core.int get blockTime => $_getIZ(4);
|
||||
@$pb.TagNumber(5)
|
||||
set blockTime($core.int v) { $_setUnsignedInt32(4, v); }
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool hasBlockTime() => $_has(4);
|
||||
@$pb.TagNumber(5)
|
||||
void clearBlockTime() => clearField(5);
|
||||
}
|
||||
|
||||
class AddressRequest extends $pb.GeneratedMessage {
|
||||
factory AddressRequest({
|
||||
$core.int? fromIndex,
|
||||
$core.int? toIndex,
|
||||
$core.List<$core.int>? scanSecret,
|
||||
$core.List<$core.int>? spendPubkey,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (fromIndex != null) {
|
||||
$result.fromIndex = fromIndex;
|
||||
}
|
||||
if (toIndex != null) {
|
||||
$result.toIndex = toIndex;
|
||||
}
|
||||
if (scanSecret != null) {
|
||||
$result.scanSecret = scanSecret;
|
||||
}
|
||||
if (spendPubkey != null) {
|
||||
$result.spendPubkey = spendPubkey;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
AddressRequest._() : super();
|
||||
factory AddressRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory AddressRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'AddressRequest', createEmptyInstance: create)
|
||||
..a<$core.int>(1, _omitFieldNames ? '' : 'fromIndex', $pb.PbFieldType.OU3)
|
||||
..a<$core.int>(2, _omitFieldNames ? '' : 'toIndex', $pb.PbFieldType.OU3)
|
||||
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'scanSecret', $pb.PbFieldType.OY)
|
||||
..a<$core.List<$core.int>>(4, _omitFieldNames ? '' : 'spendPubkey', $pb.PbFieldType.OY)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
AddressRequest clone() => AddressRequest()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
AddressRequest copyWith(void Function(AddressRequest) updates) => super.copyWith((message) => updates(message as AddressRequest)) as AddressRequest;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static AddressRequest create() => AddressRequest._();
|
||||
AddressRequest createEmptyInstance() => create();
|
||||
static $pb.PbList<AddressRequest> createRepeated() => $pb.PbList<AddressRequest>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static AddressRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AddressRequest>(create);
|
||||
static AddressRequest? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.int get fromIndex => $_getIZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set fromIndex($core.int v) { $_setUnsignedInt32(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasFromIndex() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearFromIndex() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.int get toIndex => $_getIZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set toIndex($core.int v) { $_setUnsignedInt32(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasToIndex() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearToIndex() => clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.List<$core.int> get scanSecret => $_getN(2);
|
||||
@$pb.TagNumber(3)
|
||||
set scanSecret($core.List<$core.int> v) { $_setBytes(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasScanSecret() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearScanSecret() => clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.List<$core.int> get spendPubkey => $_getN(3);
|
||||
@$pb.TagNumber(4)
|
||||
set spendPubkey($core.List<$core.int> v) { $_setBytes(3, v); }
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasSpendPubkey() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearSpendPubkey() => clearField(4);
|
||||
}
|
||||
|
||||
class AddressResponse extends $pb.GeneratedMessage {
|
||||
factory AddressResponse({
|
||||
$core.Iterable<$core.String>? address,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (address != null) {
|
||||
$result.address.addAll(address);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
AddressResponse._() : super();
|
||||
factory AddressResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory AddressResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'AddressResponse', createEmptyInstance: create)
|
||||
..pPS(1, _omitFieldNames ? '' : 'address')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
AddressResponse clone() => AddressResponse()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
AddressResponse copyWith(void Function(AddressResponse) updates) => super.copyWith((message) => updates(message as AddressResponse)) as AddressResponse;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static AddressResponse create() => AddressResponse._();
|
||||
AddressResponse createEmptyInstance() => create();
|
||||
static $pb.PbList<AddressResponse> createRepeated() => $pb.PbList<AddressResponse>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static AddressResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AddressResponse>(create);
|
||||
static AddressResponse? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.String> get address => $_getList(0);
|
||||
}
|
||||
|
||||
class SpentRequest extends $pb.GeneratedMessage {
|
||||
factory SpentRequest({
|
||||
$core.Iterable<$core.String>? outputId,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (outputId != null) {
|
||||
$result.outputId.addAll(outputId);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
SpentRequest._() : super();
|
||||
factory SpentRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory SpentRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'SpentRequest', createEmptyInstance: create)
|
||||
..pPS(1, _omitFieldNames ? '' : 'outputId')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
SpentRequest clone() => SpentRequest()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
SpentRequest copyWith(void Function(SpentRequest) updates) => super.copyWith((message) => updates(message as SpentRequest)) as SpentRequest;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static SpentRequest create() => SpentRequest._();
|
||||
SpentRequest createEmptyInstance() => create();
|
||||
static $pb.PbList<SpentRequest> createRepeated() => $pb.PbList<SpentRequest>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static SpentRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SpentRequest>(create);
|
||||
static SpentRequest? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.String> get outputId => $_getList(0);
|
||||
}
|
||||
|
||||
class SpentResponse extends $pb.GeneratedMessage {
|
||||
factory SpentResponse({
|
||||
$core.Iterable<$core.String>? outputId,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (outputId != null) {
|
||||
$result.outputId.addAll(outputId);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
SpentResponse._() : super();
|
||||
factory SpentResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory SpentResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'SpentResponse', createEmptyInstance: create)
|
||||
..pPS(1, _omitFieldNames ? '' : 'outputId')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
SpentResponse clone() => SpentResponse()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
SpentResponse copyWith(void Function(SpentResponse) updates) => super.copyWith((message) => updates(message as SpentResponse)) as SpentResponse;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static SpentResponse create() => SpentResponse._();
|
||||
SpentResponse createEmptyInstance() => create();
|
||||
static $pb.PbList<SpentResponse> createRepeated() => $pb.PbList<SpentResponse>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static SpentResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SpentResponse>(create);
|
||||
static SpentResponse? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.String> get outputId => $_getList(0);
|
||||
}
|
||||
|
||||
class CreateRequest extends $pb.GeneratedMessage {
|
||||
factory CreateRequest({
|
||||
$core.List<$core.int>? rawTx,
|
||||
$core.List<$core.int>? scanSecret,
|
||||
$core.List<$core.int>? spendSecret,
|
||||
$fixnum.Int64? feeRatePerKb,
|
||||
$core.bool? dryRun,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (rawTx != null) {
|
||||
$result.rawTx = rawTx;
|
||||
}
|
||||
if (scanSecret != null) {
|
||||
$result.scanSecret = scanSecret;
|
||||
}
|
||||
if (spendSecret != null) {
|
||||
$result.spendSecret = spendSecret;
|
||||
}
|
||||
if (feeRatePerKb != null) {
|
||||
$result.feeRatePerKb = feeRatePerKb;
|
||||
}
|
||||
if (dryRun != null) {
|
||||
$result.dryRun = dryRun;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
CreateRequest._() : super();
|
||||
factory CreateRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory CreateRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CreateRequest', createEmptyInstance: create)
|
||||
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'rawTx', $pb.PbFieldType.OY)
|
||||
..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'scanSecret', $pb.PbFieldType.OY)
|
||||
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'spendSecret', $pb.PbFieldType.OY)
|
||||
..a<$fixnum.Int64>(4, _omitFieldNames ? '' : 'feeRatePerKb', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO)
|
||||
..aOB(5, _omitFieldNames ? '' : 'dryRun')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
CreateRequest clone() => CreateRequest()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
CreateRequest copyWith(void Function(CreateRequest) updates) => super.copyWith((message) => updates(message as CreateRequest)) as CreateRequest;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static CreateRequest create() => CreateRequest._();
|
||||
CreateRequest createEmptyInstance() => create();
|
||||
static $pb.PbList<CreateRequest> createRepeated() => $pb.PbList<CreateRequest>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static CreateRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CreateRequest>(create);
|
||||
static CreateRequest? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.int> get rawTx => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set rawTx($core.List<$core.int> v) { $_setBytes(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasRawTx() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearRawTx() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.List<$core.int> get scanSecret => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set scanSecret($core.List<$core.int> v) { $_setBytes(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasScanSecret() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearScanSecret() => clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.List<$core.int> get spendSecret => $_getN(2);
|
||||
@$pb.TagNumber(3)
|
||||
set spendSecret($core.List<$core.int> v) { $_setBytes(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasSpendSecret() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearSpendSecret() => clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$fixnum.Int64 get feeRatePerKb => $_getI64(3);
|
||||
@$pb.TagNumber(4)
|
||||
set feeRatePerKb($fixnum.Int64 v) { $_setInt64(3, v); }
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasFeeRatePerKb() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearFeeRatePerKb() => clearField(4);
|
||||
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool get dryRun => $_getBF(4);
|
||||
@$pb.TagNumber(5)
|
||||
set dryRun($core.bool v) { $_setBool(4, v); }
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool hasDryRun() => $_has(4);
|
||||
@$pb.TagNumber(5)
|
||||
void clearDryRun() => clearField(5);
|
||||
}
|
||||
|
||||
class CreateResponse extends $pb.GeneratedMessage {
|
||||
factory CreateResponse({
|
||||
$core.List<$core.int>? rawTx,
|
||||
$core.Iterable<$core.String>? outputId,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (rawTx != null) {
|
||||
$result.rawTx = rawTx;
|
||||
}
|
||||
if (outputId != null) {
|
||||
$result.outputId.addAll(outputId);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
CreateResponse._() : super();
|
||||
factory CreateResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory CreateResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CreateResponse', createEmptyInstance: create)
|
||||
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'rawTx', $pb.PbFieldType.OY)
|
||||
..pPS(2, _omitFieldNames ? '' : 'outputId')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
CreateResponse clone() => CreateResponse()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
CreateResponse copyWith(void Function(CreateResponse) updates) => super.copyWith((message) => updates(message as CreateResponse)) as CreateResponse;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static CreateResponse create() => CreateResponse._();
|
||||
CreateResponse createEmptyInstance() => create();
|
||||
static $pb.PbList<CreateResponse> createRepeated() => $pb.PbList<CreateResponse>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static CreateResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CreateResponse>(create);
|
||||
static CreateResponse? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.int> get rawTx => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set rawTx($core.List<$core.int> v) { $_setBytes(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasRawTx() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearRawTx() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.List<$core.String> get outputId => $_getList(1);
|
||||
}
|
||||
|
||||
class BroadcastRequest extends $pb.GeneratedMessage {
|
||||
factory BroadcastRequest({
|
||||
$core.List<$core.int>? rawTx,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (rawTx != null) {
|
||||
$result.rawTx = rawTx;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
BroadcastRequest._() : super();
|
||||
factory BroadcastRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory BroadcastRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BroadcastRequest', createEmptyInstance: create)
|
||||
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'rawTx', $pb.PbFieldType.OY)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
BroadcastRequest clone() => BroadcastRequest()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
BroadcastRequest copyWith(void Function(BroadcastRequest) updates) => super.copyWith((message) => updates(message as BroadcastRequest)) as BroadcastRequest;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static BroadcastRequest create() => BroadcastRequest._();
|
||||
BroadcastRequest createEmptyInstance() => create();
|
||||
static $pb.PbList<BroadcastRequest> createRepeated() => $pb.PbList<BroadcastRequest>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static BroadcastRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BroadcastRequest>(create);
|
||||
static BroadcastRequest? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.int> get rawTx => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set rawTx($core.List<$core.int> v) { $_setBytes(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasRawTx() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearRawTx() => clearField(1);
|
||||
}
|
||||
|
||||
class BroadcastResponse extends $pb.GeneratedMessage {
|
||||
factory BroadcastResponse({
|
||||
$core.String? txid,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (txid != null) {
|
||||
$result.txid = txid;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
BroadcastResponse._() : super();
|
||||
factory BroadcastResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory BroadcastResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'BroadcastResponse', createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'txid')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
BroadcastResponse clone() => BroadcastResponse()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
BroadcastResponse copyWith(void Function(BroadcastResponse) updates) => super.copyWith((message) => updates(message as BroadcastResponse)) as BroadcastResponse;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static BroadcastResponse create() => BroadcastResponse._();
|
||||
BroadcastResponse createEmptyInstance() => create();
|
||||
static $pb.PbList<BroadcastResponse> createRepeated() => $pb.PbList<BroadcastResponse>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static BroadcastResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BroadcastResponse>(create);
|
||||
static BroadcastResponse? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get txid => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set txid($core.String v) { $_setString(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasTxid() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearTxid() => clearField(1);
|
||||
}
|
||||
|
||||
|
||||
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
|
||||
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
|
159
cw_mweb/lib/mwebd.pbgrpc.dart
Normal file
159
cw_mweb/lib/mwebd.pbgrpc.dart
Normal file
|
@ -0,0 +1,159 @@
|
|||
//
|
||||
// Generated code. Do not modify.
|
||||
// source: mwebd.proto
|
||||
//
|
||||
// @dart = 2.12
|
||||
|
||||
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
|
||||
// ignore_for_file: constant_identifier_names, library_prefixes
|
||||
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
|
||||
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
|
||||
|
||||
import 'dart:async' as $async;
|
||||
import 'dart:core' as $core;
|
||||
|
||||
import 'package:grpc/service_api.dart' as $grpc;
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
import 'mwebd.pb.dart' as $0;
|
||||
|
||||
export 'mwebd.pb.dart';
|
||||
|
||||
@$pb.GrpcServiceName('Rpc')
|
||||
class RpcClient extends $grpc.Client {
|
||||
static final _$status = $grpc.ClientMethod<$0.StatusRequest, $0.StatusResponse>(
|
||||
'/Rpc/Status',
|
||||
($0.StatusRequest value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.StatusResponse.fromBuffer(value));
|
||||
static final _$utxos = $grpc.ClientMethod<$0.UtxosRequest, $0.Utxo>(
|
||||
'/Rpc/Utxos',
|
||||
($0.UtxosRequest value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.Utxo.fromBuffer(value));
|
||||
static final _$addresses = $grpc.ClientMethod<$0.AddressRequest, $0.AddressResponse>(
|
||||
'/Rpc/Addresses',
|
||||
($0.AddressRequest value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.AddressResponse.fromBuffer(value));
|
||||
static final _$spent = $grpc.ClientMethod<$0.SpentRequest, $0.SpentResponse>(
|
||||
'/Rpc/Spent',
|
||||
($0.SpentRequest value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.SpentResponse.fromBuffer(value));
|
||||
static final _$create = $grpc.ClientMethod<$0.CreateRequest, $0.CreateResponse>(
|
||||
'/Rpc/Create',
|
||||
($0.CreateRequest value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.CreateResponse.fromBuffer(value));
|
||||
static final _$broadcast = $grpc.ClientMethod<$0.BroadcastRequest, $0.BroadcastResponse>(
|
||||
'/Rpc/Broadcast',
|
||||
($0.BroadcastRequest value) => value.writeToBuffer(),
|
||||
($core.List<$core.int> value) => $0.BroadcastResponse.fromBuffer(value));
|
||||
|
||||
RpcClient($grpc.ClientChannel channel,
|
||||
{$grpc.CallOptions? options,
|
||||
$core.Iterable<$grpc.ClientInterceptor>? interceptors})
|
||||
: super(channel, options: options,
|
||||
interceptors: interceptors);
|
||||
|
||||
$grpc.ResponseFuture<$0.StatusResponse> status($0.StatusRequest request, {$grpc.CallOptions? options}) {
|
||||
return $createUnaryCall(_$status, request, options: options);
|
||||
}
|
||||
|
||||
$grpc.ResponseStream<$0.Utxo> utxos($0.UtxosRequest request, {$grpc.CallOptions? options}) {
|
||||
return $createStreamingCall(_$utxos, $async.Stream.fromIterable([request]), options: options);
|
||||
}
|
||||
|
||||
$grpc.ResponseFuture<$0.AddressResponse> addresses($0.AddressRequest request, {$grpc.CallOptions? options}) {
|
||||
return $createUnaryCall(_$addresses, request, options: options);
|
||||
}
|
||||
|
||||
$grpc.ResponseFuture<$0.SpentResponse> spent($0.SpentRequest request, {$grpc.CallOptions? options}) {
|
||||
return $createUnaryCall(_$spent, request, options: options);
|
||||
}
|
||||
|
||||
$grpc.ResponseFuture<$0.CreateResponse> create($0.CreateRequest request, {$grpc.CallOptions? options}) {
|
||||
return $createUnaryCall(_$create, request, options: options);
|
||||
}
|
||||
|
||||
$grpc.ResponseFuture<$0.BroadcastResponse> broadcast($0.BroadcastRequest request, {$grpc.CallOptions? options}) {
|
||||
return $createUnaryCall(_$broadcast, request, options: options);
|
||||
}
|
||||
}
|
||||
|
||||
@$pb.GrpcServiceName('Rpc')
|
||||
abstract class RpcServiceBase extends $grpc.Service {
|
||||
$core.String get $name => 'Rpc';
|
||||
|
||||
RpcServiceBase() {
|
||||
$addMethod($grpc.ServiceMethod<$0.StatusRequest, $0.StatusResponse>(
|
||||
'Status',
|
||||
status_Pre,
|
||||
false,
|
||||
false,
|
||||
($core.List<$core.int> value) => $0.StatusRequest.fromBuffer(value),
|
||||
($0.StatusResponse value) => value.writeToBuffer()));
|
||||
$addMethod($grpc.ServiceMethod<$0.UtxosRequest, $0.Utxo>(
|
||||
'Utxos',
|
||||
utxos_Pre,
|
||||
false,
|
||||
true,
|
||||
($core.List<$core.int> value) => $0.UtxosRequest.fromBuffer(value),
|
||||
($0.Utxo value) => value.writeToBuffer()));
|
||||
$addMethod($grpc.ServiceMethod<$0.AddressRequest, $0.AddressResponse>(
|
||||
'Addresses',
|
||||
addresses_Pre,
|
||||
false,
|
||||
false,
|
||||
($core.List<$core.int> value) => $0.AddressRequest.fromBuffer(value),
|
||||
($0.AddressResponse value) => value.writeToBuffer()));
|
||||
$addMethod($grpc.ServiceMethod<$0.SpentRequest, $0.SpentResponse>(
|
||||
'Spent',
|
||||
spent_Pre,
|
||||
false,
|
||||
false,
|
||||
($core.List<$core.int> value) => $0.SpentRequest.fromBuffer(value),
|
||||
($0.SpentResponse value) => value.writeToBuffer()));
|
||||
$addMethod($grpc.ServiceMethod<$0.CreateRequest, $0.CreateResponse>(
|
||||
'Create',
|
||||
create_Pre,
|
||||
false,
|
||||
false,
|
||||
($core.List<$core.int> value) => $0.CreateRequest.fromBuffer(value),
|
||||
($0.CreateResponse value) => value.writeToBuffer()));
|
||||
$addMethod($grpc.ServiceMethod<$0.BroadcastRequest, $0.BroadcastResponse>(
|
||||
'Broadcast',
|
||||
broadcast_Pre,
|
||||
false,
|
||||
false,
|
||||
($core.List<$core.int> value) => $0.BroadcastRequest.fromBuffer(value),
|
||||
($0.BroadcastResponse value) => value.writeToBuffer()));
|
||||
}
|
||||
|
||||
$async.Future<$0.StatusResponse> status_Pre($grpc.ServiceCall call, $async.Future<$0.StatusRequest> request) async {
|
||||
return status(call, await request);
|
||||
}
|
||||
|
||||
$async.Stream<$0.Utxo> utxos_Pre($grpc.ServiceCall call, $async.Future<$0.UtxosRequest> request) async* {
|
||||
yield* utxos(call, await request);
|
||||
}
|
||||
|
||||
$async.Future<$0.AddressResponse> addresses_Pre($grpc.ServiceCall call, $async.Future<$0.AddressRequest> request) async {
|
||||
return addresses(call, await request);
|
||||
}
|
||||
|
||||
$async.Future<$0.SpentResponse> spent_Pre($grpc.ServiceCall call, $async.Future<$0.SpentRequest> request) async {
|
||||
return spent(call, await request);
|
||||
}
|
||||
|
||||
$async.Future<$0.CreateResponse> create_Pre($grpc.ServiceCall call, $async.Future<$0.CreateRequest> request) async {
|
||||
return create(call, await request);
|
||||
}
|
||||
|
||||
$async.Future<$0.BroadcastResponse> broadcast_Pre($grpc.ServiceCall call, $async.Future<$0.BroadcastRequest> request) async {
|
||||
return broadcast(call, await request);
|
||||
}
|
||||
|
||||
$async.Future<$0.StatusResponse> status($grpc.ServiceCall call, $0.StatusRequest request);
|
||||
$async.Stream<$0.Utxo> utxos($grpc.ServiceCall call, $0.UtxosRequest request);
|
||||
$async.Future<$0.AddressResponse> addresses($grpc.ServiceCall call, $0.AddressRequest request);
|
||||
$async.Future<$0.SpentResponse> spent($grpc.ServiceCall call, $0.SpentRequest request);
|
||||
$async.Future<$0.CreateResponse> create($grpc.ServiceCall call, $0.CreateRequest request);
|
||||
$async.Future<$0.BroadcastResponse> broadcast($grpc.ServiceCall call, $0.BroadcastRequest request);
|
||||
}
|
19
cw_mweb/macos/Classes/CwMwebPlugin.swift
Normal file
19
cw_mweb/macos/Classes/CwMwebPlugin.swift
Normal file
|
@ -0,0 +1,19 @@
|
|||
import Cocoa
|
||||
import FlutterMacOS
|
||||
|
||||
public class CwMwebPlugin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
let channel = FlutterMethodChannel(name: "cw_mweb", binaryMessenger: registrar.messenger)
|
||||
let instance = CwMwebPlugin()
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
switch call.method {
|
||||
case "getPlatformVersion":
|
||||
result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
23
cw_mweb/macos/cw_mweb.podspec
Normal file
23
cw_mweb/macos/cw_mweb.podspec
Normal file
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint cw_mweb.podspec` to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'cw_mweb'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'A new Flutter plugin project.'
|
||||
s.description = <<-DESC
|
||||
A new Flutter plugin project.
|
||||
DESC
|
||||
s.homepage = 'http://example.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Your Company' => 'email@example.com' }
|
||||
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.dependency 'FlutterMacOS'
|
||||
|
||||
s.platform = :osx, '10.11'
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
||||
s.swift_version = '5.0'
|
||||
end
|
76
cw_mweb/pubspec.yaml
Normal file
76
cw_mweb/pubspec.yaml
Normal file
|
@ -0,0 +1,76 @@
|
|||
name: cw_mweb
|
||||
description: A new Flutter plugin project.
|
||||
version: 0.0.1
|
||||
homepage:
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.6 <4.0.0'
|
||||
flutter: ">=3.3.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
grpc: ^3.2.4
|
||||
path_provider: ^2.1.2
|
||||
plugin_platform_interface: ^2.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
# This section identifies this Flutter project as a plugin project.
|
||||
# The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
|
||||
# which should be registered in the plugin registry. This is required for
|
||||
# using method channels.
|
||||
# The Android 'package' specifies package in which the registered class is.
|
||||
# This is required for using method channels on Android.
|
||||
# The 'ffiPlugin' specifies that native code should be built and bundled.
|
||||
# This is required for using `dart:ffi`.
|
||||
# All these are used by the tooling to maintain consistency when
|
||||
# adding or updating assets for this project.
|
||||
plugin:
|
||||
platforms:
|
||||
android:
|
||||
package: com.cakewallet.mweb
|
||||
pluginClass: CwMwebPlugin
|
||||
ios:
|
||||
pluginClass: CwMwebPlugin
|
||||
macos:
|
||||
pluginClass: CwMwebPlugin
|
||||
|
||||
# To add assets to your plugin package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# To add custom fonts to your plugin package, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts in packages, see
|
||||
# https://flutter.dev/custom-fonts/#from-packages
|
|
@ -261,6 +261,8 @@ class CWBitcoin extends Bitcoin {
|
|||
return SegwitAddresType.p2tr;
|
||||
case BitcoinReceivePageOption.p2wsh:
|
||||
return SegwitAddresType.p2wsh;
|
||||
case BitcoinReceivePageOption.mweb:
|
||||
return SegwitAddresType.mweb;
|
||||
case BitcoinReceivePageOption.p2wpkh:
|
||||
default:
|
||||
return SegwitAddresType.p2wpkh;
|
||||
|
|
|
@ -9,8 +9,9 @@ class AddressValidator extends TextValidator {
|
|||
AddressValidator({required CryptoCurrency type})
|
||||
: super(
|
||||
errorMessage: S.current.error_text_address,
|
||||
useAdditionalValidation: type == CryptoCurrency.btc
|
||||
? (String txt) => validateAddress(address: txt, network: BitcoinNetwork.mainnet)
|
||||
useAdditionalValidation: type == CryptoCurrency.btc || type == CryptoCurrency.ltc
|
||||
? (String txt) => validateAddress(address: txt, network:
|
||||
type == CryptoCurrency.btc ? BitcoinNetwork.mainnet : LitecoinNetwork.mainnet)
|
||||
: null,
|
||||
pattern: getPattern(type),
|
||||
length: getLength(type));
|
||||
|
@ -27,6 +28,8 @@ class AddressValidator extends TextValidator {
|
|||
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
|
||||
case CryptoCurrency.btc:
|
||||
return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$';
|
||||
case CryptoCurrency.ltc:
|
||||
return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$|^${MwebAddress.regex.pattern}\$';
|
||||
case CryptoCurrency.nano:
|
||||
return '[0-9a-zA-Z_]';
|
||||
case CryptoCurrency.banano:
|
||||
|
@ -96,8 +99,6 @@ class AddressValidator extends TextValidator {
|
|||
return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{42}\$|^bitcoincash:q|p[0-9a-zA-Z]{41}\$|^bitcoincash:q|p[0-9a-zA-Z]{42}\$';
|
||||
case CryptoCurrency.bnb:
|
||||
return '[0-9a-zA-Z]';
|
||||
case CryptoCurrency.ltc:
|
||||
return '^(?!(ltc|LTC)1)[0-9a-zA-Z]*\$|(^LTC1[A-Z0-9]*\$)|(^ltc1[a-z0-9]*\$)';
|
||||
case CryptoCurrency.hbar:
|
||||
return '[0-9a-zA-Z.]';
|
||||
case CryptoCurrency.zaddr:
|
||||
|
@ -144,6 +145,8 @@ class AddressValidator extends TextValidator {
|
|||
return null;
|
||||
case CryptoCurrency.btc:
|
||||
return null;
|
||||
case CryptoCurrency.ltc:
|
||||
return null;
|
||||
case CryptoCurrency.dash:
|
||||
return [34];
|
||||
case CryptoCurrency.eos:
|
||||
|
@ -190,8 +193,6 @@ class AddressValidator extends TextValidator {
|
|||
return [42, 43, 44, 54, 55];
|
||||
case CryptoCurrency.bnb:
|
||||
return [42];
|
||||
case CryptoCurrency.ltc:
|
||||
return [34, 43, 63];
|
||||
case CryptoCurrency.nano:
|
||||
return [64, 65];
|
||||
case CryptoCurrency.banano:
|
||||
|
@ -278,7 +279,8 @@ class AddressValidator extends TextValidator {
|
|||
case CryptoCurrency.ltc:
|
||||
return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)ltc[a-zA-Z0-9]{26,45}([^0-9a-zA-Z]|\$)';
|
||||
'|([^0-9a-zA-Z]|^)ltc[a-zA-Z0-9]{26,45}([^0-9a-zA-Z]|\$)'
|
||||
'|([^0-9a-zA-Z]|^)((ltc|t)mweb1q[ac-hj-np-z02-9]{90,120})([^0-9a-zA-Z]|\$)';
|
||||
case CryptoCurrency.eth:
|
||||
return '0x[0-9a-zA-Z]{42}';
|
||||
case CryptoCurrency.maticpoly:
|
||||
|
|
|
@ -248,7 +248,6 @@ Future<void> initialSetup(
|
|||
navigatorKey: navigatorKey,
|
||||
);
|
||||
await bootstrap(navigatorKey);
|
||||
monero?.onStartup();
|
||||
}
|
||||
|
||||
class App extends StatefulWidget {
|
||||
|
|
|
@ -219,7 +219,8 @@ class AddressPage extends BasePage {
|
|||
}
|
||||
break;
|
||||
default:
|
||||
if (addressListViewModel.type == WalletType.bitcoin) {
|
||||
if (addressListViewModel.type == WalletType.bitcoin ||
|
||||
addressListViewModel.type == WalletType.litecoin) {
|
||||
addressListViewModel.setAddressType(bitcoin!.getBitcoinAddressType(option));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_receive_page_option.dart';
|
||||
import 'package:cw_core/receive_page_option.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
@ -11,19 +12,30 @@ class ReceiveOptionViewModel = ReceiveOptionViewModelBase with _$ReceiveOptionVi
|
|||
abstract class ReceiveOptionViewModelBase with Store {
|
||||
ReceiveOptionViewModelBase(this._wallet, this.initialPageOption)
|
||||
: selectedReceiveOption = initialPageOption ??
|
||||
(_wallet.type == WalletType.bitcoin
|
||||
(_wallet.type == WalletType.bitcoin ||
|
||||
_wallet.type == WalletType.litecoin
|
||||
? bitcoin!.getSelectedAddressType(_wallet)
|
||||
: ReceivePageOption.mainnet),
|
||||
_options = [] {
|
||||
final walletType = _wallet.type;
|
||||
_options = walletType == WalletType.haven
|
||||
? [ReceivePageOption.mainnet]
|
||||
: walletType == WalletType.bitcoin
|
||||
? [
|
||||
...bitcoin!.getBitcoinReceivePageOptions(),
|
||||
...ReceivePageOptions.where((element) => element != ReceivePageOption.mainnet)
|
||||
]
|
||||
: ReceivePageOptions;
|
||||
switch (_wallet.type) {
|
||||
case WalletType.bitcoin:
|
||||
_options = [
|
||||
...bitcoin!.getBitcoinReceivePageOptions(),
|
||||
...ReceivePageOptions.where((element) => element != ReceivePageOption.mainnet)
|
||||
];
|
||||
break;
|
||||
case WalletType.litecoin:
|
||||
_options = [
|
||||
...BitcoinReceivePageOption.allLitecoin,
|
||||
...ReceivePageOptions.where((element) => element != ReceivePageOption.mainnet)
|
||||
];
|
||||
break;
|
||||
case WalletType.haven:
|
||||
_options = [ReceivePageOption.mainnet];
|
||||
break;
|
||||
default:
|
||||
_options = ReceivePageOptions;
|
||||
}
|
||||
}
|
||||
|
||||
final WalletBase _wallet;
|
||||
|
|
|
@ -430,7 +430,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
|||
|
||||
@action
|
||||
Future<void> setAddressType(dynamic option) async {
|
||||
if (wallet.type == WalletType.bitcoin) {
|
||||
if (wallet.type == WalletType.bitcoin ||
|
||||
wallet.type == WalletType.litecoin) {
|
||||
await bitcoin!.setAddressType(wallet, option);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import Foundation
|
|||
|
||||
import connectivity_plus
|
||||
import cw_monero
|
||||
import cw_mweb
|
||||
import device_info_plus
|
||||
import devicelocale
|
||||
import flutter_inappwebview_macos
|
||||
|
@ -24,6 +25,7 @@ import wakelock_plus
|
|||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
||||
CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin"))
|
||||
CwMwebPlugin.register(with: registry.registrar(forPlugin: "CwMwebPlugin"))
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
|
||||
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
|
||||
|
|
Loading…
Reference in a new issue