mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 01:37:54 +00:00
Merge branch 'staging' into update-epic
This commit is contained in:
commit
2917db6bd6
13 changed files with 3397 additions and 3147 deletions
|
@ -385,6 +385,19 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
|
|||
final sendAmount = ref.read(exchangeFormStateProvider).sendAmount!;
|
||||
final estimate = ref.read(exchangeFormStateProvider).estimate!;
|
||||
|
||||
if (rateType == ExchangeRateType.fixed && toTicker.toUpperCase() == "WOW") {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => const StackOkDialog(
|
||||
title: "WOW error",
|
||||
message:
|
||||
"Wownero is temporarily disabled as a receiving currency for fixed rate trades due to network issues",
|
||||
),
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
String rate;
|
||||
|
||||
switch (rateType) {
|
||||
|
|
|
@ -117,6 +117,9 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
status = changeNowTransactionStatusFromStringIgnoreCase(statusString);
|
||||
} on ArgumentError catch (_) {
|
||||
status = ChangeNowTransactionStatus.Failed;
|
||||
if (statusString == "Processing payment") {
|
||||
status = ChangeNowTransactionStatus.Sending;
|
||||
}
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
|
@ -158,6 +161,8 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
trade.status == "failed");
|
||||
|
||||
//todo: check if print needed
|
||||
// debugPrint("walletId: $walletId");
|
||||
// debugPrint("transactionIfSentFromStack: $transactionIfSentFromStack");
|
||||
// debugPrint("sentFromStack: $sentFromStack");
|
||||
// debugPrint("hasTx: $hasTx");
|
||||
// debugPrint("trade: ${trade.toString()}");
|
||||
|
|
|
@ -1024,7 +1024,6 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
await checkAllCurrentReceivingPaynymAddressesForTransactions();
|
||||
|
||||
final fetchFuture = _refreshTransactions();
|
||||
final utxosRefreshFuture = _updateUTXOs();
|
||||
GlobalEventBus.instance
|
||||
.fire(RefreshPercentChangedEvent(0.50, walletId));
|
||||
|
||||
|
@ -1036,12 +1035,12 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
.fire(RefreshPercentChangedEvent(0.70, walletId));
|
||||
_feeObject = Future(() => feeObj);
|
||||
|
||||
await utxosRefreshFuture;
|
||||
await fetchFuture;
|
||||
GlobalEventBus.instance
|
||||
.fire(RefreshPercentChangedEvent(0.80, walletId));
|
||||
|
||||
await fetchFuture;
|
||||
await checkForNotificationTransactionsTo(codesToCheck);
|
||||
await _updateUTXOs();
|
||||
await getAllTxsToWatch();
|
||||
GlobalEventBus.instance
|
||||
.fire(RefreshPercentChangedEvent(0.90, walletId));
|
||||
|
@ -2179,7 +2178,10 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
.txidEqualTo(txHash["tx_hash"] as String)
|
||||
.findFirst();
|
||||
|
||||
// TODO: remove bip47Notification type check sometime after Q2 2023
|
||||
if (storedTx == null ||
|
||||
storedTx.subType ==
|
||||
isar_models.TransactionSubType.bip47Notification ||
|
||||
!storedTx.isConfirmed(currentHeight, MINIMUM_CONFIRMATIONS)) {
|
||||
final tx = await cachedElectrumXClient.getTransaction(
|
||||
txHash: txHash["tx_hash"] as String,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:bip47/src/util.dart';
|
||||
import 'package:decimal/decimal.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
|
@ -156,6 +158,14 @@ mixin ElectrumXParsing {
|
|||
|
||||
for (final json in txData["vin"] as List) {
|
||||
bool isCoinBase = json['coinbase'] != null;
|
||||
String? witness;
|
||||
if (json['witness'] != null && json['witness'] is String) {
|
||||
witness = json['witness'] as String;
|
||||
} else if (json['txinwitness'] != null) {
|
||||
if (json['txinwitness'] is List) {
|
||||
witness = jsonEncode(json['txinwitness']);
|
||||
}
|
||||
}
|
||||
final input = Input(
|
||||
txid: json['txid'] as String,
|
||||
vout: json['vout'] as int? ?? -1,
|
||||
|
@ -164,6 +174,7 @@ mixin ElectrumXParsing {
|
|||
isCoinbase: isCoinBase ? isCoinBase : json['is_coinbase'] as bool?,
|
||||
sequence: json['sequence'] as int?,
|
||||
innerRedeemScriptAsm: json['innerRedeemscriptAsm'] as String?,
|
||||
witness: witness,
|
||||
);
|
||||
ins.add(input);
|
||||
}
|
||||
|
|
|
@ -176,17 +176,18 @@ mixin PaynymWalletInterface {
|
|||
PaymentCode sender,
|
||||
int index,
|
||||
) async {
|
||||
final myPrivateKey = await deriveReceivingPrivateKey(
|
||||
final myPrivateKeyNode = await deriveReceivingPrivateKeyNode(
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
index: index,
|
||||
);
|
||||
|
||||
final paymentAddress = PaymentAddress.initWithPrivateKey(
|
||||
myPrivateKey,
|
||||
sender,
|
||||
0,
|
||||
final paymentAddress = PaymentAddress(
|
||||
bip32Node: myPrivateKeyNode,
|
||||
paymentCode: sender,
|
||||
networkType: networkType,
|
||||
);
|
||||
|
||||
final pair = paymentAddress.getReceiveAddressKeyPair();
|
||||
final address = await generatePaynymReceivingAddressFromKeyPair(
|
||||
pair: pair,
|
||||
|
@ -248,7 +249,7 @@ mixin PaynymWalletInterface {
|
|||
return root;
|
||||
}
|
||||
|
||||
Future<Uint8List> deriveNotificationPrivateKey({
|
||||
Future<bip32.BIP32> deriveNotificationBip32Node({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
}) async {
|
||||
|
@ -257,10 +258,10 @@ mixin PaynymWalletInterface {
|
|||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
final node = root.derivePath(kPaynymDerivePath).derive(0);
|
||||
return node.privateKey!;
|
||||
return node;
|
||||
}
|
||||
|
||||
Future<Uint8List> deriveReceivingPrivateKey({
|
||||
Future<bip32.BIP32> deriveReceivingPrivateKeyNode({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
required int index,
|
||||
|
@ -270,7 +271,7 @@ mixin PaynymWalletInterface {
|
|||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
final node = root.derivePath(kPaynymDerivePath).derive(index);
|
||||
return node.privateKey!;
|
||||
return node;
|
||||
}
|
||||
|
||||
/// fetch or generate this wallet's bip47 payment code
|
||||
|
@ -287,11 +288,12 @@ mixin PaynymWalletInterface {
|
|||
}
|
||||
|
||||
Future<Uint8List> signWithNotificationKey(Uint8List data) async {
|
||||
final privateKey = await deriveNotificationPrivateKey(
|
||||
final myPrivateKeyNode = await deriveNotificationBip32Node(
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
);
|
||||
final pair = btc_dart.ECPair.fromPrivateKey(privateKey, network: _network);
|
||||
final pair = btc_dart.ECPair.fromPrivateKey(myPrivateKeyNode.privateKey!,
|
||||
network: _network);
|
||||
final signed = pair.sign(SHA256Digest().process(data));
|
||||
return signed;
|
||||
}
|
||||
|
@ -310,13 +312,13 @@ mixin PaynymWalletInterface {
|
|||
throw PaynymSendException(
|
||||
"No notification transaction sent to $paymentCode");
|
||||
} else {
|
||||
final myPrivateKey = await deriveNotificationPrivateKey(
|
||||
final myPrivateKeyNode = await deriveNotificationBip32Node(
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
);
|
||||
final sendToAddress = await nextUnusedSendAddressFrom(
|
||||
pCode: paymentCode,
|
||||
privateKey: myPrivateKey,
|
||||
privateKeyNode: myPrivateKeyNode,
|
||||
);
|
||||
|
||||
return _prepareSend(
|
||||
|
@ -331,7 +333,7 @@ mixin PaynymWalletInterface {
|
|||
/// and your own private key
|
||||
Future<Address> nextUnusedSendAddressFrom({
|
||||
required PaymentCode pCode,
|
||||
required Uint8List privateKey,
|
||||
required bip32.BIP32 privateKeyNode,
|
||||
int startIndex = 0,
|
||||
}) async {
|
||||
// https://en.bitcoin.it/wiki/BIP_0047#Path_levels
|
||||
|
@ -356,10 +358,11 @@ mixin PaynymWalletInterface {
|
|||
return address;
|
||||
}
|
||||
} else {
|
||||
final pair = PaymentAddress.initWithPrivateKey(
|
||||
privateKey,
|
||||
pCode,
|
||||
i, // index to use
|
||||
final pair = PaymentAddress(
|
||||
bip32Node: privateKeyNode,
|
||||
index: i, // index to use
|
||||
paymentCode: pCode,
|
||||
networkType: networkType,
|
||||
).getSendAddressKeyPair();
|
||||
|
||||
// add address to local db
|
||||
|
@ -607,8 +610,9 @@ mixin PaynymWalletInterface {
|
|||
final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev);
|
||||
|
||||
final blindedPaymentCode = PaymentCode.blind(
|
||||
myCode.getPayload(),
|
||||
blindingMask,
|
||||
payload: myCode.getPayload(),
|
||||
mask: blindingMask,
|
||||
unBlind: false,
|
||||
);
|
||||
|
||||
final opReturnScript = bscript.compile([
|
||||
|
@ -728,6 +732,24 @@ mixin PaynymWalletInterface {
|
|||
return false;
|
||||
}
|
||||
|
||||
Uint8List? _pubKeyFromInput(Input input) {
|
||||
final scriptSigComponents = input.scriptSigAsm?.split(" ") ?? [];
|
||||
if (scriptSigComponents.length > 1) {
|
||||
return scriptSigComponents[1].fromHex;
|
||||
}
|
||||
if (input.witness != null) {
|
||||
try {
|
||||
final witnessComponents = jsonDecode(input.witness!) as List;
|
||||
if (witnessComponents.length == 2) {
|
||||
return (witnessComponents[1] as String).fromHex;
|
||||
}
|
||||
} catch (_) {
|
||||
//
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<PaymentCode?> unBlindedPaymentCodeFromTransaction({
|
||||
required Transaction transaction,
|
||||
required Address myNotificationAddress,
|
||||
|
@ -756,21 +778,25 @@ mixin PaynymWalletInterface {
|
|||
final buffer = rev.buffer.asByteData();
|
||||
buffer.setUint32(txPoint.length, txPointIndex, Endian.little);
|
||||
|
||||
final pubKey = designatedInput.scriptSigAsm!.split(" ")[1].fromHex;
|
||||
final pubKey = _pubKeyFromInput(designatedInput)!;
|
||||
|
||||
final myPrivateKey = await deriveNotificationPrivateKey(
|
||||
final myPrivateKey = (await deriveNotificationBip32Node(
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
);
|
||||
))
|
||||
.privateKey!;
|
||||
|
||||
final S = SecretPoint(myPrivateKey, pubKey);
|
||||
|
||||
final mask = PaymentCode.getMask(S.ecdhSecret(), rev);
|
||||
|
||||
final unBlindedPayload = PaymentCode.blind(blindedCodeBytes, mask);
|
||||
final unBlindedPayload = PaymentCode.blind(
|
||||
payload: blindedCodeBytes,
|
||||
mask: mask,
|
||||
unBlind: true,
|
||||
);
|
||||
|
||||
final unBlindedPaymentCode =
|
||||
PaymentCode.initFromPayload(unBlindedPayload);
|
||||
final unBlindedPaymentCode = PaymentCode.fromPayload(unBlindedPayload);
|
||||
|
||||
return unBlindedPaymentCode;
|
||||
} catch (e) {
|
||||
|
@ -904,7 +930,7 @@ mixin PaynymWalletInterface {
|
|||
final mnemonic = (await _getMnemonicString())!;
|
||||
final mnemonicPassphrase = (await _getMnemonicPassphrase())!;
|
||||
|
||||
final mySendPrivateKey = await deriveNotificationPrivateKey(
|
||||
final mySendBip32Node = await deriveNotificationBip32Node(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
|
@ -924,10 +950,11 @@ mixin PaynymWalletInterface {
|
|||
outgoingGapCounter < maxUnusedAddressGap);
|
||||
i++) {
|
||||
if (outgoingGapCounter < maxUnusedAddressGap) {
|
||||
final paymentAddressSending = PaymentAddress.initWithPrivateKey(
|
||||
mySendPrivateKey,
|
||||
other,
|
||||
i, // index to use
|
||||
final paymentAddressSending = PaymentAddress(
|
||||
paymentCode: other,
|
||||
bip32Node: mySendBip32Node,
|
||||
index: i,
|
||||
networkType: networkType,
|
||||
);
|
||||
final pair = paymentAddressSending.getSendAddressKeyPair();
|
||||
final address = await generatePaynymSendAddressFromKeyPair(
|
||||
|
@ -948,12 +975,13 @@ mixin PaynymWalletInterface {
|
|||
}
|
||||
|
||||
if (receivingGapCounter < maxUnusedAddressGap) {
|
||||
final myReceivingPrivateKey = receivingNode.derive(i).privateKey!;
|
||||
final paymentAddressReceiving = PaymentAddress.initWithPrivateKey(
|
||||
myReceivingPrivateKey,
|
||||
other,
|
||||
0,
|
||||
final paymentAddressReceiving = PaymentAddress(
|
||||
paymentCode: other,
|
||||
bip32Node: receivingNode.derive(i),
|
||||
index: 0,
|
||||
networkType: networkType,
|
||||
);
|
||||
|
||||
final pair = paymentAddressReceiving.getReceiveAddressKeyPair();
|
||||
final address = await generatePaynymReceivingAddressFromKeyPair(
|
||||
pair: pair,
|
||||
|
@ -1168,9 +1196,8 @@ mixin PaynymWalletInterface {
|
|||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
);
|
||||
final node = root.derivePath(kPaynymDerivePath);
|
||||
final paymentCode = PaymentCode.initFromPubKey(
|
||||
node.publicKey,
|
||||
node.chainCode,
|
||||
final paymentCode = PaymentCode.fromBip32Node(
|
||||
node,
|
||||
_network,
|
||||
);
|
||||
|
||||
|
|
|
@ -100,8 +100,8 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: "87bb760be323228aed6ca7bd4532a709a4f10690"
|
||||
resolved-ref: "87bb760be323228aed6ca7bd4532a709a4f10690"
|
||||
ref: "7b7c0b9284e7457f40dc60ea4420d8badf1aed39"
|
||||
resolved-ref: "7b7c0b9284e7457f40dc60ea4420d8badf1aed39"
|
||||
url: "https://github.com/cypherstack/bip47.git"
|
||||
source: git
|
||||
version: "1.0.0"
|
||||
|
|
|
@ -11,7 +11,7 @@ description: Stack Wallet
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.5.39+126
|
||||
version: 1.5.40+127
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
|
@ -59,7 +59,7 @@ dependencies:
|
|||
bip47:
|
||||
git:
|
||||
url: https://github.com/cypherstack/bip47.git
|
||||
ref: 87bb760be323228aed6ca7bd4532a709a4f10690
|
||||
ref: 48dd65f88822fba8543826274f6d51c17f735f93
|
||||
|
||||
# Utility plugins
|
||||
# provider: ^6.0.1
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue