mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-12 09:27:01 +00:00
commit
4eb495901f
16 changed files with 303 additions and 44 deletions
|
@ -1,11 +1,18 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_908_22491)">
|
||||
<g opacity="0.4">
|
||||
<path d="M22.2 6C23.3297 5.37187 24 4.59422 24 3.75C24 1.67906 19.9688 0 15 0C9.98906 0 6 1.67906 6 3.75C6 4.59422 6.67031 5.37187 7.8 6C7.80937 6.00469 7.81758 6.00937 7.82578 6.01406C7.83398 6.01875 7.84219 6.02344 7.85156 6.02813C8.23125 6.00938 8.61094 6 9 6C11.6344 6 14.0906 6.44062 15.9422 7.21406C16.1203 7.28906 16.2984 7.36875 16.4672 7.44844C18.8062 7.28906 20.8359 6.75469 22.2 6Z" fill="#232323"/>
|
||||
<path d="M19.9435 12.9151C19.7958 12.9551 19.6477 12.9951 19.5 13.0359V13.5C20.7602 13.5 21.9296 13.8885 22.8951 14.5522C23.5995 14.0172 24 13.4028 24 12.75V11.0906C23.4141 11.5734 22.7063 11.9672 21.9422 12.2859C21.3382 12.5376 20.6447 12.7253 19.9435 12.9151Z" fill="#232323"/>
|
||||
<path d="M18.3703 8.74688C19.0031 9.37969 19.5 10.2234 19.5 11.25V11.4984C20.4328 11.2734 21.2625 10.9781 21.9469 10.6359C21.9739 10.6209 22.0009 10.6021 22.0279 10.5833C22.0852 10.5432 22.1426 10.5032 22.2 10.5C23.3297 9.87187 24 9.09375 24 8.25V6.59063C23.4141 7.07344 22.7063 7.46719 21.9422 7.78594C20.9109 8.2125 19.6969 8.54063 18.3703 8.74688Z" fill="#232323"/>
|
||||
<path d="M22.2 6C23.3297 5.37187 24 4.59422 24 3.75C24 1.67906 19.9688 0 15 0C9.98906 0 6 1.67906 6 3.75C6 4.59422 6.67031 5.37187 7.8 6C7.80937 6.00469 7.81758 6.00937 7.82578 6.01406C7.83398 6.01875 7.84219 6.02344 7.85156 6.02813C8.23125 6.00938 8.61094 6 9 6C11.6344 6 14.0906 6.44062 15.9422 7.21406C16.1203 7.28906 16.2984 7.36875 16.4672 7.44844C18.8062 7.28906 20.8359 6.75469 22.2 6Z" fill="#D12B41"/>
|
||||
<path d="M19.9435 12.9151C19.7958 12.9551 19.6477 12.9951 19.5 13.0359V13.5C20.7602 13.5 21.9296 13.8885 22.8951 14.5522C23.5995 14.0172 24 13.4028 24 12.75V11.0906C23.4141 11.5734 22.7063 11.9672 21.9422 12.2859C21.3382 12.5376 20.6447 12.7253 19.9435 12.9151Z" fill="#D12B41"/>
|
||||
<path d="M18.3703 8.74688C19.0031 9.37969 19.5 10.2234 19.5 11.25V11.4984C20.4328 11.2734 21.2625 10.9781 21.9469 10.6359C21.9739 10.6209 22.0009 10.6021 22.0279 10.5833C22.0852 10.5432 22.1426 10.5032 22.2 10.5C23.3297 9.87187 24 9.09375 24 8.25V6.59063C23.4141 7.07344 22.7063 7.46719 21.9422 7.78594C20.9109 8.2125 19.6969 8.54063 18.3703 8.74688Z" fill="#D12B41"/>
|
||||
</g>
|
||||
<path d="M16.2 13.5C17.3297 12.8719 18 12.0938 18 11.25C18 9.17813 13.9688 7.5 9 7.5C4.02938 7.5 0 9.17813 0 11.25C0 12.0938 0.669375 12.8719 1.79953 13.5C1.85443 13.5031 1.91057 13.5415 1.96782 13.5807C1.9966 13.6004 2.02567 13.6203 2.055 13.6359C3.70594 14.4703 6.20625 15 9 15C11.9438 15 14.5594 14.4094 16.2 13.5Z" fill="#232323"/>
|
||||
<path d="M14.8788 15.6729C13.1948 16.2046 11.1571 16.5 9 16.5C6.36562 16.5 3.91125 16.0594 2.05922 15.2859C1.29469 14.9672 0.583594 14.5734 0 14.0906V15.75C0 16.5938 0.669375 17.3719 1.79953 18C3.44109 18.9094 6.05625 19.5 9 19.5C10.6471 19.5 12.1916 19.3159 13.5211 18.9937C13.6261 17.7367 14.1186 16.5898 14.8788 15.6729Z" fill="#232323"/>
|
||||
<path d="M13.5862 20.5191C13.7529 21.4936 14.1547 22.3879 14.731 23.1415C13.1742 23.6778 11.1771 24 9 24C4.02938 24 0 22.3219 0 20.25V18.5906C0.583594 19.0734 1.29469 19.4672 2.05922 19.7859C3.91125 20.5594 6.36562 21 9 21C10.6307 21 12.1932 20.8312 13.5862 20.5191Z" fill="#232323"/>
|
||||
<path d="M24 19.5C24 21.9844 21.9844 24 19.5 24C17.0156 24 15 21.9844 15 19.5C15 17.0156 17.0156 15 19.5 15C21.9844 15 24 17.0156 24 19.5ZM19 17.4719V18.9719H17.5C17.225 18.9719 17 19.225 17 19.4719C17 19.775 17.225 19.9719 17.5 19.9719H19V21.4719C19 21.775 19.225 21.9719 19.5 21.9719C19.775 21.9719 20 21.775 20 21.4719V19.9719H21.5C21.775 19.9719 22 19.775 22 19.4719C22 19.225 21.775 18.9719 21.5 18.9719H20V17.4719C20 17.225 19.775 16.9719 19.5 16.9719C19.225 16.9719 19 17.225 19 17.4719Z" fill="#232323"/>
|
||||
<path d="M16.2 13.5C17.3297 12.8719 18 12.0938 18 11.25C18 9.17813 13.9688 7.5 9 7.5C4.02938 7.5 0 9.17813 0 11.25C0 12.0938 0.669375 12.8719 1.79953 13.5C1.85443 13.5031 1.91057 13.5415 1.96782 13.5807C1.9966 13.6004 2.02567 13.6203 2.055 13.6359C3.70594 14.4703 6.20625 15 9 15C11.9438 15 14.5594 14.4094 16.2 13.5Z" fill="#D12B41"/>
|
||||
<path d="M14.8788 15.6729C13.1948 16.2046 11.1571 16.5 9 16.5C6.36562 16.5 3.91125 16.0594 2.05922 15.2859C1.29469 14.9672 0.583594 14.5734 0 14.0906V15.75C0 16.5938 0.669375 17.3719 1.79953 18C3.44109 18.9094 6.05625 19.5 9 19.5C10.6471 19.5 12.1916 19.3159 13.5211 18.9937C13.6261 17.7367 14.1186 16.5898 14.8788 15.6729Z" fill="#D12B41"/>
|
||||
<path d="M13.5862 20.5191C13.7529 21.4936 14.1547 22.3879 14.731 23.1415C13.1742 23.6778 11.1771 24 9 24C4.02938 24 0 22.3219 0 20.25V18.5906C0.583594 19.0734 1.29469 19.4672 2.05922 19.7859C3.91125 20.5594 6.36562 21 9 21C10.6307 21 12.1932 20.8312 13.5862 20.5191Z" fill="#D12B41"/>
|
||||
<path d="M24 19.5C24 21.9844 21.9844 24 19.5 24C17.0156 24 15 21.9844 15 19.5C15 17.0156 17.0156 15 19.5 15C21.9844 15 24 17.0156 24 19.5ZM19 17.4719V18.9719H17.5C17.225 18.9719 17 19.225 17 19.4719C17 19.775 17.225 19.9719 17.5 19.9719H19V21.4719C19 21.775 19.225 21.9719 19.5 21.9719C19.775 21.9719 20 21.775 20 21.4719V19.9719H21.5C21.775 19.9719 22 19.775 22 19.4719C22 19.225 21.775 18.9719 21.5 18.9719H20V17.4719C20 17.225 19.775 16.9719 19.5 16.9719C19.225 16.9719 19 17.225 19 17.4719Z" fill="#D12B41"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_908_22491">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.7 KiB |
|
@ -1,4 +1,4 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.6695 1.06575C15.1855 0.607104 15.9756 0.65358 16.4343 1.16956L20.4343 5.66956C20.8552 6.14317 20.8552 6.85686 20.4343 7.33047L16.4343 11.8305C15.9756 12.3464 15.1855 12.3929 14.6695 11.9343C14.1536 11.4756 14.1071 10.6855 14.5657 10.1696L16.7164 7.75001H6C4.48122 7.75001 3.25 8.98123 3.25 10.5C3.25 11.1904 2.69036 11.75 2 11.75C1.30964 11.75 0.75 11.1904 0.75 10.5C0.75 7.60052 3.10051 5.25001 6 5.25001H16.7164L14.5657 2.83047C14.1071 2.31449 14.1536 1.5244 14.6695 1.06575Z" fill="#232323"/>
|
||||
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M9.33045 23.4342C8.81448 23.8929 8.02439 23.8464 7.56574 23.3304L3.56574 18.8304C3.14475 18.3568 3.14475 17.6431 3.56574 17.1695L7.56574 12.6695C8.02439 12.1536 8.81448 12.1071 9.33046 12.5657C9.84643 13.0244 9.89291 13.8145 9.43426 14.3304L7.28355 16.75L18 16.75C19.5188 16.75 20.75 15.5188 20.75 14C20.75 13.3096 21.3096 12.75 22 12.75C22.6904 12.75 23.25 13.3096 23.25 14C23.25 16.8995 20.8995 19.25 18 19.25L7.28355 19.25L9.43426 21.6695C9.89291 22.1855 9.84643 22.9756 9.33045 23.4342Z" fill="#232323"/>
|
||||
<path d="M19.5 6.5H6C3.79086 6.5 2 8.29086 2 10.5M19.5 6.5L15.5 2M19.5 6.5L15.5 11" stroke="#D12B41" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path opacity="0.4" d="M4.5 18L18 18C20.2091 18 22 16.2091 22 14M4.5 18L8.5 22.5M4.5 18L8.5 13.5" stroke="#D12B41" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 455 B |
|
@ -50,7 +50,7 @@ class _HomeViewState extends ConsumerState<HomeView> {
|
|||
|
||||
Future<bool> _onWillPop() async {
|
||||
// go to home view when tapping back on the main exchange view
|
||||
if (ref.read(homeViewPageIndexStateProvider.state).state == 1) {
|
||||
if (ref.read(homeViewPageIndexStateProvider.state).state != 0) {
|
||||
ref.read(homeViewPageIndexStateProvider.state).state = 0;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -181,9 +181,44 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
|
|||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Text(
|
||||
widget.accountLite.nymName,
|
||||
style: STextStyles.w600_12(context),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.accountLite.nymName,
|
||||
style: STextStyles.w600_12(context),
|
||||
),
|
||||
FutureBuilder(
|
||||
future:
|
||||
wallet.hasConnected(widget.accountLite.code),
|
||||
builder: (context, AsyncSnapshot<bool> snapshot) {
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.done &&
|
||||
snapshot.data == true) {
|
||||
return Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
Text(
|
||||
"Connected",
|
||||
style: STextStyles.w500_10(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorGreen,
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -176,9 +176,42 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Text(
|
||||
widget.accountLite.nymName,
|
||||
style: STextStyles.desktopTextSmall(context),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.accountLite.nymName,
|
||||
style: STextStyles.desktopTextSmall(context),
|
||||
),
|
||||
FutureBuilder(
|
||||
future: wallet.hasConnected(widget.accountLite.code),
|
||||
builder: (context, AsyncSnapshot<bool> snapshot) {
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.done &&
|
||||
snapshot.data == true) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
Text(
|
||||
"Connected",
|
||||
style: STextStyles.desktopTextSmall(context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorGreen,
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -175,7 +175,7 @@ class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
|
|||
children: [
|
||||
Text(
|
||||
"Paynym",
|
||||
style: STextStyles.w600_12(context),
|
||||
style: STextStyles.buttonSmall(context),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
|
@ -184,6 +184,9 @@ class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
|
|||
Assets.svg.robotHead,
|
||||
height: 20,
|
||||
width: 20,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.bottomNavIconIcon,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -40,6 +40,7 @@ import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
|
|||
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
||||
import 'package:stackwallet/utilities/format.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/paynym_is_api.dart';
|
||||
import 'package:stackwallet/utilities/prefs.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
@ -704,16 +705,28 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
...p2shChangeAddressArray,
|
||||
]);
|
||||
|
||||
// generate to ensure notification address is in db before refreshing transactions
|
||||
await getMyNotificationAddress(DerivePathType.bip44);
|
||||
// get own payment code
|
||||
final myCode = await getPaymentCode(DerivePathType.bip44);
|
||||
|
||||
// refresh transactions to pick up any received notification transactions
|
||||
await _refreshTransactions();
|
||||
|
||||
final Set<String> codesToCheck = {};
|
||||
final nym = await PaynymIsApi().nym(myCode.toString());
|
||||
if (nym.value != null) {
|
||||
for (final follower in nym.value!.followers) {
|
||||
codesToCheck.add(follower.code);
|
||||
}
|
||||
for (final following in nym.value!.following) {
|
||||
codesToCheck.add(following.code);
|
||||
}
|
||||
}
|
||||
|
||||
// restore paynym transactions
|
||||
await restoreAllHistory(
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
paymentCodeStrings: codesToCheck,
|
||||
);
|
||||
|
||||
await _updateUTXOs();
|
||||
|
@ -940,6 +953,17 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId));
|
||||
|
||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.1, walletId));
|
||||
final myCode = await getPaymentCode(DerivePathType.bip44);
|
||||
final Set<String> codesToCheck = {};
|
||||
final nym = await PaynymIsApi().nym(myCode.toString());
|
||||
if (nym.value != null) {
|
||||
for (final follower in nym.value!.followers) {
|
||||
codesToCheck.add(follower.code);
|
||||
}
|
||||
for (final following in nym.value!.following) {
|
||||
codesToCheck.add(following.code);
|
||||
}
|
||||
}
|
||||
|
||||
final currentHeight = await chainHeight;
|
||||
const storedHeight = 1; //await storedChainHeight;
|
||||
|
@ -976,6 +1000,7 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
.fire(RefreshPercentChangedEvent(0.80, walletId));
|
||||
|
||||
await fetchFuture;
|
||||
await checkForNotificationTransactionsTo(codesToCheck);
|
||||
await getAllTxsToWatch();
|
||||
GlobalEventBus.instance
|
||||
.fire(RefreshPercentChangedEvent(0.90, walletId));
|
||||
|
@ -1833,7 +1858,7 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
|
||||
// TODO move this out of here and into IDB
|
||||
await db.isar.writeTxn(() async {
|
||||
await db.isar.utxos.clear();
|
||||
await db.isar.utxos.where().walletIdEqualTo(walletId).deleteAll();
|
||||
await db.isar.utxos.putAll(outputArray);
|
||||
});
|
||||
|
||||
|
@ -2253,6 +2278,8 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
|
||||
Logging.instance.log("spendableOutputs.length: ${spendableOutputs.length}",
|
||||
level: LogLevel.Info);
|
||||
Logging.instance.log("availableOutputs.length: ${availableOutputs.length}",
|
||||
level: LogLevel.Info);
|
||||
Logging.instance
|
||||
.log("spendableOutputs: $spendableOutputs", level: LogLevel.Info);
|
||||
Logging.instance.log("spendableSatoshiValue: $spendableSatoshiValue",
|
||||
|
@ -2360,7 +2387,10 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
],
|
||||
satoshiAmounts: [
|
||||
satoshiAmountToSend,
|
||||
satoshisBeingUsed - satoshiAmountToSend - 1
|
||||
// this can cause a problem where the output value is negative so commenting out for now
|
||||
// satoshisBeingUsed - satoshiAmountToSend - 1
|
||||
// and using dust limit instead
|
||||
DUST_LIMIT,
|
||||
], // dust limit is the minimum amount a change output should be
|
||||
))["vSize"] as int;
|
||||
|
||||
|
|
|
@ -1673,7 +1673,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
|
||||
// TODO move this out of here and into IDB
|
||||
await db.isar.writeTxn(() async {
|
||||
await db.isar.utxos.clear();
|
||||
await db.isar.utxos.where().walletIdEqualTo(walletId).deleteAll();
|
||||
await db.isar.utxos.putAll(outputArray);
|
||||
});
|
||||
|
||||
|
|
|
@ -1620,7 +1620,7 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
|
||||
// TODO move this out of here and into IDB
|
||||
await db.isar.writeTxn(() async {
|
||||
await db.isar.utxos.clear();
|
||||
await db.isar.utxos.where().walletIdEqualTo(walletId).deleteAll();
|
||||
await db.isar.utxos.putAll(outputArray);
|
||||
});
|
||||
|
||||
|
|
|
@ -3665,7 +3665,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
|
||||
// TODO move this out of here and into IDB
|
||||
await db.isar.writeTxn(() async {
|
||||
await db.isar.utxos.clear();
|
||||
await db.isar.utxos.where().walletIdEqualTo(walletId).deleteAll();
|
||||
await db.isar.utxos.putAll(outputArray);
|
||||
});
|
||||
|
||||
|
|
|
@ -1784,7 +1784,7 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
|
||||
// TODO move this out of here and into IDB
|
||||
await db.isar.writeTxn(() async {
|
||||
await db.isar.utxos.clear();
|
||||
await db.isar.utxos.where().walletIdEqualTo(walletId).deleteAll();
|
||||
await db.isar.utxos.putAll(outputArray);
|
||||
});
|
||||
|
||||
|
|
|
@ -1763,7 +1763,7 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
|
||||
// TODO move this out of here and into IDB
|
||||
await db.isar.writeTxn(() async {
|
||||
await db.isar.utxos.clear();
|
||||
await db.isar.utxos.where().walletIdEqualTo(walletId).deleteAll();
|
||||
await db.isar.utxos.putAll(outputArray);
|
||||
});
|
||||
|
||||
|
|
|
@ -1659,7 +1659,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
|
||||
// TODO move this out of here and into IDB
|
||||
await db.isar.writeTxn(() async {
|
||||
await db.isar.utxos.clear();
|
||||
await db.isar.utxos.where().walletIdEqualTo(walletId).deleteAll();
|
||||
await db.isar.utxos.putAll(outputArray);
|
||||
});
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dar
|
|||
import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/bip47_utils.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
||||
|
@ -680,6 +681,13 @@ mixin PaynymWalletInterface {
|
|||
if (paymentCodeString == unBlindedPaymentCode.toString()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tx.address.value?.otherData != null) {
|
||||
final code = await paymentCodeStringByKey(tx.address.value!.otherData!);
|
||||
if (code == paymentCodeString) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise return no
|
||||
|
@ -696,8 +704,13 @@ mixin PaynymWalletInterface {
|
|||
}
|
||||
|
||||
try {
|
||||
final blindedCode =
|
||||
transaction.outputs.elementAt(1).scriptPubKeyAsm!.split(" ")[1];
|
||||
final blindedCodeBytes =
|
||||
Bip47Utils.getBlindedPaymentCodeBytesFrom(transaction);
|
||||
|
||||
// transaction does not contain a payment code
|
||||
if (blindedCodeBytes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final designatedInput = transaction.inputs.first;
|
||||
|
||||
|
@ -718,7 +731,7 @@ mixin PaynymWalletInterface {
|
|||
|
||||
final mask = PaymentCode.getMask(S.ecdhSecret(), rev);
|
||||
|
||||
final unBlindedPayload = PaymentCode.blind(blindedCode.fromHex, mask);
|
||||
final unBlindedPayload = PaymentCode.blind(blindedCodeBytes, mask);
|
||||
|
||||
final unBlindedPaymentCode =
|
||||
PaymentCode.initFromPayload(unBlindedPayload);
|
||||
|
@ -743,33 +756,99 @@ mixin PaynymWalletInterface {
|
|||
.subTypeEqualTo(TransactionSubType.bip47Notification)
|
||||
.findAll();
|
||||
|
||||
List<PaymentCode> unBlindedList = [];
|
||||
List<PaymentCode> codes = [];
|
||||
|
||||
for (final tx in txns) {
|
||||
final unBlinded = await unBlindedPaymentCodeFromTransaction(
|
||||
transaction: tx,
|
||||
myNotificationAddress: myAddress,
|
||||
);
|
||||
if (unBlinded != null &&
|
||||
unBlindedList
|
||||
.where((e) => e.toString() == unBlinded.toString())
|
||||
.isEmpty) {
|
||||
unBlindedList.add(unBlinded);
|
||||
// tx is sent so we can check the address's otherData for the code String
|
||||
if (tx.type == TransactionType.outgoing &&
|
||||
tx.address.value?.otherData != null) {
|
||||
final codeString =
|
||||
await paymentCodeStringByKey(tx.address.value!.otherData!);
|
||||
if (codeString != null &&
|
||||
codes.where((e) => e.toString() == codeString).isEmpty) {
|
||||
codes.add(PaymentCode.fromPaymentCode(codeString, _network));
|
||||
}
|
||||
} else {
|
||||
// otherwise we need to un blind the code
|
||||
final unBlinded = await unBlindedPaymentCodeFromTransaction(
|
||||
transaction: tx,
|
||||
myNotificationAddress: myAddress,
|
||||
);
|
||||
if (unBlinded != null &&
|
||||
codes.where((e) => e.toString() == unBlinded.toString()).isEmpty) {
|
||||
codes.add(unBlinded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return unBlindedList;
|
||||
return codes;
|
||||
}
|
||||
|
||||
Future<void> checkForNotificationTransactionsTo(
|
||||
Set<String> otherCodeStrings) async {
|
||||
final sentNotificationTransactions = await _db
|
||||
.getTransactions(_walletId)
|
||||
.filter()
|
||||
.subTypeEqualTo(TransactionSubType.bip47Notification)
|
||||
.and()
|
||||
.typeEqualTo(TransactionType.outgoing)
|
||||
.findAll();
|
||||
|
||||
final List<PaymentCode> codes = [];
|
||||
for (final codeString in otherCodeStrings) {
|
||||
codes.add(PaymentCode.fromPaymentCode(codeString, _network));
|
||||
}
|
||||
|
||||
for (final tx in sentNotificationTransactions) {
|
||||
if (tx.address.value != null && tx.address.value!.otherData == null) {
|
||||
final oldAddress =
|
||||
await _db.getAddress(_walletId, tx.address.value!.value);
|
||||
for (final code in codes) {
|
||||
final notificationAddress = code.notificationAddressP2PKH();
|
||||
if (notificationAddress == oldAddress!.value) {
|
||||
final address = Address(
|
||||
walletId: _walletId,
|
||||
value: notificationAddress,
|
||||
publicKey: [],
|
||||
derivationIndex: 0,
|
||||
type: oldAddress.type,
|
||||
subType: AddressSubType.paynymNotification,
|
||||
otherData: await storeCode(code.toString()),
|
||||
);
|
||||
await _db.updateAddress(oldAddress, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restoreAllHistory({
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required Set<String> paymentCodeStrings,
|
||||
}) async {
|
||||
final codes = await getAllPaymentCodesFromNotificationTransactions();
|
||||
final List<PaymentCode> extraCodes = [];
|
||||
for (final codeString in paymentCodeStrings) {
|
||||
if (codes.where((e) => e.toString() == codeString).isEmpty) {
|
||||
final extraCode = PaymentCode.fromPaymentCode(codeString, _network);
|
||||
if (extraCode.isValid()) {
|
||||
extraCodes.add(extraCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codes.addAll(extraCodes);
|
||||
|
||||
final List<Future<void>> futures = [];
|
||||
for (final code in codes) {
|
||||
futures.add(restoreHistoryWith(
|
||||
code, maxUnusedAddressGap, maxNumberOfIndexesToCheck));
|
||||
futures.add(
|
||||
restoreHistoryWith(
|
||||
code,
|
||||
maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await Future.wait(futures);
|
||||
|
|
37
lib/utilities/bip47_utils.dart
Normal file
37
lib/utilities/bip47_utils.dart
Normal file
|
@ -0,0 +1,37 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bip47/src/util.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/output.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
|
||||
|
||||
abstract class Bip47Utils {
|
||||
/// looks at tx outputs and returns a blinded payment code if found
|
||||
static Uint8List? getBlindedPaymentCodeBytesFrom(Transaction transaction) {
|
||||
for (int i = 0; i < transaction.outputs.length; i++) {
|
||||
final bytes = getBlindedPaymentCodeBytesFromOutput(
|
||||
transaction.outputs.elementAt(i));
|
||||
if (bytes != null) {
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static Uint8List? getBlindedPaymentCodeBytesFromOutput(Output output) {
|
||||
Uint8List? blindedCodeBytes;
|
||||
|
||||
List<String>? scriptChunks = output.scriptPubKeyAsm?.split(" ");
|
||||
if (scriptChunks?.length == 2 && scriptChunks?[0] == "OP_RETURN") {
|
||||
final blindedPaymentCode = scriptChunks![1];
|
||||
final bytes = blindedPaymentCode.fromHex;
|
||||
|
||||
// https://en.bitcoin.it/wiki/BIP_0047#Sending
|
||||
if (bytes.length == 80 && bytes.first == 1) {
|
||||
blindedCodeBytes = bytes;
|
||||
}
|
||||
}
|
||||
|
||||
return blindedCodeBytes;
|
||||
}
|
||||
}
|
|
@ -967,6 +967,41 @@ class STextStyles {
|
|||
}
|
||||
}
|
||||
|
||||
static TextStyle w500_10(BuildContext context) {
|
||||
switch (_theme(context).themeType) {
|
||||
case ThemeType.light:
|
||||
return GoogleFonts.inter(
|
||||
color: _theme(context).textDark,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 10,
|
||||
);
|
||||
case ThemeType.oceanBreeze:
|
||||
return GoogleFonts.inter(
|
||||
color: _theme(context).textDark,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 10,
|
||||
);
|
||||
case ThemeType.dark:
|
||||
return GoogleFonts.inter(
|
||||
color: _theme(context).textDark,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 10,
|
||||
);
|
||||
case ThemeType.oledBlack:
|
||||
return GoogleFonts.inter(
|
||||
color: _theme(context).textDark,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 10,
|
||||
);
|
||||
case ThemeType.fruitSorbet:
|
||||
return GoogleFonts.inter(
|
||||
color: _theme(context).textDark,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 10,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static TextStyle syncPercent(BuildContext context) {
|
||||
switch (_theme(context).themeType) {
|
||||
case ThemeType.light:
|
||||
|
@ -1030,7 +1065,7 @@ class STextStyles {
|
|||
);
|
||||
case ThemeType.fruitSorbet:
|
||||
return GoogleFonts.inter(
|
||||
color: _theme(context).textDark,
|
||||
color: _theme(context).bottomNavIconIcon,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12,
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue