LCW-1144 cupcake litecoin (#2557)
What changed, and why it matters
This commit adds new Litecoin MWEB (privacy feature) wallet capabilities to Cake Wallet, including restoring wallets from extended public keys and handling special PSBT (partially signed Bitcoin-like) transactions. It also upgrades several Go dependencies and switches the local MWEB service from a network port to a Unix domain socket. There is no clear security bug, but the changes touch sensitive wallet code and key handling, so they deserve careful review.
Treat this as a high-sensitivity feature change requiring focused review: verify that scanSecret/spendPubkey are encrypted at rest via WalletKeysData, confirm the Unix socket has restrictive filesystem permissions and is not accessible to other apps, audit PSBT/UR parsing for malicious input, and review the mwebd dependency changelog for security fixes in the bumped versions. The unimplemented hog-ex detection TODO should be tracked and completed before relying on the confirmation check.
Security signals we found
New restore path accepts xpub + scanSecret + spendPubkey and stores them in WalletKeysData JSON
MWEB scan/spend secrets are passed as byte arrays over local gRPC to mwebd
Switch from TCP loopback to Unix domain socket for mwebd reduces localhost exposure
Go dependency bumps include crypto/net/sys/grpc/protobuf; no CVE mapping supplied
PSBT construction and QR/UR decoding paths added for hardware-wallet-style signing
Error handling added around scriptHash computation and server startup
TODO comment indicates hog-ex input detection is not yet implemented
Evidence from the diff
The patch is a feature merge for LCW-1144 (‘cupcake litecoin’). It introduces PSBT RPC wrappers in cw_mweb, adds LitecoinWalletFromKeysCredentials and convertLtubToXpub for restoring/view-only Litecoin wallets, extends WalletKeysData to persist scanSecret/spendPubkey, and refactors litecoin_wallet.dart to build PSBTs and commit them from UR QR codes. The Go mwebd server is switched from a TCP port to a Unix domain socket and dependency versions are bumped (mwebd 0.1.8→0.1.16, ltcd, grpc, protobuf, x/crypto, etc.). Several error-handling improvements are visible (StartServer now returns an error message pointer, scriptHash failures are caught and logged).
Changed components
cw_bitcoin/lib/litecoin_wallet.dartcw_bitcoin/lib/litecoin_wallet_addresses.dartcw_bitcoin/lib/litecoin_wallet_service.dartcw_bitcoin/lib/bitcoin_wallet_service.dartcw_bitcoin/lib/bitcoin_wallet_creation_credentials.dartcw_bitcoin/lib/bitcoin_address_record.dartcw_core/lib/wallet_keys_file.dartcw_core/lib/utils/zpub.dartcw_mweb/go/mweb.gocw_mweb/lib/cw_mweb.dartcw_mweb/lib/mweb_ffi.dartcw_mweb/lib/mwebd.pb.dartcw_mweb/lib/mwebd.pbgrpc.dartcw_mweb/go/go.modcw_mweb/go/go.sumInspect captured patch +1909 / −149
diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart
index 1509f91..2bc9fdd 100644
--- a/cw_bitcoin/lib/bitcoin_address_record.dart
+++ b/cw_bitcoin/lib/bitcoin_address_record.dart
@@ -1,4 +1,5 @@
import 'dart:convert';
+import 'package:cw_core/utils/print_verbose.dart';
import 'package:mobx/mobx.dart';
import 'package:bitcoin_base/bitcoin_base.dart';
@@ -65,8 +66,14 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
required super.type,
String? scriptHash,
required super.network,
- }) : scriptHash = scriptHash ??
- (network != null ? BitcoinAddressUtils.scriptHash(address, network: network) : null);
+ }) {
+ try {
+ this.scriptHash = scriptHash ??
+ (network != null ? BitcoinAddressUtils.scriptHash(address, network: network!) : null);
+ } catch (e) {
+ printV(e);
+ }
+}
factory BitcoinAddressRecord.fromJSON(String jsonSource, {BasedUtxoNetwork? network}) {
final decoded = json.decode(jsonSource) as Map;
diff --git a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart
index 55d301d..a0ac214 100644
--- a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart
@@ -70,6 +70,21 @@ class BitcoinWalletFromKeysCredentials extends WalletCredentials {
final String xpub;
}
+class LitecoinWalletFromKeysCredentials extends WalletCredentials {
+ LitecoinWalletFromKeysCredentials({
+ required String name,
+ required String password,
+ required this.xpub,
+ required this.scanSecret,
+ required this.spendPubkey,
+ WalletInfo? walletInfo,
+ }) : super(name: name, password: password, walletInfo: walletInfo);
+
+ final String xpub;
+ final String scanSecret;
+ final String spendPubkey;
+}
+
class BitcoinRestoreWalletFromHardware extends WalletCredentials {
BitcoinRestoreWalletFromHardware({
required String name,
diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart
index f742376..ebb0759 100644
--- a/cw_bitcoin/lib/bitcoin_wallet_service.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart
@@ -165,7 +165,7 @@ class BitcoinWalletService extends WalletService<
derivationInfo.derivationPath =
credentials.hwAccountData.derivationPath;
- final xpub = convertZpubToXpub(credentials.hwAccountData.xpub!);
+ final xpub = convertAnyToXpub(credentials.hwAccountData.xpub!);
await credentials.walletInfo!.save();
final wallet = await BitcoinWallet(
@@ -189,7 +189,7 @@ class BitcoinWalletService extends WalletService<
final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet;
credentials.walletInfo?.network = network.value;
- final xpub = convertZpubToXpub(credentials.xpub);
+ final xpub = convertAnyToXpub(credentials.xpub);
final wallet = await BitcoinWallet(
password: credentials.password!,
diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart
index 01c7171..11636b8 100644
--- a/cw_bitcoin/lib/litecoin_wallet.dart
+++ b/cw_bitcoin/lib/litecoin_wallet.dart
@@ -1,7 +1,17 @@
import 'dart:async';
import 'dart:convert';
import 'dart:math';
-
+import 'package:collection/collection.dart';
+import 'package:crypto/crypto.dart';
+import 'package:cw_bitcoin/address_from_output.dart';
+import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
+import 'package:cw_core/cake_hive.dart';
+import 'package:cw_core/mweb_utxo.dart';
+import 'package:cw_core/unspent_coin_type.dart';
+import 'package:cw_core/utils/print_verbose.dart';
+import 'package:cw_core/node.dart';
+import 'package:cw_mweb/mwebd.pbgrpc.dart';
+import 'package:fixnum/fixnum.dart';
import 'package:bip39/bip39.dart' as bip39;
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:bitcoin_base/src/crypto/keypair/sign_utils.dart';
@@ -51,6 +61,9 @@ import 'package:mobx/mobx.dart';
import 'package:pointycastle/ecc/api.dart';
import 'package:pointycastle/ecc/curves/secp256k1.dart';
import 'package:shared_preferences/shared_preferences.dart';
+import 'package:ur/cbor_lite.dart';
+import 'package:ur/ur.dart';
+import 'package:ur/ur_decoder.dart';
part 'litecoin_wallet.g.dart';
@@ -66,6 +79,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
Uint8List? seedBytes,
String? mnemonic,
String? xpub,
+ this.scanSecretOverride,
+ this.spendPubkeyOverride,
String? passphrase,
String? addressPageType,
List<BitcoinAddressRecord>? initialAddresses,
@@ -95,6 +110,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
mwebHd =
Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/1000'") as Bip32Slip10Secp256k1;
mwebEnabled = alwaysScan ?? false;
+ } else if (scanSecretOverride != null && spendPubkeyOverride != null) {
+ mwebHd = null;
+ mwebEnabled = alwaysScan ?? false;
} else {
mwebHd = null;
mwebEnabled = false;
@@ -110,6 +128,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
network: network,
mwebHd: mwebHd,
mwebEnabled: mwebEnabled,
+ scanSecretOverride: scanSecretOverride,
+ spendPubkeyOverride: spendPubkeyOverride,
isHardwareWallet: walletInfo.isHardwareWallet,
);
autorun((_) {
@@ -162,9 +182,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
@override
bool get hasRescan => true;
- List<int> get scanSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
- List<int> get spendSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000001)).privateKey.privKey.raw;
+ final String? scanSecretOverride;
+ final String? spendPubkeyOverride;
+ List<int> get scanSecret => scanSecretOverride != null
+ ? hex.decode(scanSecretOverride!)
+ : mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
+
+ List<int> get spendSecret =>
+ mwebHd?.childKey(Bip32KeyIndex(0x80000001)).privateKey.privKey.raw ?? List.filled(32, 0);
static Future<LitecoinWallet> create(
{required String mnemonic,
@@ -212,6 +238,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
);
}
+ @override
+ WalletKeysData get walletKeysData =>
+ WalletKeysData(mnemonic: seed, xPub: xpub, passphrase: passphrase, scanSecret: scanSecretOverride, spendPubkey: spendPubkeyOverride);
+
static Future<LitecoinWallet> open({
required String name,
required WalletInfo walletInfo,
@@ -277,6 +307,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
return LitecoinWallet(
mnemonic: keysData.mnemonic,
xpub: keysData.xPub,
+ scanSecretOverride: keysData.scanSecret,
+ spendPubkeyOverride: keysData.spendPubkey,
password: password,
walletInfo: walletInfo,
derivationInfo: derivationInfo,
@@ -1064,6 +1096,47 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
return fee.toInt() + feeIncrease;
}
+ Future<Uint8List> buildPsbt(PendingBitcoinTransaction transaction, bool isMweb) async {
+ final List<TxInput> inputs = [];
+ final List<TxOut> txouts = [];
+ for (final utxo in transaction.utxos) {
+ if (utxo.utxo.scriptType != SegwitAddresType.mweb) {
+ inputs.add(utxo.utxo.toInput());
+ txouts.add(TxOut(value: Int64(utxo.utxo.value.toInt()),
+ pkScript: utxo.ownerDetails.address.toScriptPubKey().toBytes()));
+ }
+ }
+ var resp = await CwMweb.psbtCreate(PsbtCreateRequest(
+ rawTx: inputs.isEmpty ? null : BtcTransaction(
+ inputs: inputs,
+ outputs: isMweb ? [] : transaction.outputs,
+ ).toBytes(),
+ witnessUtxo: txouts,
+ ));
+ for (final utxo in transaction.utxos) {
+ if (utxo.utxo.scriptType == SegwitAddresType.mweb) {
+ resp = await CwMweb.psbtAddInput(PsbtAddInputRequest(
+ psbtB64: resp.psbtB64,
+ scanSecret: scanSecret,
+ outputId: utxo.utxo.txHash,
+ addressIndex: utxo.utxo.vout,
+ ));
+ }
+ }
+ if (isMweb) for (final output in transaction.outputs) {
+ var address = addressFromOutputScript(output.scriptPubKey, LitecoinNetwork.mainnet);
+ if (output.scriptPubKey.getAddressType() == SegwitAddresType.mweb) {
+ address = SegwitBech32Encoder.encode("ltcmweb", 0, output.scriptPubKey.toBytes());
+ }
+ resp = await CwMweb.psbtAddRecipient(PsbtAddRecipientRequest(
+ psbtB64: resp.psbtB64,
+ recipient: PsbtRecipient(address: address, value: Int64(output.amount.toInt())),
+ feeRatePerKb: Int64.parseInt(transaction.feeRate) * 1000,
+ ));
+ }
+ return base64.decode(resp.psbtB64);
+ }
+
@override
Future<PendingTransaction> createTransaction(Object credentials) async {
try {
@@ -1074,18 +1147,13 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
tx.changeAddressOverride = (await (walletAddresses as LitecoinWalletAddresses)
.getChangeAddress(coinTypeToSpendFrom: UnspentCoinType.nonMweb))
.address;
+ if (tx.shouldCommitUR()) {
+ tx.unsignedPsbt = await buildPsbt(tx, false);
+ }
return tx;
}
await waitForMwebAddresses();
- final resp = await CwMweb.create(CreateRequest(
- rawTx: hex.decode(tx.hex),
- scanSecret: scanSecret,
- spendSecret: spendSecret,
- feeRatePerKb: Int64.parseInt(tx.feeRate) * 1000,
- ));
- final tx2 = BtcTransaction.fromRaw(hex.encode(resp.rawTx));
-
// check if the transaction doesn't contain any mweb inputs or outputs:
final transactionCredentials = credentials as BitcoinTransactionCredentials;
@@ -1117,6 +1185,26 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
for (final utxo in tx.utxos) {
if (utxo.utxo.scriptType == SegwitAddresType.mweb) {
hasMwebInput = true;
+
+ } else {
+ // check if any of the inputs of this transaction are hog-ex:
+ // this list is only non-mweb inputs:
+ bool isHogEx = true;
+
+ final coin = unspentCoins
+ .firstWhere((coin) => coin.hash == utxo.utxo.txHash && coin.vout == utxo.utxo.vout);
+
+ // TODO: detect actual hog-ex inputs
+
+ if (!isHogEx) {
+ continue;
+ }
+
+ int confirmations = coin.confirmations ?? 0;
+ if (confirmations < 6) {
+ throw Exception(
+ "A transaction input has less than 6 confirmations, please try again later.");
+ }
}
}
@@ -1132,29 +1220,24 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
.address;
if (isRegular) {
tx.isMweb = false;
+ if (tx.shouldCommitUR()) {
+ tx.unsignedPsbt = await buildPsbt(tx, false);
+ }
return tx;
}
- // check if any of the inputs of this transaction are hog-ex:
- // this list is only non-mweb inputs:
- tx2.inputs.forEach((txInput) {
- bool isHogEx = true;
-
- final utxo = unspentCoins
- .firstWhere((utxo) => utxo.hash == txInput.txId && utxo.vout == txInput.txIndex);
-
- // TODO: detect actual hog-ex inputs
-
- if (!isHogEx) {
- return;
- }
+ if (tx.shouldCommitUR()) {
+ tx.unsignedPsbt = await buildPsbt(tx, true);
+ return tx;
+ }
- int confirmations = utxo.confirmations ?? 0;
- if (confirmations < 6) {
- throw Exception(
- "A transaction input has less than 6 confirmations, please try again later.");
- }
- });
+ final resp = await CwMweb.create(CreateRequest(
+ rawTx: hex.decode(tx.hex),
+ scanSecret: scanSecret,
+ spendSecret: spendSecret,
+ feeRatePerKb: Int64.parseInt(tx.feeRate) * 1000,
+ ));
+ final tx2 = BtcTransaction.fromRaw(hex.encode(resp.rawTx));
tx.hexOverride = tx2
.copyWith(
@@ -1177,31 +1260,109 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
.toHex();
tx.outputAddresses = resp.outputId;
- return tx
- ..addListener((transaction) async {
- final addresses = <String>{};
- transaction.inputAddresses?.forEach((id) async {
- final utxo = mwebUtxosBox.get(id);
- // await mwebUtxosBox.delete(id); // gets deleted in checkMwebUtxosSpent
- if (utxo == null) return;
- // mark utxo as spent so we add it to the unconfirmed balance (as negative):
- utxo.spent = true;
- await mwebUtxosBox.put(id, utxo);
- final addressRecord = walletAddresses.allAddresses
- .firstWhere((addressRecord) => addressRecord.address == utxo.address);
- if (!addresses.contains(utxo.address)) {
- addresses.add(utxo.address);
- }
- addressRecord.balance -= utxo.value.toInt();
- });
- transaction.inputAddresses?.addAll(addresses);
- printV("isPegIn: $isPegIn, isPegOut: $isPegOut");
- transaction.additionalInfo["isPegIn"] = isPegIn;
- transaction.additionalInfo["isPegOut"] = isPegOut;
- transactionHistory.addOne(transaction);
- await updateUnspent();
- await updateBalance();
- });
+ addTransactionListener(tx, [], isPegIn, isPegOut);
+ return tx;
+ } catch (e, s) {
+ printV(e);
+ printV(s);
+ if (e.toString().contains("commit failed")) {
+ printV(e);
+ throw Exception("Transaction commit failed (no peers responded), please try again.");
+ }
+ rethrow;
+ }
+ }
+
+ void addTransactionListener(PendingBitcoinTransaction tx,
+ List<String> inputAddresses, bool isPegIn, bool isPegOut) {
+ tx.addListener((transaction) async {
+ final addresses = <String>{};
+ transaction.inputAddresses?.addAll(inputAddresses);
+ transaction.inputAddresses?.forEach((id) async {
+ final utxo = mwebUtxosBox.get(id);
+ // await mwebUtxosBox.delete(id); // gets deleted in checkMwebUtxosSpent
+ if (utxo == null) return;
+ // mark utxo as spent so we add it to the unconfirmed balance (as negative):
+ utxo.spent = true;
+ await mwebUtxosBox.put(id, utxo);
+ final addressRecord = walletAddresses.allAddresses
+ .firstWhere((addressRecord) => addressRecord.address == utxo.address);
+ if (!addresses.contains(utxo.address)) {
+ addresses.add(utxo.address);
+ }
+ addressRecord.balance -= utxo.value.toInt();
+ });
+ transaction.inputAddresses?.addAll(addresses);
+ printV("isPegIn: $isPegIn, isPegOut: $isPegOut");
+ transaction.additionalInfo["isPegIn"] = isPegIn;
+ transaction.additionalInfo["isPegOut"] = isPegOut;
+ transactionHistory.addOne(transaction);
+ await updateUnspent();
+ await updateBalance();
+ });
+ }
+
+ Future<void> commitPsbtUR(List<String> urCodes) async {
+ if (urCodes.isEmpty) throw Exception("No QR code got scanned");
+ bool isUr = urCodes.any((str) {
+ return str.startsWith("ur:psbt/");
+ });
+ if (!isUr) return;
+
+ final ur = URDecoder();
+ for (final inp in urCodes) {
+ ur.receivePart(inp);
+ }
+ final result = ur.result as UR;
+ final psbtB64 = base64Encode(CBORDecoder(result.cbor).decodeBytes().$1);
+
+ final resp = await CwMweb.psbtGetRecipients(PsbtGetRecipientsRequest(psbtB64: psbtB64));
+
+ bool hasMwebInput = false;
+ bool hasMwebOutput = false;
+ bool hasRegularOutput = false;
+
+ for (final recipient in resp.recipient) {
+ if (recipient.address.contains("mweb")) {
+ hasMwebOutput = true;
+ } else {
+ hasRegularOutput = true;
+ }
+ }
+
+ for (final address in resp.inputAddress) {
+ try {
+ LitecoinAddress(address);
+ } catch (_) {
+ hasMwebInput = true;
+ }
+ }
+
+ bool isPegIn = !hasMwebInput && hasMwebOutput;
+ bool isPegOut = hasMwebInput && hasRegularOutput;
+ bool isRegular = !hasMwebInput && !hasMwebOutput;
+
+ final resp2 = await CwMweb.psbtExtract(PsbtExtractRequest(psbtB64: psbtB64));
+
+ final btcTx = BtcTransaction.fromRaw(hex.encode(resp2.rawTx));
+
+ final tx = PendingBitcoinTransaction(
+ btcTx,
+ type,
+ electrumClient: electrumClient,
+ amount: btcTx.outputs.reduce((a, b) => TxOutput(amount: a.amount + b.amount, scriptPubKey: a.scriptPubKey)).amount.toInt(),
+ fee: resp.fee.toInt(),
+ feeRate: "",
+ network: network,
+ hasChange: resp.recipient.length > 1,
+ isMweb: !isRegular,
+ isViewOnly: false,
+ );
+ tx.outputAddresses = resp2.outputId;
+ addTransactionListener(tx, resp.inputAddress, isPegIn, isPegOut);
+
+ try {
+ await tx.commit();
} catch (e, s) {
printV(e);
printV(s);
diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
index 76228c1..4968e95 100644
--- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
@@ -28,6 +28,8 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
required super.isHardwareWallet,
required this.mwebHd,
required this.mwebEnabled,
+ required this.scanSecretOverride,
+ required this.spendPubkeyOverride,
super.initialAddresses,
super.initialMwebAddresses,
super.initialRegularAddressIndex,
@@ -45,9 +47,15 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
List<String> mwebAddrs = [];
bool generating = false;
- List<int> get scanSecret => mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
- List<int> get spendPubkey =>
- mwebHd!.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
+ final String? scanSecretOverride;
+ final String? spendPubkeyOverride;
+
+ List<int> get scanSecret => scanSecretOverride != null
+ ? hex.decode(scanSecretOverride!)
+ : mwebHd!.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw;
+ List<int> get spendPubkey => spendPubkeyOverride != null
+ ? hex.decode(spendPubkeyOverride!)
+ : mwebHd!.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
@override
Future<void> init() async {
@@ -65,6 +73,10 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return null;
}
+ if ((scanSecret.length < 1 || scanSecret.reduce((a, b) => a + b) == 0) ||
+ (spendPubkey.length < 1 || spendPubkey.reduce((a, b) => a + b) == 0)) {
+ return null;
+ }
Uint8List scan = Uint8List.fromList(scanSecret);
Uint8List spend = Uint8List.fromList(spendPubkey);
@@ -95,7 +107,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
// ensure mweb addresses are up to date:
// This is the Case if the Litecoin Wallet is a hardware Wallet
- if (mwebHd == null) return;
+ if (mwebHd == null && scanSecretOverride == null) return;
if (mwebAddresses.length < mwebAddrs.length) {
List<BitcoinAddressRecord> addressRecords = mwebAddrs
@@ -127,6 +139,9 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
BitcoinAddressType? addressType,
}) {
if (addressType == SegwitAddresType.mweb) {
+ if (mwebAddrs.length == 0) {
+ return "null";
+ }
return hd == sideHd ? mwebAddrs[0] : mwebAddrs[index + 1];
}
return generateP2WPKHAddress(hd: hd, index: index, network: network);
diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart
index 126b6a9..739602e 100644
--- a/cw_bitcoin/lib/litecoin_wallet_service.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_service.dart
@@ -20,7 +20,7 @@ import 'package:path_provider/path_provider.dart';
class LitecoinWalletService extends WalletService<
BitcoinNewWalletCredentials,
BitcoinRestoreWalletFromSeedCredentials,
- BitcoinRestoreWalletFromWIFCredentials,
+ LitecoinWalletFromKeysCredentials,
BitcoinRestoreWalletFromHardware> {
LitecoinWalletService(this.unspentCoinsInfoSource, this.isDirect);
@@ -186,9 +186,26 @@ class LitecoinWalletService extends WalletService<
}
@override
- Future<LitecoinWallet> restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials,
- {bool? isTestnet}) async =>
- throw UnimplementedError();
+ Future<LitecoinWallet> restoreFromKeys(LitecoinWalletFromKeysCredentials credentials,
+ {bool? isTestnet}) async {
+ final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
+ credentials.walletInfo?.network = network.value;
+
+ final wallet = await LitecoinWallet(
+ password: credentials.password!,
+ xpub: credentials.xpub,
+ scanSecretOverride: credentials.scanSecret,
+ spendPubkeyOverride: credentials.spendPubkey,
+ walletInfo: credentials.walletInfo!,
+ derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
+ unspentCoinsInfo: unspentCoinsInfoSource,
+ encryptionFileUtils: encryptionFileUtilsFor(isDirect),
+ );
+
+ await wallet.save();
+ await wallet.init();
+ return wallet;
+ }
@override
Future<LitecoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials,
diff --git a/cw_core/lib/utils/zpub.dart b/cw_core/lib/utils/zpub.dart
index 90f0389..a64f902 100644
--- a/cw_core/lib/utils/zpub.dart
+++ b/cw_core/lib/utils/zpub.dart
@@ -3,6 +3,15 @@ import 'dart:typed_data';
import 'package:blockchain_utils/blockchain_utils.dart';
+String convertAnyToXpub(String any) {
+ if (any.toLowerCase().startsWith("zpub")) {
+ return convertZpubToXpub(any);
+ } else if (any.toLowerCase().startsWith("ltub")) {
+ return convertLtubToXpub(any);
+ }
+ return any;
+}
+
String convertZpubToXpub(String zpub) {
try {
final decoded = Base58Decoder.checkDecode(zpub);
@@ -37,6 +46,36 @@ String convertZpubToXpub(String zpub) {
}
}
+String convertLtubToXpub(String ltub) {
+ try {
+ final decoded = Base58Decoder.checkDecode(ltub);
+
+ if (decoded.length < 4) {
+ throw ArgumentError('Invalid extended public key length');
+ }
+
+ final versionBytes = decoded.sublist(0, 4);
+ final ltubVersionBytes = [0x01, 0x9D, 0xA4, 0x62]; // Ltub mainnet version
+
+ bool isLtub = listEquals(versionBytes, ltubVersionBytes);
+
+ if (!isLtub) {
+ return ltub;
+ }
+
+ final xpubVersionBytes = [0x04, 0x88, 0xb2, 0x1e];
+
+ final newExtendedKey = Uint8List.fromList([
+ ...xpubVersionBytes,
+ ...decoded.sublist(4),
+ ]);
+
+ return Base58Encoder.checkEncode(newExtendedKey);
+ } catch (e) {
+ throw ArgumentError('Failed to convert ltub to xpub: $e');
+ }
+}
+
bool listEquals<T>(List<T> a, List<T> b) {
if (a.length != b.length) return false;
for (int i = 0; i < a.length; i++) {
diff --git a/cw_core/lib/wallet_keys_file.dart b/cw_core/lib/wallet_keys_file.dart
index 638cdc3..ee25713 100644
--- a/cw_core/lib/wallet_keys_file.dart
+++ b/cw_core/lib/wallet_keys_file.dart
@@ -98,15 +98,19 @@ class WalletKeysData {
final String? altMnemonic;
final String? passphrase;
final String? xPub;
+ final String? scanSecret;
+ final String? spendPubkey;
- WalletKeysData({this.privateKey, this.mnemonic, this.altMnemonic, this.passphrase, this.xPub});
+ WalletKeysData({this.privateKey, this.mnemonic, this.altMnemonic, this.passphrase, this.xPub, this.scanSecret, this.spendPubkey});
String toJSON() => jsonEncode({
"privateKey": privateKey,
"mnemonic": mnemonic,
if (altMnemonic != null) "altMnemonic": altMnemonic,
if (passphrase != null) "passphrase": passphrase,
- if (xPub != null) "xPub": xPub
+ if (xPub != null) "xPub": xPub,
+ if (scanSecret != null) "scanSecret": scanSecret,
+ if (spendPubkey != null) "spendPubkey": spendPubkey,
});
static WalletKeysData fromJSON(Map<String, dynamic> json) => WalletKeysData(
@@ -115,5 +119,7 @@ class WalletKeysData {
altMnemonic: json["altMnemonic"] as String?,
passphrase: json["passphrase"] as String?,
xPub: json["xPub"] as String?,
+ scanSecret: json["scanSecret"] as String?,
+ spendPubkey: json["spendPubkey"] as String?,
);
}
diff --git a/cw_mweb/.gitignore b/cw_mweb/.gitignore
index 96486fd..9d90768 100644
--- a/cw_mweb/.gitignore
+++ b/cw_mweb/.gitignore
@@ -28,3 +28,4 @@ migrate_working_dir/
.dart_tool/
.packages
build/
+jniLibs/
diff --git a/cw_mweb/go/go.mod b/cw_mweb/go/go.mod
index 36d1e46..e01117a 100644
--- a/cw_mweb/go/go.mod
+++ b/cw_mweb/go/go.mod
@@ -1,6 +1,10 @@
module github.com/cake-tech/cake_wallet/cw_mweb/go
-go 1.24.2
+go 1.24.1
+
+require github.com/ltcmweb/mwebd v0.1.16
+
+require github.com/ltcmweb/mwebd v0.1.16
require (
github.com/Microsoft/go-winio v0.6.2 // indirect
@@ -23,10 +27,9 @@ require (
github.com/kkdai/bstream v1.0.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/ltcmweb/coinswapd v0.1.0 // indirect
- github.com/ltcmweb/ltcd v0.25.6 // indirect
+ github.com/ltcmweb/ltcd v0.25.11 // indirect
github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 // indirect
github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 // indirect
- github.com/ltcmweb/mwebd v0.1.8 // indirect
github.com/ltcmweb/neutrino v0.17.4 // indirect
github.com/ltcmweb/neutrino/cache v1.1.0 // indirect
github.com/ltcmweb/secp256k1 v0.1.1 // indirect
@@ -37,14 +40,14 @@ require (
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
go.etcd.io/bbolt v1.3.10 // indirect
- golang.org/x/crypto v0.33.0 // indirect
+ golang.org/x/crypto v0.39.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
- golang.org/x/net v0.35.0 // indirect
- golang.org/x/sys v0.30.0 // indirect
- golang.org/x/text v0.22.0 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 // indirect
- google.golang.org/grpc v1.63.2 // indirect
- google.golang.org/protobuf v1.34.2 // indirect
+ golang.org/x/net v0.41.0 // indirect
+ golang.org/x/sys v0.33.0 // indirect
+ golang.org/x/text v0.26.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
+ google.golang.org/grpc v1.75.0 // indirect
+ google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
lukechampine.com/blake3 v1.3.0 // indirect
)
diff --git a/cw_mweb/go/go.sum b/cw_mweb/go/go.sum
index c973d85..f09c4a6 100644
--- a/cw_mweb/go/go.sum
+++ b/cw_mweb/go/go.sum
@@ -6,12 +6,22 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alitto/pond/v2 v2.2.0 h1:hX3B1Lu4b5PjSHR+IWNRDKD0Jfw2ew8V25J7Vu5j7RM=
github.com/alitto/pond/v2 v2.2.0/go.mod h1:xkjYEgQ05RSpWdfSd1nM3OVv7TBhLdy7rMp3+2Nq+yE=
+github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
+github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
+github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
+github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
+github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
+github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
+github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=
+github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
+github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI=
+github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
@@ -22,11 +32,25 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnN
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/decred/dcrd/lru v1.1.2 h1:KdCzlkxppuoIDGEvCGah1fZRicrDH36IipvlB1ROkFY=
github.com/decred/dcrd/lru v1.1.2/go.mod h1:gEdCVgXs1/YoBvFWt7Scgknbhwik3FgVSzlnCcXL2N8=
+github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA=
+github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
github.com/ethereum/go-ethereum v1.14.8 h1:NgOWvXS+lauK+zFukEvi85UmmsS/OkV0N23UZ1VTIig=
github.com/ethereum/go-ethereum v1.14.8/go.mod h1:TJhyuDq0JDppAkFXgqjwpdlQApywnu/m10kFPxh8vvs=
+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
+github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
@@ -39,14 +63,14 @@ github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuV
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/ltcmweb/coinswapd v0.1.0 h1:M6eoz4g7fDpsQeNA8wWbBh6PY1xykrihyLU44SgljeI=
github.com/ltcmweb/coinswapd v0.1.0/go.mod h1:CY5cVSympaLrMO8fHWXO+e/iuPLs2L0U9daMCRTstEM=
-github.com/ltcmweb/ltcd v0.25.6 h1:96aC38ZEyNVztylrBBqYnVZJ6cuF7IUvL2knhbMxs3Y=
-github.com/ltcmweb/ltcd v0.25.6/go.mod h1:jQbvPfnT4bBXJKRwU5SdD9ZUopwmSvhngdjeopv2cIU=
+github.com/ltcmweb/ltcd v0.25.11 h1:MI0n/9I0P2Ig+myofegrXXEvh00lY3TUqPk1akYHBxA=
+github.com/ltcmweb/ltcd v0.25.11/go.mod h1:jQbvPfnT4bBXJKRwU5SdD9ZUopwmSvhngdjeopv2cIU=
github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 h1:gJc1ljDPCBtwBKFcC4SW44BFoJqoZzkeagndMYdqKKE=
github.com/ltcmweb/ltcd/btcec/v2 v2.3.3/go.mod h1:NRr2WtpiSiSO29TkdZhbGNRA/Q16DV2eNbORf+M2ykI=
github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 h1:CAPyzHI3bCFRrrVHZkDUR2i3Awj6l/aqAZIEi0E/nfM=
github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3/go.mod h1:zB+HhI2IbIwTGpdAhdzpm1GVX4ShcWTgN42+ar9HXrg=
-github.com/ltcmweb/mwebd v0.1.8 h1:5TJgrM76H3s6kWUJ6CsU1L+DaafcAZ1edDlkyJ+GWt0=
-github.com/ltcmweb/mwebd v0.1.8/go.mod h1:KPf+lXEvEMuG0NaHume0imWMb9Cvr15SNPujZO6EAv4=
+github.com/ltcmweb/mwebd v0.1.16 h1:DaOIp/5TDhcDUxjvnWKHXkr6hF4LHe2bbY8I0zo7m9w=
+github.com/ltcmweb/mwebd v0.1.16/go.mod h1:GEhTe4RTG4ImmzsyqCzO2NKK11U2Zgb5+leQnwY+u+4=
github.com/ltcmweb/neutrino v0.17.4 h1:ZsguBvicTM5CtZDsKg+OBFuPUCKjfEJ3lRSGXPjF2oM=
github.com/ltcmweb/neutrino v0.17.4/go.mod h1:KktZ+McIwHuTHe0K8JK9Wv4qgv8orkA21a0ZOU4SwJ4=
github.com/ltcmweb/neutrino/cache v1.1.0 h1:C0Qn2p8ogcskRPfrBKPUayjn3m/CUJqI7otopNScvhk=
@@ -58,10 +82,38 @@ github.com/ltcsuite/lnd/queue v1.1.0/go.mod h1:DJrxK2gPC2FjJAVYxPOcnY2CplI3rhL2P
github.com/ltcsuite/lnd/ticker v1.0.1/go.mod h1:WZKpekfDVAVv7Gsrr0GAWC/U1XURfGesFg9sQYJbeL4=
github.com/ltcsuite/lnd/ticker v1.1.0 h1:3zYM/JlKNqq+DotW8jiEdHVeY5Yl7n7cUb2bTof1yXM=
github.com/ltcsuite/lnd/ticker v1.1.0/go.mod h1:K2qQ3EPe8enztYvn/VAbLafCPy13XHMuCRPsySoAbt8=
+github.com/ltcsuite/ltcd v0.22.0-beta h1:jYVHOeg2oBDvsduV26LtCZnzwifMDWoVbkdHTjGvHTk=
+github.com/ltcsuite/ltcd v0.22.0-beta/go.mod h1:/BXtm50r591uMfXf8XgSpL5er32HCvheJtBSPYK5bFM=
+github.com/ltcsuite/ltcd/btcec/v2 v2.1.0 h1:0DMWBjQDb0V1+4kCLOJlNdHs7ewwYturuUfLHq8mosY=
+github.com/ltcsuite/ltcd/btcec/v2 v2.1.0/go.mod h1:Vc9ZYXMcl5D6bA0VwMvGRDJYggO3YZ7/BuIri02Lq0E=
+github.com/ltcsuite/ltcd/ltcutil v1.1.0 h1:btwbdHO9cEr22zW/vgCLiF6ghh+IDngJdJsyhJ6mntU=
+github.com/ltcsuite/ltcd/ltcutil v1.1.0/go.mod h1:VbZlcopVgQteiCC5KRjIuxXH5wi1CtzhsvoYZ3K7FaE=
+github.com/ltcsuite/ltcwallet v0.13.1 h1:XMyrDHn0BmgUgkNbR/Lzg36vjRsup3xdiPLSD471UMg=
+github.com/ltcsuite/ltcwallet v0.13.1/go.mod h1:e6pIWRM9gsd5JnMsI9SgCJM0wi7awWdr20F1C1KUPiw=
+github.com/ltcsuite/ltcwallet/wallet/txauthor v1.1.0 h1:MaSgMq7LCB+6dVm9oLzNCVp0lmY1WKmevmMK/t2c6To=
+github.com/ltcsuite/ltcwallet/wallet/txauthor v1.1.0/go.mod h1:I53YELeELfA+dVporL+t44O8ArpuF8AjdJbbWIQaE2Q=
+github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 h1:P6H9zsMpBBuGOsp9lnil7XfPaPujDqrbcmkqvDdiSiI=
+github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0/go.mod h1:lmA2Ozxvbr2M8Mqb6ugOv5/FQT6x2Qnwg3yT/NiWEks=
+github.com/ltcsuite/ltcwallet/wallet/txsizes v1.1.0 h1:W884jMwG3K3Hu8FEMnV7KX1bd4HQd/4yvaevisFo9s8=
+github.com/ltcsuite/ltcwallet/wallet/txsizes v1.1.0/go.mod h1:G9+XTWnE0xaXzHRzTuP+SOIXFPXFMfYF+w/wxPHb0K8=
github.com/ltcsuite/ltcwallet/walletdb v1.3.5 h1:WymVw0FBQ8KJgH7B88ujRqBOJ9R0en9K9urpJW4atAE=
github.com/ltcsuite/ltcwallet/walletdb v1.3.5/go.mod h1:29SBzxA55wNxY3ctFw6t5PgsULwf3NMwg2MiGQgtrJE=
+github.com/ltcsuite/neutrino v0.13.2 h1:SDbRn4zt4e6z/4uVkVzVeKYpgXyoAh8ksA3m/uCIBaU=
+github.com/ltcsuite/neutrino v0.13.2/go.mod h1:eTkaETZBeu3es/FisfjY8Cp3M2fC4s+2V2VUeS8O1Ic=
+github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
+github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
+github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
+github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
@@ -69,29 +121,51 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f
go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
-golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
-golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
+go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
+go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
+go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
+go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
+go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
+go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
+go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
+go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
+go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
+go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
+golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
+golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
-golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
-golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
+golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
+golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
+golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
+golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
-golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
-golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 h1:umK/Ey0QEzurTNlsV3R+MfxHAb78HCEX/IkuR+zH4WQ=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
-google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
-google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
-google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
-google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
+golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
+gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
+gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
+google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
+google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
+gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
+rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
+rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
diff --git a/cw_mweb/go/mweb.go b/cw_mweb/go/mweb.go
index 0fc2d3a..46e1bee 100644
--- a/cw_mweb/go/mweb.go
+++ b/cw_mweb/go/mweb.go
@@ -10,7 +10,7 @@ import (
var server *mwebd.Server
//export StartServer
-func StartServer(chain *C.char, dataDir *C.char, nodeUri *C.char) C.int {
+func StartServer(chain *C.char, dataDir *C.char, nodeUri *C.char, errMsg **C.char) C.int {
if server != nil {
server.Stop()
}
@@ -21,15 +21,17 @@ func StartServer(chain *C.char, dataDir *C.char, nodeUri *C.char) C.int {
var err error
server, err = mwebd.NewServer(goChain, goDataDir, goNodeUri)
if err != nil {
+ *errMsg = C.CString(err.Error())
return 0
}
- start, err := server.Start(0)
+ err = server.StartUnix(goDataDir + "/mwebd.sock")
if err != nil {
+ *errMsg = C.CString(err.Error())
return 0
}
- return C.int(start)
+ return 1
}
//export StopServer
diff --git a/cw_mweb/lib/cw_mweb.dart b/cw_mweb/lib/cw_mweb.dart
index bcd1827..681ffe7 100644
--- a/cw_mweb/lib/cw_mweb.dart
+++ b/cw_mweb/lib/cw_mweb.dart
@@ -4,8 +4,8 @@ import 'dart:developer';
import 'dart:io';
import 'dart:typed_data';
-import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_mweb/mweb_ffi.dart';
+import 'package:cw_mweb/print_verbose.dart';
import 'package:grpc/grpc.dart';
import 'package:path_provider/path_provider.dart';
import 'mwebd.pbgrpc.dart';
@@ -64,10 +64,8 @@ class CwMweb {
}
printV("Attempting to connect to server on port: $_port");
- // wait for the server to finish starting up before we try to connect to it:
- await Future.delayed(const Duration(seconds: 8));
-
- _clientChannel = ClientChannel('127.0.0.1', port: _port!, channelShutdownHandler: () {
+ final address = InternetAddress("${appDir.path}/mwebd.sock", type: InternetAddressType.unix);
+ _clientChannel = ClientChannel(address, channelShutdownHandler: () {
_rpcClient = null;
printV("Channel is shutting down!");
},
@@ -219,4 +217,45 @@ class CwMweb {
rethrow;
}
}
+
+ static Future<PsbtResponse> psbtCreate(PsbtCreateRequest request) async {
+ log("mweb.psbtCreate() called");
+ _rpcClient = await stub();
+ return await _rpcClient!.psbtCreate(request, options: CallOptions(timeout: TIMEOUT_DURATION));
+ }
+
+ static Future<PsbtResponse> psbtAddInput(PsbtAddInputRequest request) async {
+ log("mweb.psbtAddInput() called");
+ _rpcClient = await stub();
+ return await _rpcClient!.psbtAddInput(request, options: CallOptions(timeout: TIMEOUT_DURATION));
+ }
+
+ static Future<PsbtResponse> psbtAddRecipient(PsbtAddRecipientRequest request) async {
+ log("mweb.psbtAddRecipient() called");
+ _rpcClient = await stub();
+ return await _rpcClient!.psbtAddRecipient(request, options: CallOptions(timeout: TIMEOUT_DURATION));
+ }
+
+ static Future<PsbtGetRecipientsResponse> psbtGetRecipients(PsbtGetRecipientsRequest request) async {
+ log("mweb.psbtGetRecipients() called");
+ _rpcClient = await stub();
+ return await _rpcClient!.psbtGetRecipients(request, options: CallOptions(timeout: TIMEOUT_DURATION));
+ }
+
+ static Future<CreateResponse> psbtExtract(PsbtExtractRequest request) async {
+ log("mweb.psbtExtract() called");
+ _rpcClient = await stub();
+ return await _rpcClient!.psbtExtract(request, options: CallOptions(timeout: TIMEOUT_DURATION));
+ }
+ static Future<PsbtResponse> psbtSign(PsbtSignRequest request) async {
+ printV("mweb.psbtSign() called");
+ _rpcClient = await stub();
+ return await _rpcClient!.psbtSign(request, options: CallOptions(timeout: TIMEOUT_DURATION));
+ }
+
+ static Future<PsbtResponse> psbtSignNonMweb(PsbtSignNonMwebRequest request) async {
+ printV("mweb.psbtSignNonMweb() called");
+ _rpcClient = await stub();
+ return await _rpcClient!.psbtSignNonMweb(request, options: CallOptions(timeout: TIMEOUT_DURATION));
+ }
}
diff --git a/cw_mweb/lib/mweb_ffi.dart b/cw_mweb/lib/mweb_ffi.dart
index 14f49ba..1413a0e 100644
--- a/cw_mweb/lib/mweb_ffi.dart
+++ b/cw_mweb/lib/mweb_ffi.dart
@@ -3,6 +3,7 @@ import 'dart:io';
import 'dart:typed_data';
import 'package:cw_mweb/generated_bindings.g.dart';
+import 'package:cw_mweb/print_verbose.dart';
import 'package:ffi/ffi.dart';
String libPath = (() {
@@ -24,12 +25,19 @@ class MWebFfi {
final chain = "".toNativeUtf8().cast<Char>();
final dataDir_ = dataDir.toNativeUtf8().cast<Char>();
final nodeUri_ = nodeUri.toNativeUtf8().cast<Char>();
+ final errMsgPtr = calloc<Pointer<Char>>();
- final port = lib.StartServer(chain, dataDir_, nodeUri_);
+ final port = lib.StartServer(chain, dataDir_, nodeUri_, errMsgPtr);
+ if (port == 0) {
+ final errMsg = errMsgPtr.value.cast<Utf8>().toDartString();
+ printV('Error starting server: $errMsg');
+ calloc.free(errMsgPtr.value);
+ }
calloc.free(chain);
calloc.free(dataDir_);
calloc.free(nodeUri_);
+ calloc.free(errMsgPtr);
return port;
}
diff --git a/cw_mweb/lib/mwebd.pb.dart b/cw_mweb/lib/mwebd.pb.dart
index d0dd486..faf5511 100644
--- a/cw_mweb/lib/mwebd.pb.dart
+++ b/cw_mweb/lib/mwebd.pb.dart
@@ -101,6 +101,7 @@ class StatusResponse extends $pb.GeneratedMessage {
static StatusResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<StatusResponse>(create);
static StatusResponse? _defaultInstance;
+ /// The height of the latest block.
@$pb.TagNumber(1)
$core.int get blockHeaderHeight => $_getIZ(0);
@$pb.TagNumber(1)
@@ -110,6 +111,7 @@ class StatusResponse extends $pb.GeneratedMessage {
@$pb.TagNumber(1)
void clearBlockHeaderHeight() => clearField(1);
+ /// The height of the latest MWEB header.
@$pb.TagNumber(2)
$core.int get mwebHeaderHeight => $_getIZ(1);
@$pb.TagNumber(2)
@@ -119,6 +121,7 @@ class StatusResponse extends $pb.GeneratedMessage {
@$pb.TagNumber(2)
void clearMwebHeaderHeight() => clearField(2);
+ /// The height at which the MWEB utxo set is synced to.
@$pb.TagNumber(3)
$core.int get mwebUtxosHeight => $_getIZ(2);
@$pb.TagNumber(3)
@@ -128,6 +131,7 @@ class StatusResponse extends $pb.GeneratedMessage {
@$pb.TagNumber(3)
void clearMwebUtxosHeight() => clearField(3);
+ /// The timestamp of the latest block.
@$pb.TagNumber(4)
$core.int get blockTime => $_getIZ(3);
@$pb.TagNumber(4)
@@ -183,6 +187,10 @@ class UtxosRequest extends $pb.GeneratedMessage {
static UtxosRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<UtxosRequest>(create);
static UtxosRequest? _defaultInstance;
+ /// The block height from which to start fetching utxos from.
+ /// After all mined utxos have been streamed, unconfirmed and
+ /// newly confirmed utxos will also be streamed. If this is set
+ /// to 0 then all utxos belonging to the account will be fetched.
@$pb.TagNumber(1)
$core.int get fromHeight => $_getIZ(0);
@$pb.TagNumber(1)
@@ -192,6 +200,8 @@ class UtxosRequest extends $pb.GeneratedMessage {
@$pb.TagNumber(1)
void clearFromHeight() => clearField(1);
+ /// The scan secret or view key represents the account for
+ /// which utxos should be streamed.
@$pb.TagNumber(2)
$core.List<$core.int> get scanSecret => $_getN(1);
@$pb.TagNumber(2)
@@ -262,6 +272,7 @@ class Utxo extends $pb.GeneratedMessage {
static Utxo getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Utxo>(create);
static Utxo? _defaultInstance;
+ /// The block height of the utxo, or 0 for unconfirmed.
@$pb.TagNumber(1)
$core.int get height => $_getIZ(0);
@$pb.TagNumber(1)
@@ -271,6 +282,7 @@ class Utxo extends $pb.GeneratedMessage {
@$pb.TagNumber(1)
void clearHeight() => clearField(1);
+ /// The value of the utxo in litoshis.
@$pb.TagNumber(2)
$fixnum.Int64 get value => $_getI64(1);
@$pb.TagNumber(2)
@@ -280,6 +292,7 @@ class Utxo extends $pb.GeneratedMessage {
@$pb.TagNumber(2)
void clearValue() => clearField(2);
+ /// The MWEB address that the utxo was received on.
@$pb.TagNumber(3)
$core.String get address => $_getSZ(2);
@$pb.TagNumber(3)
@@ -289,6 +302,8 @@ class Utxo extends $pb.GeneratedMessage {
@$pb.TagNumber(3)
void clearAddress() => clearField(3);
+ /// The output ID. This functions like a transaction hash,
+ /// but is unique to every utxo.
@$pb.TagNumber(4)
$core.String get outputId => $_getSZ(3);
@$pb.TagNumber(4)
@@ -298,6 +313,7 @@ class Utxo extends $pb.GeneratedMessage {
@$pb.TagNumber(4)
void clearOutputId() => clearField(4);
+ /// The timestamp of the block the utxo was mined in.
@$pb.TagNumber(5)
$core.int get blockTime => $_getIZ(4);
@$pb.TagNumber(5)
@@ -363,6 +379,7 @@ class AddressRequest extends $pb.GeneratedMessage {
static AddressRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AddressRequest>(create);
static AddressRequest? _defaultInstance;
+ /// The starting index of the range.
@$pb.TagNumber(1)
$core.int get fromIndex => $_getIZ(0);
@$pb.TagNumber(1)
@@ -372,6 +389,8 @@ class AddressRequest extends $pb.GeneratedMessage {
@$pb.TagNumber(1)
void clearFromIndex() => clearField(1);
+ /// The ending index of the range. The result will contain all
+ /// addresses up to but not including this index.
@$pb.TagNumber(2)
$core.int get toIndex => $_getIZ(1);
@$pb.TagNumber(2)
@@ -381,6 +400,8 @@ class AddressRequest extends $pb.GeneratedMessage {
@$pb.TagNumber(2)
void clearToIndex() => clearField(2);
+ /// The scan secret or view key represents the account for
+ /// which addresses should be returned.
@$pb.TagNumber(3)
$core.List<$core.int> get scanSecret => $_getN(2);
@$pb.TagNumber(3)
@@ -390,6 +411,9 @@ class AddressRequest extends $pb.GeneratedMessage {
@$pb.TagNumber(3)
void clearScanSecret() => clearField(3);
+ /// The public key of the spend secret for the account. The spend
+ /// key is required for spending utxos but is also required
+ /// for generating addresses.
@$pb.TagNumber(4)
$core.List<$core.int> get spendPubkey => $_getN(3);
@$pb.TagNumber(4)
@@ -440,10 +464,61 @@ class AddressResponse extends $pb.GeneratedMessage {
static AddressResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AddressResponse>(create);
static AddressResponse? _defaultInstance;
+ /// An array of MWEB addresses within the requested range.
@$pb.TagNumber(1)
$core.List<$core.String> get address => $_getList(0);
}
+class LedgerApdu extends $pb.GeneratedMessage {
+ factory LedgerApdu({
+ $core.List<$core.int>? data,
+ }) {
+ final $result = create();
+ if (data != null) {
+ $result.data = data;
+ }
+ return $result;
+ }
+ LedgerApdu._() : super();
+ factory LedgerApdu.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory LedgerApdu.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'LedgerApdu', createEmptyInstance: create)
+ ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'data', $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')
+ LedgerApdu clone() => LedgerApdu()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ LedgerApdu copyWith(void Function(LedgerApdu) updates) => super.copyWith((message) => updates(message as LedgerApdu)) as LedgerApdu;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static LedgerApdu create() => LedgerApdu._();
+ LedgerApdu createEmptyInstance() => create();
+ static $pb.PbList<LedgerApdu> createRepeated() => $pb.PbList<LedgerApdu>();
+ @$core.pragma('dart2js:noInline')
+ static LedgerApdu getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<LedgerApdu>(create);
+ static LedgerApdu? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.List<$core.int> get data => $_getN(0);
+ @$pb.TagNumber(1)
+ set data($core.List<$core.int> v) { $_setBytes(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasData() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearData() => clearField(1);
+}
+
class SpentRequest extends $pb.GeneratedMessage {
factory SpentRequest({
$core.Iterable<$core.String>? outputId,
@@ -484,6 +559,7 @@ class SpentRequest extends $pb.GeneratedMessage {
static SpentRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SpentRequest>(create);
static SpentRequest? _defaultInstance;
+ /// An array of output IDs to perform checks for.
@$pb.TagNumber(1)
$core.List<$core.String> get outputId => $_getList(0);
}
@@ -528,6 +604,9 @@ class SpentResponse extends $pb.GeneratedMessage {
static SpentResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<SpentResponse>(create);
static SpentResponse? _defaultInstance;
+ /// An array of the output IDs that were not found in the
+ /// unspent set. This means that the outputs are either
+ /// unconfirmed or were spent.
@$pb.TagNumber(1)
$core.List<$core.String> get outputId => $_getList(0);
}
@@ -592,6 +671,16 @@ class CreateRequest extends $pb.GeneratedMessage {
static CreateRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CreateRequest>(create);
static CreateRequest? _defaultInstance;
+ /// The raw bytes of the serialized transaction. This will be
+ /// a template where the non-MWEB inputs will remain unchanged,
+ /// and the MWEB inputs are specified by TxIns with the outpoint
+ /// hash set to the output ID of the utxo being spent, and the
+ /// outpoint index set to the index of the address that the utxo
+ /// was received on. MWEB outputs are specified by TxOuts with
+ /// the script pubkey set to the serialized scan and spend pubkeys
+ /// of the destination MWEB address. Any non-MWEB outputs will be
+ /// transformed into MWEB peg-outs. If the transaction doesn't
+ /// contain any MWEB i/o then the result will be unchanged.
@$pb.TagNumber(1)
$core.List<$core.int> get rawTx => $_getN(0);
@$pb.TagNumber(1)
@@ -601,6 +690,8 @@ class CreateRequest extends $pb.GeneratedMessage {
@$pb.TagNumber(1)
void clearRawTx() => clearField(1);
+ /// The scan secret or view key represents the account that
+ /// the utxos being spent belong to.
@$pb.TagNumber(2)
$core.List<$core.int> get scanSecret => $_getN(1);
@$pb.TagNumber(2)
@@ -610,6 +701,8 @@ class CreateRequest extends $pb.GeneratedMessage {
@$pb.TagNumber(2)
void clearScanSecret() => clearField(2);
+ /// The spend secret is the private key necessary for spending
+ /// the utxos belonging to the account.
@$pb.TagNumber(3)
$core.List<$core.int> get spendSecret => $_getN(2);
@$pb.TagNumber(3)
@@ -619,6 +712,7 @@ class CreateRequest extends $pb.GeneratedMessage {
@$pb.TagNumber(3)
void clearSpendSecret() => clearField(3);
+ /// The fee rate per KB in litoshis.
@$pb.TagNumber(4)
$fixnum.Int64 get feeRatePerKb => $_getI64(3);
@$pb.TagNumber(4)
@@ -628,6 +722,8 @@ class CreateRequest extends $pb.GeneratedMessage {
@$pb.TagNumber(4)
void clearFeeRatePerKb() => clearField(4);
+ /// Whether to skip MWEB transaction creation. This is useful
+ /// for fee estimation.
@$pb.TagNumber(5)
$core.bool get dryRun => $_getBF(4);
@$pb.TagNumber(5)
@@ -683,6 +779,10 @@ class CreateResponse extends $pb.GeneratedMessage {
static CreateResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CreateResponse>(create);
static CreateResponse? _defaultInstance;
+ /// The raw bytes of the serialized transaction. It will contain
+ /// a single TxOut representing the peg-in required. From this
+ /// it is possible to determine the addtional fee that was added
+ /// by the MWEB transaction.
@$pb.TagNumber(1)
$core.List<$core.int> get rawTx => $_getN(0);
@$pb.TagNumber(1)
@@ -692,26 +792,33 @@ class CreateResponse extends $pb.GeneratedMessage {
@$pb.TagNumber(1)
void clearRawTx() => clearField(1);
+ /// The output IDs of any utxos created by the transaction,
+ /// in the same order as in the template.
@$pb.TagNumber(2)
$core.List<$core.String> get outputId => $_getList(1);
}
-class BroadcastRequest extends $pb.GeneratedMessage {
- factory BroadcastRequest({
+class PsbtCreateRequest extends $pb.GeneratedMessage {
+ factory PsbtCreateRequest({
$core.List<$core.int>? rawTx,
+ $core.Iterable<TxOut>? witnessUtxo,
}) {
final $result = create();
if (rawTx != null) {
$result.rawTx = rawTx;
}
+ if (witnessUtxo != null) {
+ $result.witnessUtxo.addAll(witnessUtxo);
+ }
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);
+ PsbtCreateRequest._() : super();
+ factory PsbtCreateRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtCreateRequest.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)
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtCreateRequest', createEmptyInstance: create)
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'rawTx', $pb.PbFieldType.OY)
+ ..pc<TxOut>(2, _omitFieldNames ? '' : 'witnessUtxo', $pb.PbFieldType.PM, subBuilder: TxOut.create)
..hasRequiredFields = false
;
@@ -719,23 +826,24 @@ class BroadcastRequest extends $pb.GeneratedMessage {
'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);
+ PsbtCreateRequest clone() => PsbtCreateRequest()..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;
+ PsbtCreateRequest copyWith(void Function(PsbtCreateRequest) updates) => super.copyWith((message) => updates(message as PsbtCreateRequest)) as PsbtCreateRequest;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
- static BroadcastRequest create() => BroadcastRequest._();
- BroadcastRequest createEmptyInstance() => create();
- static $pb.PbList<BroadcastRequest> createRepeated() => $pb.PbList<BroadcastRequest>();
+ static PsbtCreateRequest create() => PsbtCreateRequest._();
+ PsbtCreateRequest createEmptyInstance() => create();
+ static $pb.PbList<PsbtCreateRequest> createRepeated() => $pb.PbList<PsbtCreateRequest>();
@$core.pragma('dart2js:noInline')
- static BroadcastRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BroadcastRequest>(create);
- static BroadcastRequest? _defaultInstance;
+ static PsbtCreateRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtCreateRequest>(create);
+ static PsbtCreateRequest? _defaultInstance;
+ /// The raw bytes of the serialized transaction.
@$pb.TagNumber(1)
$core.List<$core.int> get rawTx => $_getN(0);
@$pb.TagNumber(1)
@@ -744,24 +852,33 @@ class BroadcastRequest extends $pb.GeneratedMessage {
$core.bool hasRawTx() => $_has(0);
@$pb.TagNumber(1)
void clearRawTx() => clearField(1);
+
+ /// Witness utxos for each input.
+ @$pb.TagNumber(2)
+ $core.List<TxOut> get witnessUtxo => $_getList(1);
}
-class BroadcastResponse extends $pb.GeneratedMessage {
- factory BroadcastResponse({
- $core.String? txid,
+class TxOut extends $pb.GeneratedMessage {
+ factory TxOut({
+ $fixnum.Int64? value,
+ $core.List<$core.int>? pkScript,
}) {
final $result = create();
- if (txid != null) {
- $result.txid = txid;
+ if (value != null) {
+ $result.value = value;
+ }
+ if (pkScript != null) {
+ $result.pkScript = pkScript;
}
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);
+ TxOut._() : super();
+ factory TxOut.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory TxOut.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')
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'TxOut', createEmptyInstance: create)
+ ..aInt64(1, _omitFieldNames ? '' : 'value')
+ ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'pkScript', $pb.PbFieldType.OY)
..hasRequiredFields = false
;
@@ -769,33 +886,934 @@ class BroadcastResponse extends $pb.GeneratedMessage {
'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);
+ TxOut clone() => TxOut()..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;
+ TxOut copyWith(void Function(TxOut) updates) => super.copyWith((message) => updates(message as TxOut)) as TxOut;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
- static BroadcastResponse create() => BroadcastResponse._();
- BroadcastResponse createEmptyInstance() => create();
- static $pb.PbList<BroadcastResponse> createRepeated() => $pb.PbList<BroadcastResponse>();
+ static TxOut create() => TxOut._();
+ TxOut createEmptyInstance() => create();
+ static $pb.PbList<TxOut> createRepeated() => $pb.PbList<TxOut>();
@$core.pragma('dart2js:noInline')
- static BroadcastResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BroadcastResponse>(create);
- static BroadcastResponse? _defaultInstance;
+ static TxOut getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<TxOut>(create);
+ static TxOut? _defaultInstance;
@$pb.TagNumber(1)
- $core.String get txid => $_getSZ(0);
+ $fixnum.Int64 get value => $_getI64(0);
@$pb.TagNumber(1)
- set txid($core.String v) { $_setString(0, v); }
+ set value($fixnum.Int64 v) { $_setInt64(0, v); }
@$pb.TagNumber(1)
- $core.bool hasTxid() => $_has(0);
+ $core.bool hasValue() => $_has(0);
@$pb.TagNumber(1)
- void clearTxid() => clearField(1);
+ void clearValue() => clearField(1);
+
+ @$pb.TagNumber(2)
+ $core.List<$core.int> get pkScript => $_getN(1);
+ @$pb.TagNumber(2)
+ set pkScript($core.List<$core.int> v) { $_setBytes(1, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasPkScript() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearPkScript() => clearField(2);
+}
+
+class PsbtResponse extends $pb.GeneratedMessage {
+ factory PsbtResponse({
+ $core.String? psbtB64,
+ }) {
+ final $result = create();
+ if (psbtB64 != null) {
+ $result.psbtB64 = psbtB64;
+ }
+ return $result;
+ }
+ PsbtResponse._() : super();
+ factory PsbtResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtResponse', createEmptyInstance: create)
+ ..aOS(1, _omitFieldNames ? '' : 'psbtB64')
+ ..hasRequiredFields = false
+ ;
+
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ PsbtResponse clone() => PsbtResponse()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtResponse copyWith(void Function(PsbtResponse) updates) => super.copyWith((message) => updates(message as PsbtResponse)) as PsbtResponse;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtResponse create() => PsbtResponse._();
+ PsbtResponse createEmptyInstance() => create();
+ static $pb.PbList<PsbtResponse> createRepeated() => $pb.PbList<PsbtResponse>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtResponse>(create);
+ static PsbtResponse? _defaultInstance;
+
+ /// The PSBT in base64 encoding.
+ @$pb.TagNumber(1)
+ $core.String get psbtB64 => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set psbtB64($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasPsbtB64() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPsbtB64() => clearField(1);
+}
+
+class PsbtAddInputRequest extends $pb.GeneratedMessage {
+ factory PsbtAddInputRequest({
+ $core.String? psbtB64,
+ $core.List<$core.int>? scanSecret,
+ $core.String? outputId,
+ $core.int? addressIndex,
+ }) {
+ final $result = create();
+ if (psbtB64 != null) {
+ $result.psbtB64 = psbtB64;
+ }
+ if (scanSecret != null) {
+ $result.scanSecret = scanSecret;
+ }
+ if (outputId != null) {
+ $result.outputId = outputId;
+ }
+ if (addressIndex != null) {
+ $result.addressIndex = addressIndex;
+ }
+ return $result;
+ }
+ PsbtAddInputRequest._() : super();
+ factory PsbtAddInputRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtAddInputRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtAddInputRequest', createEmptyInstance: create)
+ ..aOS(1, _omitFieldNames ? '' : 'psbtB64')
+ ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'scanSecret', $pb.PbFieldType.OY)
+ ..aOS(3, _omitFieldNames ? '' : 'outputId')
+ ..a<$core.int>(4, _omitFieldNames ? '' : 'addressIndex', $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')
+ PsbtAddInputRequest clone() => PsbtAddInputRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtAddInputRequest copyWith(void Function(PsbtAddInputRequest) updates) => super.copyWith((message) => updates(message as PsbtAddInputRequest)) as PsbtAddInputRequest;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtAddInputRequest create() => PsbtAddInputRequest._();
+ PsbtAddInputRequest createEmptyInstance() => create();
+ static $pb.PbList<PsbtAddInputRequest> createRepeated() => $pb.PbList<PsbtAddInputRequest>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtAddInputRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtAddInputRequest>(create);
+ static PsbtAddInputRequest? _defaultInstance;
+
+ /// The PSBT in base64 encoding.
+ @$pb.TagNumber(1)
+ $core.String get psbtB64 => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set psbtB64($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasPsbtB64() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPsbtB64() => clearField(1);
+
+ /// The scan secret or view key represents the account that
+ /// the utxos being spent belong to.
+ @$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);
+
+ /// The output ID of the utxo.
+ @$pb.TagNumber(3)
+ $core.String get outputId => $_getSZ(2);
+ @$pb.TagNumber(3)
+ set outputId($core.String v) { $_setString(2, v); }
+ @$pb.TagNumber(3)
+ $core.bool hasOutputId() => $_has(2);
+ @$pb.TagNumber(3)
+ void clearOutputId() => clearField(3);
+
+ /// The address index of the utxo.
+ @$pb.TagNumber(4)
+ $core.int get addressIndex => $_getIZ(3);
+ @$pb.TagNumber(4)
+ set addressIndex($core.int v) { $_setUnsignedInt32(3, v); }
+ @$pb.TagNumber(4)
+ $core.bool hasAddressIndex() => $_has(3);
+ @$pb.TagNumber(4)
+ void clearAddressIndex() => clearField(4);
+}
+
+class PsbtAddRecipientRequest extends $pb.GeneratedMessage {
+ factory PsbtAddRecipientRequest({
+ $core.String? psbtB64,
+ PsbtRecipient? recipient,
+ $fixnum.Int64? feeRatePerKb,
+ }) {
+ final $result = create();
+ if (psbtB64 != null) {
+ $result.psbtB64 = psbtB64;
+ }
+ if (recipient != null) {
+ $result.recipient = recipient;
+ }
+ if (feeRatePerKb != null) {
+ $result.feeRatePerKb = feeRatePerKb;
+ }
+ return $result;
+ }
+ PsbtAddRecipientRequest._() : super();
+ factory PsbtAddRecipientRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtAddRecipientRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtAddRecipientRequest', createEmptyInstance: create)
+ ..aOS(1, _omitFieldNames ? '' : 'psbtB64')
+ ..aOM<PsbtRecipient>(2, _omitFieldNames ? '' : 'recipient', subBuilder: PsbtRecipient.create)
+ ..a<$fixnum.Int64>(3, _omitFieldNames ? '' : 'feeRatePerKb', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO)
+ ..hasRequiredFields = false
+ ;
+
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ PsbtAddRecipientRequest clone() => PsbtAddRecipientRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtAddRecipientRequest copyWith(void Function(PsbtAddRecipientRequest) updates) => super.copyWith((message) => updates(message as PsbtAddRecipientRequest)) as PsbtAddRecipientRequest;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtAddRecipientRequest create() => PsbtAddRecipientRequest._();
+ PsbtAddRecipientRequest createEmptyInstance() => create();
+ static $pb.PbList<PsbtAddRecipientRequest> createRepeated() => $pb.PbList<PsbtAddRecipientRequest>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtAddRecipientRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtAddRecipientRequest>(create);
+ static PsbtAddRecipientRequest? _defaultInstance;
+
+ /// The PSBT in base64 encoding.
+ @$pb.TagNumber(1)
+ $core.String get psbtB64 => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set psbtB64($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasPsbtB64() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPsbtB64() => clearField(1);
+
+ @$pb.TagNumber(2)
+ PsbtRecipient get recipient => $_getN(1);
+ @$pb.TagNumber(2)
+ set recipient(PsbtRecipient v) { setField(2, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasRecipient() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearRecipient() => clearField(2);
+ @$pb.TagNumber(2)
+ PsbtRecipient ensureRecipient() => $_ensure(1);
+
+ /// The fee rate per KB in litoshis.
+ @$pb.TagNumber(3)
+ $fixnum.Int64 get feeRatePerKb => $_getI64(2);
+ @$pb.TagNumber(3)
+ set feeRatePerKb($fixnum.Int64 v) { $_setInt64(2, v); }
+ @$pb.TagNumber(3)
+ $core.bool hasFeeRatePerKb() => $_has(2);
+ @$pb.TagNumber(3)
+ void clearFeeRatePerKb() => clearField(3);
+}
+
+class PsbtGetRecipientsRequest extends $pb.GeneratedMessage {
+ factory PsbtGetRecipientsRequest({
+ $core.String? psbtB64,
+ }) {
+ final $result = create();
+ if (psbtB64 != null) {
+ $result.psbtB64 = psbtB64;
+ }
+ return $result;
+ }
+ PsbtGetRecipientsRequest._() : super();
+ factory PsbtGetRecipientsRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtGetRecipientsRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtGetRecipientsRequest', createEmptyInstance: create)
+ ..aOS(1, _omitFieldNames ? '' : 'psbtB64')
+ ..hasRequiredFields = false
+ ;
+
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ PsbtGetRecipientsRequest clone() => PsbtGetRecipientsRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtGetRecipientsRequest copyWith(void Function(PsbtGetRecipientsRequest) updates) => super.copyWith((message) => updates(message as PsbtGetRecipientsRequest)) as PsbtGetRecipientsRequest;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtGetRecipientsRequest create() => PsbtGetRecipientsRequest._();
+ PsbtGetRecipientsRequest createEmptyInstance() => create();
+ static $pb.PbList<PsbtGetRecipientsRequest> createRepeated() => $pb.PbList<PsbtGetRecipientsRequest>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtGetRecipientsRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtGetRecipientsRequest>(create);
+ static PsbtGetRecipientsRequest? _defaultInstance;
+
+ /// The PSBT in base64 encoding.
+ @$pb.TagNumber(1)
+ $core.String get psbtB64 => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set psbtB64($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasPsbtB64() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPsbtB64() => clearField(1);
+}
+
+class PsbtGetRecipientsResponse extends $pb.GeneratedMessage {
+ factory PsbtGetRecipientsResponse({
+ $core.Iterable<PsbtRecipient>? recipient,
+ $core.Iterable<$core.String>? inputAddress,
+ $fixnum.Int64? fee,
+ }) {
+ final $result = create();
+ if (recipient != null) {
+ $result.recipient.addAll(recipient);
+ }
+ if (inputAddress != null) {
+ $result.inputAddress.addAll(inputAddress);
+ }
+ if (fee != null) {
+ $result.fee = fee;
+ }
+ return $result;
+ }
+ PsbtGetRecipientsResponse._() : super();
+ factory PsbtGetRecipientsResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtGetRecipientsResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtGetRecipientsResponse', createEmptyInstance: create)
+ ..pc<PsbtRecipient>(1, _omitFieldNames ? '' : 'recipient', $pb.PbFieldType.PM, subBuilder: PsbtRecipient.create)
+ ..pPS(2, _omitFieldNames ? '' : 'inputAddress')
+ ..aInt64(3, _omitFieldNames ? '' : 'fee')
+ ..hasRequiredFields = false
+ ;
+
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ PsbtGetRecipientsResponse clone() => PsbtGetRecipientsResponse()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtGetRecipientsResponse copyWith(void Function(PsbtGetRecipientsResponse) updates) => super.copyWith((message) => updates(message as PsbtGetRecipientsResponse)) as PsbtGetRecipientsResponse;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtGetRecipientsResponse create() => PsbtGetRecipientsResponse._();
+ PsbtGetRecipientsResponse createEmptyInstance() => create();
+ static $pb.PbList<PsbtGetRecipientsResponse> createRepeated() => $pb.PbList<PsbtGetRecipientsResponse>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtGetRecipientsResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtGetRecipientsResponse>(create);
+ static PsbtGetRecipientsResponse? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.List<PsbtRecipient> get recipient => $_getList(0);
+
+ @$pb.TagNumber(2)
+ $core.List<$core.String> get inputAddress => $_getList(1);
+
+ @$pb.TagNumber(3)
+ $fixnum.Int64 get fee => $_getI64(2);
+ @$pb.TagNumber(3)
+ set fee($fixnum.Int64 v) { $_setInt64(2, v); }
+ @$pb.TagNumber(3)
+ $core.bool hasFee() => $_has(2);
+ @$pb.TagNumber(3)
+ void clearFee() => clearField(3);
+}
+
+class PsbtRecipient extends $pb.GeneratedMessage {
+ factory PsbtRecipient({
+ $core.String? address,
+ $fixnum.Int64? value,
+ }) {
+ final $result = create();
+ if (address != null) {
+ $result.address = address;
+ }
+ if (value != null) {
+ $result.value = value;
+ }
+ return $result;
+ }
+ PsbtRecipient._() : super();
+ factory PsbtRecipient.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtRecipient.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtRecipient', createEmptyInstance: create)
+ ..aOS(1, _omitFieldNames ? '' : 'address')
+ ..aInt64(2, _omitFieldNames ? '' : 'value')
+ ..hasRequiredFields = false
+ ;
+
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ PsbtRecipient clone() => PsbtRecipient()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtRecipient copyWith(void Function(PsbtRecipient) updates) => super.copyWith((message) => updates(message as PsbtRecipient)) as PsbtRecipient;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtRecipient create() => PsbtRecipient._();
+ PsbtRecipient createEmptyInstance() => create();
+ static $pb.PbList<PsbtRecipient> createRepeated() => $pb.PbList<PsbtRecipient>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtRecipient getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtRecipient>(create);
+ static PsbtRecipient? _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get address => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set address($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasAddress() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearAddress() => 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);
+}
+
+class PsbtSignRequest extends $pb.GeneratedMessage {
+ factory PsbtSignRequest({
+ $core.String? psbtB64,
+ $core.List<$core.int>? scanSecret,
+ $core.List<$core.int>? spendSecret,
+ }) {
+ final $result = create();
+ if (psbtB64 != null) {
+ $result.psbtB64 = psbtB64;
+ }
+ if (scanSecret != null) {
+ $result.scanSecret = scanSecret;
+ }
+ if (spendSecret != null) {
+ $result.spendSecret = spendSecret;
+ }
+ return $result;
+ }
+ PsbtSignRequest._() : super();
+ factory PsbtSignRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtSignRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtSignRequest', createEmptyInstance: create)
+ ..aOS(1, _omitFieldNames ? '' : 'psbtB64')
+ ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'scanSecret', $pb.PbFieldType.OY)
+ ..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'spendSecret', $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')
+ PsbtSignRequest clone() => PsbtSignRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtSignRequest copyWith(void Function(PsbtSignRequest) updates) => super.copyWith((message) => updates(message as PsbtSignRequest)) as PsbtSignRequest;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtSignRequest create() => PsbtSignRequest._();
+ PsbtSignRequest createEmptyInstance() => create();
+ static $pb.PbList<PsbtSignRequest> createRepeated() => $pb.PbList<PsbtSignRequest>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtSignRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtSignRequest>(create);
+ static PsbtSignRequest? _defaultInstance;
+
+ /// The PSBT in base64 encoding.
+ @$pb.TagNumber(1)
+ $core.String get psbtB64 => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set psbtB64($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasPsbtB64() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPsbtB64() => clearField(1);
+
+ /// The scan secret or view key represents the account that
+ /// the utxos being spent belong to.
+ @$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);
+
+ /// The spend secret is the private key necessary for spending
+ /// the utxos belonging to the account.
+ @$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);
+}
+
+class PsbtSignNonMwebRequest extends $pb.GeneratedMessage {
+ factory PsbtSignNonMwebRequest({
+ $core.String? psbtB64,
+ $core.List<$core.int>? privKey,
+ $core.int? index,
+ }) {
+ final $result = create();
+ if (psbtB64 != null) {
+ $result.psbtB64 = psbtB64;
+ }
+ if (privKey != null) {
+ $result.privKey = privKey;
+ }
+ if (index != null) {
+ $result.index = index;
+ }
+ return $result;
+ }
+ PsbtSignNonMwebRequest._() : super();
+ factory PsbtSignNonMwebRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtSignNonMwebRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtSignNonMwebRequest', createEmptyInstance: create)
+ ..aOS(1, _omitFieldNames ? '' : 'psbtB64')
+ ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'privKey', $pb.PbFieldType.OY)
+ ..a<$core.int>(3, _omitFieldNames ? '' : 'index', $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')
+ PsbtSignNonMwebRequest clone() => PsbtSignNonMwebRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtSignNonMwebRequest copyWith(void Function(PsbtSignNonMwebRequest) updates) => super.copyWith((message) => updates(message as PsbtSignNonMwebRequest)) as PsbtSignNonMwebRequest;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtSignNonMwebRequest create() => PsbtSignNonMwebRequest._();
+ PsbtSignNonMwebRequest createEmptyInstance() => create();
+ static $pb.PbList<PsbtSignNonMwebRequest> createRepeated() => $pb.PbList<PsbtSignNonMwebRequest>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtSignNonMwebRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtSignNonMwebRequest>(create);
+ static PsbtSignNonMwebRequest? _defaultInstance;
+
+ /// The PSBT in base64 encoding.
+ @$pb.TagNumber(1)
+ $core.String get psbtB64 => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set psbtB64($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasPsbtB64() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPsbtB64() => clearField(1);
+
+ /// The private key necessary for spending the input.
+ @$pb.TagNumber(2)
+ $core.List<$core.int> get privKey => $_getN(1);
+ @$pb.TagNumber(2)
+ set privKey($core.List<$core.int> v) { $_setBytes(1, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasPrivKey() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearPrivKey() => clearField(2);
+
+ /// The index of the input to sign.
+ @$pb.TagNumber(3)
+ $core.int get index => $_getIZ(2);
+ @$pb.TagNumber(3)
+ set index($core.int v) { $_setUnsignedInt32(2, v); }
+ @$pb.TagNumber(3)
+ $core.bool hasIndex() => $_has(2);
+ @$pb.TagNumber(3)
+ void clearIndex() => clearField(3);
+}
+
+class PsbtExtractRequest extends $pb.GeneratedMessage {
+ factory PsbtExtractRequest({
+ $core.String? psbtB64,
+ $core.bool? unsigned,
+ }) {
+ final $result = create();
+ if (psbtB64 != null) {
+ $result.psbtB64 = psbtB64;
+ }
+ if (unsigned != null) {
+ $result.unsigned = unsigned;
+ }
+ return $result;
+ }
+ PsbtExtractRequest._() : super();
+ factory PsbtExtractRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory PsbtExtractRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'PsbtExtractRequest', createEmptyInstance: create)
+ ..aOS(1, _omitFieldNames ? '' : 'psbtB64')
+ ..aOB(2, _omitFieldNames ? '' : 'unsigned')
+ ..hasRequiredFields = false
+ ;
+
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
+ 'Will be removed in next major version')
+ PsbtExtractRequest clone() => PsbtExtractRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ PsbtExtractRequest copyWith(void Function(PsbtExtractRequest) updates) => super.copyWith((message) => updates(message as PsbtExtractRequest)) as PsbtExtractRequest;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static PsbtExtractRequest create() => PsbtExtractRequest._();
+ PsbtExtractRequest createEmptyInstance() => create();
+ static $pb.PbList<PsbtExtractRequest> createRepeated() => $pb.PbList<PsbtExtractRequest>();
+ @$core.pragma('dart2js:noInline')
+ static PsbtExtractRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<PsbtExtractRequest>(create);
+ static PsbtExtractRequest? _defaultInstance;
+
+ /// The PSBT in base64 encoding.
+ @$pb.TagNumber(1)
+ $core.String get psbtB64 => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set psbtB64($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasPsbtB64() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPsbtB64() => clearField(1);
+
+ /// Extract the unsigned transaction.
+ @$pb.TagNumber(2)
+ $core.bool get unsigned => $_getBF(1);
+ @$pb.TagNumber(2)
+ set unsigned($core.bool v) { $_setBool(1, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasUnsigned() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearUnsigned() => clearField(2);
+}
+
+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;
+
+ /// The raw bytes of the serialized transaction.
+ @$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;
+
+ /// The transaction ID.
+ @$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);
+}
+
+class CoinswapRequest extends $pb.GeneratedMessage {
+ factory CoinswapRequest({
+ $core.List<$core.int>? scanSecret,
+ $core.List<$core.int>? spendSecret,
+ $core.String? outputId,
+ $core.int? addrIndex,
+ }) {
+ final $result = create();
+ if (scanSecret != null) {
+ $result.scanSecret = scanSecret;
+ }
+ if (spendSecret != null) {
+ $result.spendSecret = spendSecret;
+ }
+ if (outputId != null) {
+ $result.outputId = outputId;
+ }
+ if (addrIndex != null) {
+ $result.addrIndex = addrIndex;
+ }
+ return $result;
+ }
+ CoinswapRequest._() : super();
+ factory CoinswapRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory CoinswapRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CoinswapRequest', createEmptyInstance: create)
+ ..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'scanSecret', $pb.PbFieldType.OY)
+ ..a<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'spendSecret', $pb.PbFieldType.OY)
+ ..aOS(3, _omitFieldNames ? '' : 'outputId')
+ ..a<$core.int>(4, _omitFieldNames ? '' : 'addrIndex', $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')
+ CoinswapRequest clone() => CoinswapRequest()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ CoinswapRequest copyWith(void Function(CoinswapRequest) updates) => super.copyWith((message) => updates(message as CoinswapRequest)) as CoinswapRequest;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static CoinswapRequest create() => CoinswapRequest._();
+ CoinswapRequest createEmptyInstance() => create();
+ static $pb.PbList<CoinswapRequest> createRepeated() => $pb.PbList<CoinswapRequest>();
+ @$core.pragma('dart2js:noInline')
+ static CoinswapRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CoinswapRequest>(create);
+ static CoinswapRequest? _defaultInstance;
+
+ /// The scan secret or view key represents the account that
+ /// the utxo belongs to.
+ @$pb.TagNumber(1)
+ $core.List<$core.int> get scanSecret => $_getN(0);
+ @$pb.TagNumber(1)
+ set scanSecret($core.List<$core.int> v) { $_setBytes(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasScanSecret() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearScanSecret() => clearField(1);
+
+ /// The spend secret is the private key necessary for spending
+ /// the utxos belonging to the account.
+ @$pb.TagNumber(2)
+ $core.List<$core.int> get spendSecret => $_getN(1);
+ @$pb.TagNumber(2)
+ set spendSecret($core.List<$core.int> v) { $_setBytes(1, v); }
+ @$pb.TagNumber(2)
+ $core.bool hasSpendSecret() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearSpendSecret() => clearField(2);
+
+ /// Output ID of the utxo to request a coinswap for.
+ @$pb.TagNumber(3)
+ $core.String get outputId => $_getSZ(2);
+ @$pb.TagNumber(3)
+ set outputId($core.String v) { $_setString(2, v); }
+ @$pb.TagNumber(3)
+ $core.bool hasOutputId() => $_has(2);
+ @$pb.TagNumber(3)
+ void clearOutputId() => clearField(3);
+
+ /// Address index of the utxo.
+ @$pb.TagNumber(4)
+ $core.int get addrIndex => $_getIZ(3);
+ @$pb.TagNumber(4)
+ set addrIndex($core.int v) { $_setUnsignedInt32(3, v); }
+ @$pb.TagNumber(4)
+ $core.bool hasAddrIndex() => $_has(3);
+ @$pb.TagNumber(4)
+ void clearAddrIndex() => clearField(4);
+}
+
+class CoinswapResponse extends $pb.GeneratedMessage {
+ factory CoinswapResponse({
+ $core.String? outputId,
+ }) {
+ final $result = create();
+ if (outputId != null) {
+ $result.outputId = outputId;
+ }
+ return $result;
+ }
+ CoinswapResponse._() : super();
+ factory CoinswapResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+ factory CoinswapResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'CoinswapResponse', createEmptyInstance: create)
+ ..aOS(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')
+ CoinswapResponse clone() => CoinswapResponse()..mergeFromMessage(this);
+ @$core.Deprecated(
+ 'Using this can add significant overhead to your binary. '
+ 'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
+ 'Will be removed in next major version')
+ CoinswapResponse copyWith(void Function(CoinswapResponse) updates) => super.copyWith((message) => updates(message as CoinswapResponse)) as CoinswapResponse;
+
+ $pb.BuilderInfo get info_ => _i;
+
+ @$core.pragma('dart2js:noInline')
+ static CoinswapResponse create() => CoinswapResponse._();
+ CoinswapResponse createEmptyInstance() => create();
+ static $pb.PbList<CoinswapResponse> createRepeated() => $pb.PbList<CoinswapResponse>();
+ @$core.pragma('dart2js:noInline')
+ static CoinswapResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<CoinswapResponse>(create);
+ static CoinswapResponse? _defaultInstance;
+
+ /// Output ID of the utxo created by the transaction.
+ @$pb.TagNumber(1)
+ $core.String get outputId => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set outputId($core.String v) { $_setString(0, v); }
+ @$pb.TagNumber(1)
+ $core.bool hasOutputId() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearOutputId() => clearField(1);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
-const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
+const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
\ No newline at end of file
diff --git a/cw_mweb/lib/mwebd.pbgrpc.dart b/cw_mweb/lib/mwebd.pbgrpc.dart
index 6bc48cf..b5a2852 100644
--- a/cw_mweb/lib/mwebd.pbgrpc.dart
+++ b/cw_mweb/lib/mwebd.pbgrpc.dart
@@ -41,10 +41,46 @@ class RpcClient extends $grpc.Client {
'/Rpc/Create',
($0.CreateRequest value) => value.writeToBuffer(),
($core.List<$core.int> value) => $0.CreateResponse.fromBuffer(value));
+ static final _$psbtCreate = $grpc.ClientMethod<$0.PsbtCreateRequest, $0.PsbtResponse>(
+ '/Rpc/PsbtCreate',
+ ($0.PsbtCreateRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.PsbtResponse.fromBuffer(value));
+ static final _$psbtAddInput = $grpc.ClientMethod<$0.PsbtAddInputRequest, $0.PsbtResponse>(
+ '/Rpc/PsbtAddInput',
+ ($0.PsbtAddInputRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.PsbtResponse.fromBuffer(value));
+ static final _$psbtAddRecipient = $grpc.ClientMethod<$0.PsbtAddRecipientRequest, $0.PsbtResponse>(
+ '/Rpc/PsbtAddRecipient',
+ ($0.PsbtAddRecipientRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.PsbtResponse.fromBuffer(value));
+ static final _$psbtGetRecipients = $grpc.ClientMethod<$0.PsbtGetRecipientsRequest, $0.PsbtGetRecipientsResponse>(
+ '/Rpc/PsbtGetRecipients',
+ ($0.PsbtGetRecipientsRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.PsbtGetRecipientsResponse.fromBuffer(value));
+ static final _$psbtSign = $grpc.ClientMethod<$0.PsbtSignRequest, $0.PsbtResponse>(
+ '/Rpc/PsbtSign',
+ ($0.PsbtSignRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.PsbtResponse.fromBuffer(value));
+ static final _$psbtSignNonMweb = $grpc.ClientMethod<$0.PsbtSignNonMwebRequest, $0.PsbtResponse>(
+ '/Rpc/PsbtSignNonMweb',
+ ($0.PsbtSignNonMwebRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.PsbtResponse.fromBuffer(value));
+ static final _$psbtExtract = $grpc.ClientMethod<$0.PsbtExtractRequest, $0.CreateResponse>(
+ '/Rpc/PsbtExtract',
+ ($0.PsbtExtractRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.CreateResponse.fromBuffer(value));
+ static final _$ledgerExchange = $grpc.ClientMethod<$0.LedgerApdu, $0.LedgerApdu>(
+ '/Rpc/LedgerExchange',
+ ($0.LedgerApdu value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.LedgerApdu.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));
+ static final _$coinswap = $grpc.ClientMethod<$0.CoinswapRequest, $0.CoinswapResponse>(
+ '/Rpc/Coinswap',
+ ($0.CoinswapRequest value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.CoinswapResponse.fromBuffer(value));
RpcClient($grpc.ClientChannel channel,
{$grpc.CallOptions? options,
@@ -72,9 +108,45 @@ class RpcClient extends $grpc.Client {
return $createUnaryCall(_$create, request, options: options);
}
+ $grpc.ResponseFuture<$0.PsbtResponse> psbtCreate($0.PsbtCreateRequest request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$psbtCreate, request, options: options);
+ }
+
+ $grpc.ResponseFuture<$0.PsbtResponse> psbtAddInput($0.PsbtAddInputRequest request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$psbtAddInput, request, options: options);
+ }
+
+ $grpc.ResponseFuture<$0.PsbtResponse> psbtAddRecipient($0.PsbtAddRecipientRequest request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$psbtAddRecipient, request, options: options);
+ }
+
+ $grpc.ResponseFuture<$0.PsbtGetRecipientsResponse> psbtGetRecipients($0.PsbtGetRecipientsRequest request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$psbtGetRecipients, request, options: options);
+ }
+
+ $grpc.ResponseFuture<$0.PsbtResponse> psbtSign($0.PsbtSignRequest request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$psbtSign, request, options: options);
+ }
+
+ $grpc.ResponseFuture<$0.PsbtResponse> psbtSignNonMweb($0.PsbtSignNonMwebRequest request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$psbtSignNonMweb, request, options: options);
+ }
+
+ $grpc.ResponseFuture<$0.CreateResponse> psbtExtract($0.PsbtExtractRequest request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$psbtExtract, request, options: options);
+ }
+
+ $grpc.ResponseFuture<$0.LedgerApdu> ledgerExchange($0.LedgerApdu request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$ledgerExchange, request, options: options);
+ }
+
$grpc.ResponseFuture<$0.BroadcastResponse> broadcast($0.BroadcastRequest request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$broadcast, request, options: options);
}
+
+ $grpc.ResponseFuture<$0.CoinswapResponse> coinswap($0.CoinswapRequest request, {$grpc.CallOptions? options}) {
+ return $createUnaryCall(_$coinswap, request, options: options);
+ }
}
@$pb.GrpcServiceName('Rpc')
@@ -117,6 +189,62 @@ abstract class RpcServiceBase extends $grpc.Service {
false,
($core.List<$core.int> value) => $0.CreateRequest.fromBuffer(value),
($0.CreateResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.PsbtCreateRequest, $0.PsbtResponse>(
+ 'PsbtCreate',
+ psbtCreate_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.PsbtCreateRequest.fromBuffer(value),
+ ($0.PsbtResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.PsbtAddInputRequest, $0.PsbtResponse>(
+ 'PsbtAddInput',
+ psbtAddInput_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.PsbtAddInputRequest.fromBuffer(value),
+ ($0.PsbtResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.PsbtAddRecipientRequest, $0.PsbtResponse>(
+ 'PsbtAddRecipient',
+ psbtAddRecipient_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.PsbtAddRecipientRequest.fromBuffer(value),
+ ($0.PsbtResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.PsbtGetRecipientsRequest, $0.PsbtGetRecipientsResponse>(
+ 'PsbtGetRecipients',
+ psbtGetRecipients_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.PsbtGetRecipientsRequest.fromBuffer(value),
+ ($0.PsbtGetRecipientsResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.PsbtSignRequest, $0.PsbtResponse>(
+ 'PsbtSign',
+ psbtSign_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.PsbtSignRequest.fromBuffer(value),
+ ($0.PsbtResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.PsbtSignNonMwebRequest, $0.PsbtResponse>(
+ 'PsbtSignNonMweb',
+ psbtSignNonMweb_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.PsbtSignNonMwebRequest.fromBuffer(value),
+ ($0.PsbtResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.PsbtExtractRequest, $0.CreateResponse>(
+ 'PsbtExtract',
+ psbtExtract_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.PsbtExtractRequest.fromBuffer(value),
+ ($0.CreateResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.LedgerApdu, $0.LedgerApdu>(
+ 'LedgerExchange',
+ ledgerExchange_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.LedgerApdu.fromBuffer(value),
+ ($0.LedgerApdu value) => value.writeToBuffer()));
$addMethod($grpc.ServiceMethod<$0.BroadcastRequest, $0.BroadcastResponse>(
'Broadcast',
broadcast_Pre,
@@ -124,6 +252,13 @@ abstract class RpcServiceBase extends $grpc.Service {
false,
($core.List<$core.int> value) => $0.BroadcastRequest.fromBuffer(value),
($0.BroadcastResponse value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.CoinswapRequest, $0.CoinswapResponse>(
+ 'Coinswap',
+ coinswap_Pre,
+ false,
+ false,
+ ($core.List<$core.int> value) => $0.CoinswapRequest.fromBuffer(value),
+ ($0.CoinswapResponse value) => value.writeToBuffer()));
}
$async.Future<$0.StatusResponse> status_Pre($grpc.ServiceCall call, $async.Future<$0.StatusRequest> request) async {
@@ -146,14 +281,59 @@ abstract class RpcServiceBase extends $grpc.Service {
return create(call, await request);
}
+ $async.Future<$0.PsbtResponse> psbtCreate_Pre($grpc.ServiceCall call, $async.Future<$0.PsbtCreateRequest> request) async {
+ return psbtCreate(call, await request);
+ }
+
+ $async.Future<$0.PsbtResponse> psbtAddInput_Pre($grpc.ServiceCall call, $async.Future<$0.PsbtAddInputRequest> request) async {
+ return psbtAddInput(call, await request);
+ }
+
+ $async.Future<$0.PsbtResponse> psbtAddRecipient_Pre($grpc.ServiceCall call, $async.Future<$0.PsbtAddRecipientRequest> request) async {
+ return psbtAddRecipient(call, await request);
+ }
+
+ $async.Future<$0.PsbtGetRecipientsResponse> psbtGetRecipients_Pre($grpc.ServiceCall call, $async.Future<$0.PsbtGetRecipientsRequest> request) async {
+ return psbtGetRecipients(call, await request);
+ }
+
+ $async.Future<$0.PsbtResponse> psbtSign_Pre($grpc.ServiceCall call, $async.Future<$0.PsbtSignRequest> request) async {
+ return psbtSign(call, await request);
+ }
+
+ $async.Future<$0.PsbtResponse> psbtSignNonMweb_Pre($grpc.ServiceCall call, $async.Future<$0.PsbtSignNonMwebRequest> request) async {
+ return psbtSignNonMweb(call, await request);
+ }
+
+ $async.Future<$0.CreateResponse> psbtExtract_Pre($grpc.ServiceCall call, $async.Future<$0.PsbtExtractRequest> request) async {
+ return psbtExtract(call, await request);
+ }
+
+ $async.Future<$0.LedgerApdu> ledgerExchange_Pre($grpc.ServiceCall call, $async.Future<$0.LedgerApdu> request) async {
+ return ledgerExchange(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.CoinswapResponse> coinswap_Pre($grpc.ServiceCall call, $async.Future<$0.CoinswapRequest> request) async {
+ return coinswap(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.PsbtResponse> psbtCreate($grpc.ServiceCall call, $0.PsbtCreateRequest request);
+ $async.Future<$0.PsbtResponse> psbtAddInput($grpc.ServiceCall call, $0.PsbtAddInputRequest request);
+ $async.Future<$0.PsbtResponse> psbtAddRecipient($grpc.ServiceCall call, $0.PsbtAddRecipientRequest request);
+ $async.Future<$0.PsbtGetRecipientsResponse> psbtGetRecipients($grpc.ServiceCall call, $0.PsbtGetRecipientsRequest request);
+ $async.Future<$0.PsbtResponse> psbtSign($grpc.ServiceCall call, $0.PsbtSignRequest request);
+ $async.Future<$0.PsbtResponse> psbtSignNonMweb($grpc.ServiceCall call, $0.PsbtSignNonMwebRequest request);
+ $async.Future<$0.CreateResponse> psbtExtract($grpc.ServiceCall call, $0.PsbtExtractRequest request);
+ $async.Future<$0.LedgerApdu> ledgerExchange($grpc.ServiceCall call, $0.LedgerApdu request);
$async.Future<$0.BroadcastResponse> broadcast($grpc.ServiceCall call, $0.BroadcastRequest request);
-}
+ $async.Future<$0.CoinswapResponse> coinswap($grpc.ServiceCall call, $0.CoinswapRequest request);
+}
\ No newline at end of file
diff --git a/cw_mweb/lib/print_verbose.dart b/cw_mweb/lib/print_verbose.dart
new file mode 100644
index 0000000..69d4832
--- /dev/null
+++ b/cw_mweb/lib/print_verbose.dart
@@ -0,0 +1,107 @@
+import 'dart:io';
+import 'dart:math';
+import 'package:flutter/foundation.dart';
+
+enum LogLevel { info, debug, warn, error }
+
+/// Pass an optional [file] to also write the log to a file.
+void printV(
+ dynamic content, {
+ String? file,
+ LogLevel level = LogLevel.info,
+}) {
+ final programInfo = CustomTrace(StackTrace.current);
+ final logLine =
+ "[${level.name.toUpperCase()}] ${programInfo.fileName}#${programInfo.lineNumber}:${programInfo.columnNumber} ${programInfo.callerFunctionName}: $content";
+
+ print(logLine);
+
+ if (file != null) {
+ final logFile = File(file);
+ if (!logFile.existsSync()) {
+ logFile.createSync(recursive: true);
+ }
+ logFile.writeAsStringSync("$logLine\n", mode: FileMode.append, flush: true);
+ }
+}
+
+// https://stackoverflow.com/a/59386101
+
+class CustomTrace {
+ final StackTrace _trace;
+
+ String? fileName;
+ String? functionName;
+ String? callerFunctionName;
+ int? lineNumber;
+ int? columnNumber;
+
+ CustomTrace(this._trace) {
+ try {
+ _parseTrace();
+ } catch (e) {
+ if (kDebugMode) print("Unable to parse trace (printV): $e");
+ }
+ }
+
+ String _getFunctionNameFromFrame(String frame) {
+ /* Just giving another nickname to the frame */
+ var currentTrace = frame;
+ /* To get rid off the #number thing, get the index of the first whitespace */
+ var indexOfWhiteSpace = currentTrace.indexOf(' ');
+
+ /* Create a substring from the first whitespace index till the end of the string */
+ var subStr = currentTrace.substring(max(0, indexOfWhiteSpace));
+
+ /* Grab the function name using reg expr */
+ var indexOfFunction = subStr.indexOf(RegExp(r'[A-Za-z0-9_]'));
+
+ /* Create a new substring from the function name index till the end of string */
+ subStr = subStr.substring(indexOfFunction);
+
+ indexOfWhiteSpace = subStr.indexOf(RegExp(r'[ .]'));
+
+ /* Create a new substring from start to the first index of a whitespace. This substring gives us the function name */
+ subStr = subStr.substring(0, max(0, indexOfWhiteSpace));
+
+ return subStr;
+ }
+
+ void _parseTrace() {
+ /* The trace comes with multiple lines of strings, (each line is also known as a frame), so split the trace's string by lines to get all the frames */
+ var frames = this._trace.toString().split("\n");
+
+ /* The first frame is the current function */
+ this.functionName = _getFunctionNameFromFrame(frames[0]);
+
+ /* The second frame is the caller function */
+ this.callerFunctionName = _getFunctionNameFromFrame(frames[1]);
+
+ /* The first frame has all the information we need */
+ var traceString = frames[1];
+
+ /* Search through the string and find the index of the file name by looking for the '.dart' regex */
+ var indexOfFileName = traceString.indexOf(
+ RegExp(r'[/A-Za-z_]+.dart'), 1); // 1 to offest and not print the printV function name
+
+ var fileInfo = traceString.substring(max(0, indexOfFileName));
+
+ var listOfInfos = fileInfo.split(":");
+
+ /* Splitting fileInfo by the character ":" separates the file name, the line number and the column counter nicely.
+ Example: main.dart:5:12
+ To get the file name, we split with ":" and get the first index
+ To get the line number, we would have to get the second index
+ To get the column number, we would have to get the third index
+ */
+ try {
+ this.fileName = listOfInfos[0];
+ this.lineNumber = int.tryParse(listOfInfos[1]);
+ var columnStr = listOfInfos[2];
+ columnStr = columnStr.replaceFirst(")", "");
+ this.columnNumber = int.tryParse(columnStr);
+ } catch (e) {
+ if (kDebugMode) print("Unable to parse trace (printV): $e");
+ }
+ }
+}
diff --git a/cw_mweb/pubspec.yaml b/cw_mweb/pubspec.yaml
index 02f454d..94342fd 100644
--- a/cw_mweb/pubspec.yaml
+++ b/cw_mweb/pubspec.yaml
@@ -13,8 +13,6 @@ dependencies:
grpc: 4.0.1
path_provider: ^2.1.2
plugin_platform_interface: ^2.0.2
- cw_core:
- path: ../cw_core
ffi: ^2.1.0
dev_dependencies:
diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart
index 4a9b2f1..c80032d 100644
--- a/lib/bitcoin/cw_bitcoin.dart
+++ b/lib/bitcoin/cw_bitcoin.dart
@@ -28,6 +28,22 @@ class CWBitcoin extends Bitcoin {
BitcoinWalletFromKeysCredentials(
name: name, password: password, xpub: xpub, hardwareWalletType: hardwareWalletType);
+ @override
+ WalletCredentials createLitecoinWalletFromKeys({
+ required String name,
+ required String password,
+ required String xpub,
+ required String scanSecret,
+ required String spendPubkey,
+ }) =>
+ LitecoinWalletFromKeysCredentials(
+ name: name,
+ password: password,
+ xpub: xpub,
+ scanSecret: scanSecret,
+ spendPubkey: spendPubkey,
+ );
+
@override
WalletCredentials createBitcoinRestoreWalletFromWIFCredentials(
{required String name,
@@ -766,6 +782,7 @@ class CWBitcoin extends Bitcoin {
@override
Future<void> commitPsbtUR(Object wallet, List<String> urCodes) {
+ if (wallet is LitecoinWallet) return wallet.commitPsbtUR(urCodes);
final _wallet = wallet as BitcoinWalletBase;
return _wallet.commitPsbtUR(urCodes);
}
diff --git a/lib/src/screens/restore/wallet_restore_from_keys_form.dart b/lib/src/screens/restore/wallet_restore_from_keys_form.dart
index 8ab0f02..baa0964 100644
--- a/lib/src/screens/restore/wallet_restore_from_keys_form.dart
+++ b/lib/src/screens/restore/wallet_restore_from_keys_form.dart
@@ -56,6 +56,12 @@ class WalletRestoreFromKeysFormState extends State<WalletRestoreFromKeysForm> {
spendKeyController = restoredWallet != null
? TextEditingController(text: restoredWallet.spendKey)
: TextEditingController(),
+ scanSecretController = restoredWallet != null
+ ? TextEditingController(text: restoredWallet.scanSecret)
+ : TextEditingController(),
+ spendPubkeyController = restoredWallet != null
+ ? TextEditingController(text: restoredWallet.spendPubkey)
+ : TextEditingController(),
privateKeyController = restoredWallet != null
? TextEditingController(text: restoredWallet.privateKey)
: TextEditingController(),
@@ -72,6 +78,8 @@ class WalletRestoreFromKeysFormState extends State<WalletRestoreFromKeysForm> {
final TextEditingController addressController;
final TextEditingController viewKeyController;
final TextEditingController spendKeyController;
+ final TextEditingController scanSecretController;
+ final TextEditingController spendPubkeyController;
final TextEditingController nameTextEditingController;
final TextEditingController privateKeyController;
final TextEditingController? passwordTextEditingController;
@@ -119,6 +127,8 @@ class WalletRestoreFromKeysFormState extends State<WalletRestoreFromKeysForm> {
viewKeyController.dispose();
privateKeyController.dispose();
spendKeyController.dispose();
+ scanSecretController.dispose();
+ spendPubkeyController.dispose();
passwordTextEditingController?.dispose();
if (passwordListener != null) {
passwordTextEditingController?.removeListener(passwordListener!);
@@ -257,6 +267,22 @@ class WalletRestoreFromKeysFormState extends State<WalletRestoreFromKeysForm> {
maxLines: null,
),
),
+ Container(
+ padding: EdgeInsets.only(top: 20.0),
+ child: BaseTextFormField(
+ controller: scanSecretController,
+ hintText: "Scan secret",
+ maxLines: null,
+ ),
+ ),
+ Container(
+ padding: EdgeInsets.only(top: 20.0),
+ child: BaseTextFormField(
+ controller: spendPubkeyController,
+ hintText: "Spend public key",
+ maxLines: null,
+ ),
+ ),
if (widget.walletRestoreViewModel.hasBlockchainHeightSelector)
BlockchainHeightWidget(
key: blockchainHeightKey,
diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart
index a50384c..d673319 100644
--- a/lib/src/screens/restore/wallet_restore_page.dart
+++ b/lib/src/screens/restore/wallet_restore_page.dart
@@ -222,8 +222,12 @@ class WalletRestorePage extends BasePage {
walletRestoreFromKeysFormKey.currentState!.addressController.text;
credentials['spendKey'] =
walletRestoreFromKeysFormKey.currentState!.spendKeyController.text;
+ credentials['scanSecret'] =
+ walletRestoreFromKeysFormKey.currentState!.scanSecretController.text;
+ credentials['spendPubkey'] =
+ walletRestoreFromKeysFormKey.currentState!.spendPubkeyController.text;
credentials['height'] =
- walletRestoreFromKeysFormKey.currentState!.blockchainHeightKey.currentState!.height;
+ walletRestoreFromKeysFormKey.currentState!.blockchainHeightKey.currentState?.height;
}
}
}
@@ -517,7 +521,8 @@ class _WalletRestorePageBodyState extends State<_WalletRestorePageBody>
}
},
onViewKeyEntered: (bool entered) {
- if (widget.walletRestoreViewModel.onlyViewKeyRestore) {
+ if (widget.walletRestoreViewModel.onlyViewKeyRestore ||
+ walletRestoreViewModel.type == WalletType.litecoin) {
walletRestoreViewModel.isButtonEnabled = entered;
}
},
diff --git a/lib/view_model/restore/restore_wallet.dart b/lib/view_model/restore/restore_wallet.dart
index d84a96d..bd70fce 100644
--- a/lib/view_model/restore/restore_wallet.dart
+++ b/lib/view_model/restore/restore_wallet.dart
@@ -13,6 +13,8 @@ class RestoredWallet {
this.txId,
this.spendKey,
this.viewKey,
+ this.scanSecret,
+ this.spendPubkey,
this.mnemonicSeed,
this.passphrase,
this.txAmount,
@@ -28,6 +30,8 @@ class RestoredWallet {
final String? txId;
final String? spendKey;
final String? viewKey;
+ final String? scanSecret;
+ final String? spendPubkey;
final String? mnemonicSeed;
final String? passphrase;
final String? txAmount;
@@ -48,9 +52,13 @@ class RestoredWallet {
} catch (e) {
// fine, we don't care, it is only for monero anyway
}
+ if (json['ltub'] != null) {
+ json['xpub'] = convertLtubToXpub(json['ltub'] as String);
+ }
if (json['zpub'] != null) {
json['xpub'] = convertZpubToXpub(json['zpub'] as String);
}
+ json['xpub'] = convertAnyToXpub(json['xpub'] as String);
json['view_key'] ??= json['xpub'];
final height = json['height'] as String?;
return RestoredWallet(
@@ -60,6 +68,8 @@ class RestoredWallet {
address: json['address'] as String?,
spendKey: json['spend_key'] as String?,
viewKey: json['view_key'] as String?,
+ scanSecret: json['scan_secret'] as String?,
+ spendPubkey: json['spend_pubkey'] as String?,
height: height != null ? int.tryParse(height) ?? 0 : 0,
privateKey: json['private_key'] as String?,
);
diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart
index ce427b8..a08d582 100644
--- a/lib/view_model/wallet_restore_view_model.dart
+++ b/lib/view_model/wallet_restore_view_model.dart
@@ -56,9 +56,9 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
case WalletType.arbitrum:
case WalletType.decred:
case WalletType.bitcoin:
+ case WalletType.litecoin:
availableModes = [WalletRestoreMode.seed, WalletRestoreMode.keys];
break;
- case WalletType.litecoin:
case WalletType.bitcoinCash:
case WalletType.zano:
case WalletType.none:
@@ -238,6 +238,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
if (mode == WalletRestoreMode.keys) {
final viewKey = options['viewKey'] as String?;
final spendKey = options['spendKey'] as String?;
+ final scanSecret = options['scanSecret'] as String?;
+ final spendPubkey = options['spendPubkey'] as String?;
final address = options['address'] as String?;
switch (type) {
@@ -249,6 +251,15 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
hardwareWalletType: hardwareWalletType,
);
+ case WalletType.litecoin:
+ return bitcoin!.createLitecoinWalletFromKeys(
+ name: name,
+ password: password,
+ xpub: viewKey!,
+ scanSecret: scanSecret!,
+ spendPubkey: spendPubkey!,
+ );
+
case WalletType.monero:
return monero!.createMoneroRestoreWalletFromKeysCredentials(
name: name,
diff --git a/scripts/android/build_mwebd.sh b/scripts/android/build_mwebd.sh
index 08782ac..1847536 100755
--- a/scripts/android/build_mwebd.sh
+++ b/scripts/android/build_mwebd.sh
@@ -47,4 +47,4 @@ GOARCH=arm \
CC=${NDK_BIN}/armv7a-linux-androideabi21-clang \
go build -v -buildmode=c-shared -o ${ANDROID_OUT}/armeabi-v7a/libmweb.so .
cd ../
-dart run ffigen --config ffigen_config.yaml
+dart run ffigen --config ffigen_config.yaml
\ No newline at end of file
diff --git a/scripts/android/build_torch.sh b/scripts/android/build_torch.sh
index a3955b1..31ed084 100755
--- a/scripts/android/build_torch.sh
+++ b/scripts/android/build_torch.sh
@@ -6,4 +6,4 @@ cd "$(dirname "$0")"
cd ../torch_dart
-./build.sh aarch64-linux-android armv7a-linux-androideabi x86_64-linux-android
\ No newline at end of file
+./build.sh aarch64-linux-android armv7a-linux-androideabi x86_64-linux-android
diff --git a/tool/configure.dart b/tool/configure.dart
index caac8b3..bbb4a1b 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -184,6 +184,7 @@ abstract class Bitcoin {
});
WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({required String name, required String password, required String wif, WalletInfo? walletInfo});
WalletCredentials createBitcoinWalletFromKeys({required String name, required String password, required String xpub, HardwareWalletType? hardwareWalletType});
+ WalletCredentials createLitecoinWalletFromKeys({required String name, required String password, required String xpub, required String scanSecret, required String spendPubkey});
WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic});
WalletCredentials createBitcoinHardwareWalletCredentials({required String name, required HardwareAccountData accountData, WalletInfo? walletInfo});
List<String> getWordList();
Why this scored 37/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.