implement optional import of frostdart
What changed, and why it matters
This commit refactors how the Stack Wallet app talks to its FROST (multisignature) cryptography library. It replaces direct calls to a concrete 'Frost' service with calls through a new 'frostInterface' abstraction, and makes the underlying frostdart package import optional. The change is mostly architectural: it enables building the app without the FROST library present, and centralizes the interface. There is no direct evidence in the diff of a security vulnerability being fixed; it is a code-organization and build-flexibility change.
Treat as a normal refactoring commit. Review the new frost_interface abstraction and its generated implementation to ensure it preserves the same validation, memory-safety, and error-handling behavior as the previous direct Frost service calls. No urgent security patch action is indicated by the diff alone.
Security signals we found
Refactoring of cryptographic boundary layer
Removal of direct frostdart package imports from UI code
Removal of some direct dart:ffi pointer dereferences in FROST reshare/sign flows
No explicit security claim or CVE reference in commit message
Evidence from the diff
The commit swaps direct imports of services/frost.dart and package:frostdart/frostdart.dart for a generated/optional interface at wl_gen/interfaces/frost_interface.dart. All FROST operations (createMultisigConfig, startKeyGeneration, generateSecretShares, completeKeyGeneration, getParticipants, getThreshold, validateEncodedMultisigConfig, beginResharer, beginReshared, finishResharer, finishReshared, extractDataFromSignConfig, continueSigning, completeSigning, participantIndexFromKeys, getMultisigThreshold, getResharerSalt, decodeRConfig) are now invoked through frostInterface. The patch also removes some direct dart:ffi pointer dereferences (e.g., .machine.ref, .prior.ref) in favor of passing the wrapper objects, which may reduce FFI misuse risk but is not explicitly labeled as a security fix. The diff is large because of accompanying formatting changes.
Changed components
FROST multisig wallet creation UIFROST reshare UIFROST restore UIFROST send/sign UIStack Wallet backup/restore helperBitcoinFrostWallet implementationFROST interface template generatorInspect captured patch +1744 / −1716
diff --git a/lib/pages/add_wallet_views/frost_ms/new/create_new_frost_ms_wallet_view.dart b/lib/pages/add_wallet_views/frost_ms/new/create_new_frost_ms_wallet_view.dart
index a97c7b7..74c31d8 100644
--- a/lib/pages/add_wallet_views/frost_ms/new/create_new_frost_ms_wallet_view.dart
+++ b/lib/pages/add_wallet_views/frost_ms/new/create_new_frost_ms_wallet_view.dart
@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
+
import '../../../../frost_route_generator.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../services/frost.dart';
import '../../../../themes/stack_colors.dart';
import '../../../../utilities/text_styles.dart';
import '../../../../utilities/util.dart';
@@ -20,6 +20,7 @@ import '../../../../widgets/frost_mascot.dart';
import '../../../../widgets/frost_scaffold.dart';
import '../../../../widgets/rounded_white_container.dart';
import '../../../../widgets/stack_dialog.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
class CreateNewFrostMsWalletView extends ConsumerStatefulWidget {
const CreateNewFrostMsWalletView({
@@ -114,31 +115,22 @@ class _NewFrostMsWalletViewState
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text(
- "What is a threshold?",
- style: STextStyles.w600_20(context),
- ),
- const SizedBox(
- height: 12,
- ),
+ Text("What is a threshold?", style: STextStyles.w600_20(context)),
+ const SizedBox(height: 12),
Text(
"A threshold is the amount of people required to perform an "
"action. This does not have to be the same number as the "
"total number in the group.",
style: STextStyles.w400_16(context),
),
- const SizedBox(
- height: 6,
- ),
+ const SizedBox(height: 6),
Text(
"For example, if you have 3 people in the group, but a threshold "
"of 2, then you only need 2 out of the 3 people to sign for an "
"action to take place.",
style: STextStyles.w400_16(context),
),
- const SizedBox(
- height: 6,
- ),
+ const SizedBox(height: 6),
Text(
"Conversely if you have a group of 3 AND a threshold of 3, you "
"will need all 3 people in the group to sign to approve any "
@@ -177,17 +169,15 @@ class _NewFrostMsWalletViewState
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam est justo, ',
),
),
- body: SizedBox(
- width: 480,
- child: child,
- ),
+ body: SizedBox(width: 480, child: child),
),
child: ConditionalParent(
condition: !Util.isDesktop,
builder: (child) => Background(
child: Scaffold(
- backgroundColor:
- Theme.of(context).extension<StackColors>()!.background,
+ backgroundColor: Theme.of(
+ context,
+ ).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () {
@@ -229,8 +219,9 @@ class _NewFrostMsWalletViewState
Text(
"Threshold",
style: STextStyles.w500_14(context).copyWith(
- color:
- Theme.of(context).extension<StackColors>()!.textDark3,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textDark3,
),
),
CustomTextButton(
@@ -239,9 +230,7 @@ class _NewFrostMsWalletViewState
),
],
),
- const SizedBox(
- height: 10,
- ),
+ const SizedBox(height: 10),
TextField(
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
@@ -251,18 +240,14 @@ class _NewFrostMsWalletViewState
hintStyle: STextStyles.fieldLabel(context),
),
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
Text(
"Number of participants",
style: STextStyles.w500_14(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
),
- const SizedBox(
- height: 10,
- ),
+ const SizedBox(height: 10),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
@@ -277,9 +262,7 @@ class _NewFrostMsWalletViewState
hintStyle: STextStyles.fieldLabel(context),
),
),
- const SizedBox(
- height: 6,
- ),
+ const SizedBox(height: 6),
Row(
children: [
Expanded(
@@ -294,9 +277,7 @@ class _NewFrostMsWalletViewState
),
],
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
if (controllers.isNotEmpty)
Text(
"My name",
@@ -304,10 +285,7 @@ class _NewFrostMsWalletViewState
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
),
- if (controllers.isNotEmpty)
- const SizedBox(
- height: 10,
- ),
+ if (controllers.isNotEmpty) const SizedBox(height: 10),
if (controllers.isNotEmpty)
Column(
mainAxisSize: MainAxisSize.min,
@@ -320,9 +298,7 @@ class _NewFrostMsWalletViewState
hintStyle: STextStyles.fieldLabel(context),
),
),
- const SizedBox(
- height: 6,
- ),
+ const SizedBox(height: 6),
Row(
children: [
Expanded(
@@ -337,10 +313,7 @@ class _NewFrostMsWalletViewState
),
],
),
- if (controllers.length > 1)
- const SizedBox(
- height: 16,
- ),
+ if (controllers.length > 1) const SizedBox(height: 16),
if (controllers.length > 1)
Column(
mainAxisSize: MainAxisSize.min,
@@ -349,13 +322,12 @@ class _NewFrostMsWalletViewState
Text(
"Remaining participants",
style: STextStyles.w500_14(context).copyWith(
- color:
- Theme.of(context).extension<StackColors>()!.textDark3,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textDark3,
),
),
- const SizedBox(
- height: 6,
- ),
+ const SizedBox(height: 6),
Row(
children: [
Expanded(
@@ -375,9 +347,7 @@ class _NewFrostMsWalletViewState
children: [
for (int i = 1; i < controllers.length; i++)
Padding(
- padding: const EdgeInsets.only(
- top: 10,
- ),
+ padding: const EdgeInsets.only(top: 10),
child: TextField(
controller: controllers[i],
decoration: InputDecoration(
@@ -389,9 +359,7 @@ class _NewFrostMsWalletViewState
],
),
if (!Util.isDesktop) const Spacer(),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Create new group",
onPressed: () async {
@@ -411,14 +379,14 @@ class _NewFrostMsWalletViewState
);
}
- final config = Frost.createMultisigConfig(
+ final config = frostInterface.createMultisigConfig(
name: controllers.first.text.trim(),
threshold: int.parse(_thresholdController.text),
participants: controllers.map((e) => e.text.trim()).toList(),
);
- ref.read(pFrostMyName.notifier).state =
- controllers.first.text.trim();
+ ref.read(pFrostMyName.notifier).state = controllers.first.text
+ .trim();
ref.read(pFrostMultisigConfig.notifier).state = config;
ref.read(pFrostScaffoldArgs.state).state = (
@@ -434,9 +402,9 @@ class _NewFrostMsWalletViewState
callerRouteName: CreateNewFrostMsWalletView.routeName,
);
- await Navigator.of(context).pushNamed(
- FrostStepScaffold.routeName,
- );
+ await Navigator.of(
+ context,
+ ).pushNamed(FrostStepScaffold.routeName);
},
),
],
diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1a.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1a.dart
index 7b9efb7..5273014 100644
--- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1a.dart
+++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1a.dart
@@ -4,7 +4,6 @@ import 'package:flutter_svg/flutter_svg.dart';
import '../../../../../frost_route_generator.dart';
import '../../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../../services/frost.dart';
import '../../../../../themes/stack_colors.dart';
import '../../../../../utilities/assets.dart';
import '../../../../../utilities/text_styles.dart';
@@ -17,6 +16,7 @@ import '../../../../../widgets/detail_item.dart';
import '../../../../../widgets/dialogs/simple_mobile_dialog.dart';
import '../../../../../widgets/frost_step_user_steps.dart';
import '../../../../../widgets/qr.dart';
+import '../../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../../wallet_view/transaction_views/transaction_details_view.dart';
class FrostCreateStep1a extends ConsumerStatefulWidget {
@@ -41,7 +41,7 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
bool _userVerifyContinue = false;
void _showParticipantsDialog() {
- final participants = Frost.getParticipants(
+ final participants = frostInterface.getParticipants(
multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
);
@@ -53,9 +53,7 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- const SizedBox(
- height: 24,
- ),
+ const SizedBox(height: 24),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Text(
@@ -63,9 +61,7 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
style: STextStyles.w600_20(context),
),
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Text(
@@ -75,9 +71,7 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
),
),
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
for (final participant in participants)
Column(
mainAxisSize: MainAxisSize.min,
@@ -85,12 +79,11 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
Container(
width: double.infinity,
height: 1.5,
- color:
- Theme.of(context).extension<StackColors>()!.background,
- ),
- const SizedBox(
- height: 12,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.background,
),
+ const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Row(
@@ -99,12 +92,10 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
width: 26,
height: 26,
decoration: BoxDecoration(
- color: Theme.of(context)
- .extension<StackColors>()!
- .textFieldActiveBG,
- borderRadius: BorderRadius.circular(
- 200,
- ),
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textFieldActiveBG,
+ borderRadius: BorderRadius.circular(200),
),
child: Center(
child: SvgPicture.asset(
@@ -114,32 +105,22 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
),
),
),
- const SizedBox(
- width: 8,
- ),
+ const SizedBox(width: 8),
Expanded(
child: Text(
participant,
style: STextStyles.w500_14(context),
),
),
- const SizedBox(
- width: 8,
- ),
- IconCopyButton(
- data: participant,
- ),
+ const SizedBox(width: 8),
+ IconCopyButton(data: participant),
],
),
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
],
),
- const SizedBox(
- height: 24,
- ),
+ const SizedBox(height: 24),
],
),
),
@@ -152,12 +133,8 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
padding: const EdgeInsets.all(16),
child: Column(
children: [
- const FrostStepUserSteps(
- userSteps: info,
- ),
- const SizedBox(
- height: 20,
- ),
+ const FrostStepUserSteps(userSteps: info),
+ const SizedBox(height: 20),
SizedBox(
height: 220,
child: Row(
@@ -170,9 +147,7 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
],
),
),
- const SizedBox(
- height: 20,
- ),
+ const SizedBox(height: 20),
DetailItem(
title: "Encoded config",
detail: ref.watch(pFrostMultisigConfig.state).state ?? "Error",
@@ -186,9 +161,7 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
ref.watch(pFrostMultisigConfig.state).state ?? "Error",
),
),
- SizedBox(
- height: Util.isDesktop ? 64 : 16,
- ),
+ SizedBox(height: Util.isDesktop ? 64 : 16),
Row(
children: [
Expanded(
@@ -199,13 +172,8 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
),
],
),
- if (!Util.isDesktop)
- const Spacer(
- flex: 2,
- ),
- const SizedBox(
- height: 16,
- ),
+ if (!Util.isDesktop) const Spacer(flex: 2),
+ const SizedBox(height: 16),
CheckboxTextButton(
label: "I have verified that everyone has joined the group",
onChanged: (value) {
@@ -214,15 +182,14 @@ class _FrostCreateStep1aState extends ConsumerState<FrostCreateStep1a> {
});
},
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Start key generation",
enabled: _userVerifyContinue,
onPressed: () async {
- ref.read(pFrostStartKeyGenData.notifier).state =
- Frost.startKeyGeneration(
+ ref
+ .read(pFrostStartKeyGenData.notifier)
+ .state = frostInterface.startKeyGeneration(
multisigConfig: ref.watch(pFrostMultisigConfig.state).state!,
myName: ref.read(pFrostMyName.state).state!,
);
diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart
index 59597c6..3661e85 100644
--- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart
+++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_1b.dart
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
+
import '../../../../../frost_route_generator.dart';
import '../../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../../services/frost.dart';
import '../../../../../utilities/text_styles.dart';
import '../../../../../utilities/util.dart';
import '../../../../../widgets/custom_buttons/checkbox_text_button.dart';
@@ -11,6 +11,7 @@ import '../../../../../widgets/frost_step_user_steps.dart';
import '../../../../../widgets/rounded_white_container.dart';
import '../../../../../widgets/stack_dialog.dart';
import '../../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../../wl_gen/interfaces/frost_interface.dart';
class FrostCreateStep1b extends ConsumerStatefulWidget {
const FrostCreateStep1b({super.key});
@@ -62,12 +63,8 @@ class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
padding: const EdgeInsets.all(16),
child: Column(
children: [
- const FrostStepUserSteps(
- userSteps: info,
- ),
- const SizedBox(
- height: 16,
- ),
+ const FrostStepUserSteps(userSteps: info),
+ const SizedBox(height: 16),
FrostStepField(
controller: configFieldController,
focusNode: configFocusNode,
@@ -80,9 +77,7 @@ class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
});
},
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
FrostStepField(
controller: myNameFieldController,
focusNode: myNameFocusNode,
@@ -95,9 +90,7 @@ class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
});
},
),
- const SizedBox(
- height: 6,
- ),
+ const SizedBox(height: 6),
Row(
children: [
Expanded(
@@ -111,13 +104,9 @@ class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
),
],
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
if (!Util.isDesktop) const Spacer(),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
CheckboxTextButton(
label: "I have verified that everyone has joined the group",
onChanged: (value) {
@@ -126,9 +115,7 @@ class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
});
},
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Start key generation",
enabled: _userVerifyContinue && !_nameEmpty && !_configEmpty,
@@ -139,7 +126,9 @@ class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
final config = configFieldController.text;
- if (!Frost.validateEncodedMultisigConfig(encodedConfig: config)) {
+ if (!frostInterface.validateEncodedMultisigConfig(
+ encodedConfig: config,
+ )) {
return await showDialog<void>(
context: context,
builder: (_) => StackOkDialog(
@@ -149,7 +138,8 @@ class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
);
}
- if (!Frost.getParticipants(multisigConfig: config)
+ if (!frostInterface
+ .getParticipants(multisigConfig: config)
.contains(myNameFieldController.text)) {
return await showDialog<void>(
context: context,
@@ -163,11 +153,11 @@ class _FrostCreateStep1bState extends ConsumerState<FrostCreateStep1b> {
ref.read(pFrostMyName.state).state = myNameFieldController.text;
ref.read(pFrostMultisigConfig.notifier).state = config;
- ref.read(pFrostStartKeyGenData.state).state =
- Frost.startKeyGeneration(
- multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
- myName: ref.read(pFrostMyName.state).state!,
- );
+ ref.read(pFrostStartKeyGenData.state).state = frostInterface
+ .startKeyGeneration(
+ multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
+ myName: ref.read(pFrostMyName.state).state!,
+ );
ref.read(pFrostCreateCurrentStep.state).state = 2;
await Navigator.of(context).pushNamed(
ref
diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart
index d8aae6d..9bef38d 100644
--- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart
+++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_2.dart
@@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../../frost_route_generator.dart';
import '../../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../../services/frost.dart';
import '../../../../../utilities/logger.dart';
import '../../../../../utilities/util.dart';
import '../../../../../widgets/custom_buttons/checkbox_text_button.dart';
@@ -15,12 +14,11 @@ import '../../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../../widgets/frost_step_user_steps.dart';
import '../../../../../widgets/stack_dialog.dart';
import '../../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../../wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart';
class FrostCreateStep2 extends ConsumerStatefulWidget {
- const FrostCreateStep2({
- super.key,
- });
+ const FrostCreateStep2({super.key});
static const String routeName = "/frostCreateStep2";
static const String title = "Commitments";
@@ -47,7 +45,7 @@ class _FrostCreateStep2State extends ConsumerState<FrostCreateStep2> {
@override
void initState() {
- participants = Frost.getParticipants(
+ participants = frostInterface.getParticipants(
multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
);
myIndex = participants.indexOf(ref.read(pFrostMyName.state).state!);
@@ -81,9 +79,7 @@ class _FrostCreateStep2State extends ConsumerState<FrostCreateStep2> {
padding: const EdgeInsets.all(16),
child: Column(
children: [
- const FrostStepUserSteps(
- userSteps: info,
- ),
+ const FrostStepUserSteps(userSteps: info),
const SizedBox(height: 12),
DetailItem(
title: "My name",
@@ -94,17 +90,11 @@ class _FrostCreateStep2State extends ConsumerState<FrostCreateStep2> {
title: "My commitment",
detail: myCommitment,
button: Util.isDesktop
- ? IconCopyButton(
- data: myCommitment,
- )
- : SimpleCopyButton(
- data: myCommitment,
- ),
+ ? IconCopyButton(data: myCommitment)
+ : SimpleCopyButton(data: myCommitment),
),
const SizedBox(height: 12),
- FrostQrDialogPopupButton(
- data: myCommitment,
- ),
+ FrostQrDialogPopupButton(data: myCommitment),
const SizedBox(height: 12),
for (int i = 0; i < participants.length; i++)
Padding(
@@ -135,7 +125,8 @@ class _FrostCreateStep2State extends ConsumerState<FrostCreateStep2> {
const SizedBox(height: 12),
PrimaryButton(
label: "Generate shares",
- enabled: _userVerifyContinue &&
+ enabled:
+ _userVerifyContinue &&
!fieldIsEmptyFlags.reduce((v, e) => v |= e),
onPressed: () async {
// check for empty commitments
@@ -156,19 +147,19 @@ class _FrostCreateStep2State extends ConsumerState<FrostCreateStep2> {
commitments.insert(myIndex, myCommitment);
try {
- ref.read(pFrostSecretSharesData.notifier).state =
- Frost.generateSecretShares(
- multisigConfigWithNamePtr: ref
- .read(pFrostStartKeyGenData.state)
- .state!
- .multisigConfigWithNamePtr,
- mySeed: ref.read(pFrostStartKeyGenData.state).state!.seed,
- secretShareMachineWrapperPtr: ref
- .read(pFrostStartKeyGenData.state)
- .state!
- .secretShareMachineWrapperPtr,
- commitments: commitments,
- );
+ ref.read(pFrostSecretSharesData.notifier).state = frostInterface
+ .generateSecretShares(
+ multisigConfigWithNamePtr: ref
+ .read(pFrostStartKeyGenData.state)
+ .state!
+ .multisigConfigWithNamePtr,
+ mySeed: ref.read(pFrostStartKeyGenData.state).state!.seed,
+ secretShareMachineWrapperPtr: ref
+ .read(pFrostStartKeyGenData.state)
+ .state!
+ .secretShareMachineWrapperPtr,
+ commitments: commitments,
+ );
ref.read(pFrostCreateCurrentStep.state).state = 3;
await Navigator.of(context).pushNamed(
@@ -178,7 +169,7 @@ class _FrostCreateStep2State extends ConsumerState<FrostCreateStep2> {
.routeName,
);
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (context.mounted) {
return await showDialog<void>(
context: context,
diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart
index ec565cb..1b2ba0c 100644
--- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart
+++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_3.dart
@@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../../frost_route_generator.dart';
import '../../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../../services/frost.dart';
import '../../../../../utilities/logger.dart';
import '../../../../../utilities/util.dart';
import '../../../../../widgets/custom_buttons/checkbox_text_button.dart';
@@ -15,6 +14,7 @@ import '../../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../../widgets/frost_step_user_steps.dart';
import '../../../../../widgets/stack_dialog.dart';
import '../../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../../wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart';
class FrostCreateStep3 extends ConsumerStatefulWidget {
@@ -46,7 +46,7 @@ class _FrostCreateStep3State extends ConsumerState<FrostCreateStep3> {
@override
void initState() {
- participants = Frost.getParticipants(
+ participants = frostInterface.getParticipants(
multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
);
myIndex = participants.indexOf(ref.read(pFrostMyName.state).state!);
@@ -80,9 +80,7 @@ class _FrostCreateStep3State extends ConsumerState<FrostCreateStep3> {
padding: const EdgeInsets.all(16),
child: Column(
children: [
- const FrostStepUserSteps(
- userSteps: info,
- ),
+ const FrostStepUserSteps(userSteps: info),
const SizedBox(height: 12),
DetailItem(
title: "My name",
@@ -93,17 +91,11 @@ class _FrostCreateStep3State extends ConsumerState<FrostCreateStep3> {
title: "My share",
detail: myShare,
button: Util.isDesktop
- ? IconCopyButton(
- data: myShare,
- )
- : SimpleCopyButton(
- data: myShare,
- ),
+ ? IconCopyButton(data: myShare)
+ : SimpleCopyButton(data: myShare),
),
const SizedBox(height: 12),
- FrostQrDialogPopupButton(
- data: myShare,
- ),
+ FrostQrDialogPopupButton(data: myShare),
const SizedBox(height: 12),
for (int i = 0; i < participants.length; i++)
Padding(
@@ -131,12 +123,11 @@ class _FrostCreateStep3State extends ConsumerState<FrostCreateStep3> {
});
},
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Generate",
- enabled: _userVerifyContinue &&
+ enabled:
+ _userVerifyContinue &&
!fieldIsEmptyFlags.reduce((v, e) => v |= e),
onPressed: () async {
// check for empty commitments
@@ -157,8 +148,9 @@ class _FrostCreateStep3State extends ConsumerState<FrostCreateStep3> {
shares.insert(myIndex, myShare);
try {
- ref.read(pFrostCompletedKeyGenData.notifier).state =
- Frost.completeKeyGeneration(
+ ref
+ .read(pFrostCompletedKeyGenData.notifier)
+ .state = frostInterface.completeKeyGeneration(
multisigConfigWithNamePtr: ref
.read(pFrostStartKeyGenData.state)
.state!
@@ -178,7 +170,7 @@ class _FrostCreateStep3State extends ConsumerState<FrostCreateStep3> {
.routeName,
);
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (context.mounted) {
return await showDialog<void>(
diff --git a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_5.dart b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_5.dart
index 0d7c53e..6516690 100644
--- a/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_5.dart
+++ b/lib/pages/add_wallet_views/frost_ms/new/steps/frost_create_step_5.dart
@@ -11,7 +11,6 @@ import '../../../../../pages_desktop_specific/desktop_home_view.dart';
import '../../../../../providers/frost_wallet/frost_wallet_providers.dart';
import '../../../../../providers/global/secure_store_provider.dart';
import '../../../../../providers/providers.dart';
-import '../../../../../services/frost.dart';
import '../../../../../themes/stack_colors.dart';
import '../../../../../utilities/assets.dart';
import '../../../../../utilities/logger.dart';
@@ -26,6 +25,7 @@ import '../../../../../widgets/desktop/primary_button.dart';
import '../../../../../widgets/detail_item.dart';
import '../../../../../widgets/loading_indicator.dart';
import '../../../../../widgets/rounded_container.dart';
+import '../../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../../home_view/home_view.dart';
import '../../../../wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart'
as tvd;
@@ -56,10 +56,14 @@ class _FrostCreateStep5State extends ConsumerState<FrostCreateStep5> {
@override
void initState() {
seed = ref.read(pFrostStartKeyGenData.state).state!.seed;
- serializedKeys =
- ref.read(pFrostCompletedKeyGenData.state).state!.serializedKeys;
- recoveryString =
- ref.read(pFrostCompletedKeyGenData.state).state!.recoveryString;
+ serializedKeys = ref
+ .read(pFrostCompletedKeyGenData.state)
+ .state!
+ .serializedKeys;
+ recoveryString = ref
+ .read(pFrostCompletedKeyGenData.state)
+ .state!
+ .recoveryString;
multisigConfig = ref.read(pFrostMultisigConfig.state).state!;
multisigId = ref.read(pFrostCompletedKeyGenData.state).state!.multisigId;
@@ -73,15 +77,15 @@ class _FrostCreateStep5State extends ConsumerState<FrostCreateStep5> {
child: Column(
children: [
RoundedContainer(
- color:
- Theme.of(context).extension<StackColors>()!.warningBackground,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.warningBackground,
child: Text(
_warning,
style: STextStyles.w500_14(context).copyWith(
- color:
- Theme.of(
- context,
- ).extension<StackColors>()!.warningForeground,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.warningForeground,
),
),
),
@@ -89,19 +93,17 @@ class _FrostCreateStep5State extends ConsumerState<FrostCreateStep5> {
DetailItem(
title: "Multisig Config",
detail: multisigConfig,
- button:
- Util.isDesktop
- ? tvd.IconCopyButton(data: multisigConfig)
- : SimpleCopyButton(data: multisigConfig),
+ button: Util.isDesktop
+ ? tvd.IconCopyButton(data: multisigConfig)
+ : SimpleCopyButton(data: multisigConfig),
),
const SizedBox(height: 12),
DetailItem(
title: "Keys",
detail: serializedKeys,
- button:
- Util.isDesktop
- ? tvd.IconCopyButton(data: serializedKeys)
- : SimpleCopyButton(data: serializedKeys),
+ button: Util.isDesktop
+ ? tvd.IconCopyButton(data: serializedKeys)
+ : SimpleCopyButton(data: serializedKeys),
),
if (!Util.isDesktop) const Spacer(),
const SizedBox(height: 12),
@@ -156,10 +158,10 @@ class _FrostCreateStep5State extends ConsumerState<FrostCreateStep5> {
serializedKeys: serializedKeys,
multisigId: multisigId,
myName: ref.read(pFrostMyName.state).state!,
- participants: Frost.getParticipants(
+ participants: frostInterface.getParticipants(
multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
),
- threshold: Frost.getThreshold(
+ threshold: frostInterface.getThreshold(
multisigConfig: ref.read(pFrostMultisigConfig.state).state!,
),
);
diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1a.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1a.dart
index 740baaf..9fe973b 100644
--- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1a.dart
+++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1a.dart
@@ -6,7 +6,6 @@ import '../../../../frost_route_generator.dart';
import '../../../../providers/db/main_db_provider.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
import '../../../../providers/global/wallets_provider.dart';
-import '../../../../services/frost.dart';
import '../../../../themes/stack_colors.dart';
import '../../../../utilities/assets.dart';
import '../../../../utilities/logger.dart';
@@ -23,6 +22,7 @@ import '../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../widgets/dialogs/simple_mobile_dialog.dart';
import '../../../../widgets/frost_step_user_steps.dart';
import '../../../../widgets/qr.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../wallet_view/transaction_views/transaction_details_view.dart';
class FrostReshareStep1a extends ConsumerStatefulWidget {
@@ -63,9 +63,9 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
final serializedKeys = await wallet.getSerializedKeys();
if (mounted) {
- final result = Frost.beginResharer(
+ final result = frostInterface.beginResharer(
serializedKeys: serializedKeys!,
- config: Frost.decodeRConfig(
+ config: frostInterface.decodeRConfig(
ref.read(pFrostResharingData).resharerRConfig!,
),
);
@@ -81,14 +81,12 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
);
}
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (mounted) {
await showDialog<void>(
context: context,
- builder: (_) => FrostErrorDialog(
- title: e.toString(),
- ),
+ builder: (_) => FrostErrorDialog(title: e.toString()),
);
}
} finally {
@@ -97,8 +95,10 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
}
void _showParticipantsDialog() {
- final participants =
- ref.read(pFrostResharingData).configData!.newParticipants;
+ final participants = ref
+ .read(pFrostResharingData)
+ .configData!
+ .newParticipants;
showDialog<void>(
context: context,
@@ -108,9 +108,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- const SizedBox(
- height: 24,
- ),
+ const SizedBox(height: 24),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Text(
@@ -118,9 +116,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
style: STextStyles.w600_20(context),
),
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Text(
@@ -130,9 +126,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
),
),
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
for (final participant in participants)
Column(
mainAxisSize: MainAxisSize.min,
@@ -140,12 +134,11 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
Container(
width: double.infinity,
height: 1.5,
- color:
- Theme.of(context).extension<StackColors>()!.background,
- ),
- const SizedBox(
- height: 12,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.background,
),
+ const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Row(
@@ -154,12 +147,10 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
width: 26,
height: 26,
decoration: BoxDecoration(
- color: Theme.of(context)
- .extension<StackColors>()!
- .textFieldActiveBG,
- borderRadius: BorderRadius.circular(
- 200,
- ),
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textFieldActiveBG,
+ borderRadius: BorderRadius.circular(200),
),
child: Center(
child: SvgPicture.asset(
@@ -169,32 +160,22 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
),
),
),
- const SizedBox(
- width: 8,
- ),
+ const SizedBox(width: 8),
Expanded(
child: Text(
participant,
style: STextStyles.w500_14(context),
),
),
- const SizedBox(
- width: 8,
- ),
- IconCopyButton(
- data: participant,
- ),
+ const SizedBox(width: 8),
+ IconCopyButton(data: participant),
],
),
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
],
),
- const SizedBox(
- height: 24,
- ),
+ const SizedBox(height: 24),
],
),
),
@@ -227,9 +208,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
padding: const EdgeInsets.all(16),
child: Column(
children: [
- const FrostStepUserSteps(
- userSteps: info,
- ),
+ const FrostStepUserSteps(userSteps: info),
const SizedBox(height: 20),
SizedBox(
height: 220,
@@ -243,9 +222,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
],
),
),
- const SizedBox(
- height: 32,
- ),
+ const SizedBox(height: 32),
DetailItem(
title: "Config",
detail: ref.watch(pFrostResharingData).resharerRConfig!,
@@ -257,9 +234,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
data: ref.watch(pFrostResharingData).resharerRConfig!,
),
),
- SizedBox(
- height: Util.isDesktop ? 64 : 16,
- ),
+ SizedBox(height: Util.isDesktop ? 64 : 16),
Row(
children: [
Expanded(
@@ -271,10 +246,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
],
),
if (iAmInvolved && !Util.isDesktop) const Spacer(),
- if (iAmInvolved)
- const SizedBox(
- height: 16,
- ),
+ if (iAmInvolved) const SizedBox(height: 16),
if (iAmInvolved)
CheckboxTextButton(
label: "I have verified that everyone has imported the config",
@@ -284,10 +256,7 @@ class _FrostReshareStep1aState extends ConsumerState<FrostReshareStep1a> {
});
},
),
- if (iAmInvolved)
- const SizedBox(
- height: 16,
- ),
+ if (iAmInvolved) const SizedBox(height: 16),
if (iAmInvolved)
PrimaryButton(
label: "Start resharing",
diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1b.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1b.dart
index 7224e2a..b4971d6 100644
--- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1b.dart
+++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_1b.dart
@@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:frostdart/frostdart.dart';
+
+// import 'package:frostdart/frostdart.dart';
import '../../../../frost_route_generator.dart';
import '../../../../providers/db/main_db_provider.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
import '../../../../providers/global/secure_store_provider.dart';
-import '../../../../services/frost.dart';
import '../../../../utilities/format.dart';
import '../../../../utilities/logger.dart';
import '../../../../utilities/util.dart';
@@ -16,11 +16,10 @@ import '../../../../widgets/desktop/primary_button.dart';
import '../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../widgets/frost_step_user_steps.dart';
import '../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
class FrostReshareStep1b extends ConsumerStatefulWidget {
- const FrostReshareStep1b({
- super.key,
- });
+ const FrostReshareStep1b({super.key});
static const String routeName = "/frostReshareStep1b";
static const String title = "Import reshare config";
@@ -70,8 +69,8 @@ class _FrostReshareStep1bState extends ConsumerState<FrostReshareStep1b> {
String? salt;
try {
salt = Format.uint8listToString(
- resharerSalt(
- resharerConfig: Frost.decodeRConfig(
+ frostInterface.getResharerSalt(
+ resharerConfig: frostInterface.decodeRConfig(
ref.read(pFrostResharingData).resharerRConfig!,
),
),
@@ -95,13 +94,13 @@ class _FrostReshareStep1bState extends ConsumerState<FrostReshareStep1b> {
});
}
- final serializedKeys = await ref.read(secureStoreProvider).read(
- key: "{$walletId}_serializedFROSTKeys",
- );
+ final serializedKeys = await ref
+ .read(secureStoreProvider)
+ .read(key: "{$walletId}_serializedFROSTKeys");
if (mounted) {
- final result = Frost.beginResharer(
+ final result = frostInterface.beginResharer(
serializedKeys: serializedKeys!,
- config: Frost.decodeRConfig(
+ config: frostInterface.decodeRConfig(
ref.read(pFrostResharingData).resharerRConfig!,
),
);
@@ -117,14 +116,12 @@ class _FrostReshareStep1bState extends ConsumerState<FrostReshareStep1b> {
);
}
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (mounted) {
await showDialog<void>(
context: context,
- builder: (_) => FrostErrorDialog(
- title: e.toString(),
- ),
+ builder: (_) => FrostErrorDialog(title: e.toString()),
);
}
} finally {
@@ -153,12 +150,8 @@ class _FrostReshareStep1bState extends ConsumerState<FrostReshareStep1b> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- const SizedBox(
- height: 16,
- ),
- const FrostStepUserSteps(
- userSteps: info,
- ),
+ const SizedBox(height: 16),
+ const FrostStepUserSteps(userSteps: info),
const SizedBox(height: 20),
FrostStepField(
controller: configFieldController,
@@ -172,13 +165,9 @@ class _FrostReshareStep1bState extends ConsumerState<FrostReshareStep1b> {
});
},
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
if (!Util.isDesktop) const Spacer(),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
CheckboxTextButton(
label: "I have verified that everyone has imported the config",
onChanged: (value) {
@@ -187,9 +176,7 @@ class _FrostReshareStep1bState extends ConsumerState<FrostReshareStep1b> {
});
},
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Start resharing",
enabled: !_configEmpty && _userVerifyContinue,
diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_2abd.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_2abd.dart
index b54b604..7cc2ce5 100644
--- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_2abd.dart
+++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_2abd.dart
@@ -6,7 +6,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../frost_route_generator.dart';
import '../../../../providers/db/main_db_provider.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../services/frost.dart';
import '../../../../utilities/logger.dart';
import '../../../../utilities/util.dart';
import '../../../../wallets/isar/models/frost_wallet_info.dart';
@@ -17,6 +16,7 @@ import '../../../../widgets/desktop/primary_button.dart';
import '../../../../widgets/detail_item.dart';
import '../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../wallet_view/transaction_views/transaction_details_view.dart';
class FrostReshareStep2abd extends ConsumerStatefulWidget {
@@ -60,9 +60,9 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
resharerStarts.insert(myResharerIndexIndex, myResharerStart);
}
- final result = Frost.beginReshared(
+ final result = frostInterface.beginReshared(
myName: ref.read(pFrostResharingData).myName!,
- resharerConfig: Frost.decodeRConfig(
+ resharerConfig: frostInterface.decodeRConfig(
ref.read(pFrostResharingData).resharerRConfig!,
),
resharerStarts: resharerStarts,
@@ -79,15 +79,13 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
.routeName,
);
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (mounted) {
await showDialog<void>(
context: context,
- builder: (_) => FrostErrorDialog(
- title: "Error",
- message: e.toString(),
- ),
+ builder: (_) =>
+ FrostErrorDialog(title: "Error", message: e.toString()),
);
}
} finally {
@@ -103,11 +101,14 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
.isar
.frostWalletInfo
.getByWalletIdSync(ref.read(pFrostScaffoldArgs)!.walletId!)!;
- final myOldIndex =
- frostInfo.participants.indexOf(ref.read(pFrostResharingData).myName!);
+ final myOldIndex = frostInfo.participants.indexOf(
+ ref.read(pFrostResharingData).myName!,
+ );
- myResharerStart =
- ref.read(pFrostResharingData).startResharerData!.resharerStart;
+ myResharerStart = ref
+ .read(pFrostResharingData)
+ .startResharerData!
+ .resharerStart;
resharers = ref.read(pFrostResharingData).configData!.resharers;
myResharerIndexIndex = resharers.values.toList().indexOf(myOldIndex);
@@ -151,20 +152,12 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
title: "My resharer",
detail: myResharerStart,
button: Util.isDesktop
- ? IconCopyButton(
- data: myResharerStart,
- )
- : SimpleCopyButton(
- data: myResharerStart,
- ),
+ ? IconCopyButton(data: myResharerStart)
+ : SimpleCopyButton(data: myResharerStart),
),
const SizedBox(height: 12),
- FrostQrDialogPopupButton(
- data: myResharerStart,
- ),
- const SizedBox(
- height: 12,
- ),
+ FrostQrDialogPopupButton(data: myResharerStart),
+ const SizedBox(height: 12),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@@ -175,7 +168,8 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
focusNode: focusNodes[i],
showQrScanOption: true,
label: resharers.keys.elementAt(i),
- hint: "Enter "
+ hint:
+ "Enter "
"${resharers.keys.elementAt(i)}"
"'s resharer",
onChanged: (_) {
@@ -187,9 +181,7 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
],
),
if (!Util.isDesktop) const Spacer(),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
CheckboxTextButton(
label: "I have verified that everyone has my resharer",
onChanged: (value) {
@@ -198,12 +190,11 @@ class _FrostReshareStep2abdState extends ConsumerState<FrostReshareStep2abd> {
});
},
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Continue",
- enabled: _userVerifyContinue &&
+ enabled:
+ _userVerifyContinue &&
(amOutgoingParticipant ||
!fieldIsEmptyFlags.fold(false, (v, e) => v || e)),
onPressed: _onPressed,
diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_2c.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_2c.dart
index 92a3a19..3717188 100644
--- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_2c.dart
+++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_2c.dart
@@ -5,12 +5,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../frost_route_generator.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../services/frost.dart';
import '../../../../utilities/logger.dart';
import '../../../../utilities/util.dart';
import '../../../../widgets/desktop/primary_button.dart';
import '../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
class FrostReshareStep2c extends ConsumerStatefulWidget {
const FrostReshareStep2c({super.key});
@@ -41,9 +41,9 @@ class _FrostReshareStep2cState extends ConsumerState<FrostReshareStep2c> {
// collect resharer strings
final resharerStarts = controllers.map((e) => e.text).toList();
- final result = Frost.beginReshared(
+ final result = frostInterface.beginReshared(
myName: ref.read(pFrostResharingData).myName!,
- resharerConfig: Frost.decodeRConfig(
+ resharerConfig: frostInterface.decodeRConfig(
ref.read(pFrostResharingData).resharerRConfig!,
),
resharerStarts: resharerStarts,
@@ -59,15 +59,13 @@ class _FrostReshareStep2cState extends ConsumerState<FrostReshareStep2c> {
.routeName,
);
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (mounted) {
await showDialog<void>(
context: context,
- builder: (_) => FrostErrorDialog(
- title: "Error",
- message: e.toString(),
- ),
+ builder: (_) =>
+ FrostErrorDialog(title: "Error", message: e.toString()),
);
}
} finally {
@@ -116,7 +114,8 @@ class _FrostReshareStep2cState extends ConsumerState<FrostReshareStep2c> {
focusNode: focusNodes[i],
showQrScanOption: true,
label: resharers.keys.elementAt(i),
- hint: "Enter "
+ hint:
+ "Enter "
"${resharers.keys.elementAt(i)}"
"'s resharer",
onChanged: (_) {
@@ -129,9 +128,7 @@ class _FrostReshareStep2cState extends ConsumerState<FrostReshareStep2c> {
],
),
if (!Util.isDesktop) const Spacer(),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Continue",
enabled: !fieldIsEmptyFlags.reduce((v, e) => v |= e),
diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_3abd.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_3abd.dart
index d4fc876..edd5d51 100644
--- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_3abd.dart
+++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_3abd.dart
@@ -1,11 +1,8 @@
-import 'dart:ffi';
-
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../frost_route_generator.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../services/frost.dart';
import '../../../../utilities/logger.dart';
import '../../../../utilities/util.dart';
import '../../../../widgets/custom_buttons/checkbox_text_button.dart';
@@ -15,6 +12,7 @@ import '../../../../widgets/desktop/primary_button.dart';
import '../../../../widgets/detail_item.dart';
import '../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../wallet_view/transaction_views/transaction_details_view.dart';
class FrostReshareStep3abd extends ConsumerStatefulWidget {
@@ -55,8 +53,8 @@ class _FrostReshareStep3abdState extends ConsumerState<FrostReshareStep3abd> {
encryptionKeys.insert(myIndex, myEncryptionKey!);
}
- final result = Frost.finishResharer(
- machine: ref.read(pFrostResharingData).startResharerData!.machine.ref,
+ final result = frostInterface.finishResharer(
+ machine: ref.read(pFrostResharingData).startResharerData!.machine,
encryptionKeysOfResharedTo: encryptionKeys,
);
@@ -70,14 +68,12 @@ class _FrostReshareStep3abdState extends ConsumerState<FrostReshareStep3abd> {
.routeName,
);
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (mounted) {
await showDialog<void>(
context: context,
- builder: (_) => FrostErrorDialog(
- title: "Error",
- message: e.toString(),
- ),
+ builder: (_) =>
+ FrostErrorDialog(title: "Error", message: e.toString()),
);
}
} finally {
@@ -87,8 +83,10 @@ class _FrostReshareStep3abdState extends ConsumerState<FrostReshareStep3abd> {
@override
void initState() {
- myEncryptionKey =
- ref.read(pFrostResharingData).startResharedData?.resharedStart;
+ myEncryptionKey = ref
+ .read(pFrostResharingData)
+ .startResharedData
+ ?.resharedStart;
newParticipants = ref.read(pFrostResharingData).configData!.newParticipants;
myIndex = newParticipants.indexOf(ref.read(pFrostResharingData).myName!);
@@ -136,22 +134,13 @@ class _FrostReshareStep3abdState extends ConsumerState<FrostReshareStep3abd> {
title: "My encryption key",
detail: myEncryptionKey!,
button: Util.isDesktop
- ? IconCopyButton(
- data: myEncryptionKey!,
- )
- : SimpleCopyButton(
- data: myEncryptionKey!,
- ),
+ ? IconCopyButton(data: myEncryptionKey!)
+ : SimpleCopyButton(data: myEncryptionKey!),
),
if (!amOutgoingParticipant) const SizedBox(height: 12),
if (!amOutgoingParticipant)
- FrostQrDialogPopupButton(
- data: myEncryptionKey!,
- ),
- if (!amOutgoingParticipant)
- const SizedBox(
- height: 12,
- ),
+ FrostQrDialogPopupButton(data: myEncryptionKey!),
+ if (!amOutgoingParticipant) const SizedBox(height: 12),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@@ -164,7 +153,8 @@ class _FrostReshareStep3abdState extends ConsumerState<FrostReshareStep3abd> {
focusNode: focusNodes[i],
showQrScanOption: true,
label: newParticipants[i],
- hint: "Enter "
+ hint:
+ "Enter "
"${newParticipants[i]}"
"'s encryption key",
onChanged: (_) {
@@ -177,10 +167,7 @@ class _FrostReshareStep3abdState extends ConsumerState<FrostReshareStep3abd> {
],
),
if (!Util.isDesktop) const Spacer(),
- if (!amOutgoingParticipant)
- const SizedBox(
- height: 12,
- ),
+ if (!amOutgoingParticipant) const SizedBox(height: 12),
if (!amOutgoingParticipant)
CheckboxTextButton(
label: "I have verified that everyone has my encryption key",
@@ -190,12 +177,11 @@ class _FrostReshareStep3abdState extends ConsumerState<FrostReshareStep3abd> {
});
},
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Continue",
- enabled: (amOutgoingParticipant || _userVerifyContinue) &&
+ enabled:
+ (amOutgoingParticipant || _userVerifyContinue) &&
!fieldIsEmptyFlags.reduce((v, e) => v |= e),
onPressed: _onPressed,
),
diff --git a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_4.dart b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_4.dart
index dd081d1..00765f9 100644
--- a/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_4.dart
+++ b/lib/pages/add_wallet_views/frost_ms/reshare/frost_reshare_step_4.dart
@@ -1,5 +1,3 @@
-import 'dart:ffi';
-
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -7,7 +5,6 @@ import '../../../../frost_route_generator.dart';
import '../../../../pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart';
import '../../../../providers/db/main_db_provider.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
-import '../../../../services/frost.dart';
import '../../../../utilities/logger.dart';
import '../../../../utilities/util.dart';
import '../../../../wallets/isar/models/frost_wallet_info.dart';
@@ -18,6 +15,7 @@ import '../../../../widgets/desktop/primary_button.dart';
import '../../../../widgets/detail_item.dart';
import '../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../wallet_view/transaction_views/transaction_details_view.dart';
import '../../../wallet_view/wallet_view.dart';
@@ -58,7 +56,10 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
if (amOutgoingParticipant) {
ref.read(pFrostResharingData).reset();
ref.read(pFrostScaffoldCanPopDesktop.notifier).state = true;
- ref.read(pFrostScaffoldArgs)?.parentNav.popUntil(
+ ref
+ .read(pFrostScaffoldArgs)
+ ?.parentNav
+ .popUntil(
ModalRoute.withName(
Util.isDesktop
? DesktopWalletView.routeName
@@ -72,8 +73,8 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
resharerCompletes.insert(myResharerIndexIndex!, myResharerComplete!);
}
- final data = Frost.finishReshared(
- prior: ref.read(pFrostResharingData).startResharedData!.prior.ref,
+ final data = frostInterface.finishReshared(
+ prior: ref.read(pFrostResharingData).startResharedData!.prior,
resharerCompletes: resharerCompletes,
);
@@ -88,14 +89,12 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
);
}
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (mounted) {
await showDialog<void>(
context: context,
- builder: (_) => FrostErrorDialog(
- title: "Error",
- message: e.toString(),
- ),
+ builder: (_) =>
+ FrostErrorDialog(title: "Error", message: e.toString()),
);
}
} finally {
@@ -107,9 +106,9 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
void initState() {
amNewParticipant =
ref.read(pFrostResharingData).startResharerData == null &&
- ref.read(pFrostResharingData).incompleteWallet != null &&
- ref.read(pFrostResharingData).incompleteWallet?.walletId ==
- ref.read(pFrostScaffoldArgs)!.walletId!;
+ ref.read(pFrostResharingData).incompleteWallet != null &&
+ ref.read(pFrostResharingData).incompleteWallet?.walletId ==
+ ref.read(pFrostScaffoldArgs)!.walletId!;
myName = ref.read(pFrostResharingData).myName!;
@@ -127,8 +126,9 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
.isar
.frostWalletInfo
.getByWalletIdSync(ref.read(pFrostScaffoldArgs)!.walletId!)!;
- final myOldIndex =
- frostInfo.participants.indexOf(ref.read(pFrostResharingData).myName!);
+ final myOldIndex = frostInfo.participants.indexOf(
+ ref.read(pFrostResharingData).myName!,
+ );
myResharerIndexIndex = resharers.values.toList().indexOf(myOldIndex);
if (myResharerIndexIndex! >= 0) {
@@ -173,22 +173,13 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
title: "My resharer complete",
detail: myResharerComplete!,
button: Util.isDesktop
- ? IconCopyButton(
- data: myResharerComplete!,
- )
- : SimpleCopyButton(
- data: myResharerComplete!,
- ),
+ ? IconCopyButton(data: myResharerComplete!)
+ : SimpleCopyButton(data: myResharerComplete!),
),
if (myResharerComplete != null) const SizedBox(height: 12),
if (myResharerComplete != null)
- FrostQrDialogPopupButton(
- data: myResharerComplete!,
- ),
- if (!amOutgoingParticipant)
- const SizedBox(
- height: 16,
- ),
+ FrostQrDialogPopupButton(data: myResharerComplete!),
+ if (!amOutgoingParticipant) const SizedBox(height: 16),
if (!amOutgoingParticipant)
Column(
mainAxisSize: MainAxisSize.min,
@@ -202,7 +193,8 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
focusNode: focusNodes[i],
showQrScanOption: true,
label: resharers.keys.elementAt(i),
- hint: "Enter "
+ hint:
+ "Enter "
"${resharers.keys.elementAt(i)}"
"'s resharer",
onChanged: (_) {
@@ -215,9 +207,7 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
],
),
if (!Util.isDesktop) const Spacer(),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
if (!amNewParticipant)
CheckboxTextButton(
label: "I have verified that everyone has my resharer complete",
@@ -227,13 +217,11 @@ class _FrostReshareStep4State extends ConsumerState<FrostReshareStep4> {
});
},
),
- if (!amNewParticipant)
- const SizedBox(
- height: 16,
- ),
+ if (!amNewParticipant) const SizedBox(height: 16),
PrimaryButton(
label: amOutgoingParticipant ? "Done" : "Complete",
- enabled: (amNewParticipant || _userVerifyContinue) &&
+ enabled:
+ (amNewParticipant || _userVerifyContinue) &&
(amOutgoingParticipant ||
!fieldIsEmptyFlags.fold(false, (v, e) => v || e)),
onPressed: _onPressed,
diff --git a/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart b/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart
index facaeed..33eddc5 100644
--- a/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart
+++ b/lib/pages/add_wallet_views/frost_ms/restore/restore_frost_ms_wallet_view.dart
@@ -4,13 +4,13 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:frostdart/frostdart.dart' as frost;
+
+// import 'package:frostdart/frostdart.dart' as frost;
import '../../../../notifications/show_flush_bar.dart';
import '../../../../pages_desktop_specific/desktop_home_view.dart';
import '../../../../providers/global/secure_store_provider.dart';
import '../../../../providers/providers.dart';
-import '../../../../services/frost.dart';
import '../../../../themes/stack_colors.dart';
import '../../../../utilities/assets.dart';
import '../../../../utilities/barcode_scanner_interface.dart';
@@ -38,6 +38,7 @@ import '../../../../widgets/icon_widgets/x_icon.dart';
import '../../../../widgets/stack_dialog.dart';
import '../../../../widgets/stack_text_field.dart';
import '../../../../widgets/textfield_icon_button.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../home_view/home_view.dart';
class RestoreFrostMsWalletView extends ConsumerStatefulWidget {
@@ -70,8 +71,10 @@ class _RestoreFrostMsWalletViewState
final keys = keysFieldController.text;
final config = configFieldController.text;
- final myNameIndex = frost.getParticipantIndexFromKeys(serializedKeys: keys);
- final participants = Frost.getParticipants(multisigConfig: config);
+ final myNameIndex = frostInterface.participantIndexFromKeys(
+ serializedKeys: keys,
+ );
+ final participants = frostInterface.getParticipants(multisigConfig: config);
final myName = participants[myNameIndex];
final info = WalletInfo.createNew(
@@ -92,7 +95,7 @@ class _RestoreFrostMsWalletViewState
knownSalts: [],
participants: participants,
myName: myName,
- threshold: frost.multisigThreshold(multisigConfig: config),
+ threshold: frostInterface.getMultisigThreshold(multisigConfig: config),
);
await ref.read(mainDBProvider).isar.writeTxn(() async {
@@ -173,12 +176,11 @@ class _RestoreFrostMsWalletViewState
if (mounted) {
await showDialog<void>(
context: context,
- builder:
- (_) => StackOkDialog(
- title: "Failed to restore",
- message: e.toString(),
- desktopPopRootNavigator: Util.isDesktop,
- ),
+ builder: (_) => StackOkDialog(
+ title: "Failed to restore",
+ message: e.toString(),
+ desktopPopRootNavigator: Util.isDesktop,
+ ),
);
}
} finally {
@@ -265,60 +267,59 @@ class _RestoreFrostMsWalletViewState
Widget build(BuildContext context) {
return ConditionalParent(
condition: Util.isDesktop,
- builder:
- (child) => DesktopScaffold(
- background: Theme.of(context).extension<StackColors>()!.background,
- appBar: const DesktopAppBar(
- isCompactHeight: false,
- leading: AppBarBackButton(),
- // TODO: [prio=high] get rid of placeholder text??
- trailing: FrostMascot(
- title: 'Lorem ipsum',
- body:
- 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam est justo, ',
- ),
- ),
- body: SizedBox(width: 480, child: child),
+ builder: (child) => DesktopScaffold(
+ background: Theme.of(context).extension<StackColors>()!.background,
+ appBar: const DesktopAppBar(
+ isCompactHeight: false,
+ leading: AppBarBackButton(),
+ // TODO: [prio=high] get rid of placeholder text??
+ trailing: FrostMascot(
+ title: 'Lorem ipsum',
+ body:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam est justo, ',
),
+ ),
+ body: SizedBox(width: 480, child: child),
+ ),
child: ConditionalParent(
condition: !Util.isDesktop,
- builder:
- (child) => Background(
- child: Scaffold(
- backgroundColor:
- Theme.of(context).extension<StackColors>()!.background,
- appBar: AppBar(
- leading: AppBarBackButton(
- onPressed: () {
- Navigator.of(context).pop();
- },
- ),
- title: Text(
- "Restore FROST multisig wallet",
- style: STextStyles.navBarTitle(context),
- ),
- ),
- body: SafeArea(
- child: LayoutBuilder(
- builder: (context, constraints) {
- return SingleChildScrollView(
- child: ConstrainedBox(
- constraints: BoxConstraints(
- minHeight: constraints.maxHeight,
- ),
- child: IntrinsicHeight(
- child: Padding(
- padding: const EdgeInsets.all(16),
- child: child,
- ),
- ),
+ builder: (child) => Background(
+ child: Scaffold(
+ backgroundColor: Theme.of(
+ context,
+ ).extension<StackColors>()!.background,
+ appBar: AppBar(
+ leading: AppBarBackButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ ),
+ title: Text(
+ "Restore FROST multisig wallet",
+ style: STextStyles.navBarTitle(context),
+ ),
+ ),
+ body: SafeArea(
+ child: LayoutBuilder(
+ builder: (context, constraints) {
+ return SingleChildScrollView(
+ child: ConstrainedBox(
+ constraints: BoxConstraints(
+ minHeight: constraints.maxHeight,
+ ),
+ child: IntrinsicHeight(
+ child: Padding(
+ padding: const EdgeInsets.all(16),
+ child: child,
),
- );
- },
- ),
- ),
+ ),
+ ),
+ );
+ },
),
),
+ ),
+ ),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -340,78 +341,79 @@ class _RestoreFrostMsWalletViewState
autocorrect: false,
enableSuggestions: false,
style: STextStyles.field(context),
- decoration: standardInputDecoration(
- "Enter config",
- configFocusNode,
- context,
- ).copyWith(
- contentPadding: const EdgeInsets.only(
- left: 16,
- top: 6,
- bottom: 8,
- right: 5,
- ),
- suffixIcon: Padding(
- padding:
- _configEmpty
+ decoration:
+ standardInputDecoration(
+ "Enter config",
+ configFocusNode,
+ context,
+ ).copyWith(
+ contentPadding: const EdgeInsets.only(
+ left: 16,
+ top: 6,
+ bottom: 8,
+ right: 5,
+ ),
+ suffixIcon: Padding(
+ padding: _configEmpty
? const EdgeInsets.only(right: 8)
: const EdgeInsets.only(right: 0),
- child: UnconstrainedBox(
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- !_configEmpty
- ? TextFieldIconButton(
- semanticsLabel:
- "Clear Button. Clears The Config Field.",
- key: const Key("frConfigClearButtonKey"),
- onTap: () {
- configFieldController.text = "";
-
- setState(() {
- _configEmpty = true;
- });
- },
- child: const XIcon(),
- )
- : TextFieldIconButton(
- semanticsLabel:
- "Paste Button. Pastes From Clipboard To Config Field Input.",
- key: const Key("frConfigPasteButtonKey"),
- onTap: () async {
- final ClipboardData? data =
- await Clipboard.getData(
- Clipboard.kTextPlain,
- );
- if (data?.text != null &&
- data!.text!.isNotEmpty) {
- configFieldController.text =
- data.text!.trim();
- }
-
- setState(() {
- _configEmpty =
- configFieldController.text.isEmpty;
- });
- },
- child:
- _configEmpty
- ? const ClipboardIcon()
- : const XIcon(),
- ),
- if (_configEmpty)
- TextFieldIconButton(
- semanticsLabel:
- "Scan QR Button. Opens Camera For Scanning QR Code.",
- key: const Key("frConfigScanQrButtonKey"),
- onTap: scanQr,
- child: const QrCodeIcon(),
- ),
- ],
+ child: UnconstrainedBox(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ !_configEmpty
+ ? TextFieldIconButton(
+ semanticsLabel:
+ "Clear Button. Clears The Config Field.",
+ key: const Key("frConfigClearButtonKey"),
+ onTap: () {
+ configFieldController.text = "";
+
+ setState(() {
+ _configEmpty = true;
+ });
+ },
+ child: const XIcon(),
+ )
+ : TextFieldIconButton(
+ semanticsLabel:
+ "Paste Button. Pastes From Clipboard To Config Field Input.",
+ key: const Key("frConfigPasteButtonKey"),
+ onTap: () async {
+ final ClipboardData? data =
+ await Clipboard.getData(
+ Clipboard.kTextPlain,
+ );
+ if (data?.text != null &&
+ data!.text!.isNotEmpty) {
+ configFieldController.text = data
+ .text!
+ .trim();
+ }
+
+ setState(() {
+ _configEmpty = configFieldController
+ .text
+ .isEmpty;
+ });
+ },
+ child: _configEmpty
+ ? const ClipboardIcon()
+ : const XIcon(),
+ ),
+ if (_configEmpty)
+ TextFieldIconButton(
+ semanticsLabel:
+ "Scan QR Button. Opens Camera For Scanning QR Code.",
+ key: const Key("frConfigScanQrButtonKey"),
+ onTap: scanQr,
+ child: const QrCodeIcon(),
+ ),
+ ],
+ ),
+ ),
),
),
- ),
- ),
),
),
const SizedBox(height: 16),
@@ -432,70 +434,69 @@ class _RestoreFrostMsWalletViewState
autocorrect: false,
enableSuggestions: false,
style: STextStyles.field(context),
- decoration: standardInputDecoration(
- "Keys",
- keysFocusNode,
- context,
- ).copyWith(
- contentPadding: const EdgeInsets.only(
- left: 16,
- top: 6,
- bottom: 8,
- right: 5,
- ),
- suffixIcon: Padding(
- padding:
- _keysEmpty
+ decoration:
+ standardInputDecoration(
+ "Keys",
+ keysFocusNode,
+ context,
+ ).copyWith(
+ contentPadding: const EdgeInsets.only(
+ left: 16,
+ top: 6,
+ bottom: 8,
+ right: 5,
+ ),
+ suffixIcon: Padding(
+ padding: _keysEmpty
? const EdgeInsets.only(right: 8)
: const EdgeInsets.only(right: 0),
- child: UnconstrainedBox(
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- !_keysEmpty
- ? TextFieldIconButton(
- semanticsLabel:
- "Clear Button. Clears The Keys Field.",
- key: const Key("frMyNameClearButtonKey"),
- onTap: () {
- keysFieldController.text = "";
-
- setState(() {
- _keysEmpty = true;
- });
- },
- child: const XIcon(),
- )
- : TextFieldIconButton(
- semanticsLabel:
- "Paste Button. Pastes From Clipboard To Keys Field.",
- key: const Key("frKeysPasteButtonKey"),
- onTap: () async {
- final ClipboardData? data =
- await Clipboard.getData(
- Clipboard.kTextPlain,
- );
- if (data?.text != null &&
- data!.text!.isNotEmpty) {
- keysFieldController.text =
- data.text!.trim();
- }
-
- setState(() {
- _keysEmpty =
- keysFieldController.text.isEmpty;
- });
- },
- child:
- _keysEmpty
- ? const ClipboardIcon()
- : const XIcon(),
- ),
- ],
+ child: UnconstrainedBox(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ !_keysEmpty
+ ? TextFieldIconButton(
+ semanticsLabel:
+ "Clear Button. Clears The Keys Field.",
+ key: const Key("frMyNameClearButtonKey"),
+ onTap: () {
+ keysFieldController.text = "";
+
+ setState(() {
+ _keysEmpty = true;
+ });
+ },
+ child: const XIcon(),
+ )
+ : TextFieldIconButton(
+ semanticsLabel:
+ "Paste Button. Pastes From Clipboard To Keys Field.",
+ key: const Key("frKeysPasteButtonKey"),
+ onTap: () async {
+ final ClipboardData? data =
+ await Clipboard.getData(
+ Clipboard.kTextPlain,
+ );
+ if (data?.text != null &&
+ data!.text!.isNotEmpty) {
+ keysFieldController.text = data.text!
+ .trim();
+ }
+
+ setState(() {
+ _keysEmpty =
+ keysFieldController.text.isEmpty;
+ });
+ },
+ child: _keysEmpty
+ ? const ClipboardIcon()
+ : const XIcon(),
+ ),
+ ],
+ ),
+ ),
),
),
- ),
- ),
),
),
const SizedBox(height: 16),
diff --git a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart
index f7e6d0b..2ce5376 100644
--- a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart
+++ b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_1b.dart
@@ -8,7 +8,6 @@ import '../../../../models/isar/models/isar_models.dart';
import '../../../../providers/db/main_db_provider.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
import '../../../../providers/global/wallets_provider.dart';
-import '../../../../services/frost.dart';
import '../../../../utilities/format.dart';
import '../../../../utilities/logger.dart';
import '../../../../utilities/util.dart';
@@ -19,6 +18,7 @@ import '../../../../widgets/desktop/primary_button.dart';
import '../../../../widgets/frost_step_user_steps.dart';
import '../../../../widgets/stack_dialog.dart';
import '../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
class FrostSendStep1b extends ConsumerStatefulWidget {
const FrostSendStep1b({super.key});
@@ -65,43 +65,40 @@ class _FrostSendStep1bState extends ConsumerState<FrostSendStep1b> {
ref.read(pWallets).getWallet(ref.read(pFrostScaffoldArgs)!.walletId!)
as BitcoinFrostWallet;
- final data = Frost.extractDataFromSignConfig(
+ final data = frostInterface.extractDataFromSignConfig(
signConfig: config,
coin: wallet.cryptoCurrency,
serializedKeys: (await wallet.getSerializedKeys())!,
);
- final utxos =
- await ref
- .read(mainDBProvider)
- .getUTXOs(wallet.walletId)
- .filter()
- .anyOf(
- data.inputs,
- (q, e) => q
- .txidEqualTo(Format.uint8listToString(e.hash))
- .and()
- .valueEqualTo(e.value)
- .and()
- .voutEqualTo(e.vout),
- )
- .findAll();
+ final utxos = await ref
+ .read(mainDBProvider)
+ .getUTXOs(wallet.walletId)
+ .filter()
+ .anyOf(
+ data.inputs,
+ (q, e) => q
+ .txidEqualTo(Format.uint8listToString(e.hash))
+ .and()
+ .valueEqualTo(e.value)
+ .and()
+ .voutEqualTo(e.vout),
+ )
+ .findAll();
// TODO add more data from 'data' and display to user ?
ref.read(pFrostTxData.notifier).state = TxData(
frostMSConfig: config,
- recipients:
- data.recipients
- .map(
- (e) => TxRecipient(
- address: e.address,
- amount: e.amount,
- isChange: false,
- addressType:
- wallet.cryptoCurrency.getAddressType(e.address)!,
- ),
- )
- .toList(),
+ recipients: data.recipients
+ .map(
+ (e) => TxRecipient(
+ address: e.address,
+ amount: e.amount,
+ isChange: false,
+ addressType: wallet.cryptoCurrency.getAddressType(e.address)!,
+ ),
+ )
+ .toList(),
utxos: utxos.map((e) => StandardInput(e)).toSet(),
);
@@ -123,12 +120,11 @@ class _FrostSendStep1bState extends ConsumerState<FrostSendStep1b> {
if (mounted) {
await showDialog<void>(
context: context,
- builder:
- (_) => StackOkDialog(
- title: "Import and attempt sign config failed",
- message: e.toString(),
- desktopPopRootNavigator: Util.isDesktop,
- ),
+ builder: (_) => StackOkDialog(
+ title: "Import and attempt sign config failed",
+ message: e.toString(),
+ desktopPopRootNavigator: Util.isDesktop,
+ ),
);
}
} finally {
diff --git a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_2.dart b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_2.dart
index febae8b..b0a5c66 100644
--- a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_2.dart
+++ b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_2.dart
@@ -4,7 +4,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../frost_route_generator.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
import '../../../../providers/global/wallets_provider.dart';
-import '../../../../services/frost.dart';
import '../../../../themes/stack_colors.dart';
import '../../../../utilities/logger.dart';
import '../../../../utilities/text_styles.dart';
@@ -17,6 +16,7 @@ import '../../../../widgets/detail_item.dart';
import '../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../widgets/rounded_white_container.dart';
import '../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../wallet_view/transaction_views/transaction_details_view.dart';
class FrostSendStep2 extends ConsumerStatefulWidget {
@@ -56,15 +56,16 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
@override
void initState() {
- final wallet = ref.read(pWallets).getWallet(
- ref.read(pFrostScaffoldArgs)!.walletId!,
- ) as BitcoinFrostWallet;
+ final wallet =
+ ref.read(pWallets).getWallet(ref.read(pFrostScaffoldArgs)!.walletId!)
+ as BitcoinFrostWallet;
final frostInfo = wallet.frostInfo;
myName = frostInfo.myName;
threshold = frostInfo.threshold;
- participantsWithoutMe =
- List.from(frostInfo.participants); // Copy so it isn't fixed-length.
+ participantsWithoutMe = List.from(
+ frostInfo.participants,
+ ); // Copy so it isn't fixed-length.
myIndex = participantsWithoutMe.indexOf(frostInfo.myName);
myPreprocess = ref.read(pFrostAttemptSignData.state).state!.preprocess;
@@ -103,13 +104,8 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text(
- "1.",
- style: STextStyles.w500_12(context),
- ),
- const SizedBox(
- width: 4,
- ),
+ Text("1.", style: STextStyles.w500_12(context)),
+ const SizedBox(width: 4),
Expanded(
child: Text(
"Share your preprocess with other signing group members.",
@@ -118,19 +114,12 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
),
],
),
- const SizedBox(
- height: 4,
- ),
+ const SizedBox(height: 4),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Text(
- "2.",
- style: STextStyles.w500_12(context),
- ),
- const SizedBox(
- width: 4,
- ),
+ Text("2.", style: STextStyles.w500_12(context)),
+ const SizedBox(width: 4),
Expanded(
child: RichText(
text: TextSpan(
@@ -141,7 +130,8 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
style: STextStyles.w500_12(context),
),
TextSpan(
- text: "You must have the threshold number of "
+ text:
+ "You must have the threshold number of "
"preprocesses (including yours) to send this transaction.",
style: STextStyles.w600_12(context).copyWith(
color: Theme.of(context)
@@ -158,58 +148,38 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
],
),
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
DetailItem(
title: "Threshold",
detail: "$threshold signatures",
horizontal: true,
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
DetailItem(
title: "My name",
detail: myName,
button: Util.isDesktop
- ? IconCopyButton(
- data: myName,
- )
- : SimpleCopyButton(
- data: myName,
- ),
- ),
- const SizedBox(
- height: 12,
+ ? IconCopyButton(data: myName)
+ : SimpleCopyButton(data: myName),
),
+ const SizedBox(height: 12),
DetailItem(
title: "My preprocess",
detail: myPreprocess,
button: Util.isDesktop
- ? IconCopyButton(
- data: myPreprocess,
- )
- : SimpleCopyButton(
- data: myPreprocess,
- ),
+ ? IconCopyButton(data: myPreprocess)
+ : SimpleCopyButton(data: myPreprocess),
),
const SizedBox(height: 12),
- FrostQrDialogPopupButton(
- data: myPreprocess,
- ),
- const SizedBox(
- height: 12,
- ),
+ FrostQrDialogPopupButton(data: myPreprocess),
+ const SizedBox(height: 12),
RoundedWhiteContainer(
child: Text(
"You need to obtain ${threshold - 1} preprocess from signing members to send this transaction.",
style: STextStyles.label(context),
),
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
Builder(
builder: (context) {
final count = countPreprocesses();
@@ -224,9 +194,7 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
);
},
),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@@ -247,9 +215,7 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
],
),
if (!Util.isDesktop) const Spacer(),
- const SizedBox(
- height: 12,
- ),
+ const SizedBox(height: 12),
PrimaryButton(
label: "Generate shares",
enabled: countPreprocesses() >= threshold,
@@ -271,12 +237,14 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
preprocesses.insert(myIndex, "");
try {
- ref.read(pFrostContinueSignData.notifier).state =
- Frost.continueSigning(
- machinePtr:
- ref.read(pFrostAttemptSignData.state).state!.machinePtr,
- preprocesses: preprocesses,
- );
+ ref.read(pFrostContinueSignData.notifier).state = frostInterface
+ .continueSigning(
+ machinePtr: ref
+ .read(pFrostAttemptSignData.state)
+ .state!
+ .machinePtr,
+ preprocesses: preprocesses,
+ );
ref.read(pFrostCreateCurrentStep.state).state = 3;
await Navigator.of(context).pushNamed(
@@ -291,7 +259,7 @@ class _FrostSendStep2State extends ConsumerState<FrostSendStep2> {
// arguments: widget.walletId,
// );
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (context.mounted) {
return await showDialog<void>(
diff --git a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_3.dart b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_3.dart
index f3ddc90..d3e9f91 100644
--- a/lib/pages/send_view/frost_ms/send_steps/frost_send_step_3.dart
+++ b/lib/pages/send_view/frost_ms/send_steps/frost_send_step_3.dart
@@ -5,7 +5,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../../frost_route_generator.dart';
import '../../../../providers/frost_wallet/frost_wallet_providers.dart';
import '../../../../providers/global/wallets_provider.dart';
-import '../../../../services/frost.dart';
import '../../../../utilities/amount/amount.dart';
import '../../../../utilities/logger.dart';
import '../../../../utilities/util.dart';
@@ -18,6 +17,7 @@ import '../../../../widgets/detail_item.dart';
import '../../../../widgets/dialogs/frost/frost_error_dialog.dart';
import '../../../../widgets/frost_step_user_steps.dart';
import '../../../../widgets/textfields/frost_step_field.dart';
+import '../../../../wl_gen/interfaces/frost_interface.dart';
import '../../../wallet_view/transaction_views/transaction_details_view.dart';
class FrostSendStep3 extends ConsumerStatefulWidget {
@@ -62,13 +62,12 @@ class _FrostSendStep3State extends ConsumerState<FrostSendStep3> {
myIndex = frostInfo.participants.indexOf(frostInfo.myName);
myShare = ref.read(pFrostContinueSignData.state).state!.share;
- participantsWithoutMe =
- frostInfo.participants
- .toSet()
- .intersection(
- ref.read(pFrostSelectParticipantsUnordered.state).state!.toSet(),
- )
- .toList();
+ participantsWithoutMe = frostInfo.participants
+ .toSet()
+ .intersection(
+ ref.read(pFrostSelectParticipantsUnordered.state).state!.toSet(),
+ )
+ .toList();
participantsWithoutMe.remove(myName);
@@ -104,19 +103,17 @@ class _FrostSendStep3State extends ConsumerState<FrostSendStep3> {
DetailItem(
title: "My name",
detail: myName,
- button:
- Util.isDesktop
- ? IconCopyButton(data: myName)
- : SimpleCopyButton(data: myName),
+ button: Util.isDesktop
+ ? IconCopyButton(data: myName)
+ : SimpleCopyButton(data: myName),
),
const SizedBox(height: 12),
DetailItem(
title: "My share",
detail: myShare,
- button:
- Util.isDesktop
- ? IconCopyButton(data: myShare)
- : SimpleCopyButton(data: myShare),
+ button: Util.isDesktop
+ ? IconCopyButton(data: myShare)
+ : SimpleCopyButton(data: myShare),
),
const SizedBox(height: 12),
FrostQrDialogPopupButton(data: myShare),
@@ -172,9 +169,11 @@ class _FrostSendStep3State extends ConsumerState<FrostSendStep3> {
}
try {
- final rawTx = Frost.completeSigning(
- machinePtr:
- ref.read(pFrostContinueSignData.state).state!.machinePtr,
+ final rawTx = frostInterface.completeSigning(
+ machinePtr: ref
+ .read(pFrostContinueSignData.state)
+ .state!
+ .machinePtr,
shares: shares,
);
@@ -216,10 +215,9 @@ class _FrostSendStep3State extends ConsumerState<FrostSendStep3> {
if (context.mounted) {
return await showDialog<void>(
context: context,
- builder:
- (_) => const FrostErrorDialog(
- title: "Failed to complete signing process",
- ),
+ builder: (_) => const FrostErrorDialog(
+ title: "Failed to complete signing process",
+ ),
);
}
}
diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
index 4069f06..355fc66 100644
--- a/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
+++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart
@@ -13,7 +13,6 @@ import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
-import 'package:frostdart/frostdart.dart' as frost;
import 'package:isar_community/isar.dart';
import 'package:stack_wallet_backup/stack_wallet_backup.dart';
import 'package:tuple/tuple.dart';
@@ -33,7 +32,6 @@ import '../../../../../models/stack_restoring_ui_state.dart';
import '../../../../../models/trade_wallet_lookup.dart';
import '../../../../../models/wallet_restore_state.dart';
import '../../../../../services/address_book_service.dart';
-import '../../../../../services/frost.dart';
import '../../../../../services/node_service.dart';
import '../../../../../services/trade_notes_service.dart';
import '../../../../../services/trade_sent_from_stack_service.dart';
@@ -62,6 +60,7 @@ import '../../../../../wallets/wallet/wallet.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/private_key_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart';
+import '../../../../../wl_gen/interfaces/frost_interface.dart';
class PreRestoreState {
final Set<String> walletIds;
@@ -243,12 +242,11 @@ abstract class SWB {
Logging.instance.i("...createStackWalletJSON DB.instance.mutex acquired");
Logging.instance.i("SWB backing up nodes");
try {
- final nodesFuture =
- nodeService.nodes.map((e) async {
- final map = e.toMap();
- map["password"] = await e.getPassword(_secureStore);
- return map;
- }).toList();
+ final nodesFuture = nodeService.nodes.map((e) async {
+ final map = e.toMap();
+ map["password"] = await e.getPassword(_secureStore);
+ return map;
+ }).toList();
final nodes = await Future.wait(nodesFuture);
backupJson['nodes'] = nodes;
} catch (e, s) {
@@ -280,8 +278,9 @@ abstract class SWB {
final AddressBookService addressBookService = AddressBookService();
final addresses = addressBookService.contacts;
- backupJson['addressBookEntries'] =
- addresses.map((e) => e.toMap()).toList();
+ backupJson['addressBookEntries'] = addresses
+ .map((e) => e.toMap())
+ .toList();
Logging.instance.d("SWB backing up wallets");
@@ -298,8 +297,8 @@ abstract class SWB {
(await wallet.getViewOnlyWalletData()).toJsonEncodedString();
} else if (wallet is MnemonicInterface) {
backupWallet['mnemonic'] = await wallet.getMnemonic();
- backupWallet['mnemonicPassphrase'] =
- await wallet.getMnemonicPassphrase();
+ backupWallet['mnemonicPassphrase'] = await wallet
+ .getMnemonicPassphrase();
} else if (wallet is PrivateKeyInterface) {
backupWallet['privateKey'] = await wallet.getPrivateKey();
} else if (wallet is BitcoinFrostWallet) {
@@ -332,11 +331,10 @@ abstract class SWB {
backupWallet['restoreHeight'] = wallet.info.restoreHeight;
- final isarNotes =
- await MainDB.instance.isar.transactionNotes
- .where()
- .walletIdEqualTo(wallet.walletId)
- .findAll();
+ final isarNotes = await MainDB.instance.isar.transactionNotes
+ .where()
+ .walletIdEqualTo(wallet.walletId)
+ .findAll();
final notes = isarNotes.asMap().map(
(key, value) => MapEntry(value.txid, value.value),
@@ -359,8 +357,9 @@ abstract class SWB {
// back up trade history lookup data for trades send from stack wallet
final tradeTxidLookupDataService = TradeSentFromStackService();
- final lookupData =
- tradeTxidLookupDataService.all.map((e) => e.toMap()).toList();
+ final lookupData = tradeTxidLookupDataService.all
+ .map((e) => e.toMap())
+ .toList();
backupJson["tradeTxidLookupData"] = lookupData;
Logging.instance.d("SWB backing up trade notes");
@@ -439,10 +438,10 @@ abstract class SWB {
serializedKeys = frostData["keys"] as String;
multisigConfig = frostData["config"] as String;
- final myNameIndex = frost.getParticipantIndexFromKeys(
+ final myNameIndex = frostInterface.participantIndexFromKeys(
serializedKeys: serializedKeys,
);
- final participants = Frost.getParticipants(
+ final participants = frostInterface.getParticipants(
multisigConfig: multisigConfig,
);
final myName = participants[myNameIndex];
@@ -452,7 +451,9 @@ abstract class SWB {
knownSalts: [],
participants: participants,
myName: myName,
- threshold: frost.multisigThreshold(multisigConfig: multisigConfig),
+ threshold: frostInterface.getMultisigThreshold(
+ multisigConfig: multisigConfig,
+ ),
);
await MainDB.instance.isar.writeTxn(() async {
@@ -693,11 +694,10 @@ abstract class SWB {
);
Logging.instance.d("SWB temp backup created");
- final List<String> _currentWalletIds =
- await MainDB.instance.isar.walletInfo
- .where()
- .walletIdProperty()
- .findAll();
+ final List<String> _currentWalletIds = await MainDB.instance.isar.walletInfo
+ .where()
+ .walletIdProperty()
+ .findAll();
final preRestoreState = PreRestoreState(
_currentWalletIds.toSet(),
@@ -926,12 +926,11 @@ abstract class SWB {
// ensure this contact's data matches the pre restore state
final List<ContactAddressEntry> addresses = [];
for (final address in (contact['addresses'] as List<dynamic>)) {
- final entry =
- ContactAddressEntry()
- ..coinName = address['coin'] as String
- ..address = address['address'] as String
- ..label = address['label'] as String
- ..other = address['other'] as String?;
+ final entry = ContactAddressEntry()
+ ..coinName = address['coin'] as String
+ ..address = address['address'] as String
+ ..label = address['label'] as String
+ ..other = address['other'] as String?;
try {
entry.coin;
@@ -1107,12 +1106,11 @@ abstract class SWB {
_prefs.language = prefs['language'] as String;
_prefs.showFavoriteWallets = prefs['showFavoriteWallets'] as bool;
_prefs.wifiOnly = prefs['wifiOnly'] as bool;
- _prefs.syncType =
- prefs['syncType'] == "currentWalletOnly"
- ? SyncingType.currentWalletOnly
- : prefs['syncType'] == "selectedWalletsAtStartup"
- ? SyncingType.currentWalletOnly
- : SyncingType.allWalletsOnStartup; //
+ _prefs.syncType = prefs['syncType'] == "currentWalletOnly"
+ ? SyncingType.currentWalletOnly
+ : prefs['syncType'] == "selectedWalletsAtStartup"
+ ? SyncingType.currentWalletOnly
+ : SyncingType.allWalletsOnStartup; //
_prefs.walletIdsSyncOnStartup =
(prefs['walletIdsSyncOnStartup'] as List<dynamic>)
.map<String>((e) => e as String)
@@ -1136,12 +1134,11 @@ abstract class SWB {
for (final contact in addressBookEntries) {
final List<ContactAddressEntry> addresses = [];
for (final address in (contact['addresses'] as List<dynamic>)) {
- final entry =
- ContactAddressEntry()
- ..coinName = address['coin'] as String
- ..address = address['address'] as String
- ..label = address['label'] as String
- ..other = address['other'] as String?;
+ final entry = ContactAddressEntry()
+ ..coinName = address['coin'] as String
+ ..address = address['address'] as String
+ ..label = address['label'] as String
+ ..other = address['other'] as String?;
try {
entry.coin;
@@ -1175,11 +1172,10 @@ abstract class SWB {
secureStorageInterface: secureStorageInterface,
);
if (nodes != null) {
- final primaryIds =
- primaryNodes
- ?.map((e) => e["id"] as String?)
- .whereType<String>()
- .toSet();
+ final primaryIds = primaryNodes
+ ?.map((e) => e["id"] as String?)
+ .whereType<String>()
+ .toSet();
for (final node in nodes) {
final id = node['id'] as String;
@@ -1250,8 +1246,9 @@ abstract class SWB {
final json = Map<String, dynamic>.from(tradeTxidLookupData[i] as Map);
TradeWalletLookup lookup = TradeWalletLookup.fromJson(json);
// update walletIds
- final List<String> walletIds =
- lookup.walletIds.map((e) => oldToNewWalletIdMap[e]!).toList();
+ final List<String> walletIds = lookup.walletIds
+ .map((e) => oldToNewWalletIdMap[e]!)
+ .toList();
lookup = lookup.copyWith(walletIds: walletIds);
final oldLookup = DB.instance.get<TradeWalletLookup>(
diff --git a/lib/pages/settings_views/wallet_settings_view/frost_ms/initiate_resharing/complete_reshare_config_view.dart b/lib/pages/settings_views/wallet_settings_view/frost_ms/initiate_resharing/complete_reshare_config_view.dart
index afc4864..1198e59 100644
--- a/lib/pages/settings_views/wallet_settings_view/frost_ms/initiate_resharing/complete_reshare_config_view.dart
+++ b/lib/pages/settings_views/wallet_settings_view/frost_ms/initiate_resharing/complete_reshare_config_view.dart
@@ -3,14 +3,14 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:frostdart/frostdart.dart';
+
+// import 'package:frostdart/frostdart.dart';
import '../../../../../frost_route_generator.dart';
import '../../../../../pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
import '../../../../../providers/db/main_db_provider.dart';
import '../../../../../providers/frost_wallet/frost_wallet_providers.dart';
import '../../../../../providers/global/wallets_provider.dart';
-import '../../../../../services/frost.dart';
import '../../../../../themes/stack_colors.dart';
import '../../../../../utilities/format.dart';
import '../../../../../utilities/logger.dart';
@@ -27,6 +27,7 @@ import '../../../../../widgets/desktop/primary_button.dart';
import '../../../../../widgets/frost_scaffold.dart';
import '../../../../../widgets/rounded_white_container.dart';
import '../../../../../widgets/stack_dialog.dart';
+import '../../../../../wl_gen/interfaces/frost_interface.dart';
final class CompleteReshareConfigView extends ConsumerStatefulWidget {
const CompleteReshareConfigView({
@@ -84,20 +85,21 @@ class _CompleteReshareConfigViewState
);
}
- final List<String> newParticipants =
- controllers.map((e) => e.text.trim()).toList();
+ final List<String> newParticipants = controllers
+ .map((e) => e.text.trim())
+ .toList();
if (_includeMeInReshare) {
newParticipants.insert(0, myName);
}
- final config = Frost.createResharerConfig(
+ final config = frostInterface.createResharerConfig(
newThreshold: int.parse(_newThresholdController.text),
resharers: widget.resharers.values.toList(),
newParticipants: newParticipants,
);
final salt = Format.uint8listToString(
- resharerSalt(resharerConfig: config),
+ frostInterface.getResharerSalt(resharerConfig: config),
);
if (frostInfo.knownSalts.contains(salt)) {
@@ -122,10 +124,8 @@ class _CompleteReshareConfigViewState
}
ref.read(pFrostResharingData).myName = myName;
- ref.read(pFrostResharingData).resharerRConfig = Frost.encodeRConfig(
- config,
- widget.resharers,
- );
+ ref.read(pFrostResharingData).resharerRConfig = frostInterface
+ .encodeRConfig(config, widget.resharers);
final wallet =
ref.read(pWallets).getWallet(widget.walletId) as BitcoinFrostWallet;
@@ -143,12 +143,10 @@ class _CompleteReshareConfigViewState
callerRouteName: CompleteReshareConfigView.routeName,
);
- await Navigator.of(context).pushNamed(
- FrostStepScaffold.routeName,
- );
+ await Navigator.of(context).pushNamed(FrostStepScaffold.routeName);
}
} catch (e, s) {
- Logging.instance.f("$e\n$s", error: e, stackTrace: s,);
+ Logging.instance.f("$e\n$s", error: e, stackTrace: s);
if (mounted) {
await showDialog<void>(
context: context,
@@ -269,17 +267,15 @@ class _CompleteReshareConfigViewState
leading: AppBarBackButton(),
trailing: ExitToMyStackButton(),
),
- body: SizedBox(
- width: 480,
- child: child,
- ),
+ body: SizedBox(width: 480, child: child),
),
child: ConditionalParent(
condition: !Util.isDesktop,
builder: (child) => Background(
child: Scaffold(
- backgroundColor:
- Theme.of(context).extension<StackColors>()!.background,
+ backgroundColor: Theme.of(
+ context,
+ ).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () {
@@ -318,9 +314,7 @@ class _CompleteReshareConfigViewState
? CrossAxisAlignment.start
: CrossAxisAlignment.stretch,
children: [
- const SizedBox(
- height: 8,
- ),
+ const SizedBox(height: 8),
GestureDetector(
onTap: () {
setState(() {
@@ -340,18 +334,14 @@ class _CompleteReshareConfigViewState
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
value: _includeMeInReshare,
onChanged: (value) {
- setState(
- () => _includeMeInReshare = value == true,
- );
+ setState(() => _includeMeInReshare = value == true);
_participantsCountChanged(
_newParticipantsCountController.text,
);
},
),
),
- const SizedBox(
- width: 12,
- ),
+ const SizedBox(width: 12),
Expanded(
child: Text(
"I will be a signer in the new config",
@@ -362,19 +352,16 @@ class _CompleteReshareConfigViewState
),
),
),
- const SizedBox(
- height: 20,
- ),
+ const SizedBox(height: 20),
Text(
"New threshold",
style: STextStyles.w500_14(context).copyWith(
- color:
- Theme.of(context).extension<StackColors>()!.textSubtitle1,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textSubtitle1,
),
),
- const SizedBox(
- height: 10,
- ),
+ const SizedBox(height: 10),
TextField(
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
@@ -384,31 +371,27 @@ class _CompleteReshareConfigViewState
hintStyle: STextStyles.fieldLabel(context),
),
),
- const SizedBox(
- height: 6,
- ),
+ const SizedBox(height: 6),
RoundedWhiteContainer(
child: Text(
"Enter number of signatures required for fund management.",
style: STextStyles.w500_12(context).copyWith(
- color:
- Theme.of(context).extension<StackColors>()!.textSubtitle2,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textSubtitle2,
),
),
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
Text(
"New number of participants",
style: STextStyles.w500_14(context).copyWith(
- color:
- Theme.of(context).extension<StackColors>()!.textSubtitle1,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textSubtitle1,
),
),
- const SizedBox(
- height: 10,
- ),
+ const SizedBox(height: 10),
TextField(
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
@@ -419,42 +402,37 @@ class _CompleteReshareConfigViewState
hintStyle: STextStyles.fieldLabel(context),
),
),
- const SizedBox(
- height: 6,
- ),
+ const SizedBox(height: 6),
RoundedWhiteContainer(
child: Text(
"The number of participants must be equal to or greater than the"
" number of required signatures.",
style: STextStyles.w500_12(context).copyWith(
- color:
- Theme.of(context).extension<StackColors>()!.textSubtitle2,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textSubtitle2,
),
),
),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
if (controllers.isNotEmpty)
Text(
"Participants",
style: STextStyles.w500_14(context).copyWith(
- color:
- Theme.of(context).extension<StackColors>()!.textSubtitle1,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textSubtitle1,
),
),
- if (controllers.isNotEmpty)
- const SizedBox(
- height: 10,
- ),
+ if (controllers.isNotEmpty) const SizedBox(height: 10),
if (controllers.isNotEmpty)
RoundedWhiteContainer(
child: Text(
"Type each name in one word without spaces.",
style: STextStyles.w500_12(context).copyWith(
- color: Theme.of(context)
- .extension<StackColors>()!
- .textSubtitle2,
+ color: Theme.of(
+ context,
+ ).extension<StackColors>()!.textSubtitle2,
),
),
),
@@ -463,9 +441,7 @@ class _CompleteReshareConfigViewState
children: [
for (int i = 0; i < controllers.length; i++)
Padding(
- padding: const EdgeInsets.only(
- top: 10,
- ),
+ padding: const EdgeInsets.only(top: 10),
child: TextField(
controller: controllers[i],
decoration: InputDecoration(
@@ -477,9 +453,7 @@ class _CompleteReshareConfigViewState
],
),
if (!Util.isDesktop) const Spacer(),
- const SizedBox(
- height: 16,
- ),
+ const SizedBox(height: 16),
PrimaryButton(
label: "Generate config",
onPressed: () async {
diff --git a/lib/providers/frost_wallet/frost_wallet_providers.dart b/lib/providers/frost_wallet/frost_wallet_providers.dart
index c5b934e..bee42aa 100644
--- a/lib/providers/frost_wallet/frost_wallet_providers.dart
+++ b/lib/providers/frost_wallet/frost_wallet_providers.dart
@@ -1,55 +1,50 @@
-import 'dart:ffi';
import 'dart:typed_data';
import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:frostdart/frostdart_bindings_generated.dart';
-import '../../services/frost.dart';
+
import '../../wallets/models/incomplete_frost_wallet.dart';
import '../../wallets/models/tx_data.dart';
+import '../../wl_gen/interfaces/frost_interface.dart';
// =================== wallet creation =========================================
final pFrostMultisigConfig = StateProvider<String?>((ref) => null);
final pFrostMyName = StateProvider<String?>((ref) => null);
-final pFrostStartKeyGenData = StateProvider<
- ({
- String seed,
- String commitments,
- Pointer<MultisigConfigWithName> multisigConfigWithNamePtr,
- Pointer<SecretShareMachineWrapper> secretShareMachineWrapperPtr,
- })?>((_) => null);
-
-final pFrostSecretSharesData = StateProvider<
- ({
- String share,
- Pointer<SecretSharesRes> secretSharesResPtr,
- })?>((ref) => null);
-
-final pFrostCompletedKeyGenData = StateProvider<
- ({
- Uint8List multisigId,
- String recoveryString,
- String serializedKeys,
- })?>((ref) => null);
+final pFrostStartKeyGenData =
+ StateProvider<
+ ({
+ String seed,
+ String commitments,
+ OpaqueWrapper multisigConfigWithNamePtr,
+ OpaqueWrapper secretShareMachineWrapperPtr,
+ })?
+ >((_) => null);
+
+final pFrostSecretSharesData =
+ StateProvider<({String share, OpaqueWrapper secretSharesResPtr})?>(
+ (ref) => null,
+ );
+
+final pFrostCompletedKeyGenData =
+ StateProvider<
+ ({Uint8List multisigId, String recoveryString, String serializedKeys})?
+ >((ref) => null);
// ================= transaction creation ======================================
final pFrostTxData = StateProvider<TxData?>((ref) => null);
-final pFrostAttemptSignData = StateProvider<
- ({
- Pointer<TransactionSignMachineWrapper> machinePtr,
- String preprocess,
- })?>((ref) => null);
+final pFrostAttemptSignData =
+ StateProvider<({OpaqueWrapper machinePtr, String preprocess})?>(
+ (ref) => null,
+ );
-final pFrostContinueSignData = StateProvider<
- ({
- Pointer<TransactionSignatureMachineWrapper> machinePtr,
- String share,
- })?>((ref) => null);
+final pFrostContinueSignData =
+ StateProvider<({OpaqueWrapper machinePtr, String share})?>((ref) => null);
// ===================== shared/util ===========================================
-final pFrostSelectParticipantsUnordered =
- StateProvider<List<String>?>((ref) => null);
+final pFrostSelectParticipantsUnordered = StateProvider<List<String>?>(
+ (ref) => null,
+);
// ========================= resharing =========================================
final pFrostResharingData = Provider((ref) => _ResharingData());
@@ -66,31 +61,23 @@ class _ResharingData {
int newThreshold,
Map<String, int> resharers,
List<String> newParticipants,
- })? get configData => resharerRConfig != null
- ? Frost.extractResharerConfigData(rConfig: resharerRConfig!)
+ })?
+ get configData => resharerRConfig != null
+ ? frostInterface.extractResharerConfigData(rConfig: resharerRConfig!)
: null;
// resharer start string (for sharing) and machine
- ({
- String resharerStart,
- Pointer<StartResharerRes> machine,
- })? startResharerData;
+ ({String resharerStart, OpaqueWrapper machine})? startResharerData;
// reshared start string (for sharing) and machine
- ({
- String resharedStart,
- Pointer<StartResharedRes> prior,
- })? startResharedData;
+ ({String resharedStart, OpaqueWrapper prior})? startResharedData;
// resharer complete string (for sharing)
String? resharerComplete;
// new keys and config with an ID
- ({
- String multisigConfig,
- String serializedKeys,
- String resharedId,
- })? newWalletData;
+ ({String multisigConfig, String serializedKeys, String resharedId})?
+ newWalletData;
// reset/clear all data
void reset() {
diff --git a/lib/services/frost.dart b/lib/services/frost.dart
deleted file mode 100644
index 33066de..0000000
--- a/lib/services/frost.dart
+++ /dev/null
@@ -1,605 +0,0 @@
-import 'dart:convert';
-import 'dart:ffi';
-import 'dart:typed_data';
-
-import 'package:frostdart/frostdart.dart';
-import 'package:frostdart/frostdart_bindings_generated.dart';
-import 'package:frostdart/output.dart';
-import 'package:frostdart/util.dart';
-
-import '../models/isar/models/blockchain_data/utxo.dart';
-import '../utilities/amount/amount.dart';
-import '../utilities/extensions/extensions.dart';
-import '../utilities/logger.dart';
-import '../wallets/crypto_currency/crypto_currency.dart';
-import '../wallets/models/tx_recipient.dart';
-
-abstract class Frost {
- //==================== utility ===============================================
- static List<String> getParticipants({required String multisigConfig}) {
- try {
- final numberOfParticipants = multisigParticipants(
- multisigConfig: multisigConfig,
- );
-
- final List<String> participants = [];
- for (int i = 0; i < numberOfParticipants; i++) {
- participants.add(
- multisigParticipant(multisigConfig: multisigConfig, index: i),
- );
- }
-
- return participants;
- } catch (e, s) {
- Logging.instance.f("getParticipants failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- static bool validateEncodedMultisigConfig({required String encodedConfig}) {
- try {
- decodeMultisigConfig(multisigConfig: encodedConfig);
- return true;
- } catch (e, s) {
- Logging.instance.f(
- "validateEncodedMultisigConfig failed: ",
- error: e,
- stackTrace: s,
- );
- return false;
- }
- }
-
- static int getThreshold({required String multisigConfig}) {
- try {
- final threshold = multisigThreshold(multisigConfig: multisigConfig);
-
- return threshold;
- } catch (e, s) {
- Logging.instance.f("getThreshold failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- static ({
- List<({String address, Amount amount})> recipients,
- String changeAddress,
- int feePerWeight,
- List<Output> inputs,
- })
- extractDataFromSignConfig({
- required String serializedKeys,
- required String signConfig,
- required CryptoCurrency coin,
- }) {
- try {
- final network =
- coin.network.isTestNet ? Network.Testnet : Network.Mainnet;
- final signConfigPointer = decodedSignConfig(
- encodedConfig: signConfig,
- network: network,
- serializedKeys: serializedKeys,
- );
-
- // get various data from config
- final feePerWeight = signFeePerWeight(
- signConfigPointer: signConfigPointer,
- );
- final changeAddress = signChange(signConfigPointer: signConfigPointer);
- final recipientsCount = signPayments(
- signConfigPointer: signConfigPointer,
- );
-
- // get tx recipient info
- final List<({String address, Amount amount})> recipients = [];
- for (int i = 0; i < recipientsCount; i++) {
- final String address = signPaymentAddress(
- signConfigPointer: signConfigPointer,
- index: i,
- );
- final int amount = signPaymentAmount(
- signConfigPointer: signConfigPointer,
- index: i,
- );
- recipients.add((
- address: address,
- amount: Amount(
- rawValue: BigInt.from(amount),
- fractionDigits: coin.fractionDigits,
- ),
- ));
- }
-
- // get utxos
- final count = signInputs(signConfigPointer: signConfigPointer);
- final List<Output> outputs = [];
- for (int i = 0; i < count; i++) {
- final output = signInput(
- thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
- signConfig: signConfig,
- index: i,
- network: network,
- );
-
- outputs.add(output);
- }
-
- return (
- recipients: recipients,
- changeAddress: changeAddress,
- feePerWeight: feePerWeight,
- inputs: outputs,
- );
- } catch (e, s) {
- Logging.instance.f(
- "extractDataFromSignConfig failed: ",
- error: e,
- stackTrace: s,
- );
- rethrow;
- }
- }
-
- //==================== wallet creation =======================================
-
- static String createMultisigConfig({
- required String name,
- required int threshold,
- required List<String> participants,
- }) {
- try {
- final config = newMultisigConfig(
- name: name,
- threshold: threshold,
- participants: participants,
- );
-
- return config;
- } catch (e, s) {
- Logging.instance.f(
- "createMultisigConfig failed: ",
- error: e,
- stackTrace: s,
- );
- rethrow;
- }
- }
-
- static ({
- String seed,
- String commitments,
- Pointer<MultisigConfigWithName> multisigConfigWithNamePtr,
- Pointer<SecretShareMachineWrapper> secretShareMachineWrapperPtr,
- })
- startKeyGeneration({required String multisigConfig, required String myName}) {
- try {
- final startKeyGenResPtr = startKeyGen(
- multisigConfig: multisigConfig,
- myName: myName,
- language: Language.english,
- );
-
- final seed = startKeyGenResPtr.ref.seed.toDartString();
- final commitments = startKeyGenResPtr.ref.commitments.toDartString();
- final configWithNamePtr = startKeyGenResPtr.ref.config;
- final machinePtr = startKeyGenResPtr.ref.machine;
-
- return (
- seed: seed,
- commitments: commitments,
- multisigConfigWithNamePtr: configWithNamePtr,
- secretShareMachineWrapperPtr: machinePtr,
- );
- } catch (e, s) {
- Logging.instance.f(
- "startKeyGeneration failed: ",
- error: e,
- stackTrace: s,
- );
- rethrow;
- }
- }
-
- static ({String share, Pointer<SecretSharesRes> secretSharesResPtr})
- generateSecretShares({
- required Pointer<MultisigConfigWithName> multisigConfigWithNamePtr,
- required String mySeed,
- required Pointer<SecretShareMachineWrapper> secretShareMachineWrapperPtr,
- required List<String> commitments,
- }) {
- try {
- final secretSharesResPtr = getSecretShares(
- multisigConfigWithName: multisigConfigWithNamePtr,
- seed: mySeed,
- language: Language.english,
- machine: secretShareMachineWrapperPtr,
- commitments: commitments,
- );
-
- final share = secretSharesResPtr.ref.shares.toDartString();
-
- return (share: share, secretSharesResPtr: secretSharesResPtr);
- } catch (e, s) {
- Logging.instance.f(
- "generateSecretShares failed: ",
- error: e,
- stackTrace: s,
- );
- rethrow;
- }
- }
-
- static ({Uint8List multisigId, String recoveryString, String serializedKeys})
- completeKeyGeneration({
- required Pointer<MultisigConfigWithName> multisigConfigWithNamePtr,
- required Pointer<SecretSharesRes> secretSharesResPtr,
- required List<String> shares,
- }) {
- try {
- final keyGenResPtr = completeKeyGen(
- multisigConfigWithName: multisigConfigWithNamePtr,
- machineAndCommitments: secretSharesResPtr,
- shares: shares,
- );
-
- final id = Uint8List.fromList(
- List<int>.generate(
- MULTISIG_ID_LENGTH,
- (index) => keyGenResPtr.ref.multisig_id[index],
- ),
- );
-
- final recoveryString = keyGenResPtr.ref.recovery.toDartString();
-
- final serializedKeys = serializeKeys(keys: keyGenResPtr.ref.keys);
-
- return (
- multisigId: id,
- recoveryString: recoveryString,
- serializedKeys: serializedKeys,
- );
- } catch (e, s) {
- Logging.instance.f(
- "completeKeyGeneration failed: ",
- error: e,
- stackTrace: s,
- );
- rethrow;
- }
- }
-
- //=================== transaction creation ===================================
-
- static String createSignConfig({
- required String serializedKeys,
- required int network,
- required List<
- ({
- UTXO utxo,
- Uint8List scriptPubKey,
- AddressDerivationData addressDerivationData,
- })
- >
- inputs,
- required List<TxRecipient> outputs,
- required String changeAddress,
- required int feePerWeight,
- }) {
- try {
- final signConfig = newSignConfig(
- thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
- network: network,
- outputs:
- inputs
- .map(
- (e) => Output(
- hash: e.utxo.txid.toUint8ListFromHex,
- vout: e.utxo.vout,
- value: e.utxo.value,
- scriptPubKey: e.scriptPubKey,
- addressDerivationData: e.addressDerivationData,
- ),
- )
- .toList(),
- paymentAddresses: outputs.map((e) => e.address).toList(),
- paymentAmounts: outputs.map((e) => e.amount.raw.toInt()).toList(),
- change: changeAddress,
- feePerWeight: feePerWeight,
- );
-
- return signConfig;
- } catch (e, s) {
- Logging.instance.f("createSignConfig failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- static ({
- Pointer<TransactionSignMachineWrapper> machinePtr,
- String preprocess,
- })
- attemptSignConfig({
- required int network,
- required String config,
- required String serializedKeys,
- }) {
- try {
- final keys = deserializeKeys(keys: serializedKeys);
-
- final attemptSignRes = attemptSign(
- thresholdKeysWrapperPointer: keys,
- network: network,
- signConfig: config,
- );
-
- return (
- preprocess: attemptSignRes.ref.preprocess.toDartString(),
- machinePtr: attemptSignRes.ref.machine,
- );
- } catch (e, s) {
- Logging.instance.f("attemptSignConfig failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- static ({
- Pointer<TransactionSignatureMachineWrapper> machinePtr,
- String share,
- })
- continueSigning({
- required Pointer<TransactionSignMachineWrapper> machinePtr,
- required List<String> preprocesses,
- }) {
- try {
- final continueSignRes = continueSign(
- machine: machinePtr,
- preprocesses: preprocesses,
- );
-
- return (
- share: continueSignRes.ref.preprocess.toDartString(),
- machinePtr: continueSignRes.ref.machine,
- );
- } catch (e, s) {
- Logging.instance.f("continueSigning failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- static String completeSigning({
- required Pointer<TransactionSignatureMachineWrapper> machinePtr,
- required List<String> shares,
- }) {
- try {
- final rawTransaction = completeSign(machine: machinePtr, shares: shares);
-
- return rawTransaction;
- } catch (e, s) {
- Logging.instance.f("completeSigning failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- static Pointer<SignConfig> decodedSignConfig({
- required String serializedKeys,
- required String encodedConfig,
- required int network,
- }) {
- try {
- final configPtr = decodeSignConfig(
- thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
- encodedSignConfig: encodedConfig,
- network: network,
- );
- return configPtr;
- } catch (e, s) {
- Logging.instance.f("decodedSignConfig failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- //========================== resharing =======================================
-
- static String createResharerConfig({
- required int newThreshold,
- required List<int> resharers,
- required List<String> newParticipants,
- }) {
- try {
- final config = newResharerConfig(
- newThreshold: newThreshold,
- newParticipants: newParticipants,
- resharers: resharers,
- );
-
- return config;
- } catch (e, s) {
- Logging.instance.f(
- "createResharerConfig failed: ",
- error: e,
- stackTrace: s,
- );
- rethrow;
- }
- }
-
- static ({String resharerStart, Pointer<StartResharerRes> machine})
- beginResharer({required String serializedKeys, required String config}) {
- try {
- final result = startResharer(
- serializedKeys: serializedKeys,
- config: config,
- );
-
- return (resharerStart: result.encoded, machine: result.machine);
- } catch (e, s) {
- Logging.instance.f("beginResharer failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- /// expects [resharerStarts] of length equal to resharers.
- static ({String resharedStart, Pointer<StartResharedRes> prior})
- beginReshared({
- required String myName,
- required String resharerConfig,
- required List<String> resharerStarts,
- }) {
- try {
- final result = startReshared(
- newMultisigName: 'unused_property',
- myName: myName,
- resharerConfig: resharerConfig,
- resharerStarts: resharerStarts,
- );
- return (resharedStart: result.encoded, prior: result.machine);
- } catch (e, s) {
- Logging.instance.f("beginReshared failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- /// expects [encryptionKeysOfResharedTo] of length equal to new participants
- static String finishResharer({
- required StartResharerRes machine,
- required List<String> encryptionKeysOfResharedTo,
- }) {
- try {
- final result = completeResharer(
- machine: machine,
- encryptionKeysOfResharedTo: encryptionKeysOfResharedTo,
- );
- return result;
- } catch (e, s) {
- Logging.instance.f("finishResharer failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- /// expects [resharerCompletes] of length equal to resharers
- static ({String multisigConfig, String serializedKeys, String resharedId})
- finishReshared({
- required StartResharedRes prior,
- required List<String> resharerCompletes,
- }) {
- try {
- final result = completeReshared(
- prior: prior,
- resharerCompletes: resharerCompletes,
- );
- return result;
- } catch (e, s) {
- Logging.instance.f("finishReshared failed: ", error: e, stackTrace: s);
- rethrow;
- }
- }
-
- static Pointer<ResharerConfig> decodedResharerConfig({
- required String resharerConfig,
- }) {
- try {
- final config = decodeResharerConfig(resharerConfig: resharerConfig);
-
- return config;
- } catch (e, s) {
- Logging.instance.f(
- "decodedResharerConfig failed: ",
- error: e,
- stackTrace: s,
- );
- rethrow;
- }
- }
-
- static ({
- int newThreshold,
- Map<String, int> resharers,
- List<String> newParticipants,
- })
- extractResharerConfigData({required String rConfig}) {
- final decoded = _decodeRConfigWithResharers(rConfig);
- final resharerConfig = decoded.config;
-
- try {
- final newThreshold = resharerNewThreshold(
- resharerConfigPointer: decodedResharerConfig(
- resharerConfig: resharerConfig,
- ),
- );
-
- final resharersCount = resharerResharers(
- resharerConfigPointer: decodedResharerConfig(
- resharerConfig: resharerConfig,
- ),
- );
- final List<int> resharers = [];
- for (int i = 0; i < resharersCount; i++) {
- resharers.add(
- resharerResharer(
- resharerConfigPointer: decodedResharerConfig(
- resharerConfig: resharerConfig,
- ),
- index: i,
- ),
- );
- }
-
- final newParticipantsCount = resharerNewParticipants(
- resharerConfigPointer: decodedResharerConfig(
- resharerConfig: resharerConfig,
- ),
- );
- final List<String> newParticipants = [];
- for (int i = 0; i < newParticipantsCount; i++) {
- newParticipants.add(
- resharerNewParticipant(
- resharerConfigPointer: decodedResharerConfig(
- resharerConfig: resharerConfig,
- ),
- index: i,
- ),
- );
- }
-
- final Map<String, int> resharersMap = {};
-
- for (final resharer in resharers) {
- resharersMap[decoded.resharers.entries
- .firstWhere((e) => e.value == resharer)
- .key] =
- resharer;
- }
-
- return (
- newThreshold: newThreshold,
- resharers: resharersMap,
- newParticipants: newParticipants,
- );
- } catch (e, s) {
- Logging.instance.f(
- "extractResharerConfigData failed: ",
- error: e,
- stackTrace: s,
- );
- rethrow;
- }
- }
-
- static String encodeRConfig(String config, Map<String, int> resharers) {
- return base64Encode("$config@${jsonEncode(resharers)}".toUint8ListFromUtf8);
- }
-
- static String decodeRConfig(String rConfig) {
- return base64Decode(rConfig).toUtf8String.split("@").first;
- }
-
- static ({Map<String, int> resharers, String config})
- _decodeRConfigWithResharers(String rConfig) {
- final parts = base64Decode(rConfig).toUtf8String.split("@");
-
- final config = parts[0];
- final resharers = Map<String, int>.from(jsonDecode(parts[1]) as Map);
-
- return (resharers: resharers, config: config);
- }
-}
diff --git a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart
index dc05614..00537b1 100644
--- a/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart
+++ b/lib/wallets/wallet/impl/bitcoin_frost_wallet.dart
@@ -1,11 +1,10 @@
import 'dart:async';
-import 'dart:ffi';
import 'dart:math';
import 'package:flutter/foundation.dart';
-import 'package:frostdart/frostdart.dart' as frost;
-import 'package:frostdart/frostdart_bindings_generated.dart';
-import 'package:frostdart/util.dart';
+// import 'package:frostdart/frostdart.dart' as frost;
+// import 'package:frostdart/frostdart_bindings_generated.dart';
+// import 'package:frostdart/util.dart';
import 'package:isar_community/isar.dart';
import '../../../electrumx_rpc/cached_electrumx_client.dart';
@@ -21,10 +20,10 @@ import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart';
import '../../../models/paymint/fee_object_model.dart';
import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import '../../../services/event_bus/global_event_bus.dart';
-import '../../../services/frost.dart';
import '../../../utilities/amount/amount.dart';
import '../../../utilities/extensions/extensions.dart';
import '../../../utilities/logger.dart';
+import '../../../wl_gen/interfaces/frost_interface.dart';
import '../../crypto_currency/crypto_currency.dart';
import '../../crypto_currency/intermediate/frost_currency.dart';
import '../../isar/models/frost_wallet_info.dart';
@@ -40,11 +39,10 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
BitcoinFrostWallet(CryptoCurrencyNetwork network)
: super(BitcoinFrost(network) as T);
- FrostWalletInfo get frostInfo =>
- mainDB.isar.frostWalletInfo
- .where()
- .walletIdEqualTo(walletId)
- .findFirstSync()!;
+ FrostWalletInfo get frostInfo => mainDB.isar.frostWalletInfo
+ .where()
+ .walletIdEqualTo(walletId)
+ .findFirstSync()!;
late ElectrumXClient electrumXClient;
late CachedElectrumXClient electrumXCachedClient;
@@ -61,7 +59,9 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
Logging.instance.i("Generating new FROST wallet.");
try {
- final salt = frost.multisigSalt(multisigConfig: multisigConfig).toHex;
+ final salt = frostInterface
+ .getMultisigSalt(multisigConfig: multisigConfig)
+ .toHex;
final FrostWalletInfo frostWalletInfo = FrostWalletInfo(
walletId: info.walletId,
@@ -90,14 +90,10 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
serializedKeys: serializedKeys,
secure: true,
);
- } on FrostdartException catch (e) {
- if (e.errorCode == 72) {
- // rust doesn't like the addressDerivationData
- index++;
- continue;
- } else {
- rethrow;
- }
+ } on FrostBadIndexException catch (_) {
+ // rust doesn't like the addressDerivationData
+ index++;
+ continue;
}
}
@@ -125,24 +121,22 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
.map((e) => e.amount)
.reduce((value, e) => value += e);
- final utxos =
- await mainDB
- .getUTXOs(walletId)
- .filter()
- .isBlockedEqualTo(false)
- .findAll();
+ final utxos = await mainDB
+ .getUTXOs(walletId)
+ .filter()
+ .isBlockedEqualTo(false)
+ .findAll();
if (utxos.isEmpty) {
throw Exception("No UTXOs found");
} else {
final currentHeight = await chainHeight;
utxos.removeWhere(
- (e) =>
- !e.isConfirmed(
- currentHeight,
- cryptoCurrency.minConfirms,
- cryptoCurrency.minCoinbaseConfirms,
- ),
+ (e) => !e.isConfirmed(
+ currentHeight,
+ cryptoCurrency.minConfirms,
+ cryptoCurrency.minCoinbaseConfirms,
+ ),
);
if (utxos.isEmpty) {
throw Exception("No confirmed UTXOs found");
@@ -174,10 +168,9 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
}
}
- final int network =
- cryptoCurrency.network == CryptoCurrencyNetwork.main
- ? Network.Mainnet
- : Network.Testnet;
+ final int network = cryptoCurrency.network == CryptoCurrencyNetwork.main
+ ? frostInterface.mainnet
+ : frostInterface.testnet;
final List<
({
@@ -208,7 +201,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
while (config == null) {
try {
- config = Frost.createSignConfig(
+ config = frostInterface.createSignConfig(
network: network,
inputs: inputs,
outputs: txData.recipients!,
@@ -216,9 +209,8 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
feePerWeight: feePerWeight,
serializedKeys: (await getSerializedKeys())!,
);
- } on FrostdartException catch (e) {
- if (e.errorCode == NOT_ENOUGH_FUNDS_ERROR &&
- utxosRemaining.isNotEmpty) {
+ } on FrostInsufficientFundsException catch (_) {
+ if (utxosRemaining.isNotEmpty) {
// add extra utxo
final utxo = utxosRemaining.take(1).first;
final dData = await getDerivationData(utxo.address);
@@ -281,17 +273,14 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
}
}
- Future<
- ({Pointer<TransactionSignMachineWrapper> machinePtr, String preprocess})
- >
+ Future<({OpaqueWrapper machinePtr, String preprocess})>
frostAttemptSignConfig({required String config}) async {
- final int network =
- cryptoCurrency.network == CryptoCurrencyNetwork.main
- ? Network.Mainnet
- : Network.Testnet;
+ final int network = cryptoCurrency.network == CryptoCurrencyNetwork.main
+ ? frostInterface.mainnet
+ : frostInterface.testnet;
final serializedKeys = await getSerializedKeys();
- return Frost.attemptSignConfig(
+ return frostInterface.attemptSignConfig(
network: network,
config: config,
serializedKeys: serializedKeys!,
@@ -307,13 +296,15 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
await _saveMultisigConfig(multisigConfig);
await _updateThreshold(
- frost.getThresholdFromKeys(serializedKeys: serializedKeys),
+ frostInterface.thresholdFromKeys(serializedKeys: serializedKeys),
);
- final myNameIndex = frost.getParticipantIndexFromKeys(
+ final myNameIndex = frostInterface.participantIndexFromKeys(
serializedKeys: serializedKeys,
);
- final participants = Frost.getParticipants(multisigConfig: multisigConfig);
+ final participants = frostInterface.getParticipants(
+ multisigConfig: multisigConfig,
+ );
final myName = participants[myNameIndex];
await _updateParticipants(participants);
@@ -409,16 +400,14 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
await _fetchAddressesForElectrumXScan();
// Separate receiving and change addresses.
- final Set<String> receivingAddresses =
- allAddressesOld
- .where((e) => e.subType == AddressSubType.receiving)
- .map((e) => e.value)
- .toSet();
- final Set<String> changeAddresses =
- allAddressesOld
- .where((e) => e.subType == AddressSubType.change)
- .map((e) => e.value)
- .toSet();
+ final Set<String> receivingAddresses = allAddressesOld
+ .where((e) => e.subType == AddressSubType.receiving)
+ .map((e) => e.value)
+ .toSet();
+ final Set<String> changeAddresses = allAddressesOld
+ .where((e) => e.subType == AddressSubType.change)
+ .map((e) => e.value)
+ .toSet();
// Remove duplicates.
final allAddressesSet = {...receivingAddresses, ...changeAddresses};
@@ -433,13 +422,12 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
final List<Map<String, dynamic>> allTransactions = [];
for (final txHash in allTxHashes) {
- final storedTx =
- await mainDB.isar.transactionV2s
- .where()
- .walletIdEqualTo(walletId)
- .filter()
- .txidEqualTo(txHash["tx_hash"] as String)
- .findFirst();
+ final storedTx = await mainDB.isar.transactionV2s
+ .where()
+ .walletIdEqualTo(walletId)
+ .filter()
+ .txidEqualTo(txHash["tx_hash"] as String)
+ .findFirst();
if (storedTx == null ||
!storedTx.isConfirmed(
@@ -766,21 +754,18 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
numberOfBlocksFast: f,
numberOfBlocksAverage: m,
numberOfBlocksSlow: s,
- fast:
- Amount.fromDecimal(
- fast,
- fractionDigits: cryptoCurrency.fractionDigits,
- ).raw,
- medium:
- Amount.fromDecimal(
- medium,
- fractionDigits: cryptoCurrency.fractionDigits,
- ).raw,
- slow:
- Amount.fromDecimal(
- slow,
- fractionDigits: cryptoCurrency.fractionDigits,
- ).raw,
+ fast: Amount.fromDecimal(
+ fast,
+ fractionDigits: cryptoCurrency.fractionDigits,
+ ).raw,
+ medium: Amount.fromDecimal(
+ medium,
+ fractionDigits: cryptoCurrency.fractionDigits,
+ ).raw,
+ slow: Amount.fromDecimal(
+ slow,
+ fractionDigits: cryptoCurrency.fractionDigits,
+ ).raw,
);
Logging.instance.i("fetched fees: $feeObject");
@@ -827,8 +812,9 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
try {
await refreshMutex.protect(() async {
if (!isRescan) {
- final salt =
- frost.multisigSalt(multisigConfig: multisigConfig!).toHex;
+ final salt = frostInterface
+ .getMultisigSalt(multisigConfig: multisigConfig!)
+ .toHex;
final knownSalts = _getKnownSalts();
if (knownSalts.contains(salt)) {
throw Exception("Known frost multisig salt found!");
@@ -1211,12 +1197,11 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
// =================== DB ====================================================
- List<String> _getKnownSalts() =>
- mainDB.isar.frostWalletInfo
- .where()
- .walletIdEqualTo(walletId)
- .knownSaltsProperty()
- .findFirstSync()!;
+ List<String> _getKnownSalts() => mainDB.isar.frostWalletInfo
+ .where()
+ .walletIdEqualTo(walletId)
+ .knownSaltsProperty()
+ .findFirstSync()!;
Future<void> _updateKnownSalts(List<String> knownSalts) async {
final info = frostInfo;
@@ -1229,12 +1214,11 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
});
}
- List<String> _getParticipants() =>
- mainDB.isar.frostWalletInfo
- .where()
- .walletIdEqualTo(walletId)
- .participantsProperty()
- .findFirstSync()!;
+ List<String> _getParticipants() => mainDB.isar.frostWalletInfo
+ .where()
+ .walletIdEqualTo(walletId)
+ .participantsProperty()
+ .findFirstSync()!;
Future<void> _updateParticipants(List<String> participants) async {
final info = frostInfo;
@@ -1247,12 +1231,11 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
});
}
- int _getThreshold() =>
- mainDB.isar.frostWalletInfo
- .where()
- .walletIdEqualTo(walletId)
- .thresholdProperty()
- .findFirstSync()!;
+ int _getThreshold() => mainDB.isar.frostWalletInfo
+ .where()
+ .walletIdEqualTo(walletId)
+ .thresholdProperty()
+ .findFirstSync()!;
Future<void> _updateThreshold(int threshold) async {
final info = frostInfo;
@@ -1265,12 +1248,11 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
});
}
- String _getMyName() =>
- mainDB.isar.frostWalletInfo
- .where()
- .walletIdEqualTo(walletId)
- .myNameProperty()
- .findFirstSync()!;
+ String _getMyName() => mainDB.isar.frostWalletInfo
+ .where()
+ .walletIdEqualTo(walletId)
+ .myNameProperty()
+ .findFirstSync()!;
Future<void> _updateMyName(String myName) async {
final info = frostInfo;
@@ -1299,21 +1281,20 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
// TODO [prio=low]: Use ElectrumXInterface method.
Future<void> _updateElectrumX() async {
- final failovers =
- nodeService
- .failoverNodesFor(currency: cryptoCurrency)
- .map(
- (e) => ElectrumXNode(
- address: e.host,
- port: e.port,
- name: e.name,
- id: e.id,
- useSSL: e.useSSL,
- torEnabled: e.torEnabled,
- clearnetEnabled: e.clearnetEnabled,
- ),
- )
- .toList();
+ final failovers = nodeService
+ .failoverNodesFor(currency: cryptoCurrency)
+ .map(
+ (e) => ElectrumXNode(
+ address: e.host,
+ port: e.port,
+ name: e.name,
+ id: e.id,
+ useSSL: e.useSSL,
+ torEnabled: e.torEnabled,
+ clearnetEnabled: e.clearnetEnabled,
+ ),
+ )
+ .toList();
final newNode = await _getCurrentElectrumXNode();
try {
@@ -1477,10 +1458,9 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
@override
Future<void> generateNewChangeAddress() async {
final current = await getCurrentChangeAddress();
- int index =
- current == null
- ? kFrostSecureStartingIndex
- : current.derivationIndex + 1;
+ int index = current == null
+ ? kFrostSecureStartingIndex
+ : current.derivationIndex + 1;
const chain = 1; // change address
final serializedKeys = (await getSerializedKeys())!;
@@ -1494,14 +1474,10 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
serializedKeys: serializedKeys,
secure: true,
);
- } on FrostdartException catch (e) {
- if (e.errorCode == 72) {
- // rust doesn't like the addressDerivationData
- index++;
- continue;
- } else {
- rethrow;
- }
+ } on FrostBadIndexException catch (_) {
+ // rust doesn't like the addressDerivationData
+ index++;
+ continue;
}
}
@@ -1511,10 +1487,9 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
@override
Future<void> generateNewReceivingAddress() async {
final current = await getCurrentReceivingAddress();
- int index =
- current == null
- ? kFrostSecureStartingIndex
- : current.derivationIndex + 1;
+ int index = current == null
+ ? kFrostSecureStartingIndex
+ : current.derivationIndex + 1;
const chain = 0; // receiving address
final serializedKeys = (await getSerializedKeys())!;
@@ -1528,14 +1503,10 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
serializedKeys: serializedKeys,
secure: true,
);
- } on FrostdartException catch (e) {
- if (e.errorCode == 72) {
- // rust doesn't like the addressDerivationData
- index++;
- continue;
- } else {
- rethrow;
- }
+ } on FrostBadIndexException catch (_) {
+ // rust doesn't like the addressDerivationData
+ index++;
+ continue;
}
}
@@ -1627,14 +1598,10 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
serializedKeys: serializedKeys,
secure: true,
);
- } on FrostdartException catch (e) {
- if (e.errorCode == 72) {
- // rust doesn't like the addressDerivationData
- startingIndex++;
- continue;
- } else {
- rethrow;
- }
+ } on FrostBadIndexException catch (_) {
+ // rust doesn't like the addressDerivationData
+ startingIndex++;
+ continue;
}
}
@@ -1657,13 +1624,12 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
secure: secure,
);
- final keys = frost.deserializeKeys(keys: serializedKeys);
+ final keys = frostInterface.getDeserializedKeys(keys: serializedKeys);
- final addressString = frost.addressForKeys(
- network:
- cryptoCurrency.network == CryptoCurrencyNetwork.main
- ? Network.Mainnet
- : Network.Testnet,
+ final addressString = frostInterface.getAddressForKeys(
+ network: cryptoCurrency.network == CryptoCurrencyNetwork.main
+ ? frostInterface.mainnet
+ : frostInterface.testnet,
keys: keys,
addressDerivationData: addressDerivationData,
secure: secure,
@@ -1675,12 +1641,11 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
publicKey: cryptoCurrency.addressToPubkey(address: addressString),
derivationIndex: index,
derivationPath: DerivationPath()..value = "$account/$change/$index",
- subType:
- change == 0
- ? AddressSubType.receiving
- : change == 1
- ? AddressSubType.change
- : AddressSubType.unknown,
+ subType: change == 0
+ ? AddressSubType.receiving
+ : change == 1
+ ? AddressSubType.change
+ : AddressSubType.unknown,
type: AddressType.frostMS,
zSafeFrost: secure && index >= kFrostSecureStartingIndex,
);
@@ -1708,14 +1673,10 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
serializedKeys: serializedKeys,
secure: secure,
);
- } on FrostdartException catch (e) {
- if (e.errorCode == 72) {
- // rust doesn't like the addressDerivationData
- index++;
- continue;
- } else {
- rethrow;
- }
+ } on FrostBadIndexException catch (_) {
+ // rust doesn't like the addressDerivationData
+ index++;
+ continue;
}
}
@@ -1746,18 +1707,17 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
}
Future<List<Address>> _fetchAddressesForElectrumXScan() async {
- final allAddresses =
- await mainDB
- .getAddresses(walletId)
- .filter()
- .not()
- .group(
- (q) => q
- .typeEqualTo(AddressType.nonWallet)
- .or()
- .subTypeEqualTo(AddressSubType.nonWallet),
- )
- .findAll();
+ final allAddresses = await mainDB
+ .getAddresses(walletId)
+ .filter()
+ .not()
+ .group(
+ (q) => q
+ .typeEqualTo(AddressType.nonWallet)
+ .or()
+ .subTypeEqualTo(AddressSubType.nonWallet),
+ )
+ .findAll();
return allAddresses;
}
diff --git a/lib/wl_gen/interfaces/frost_interface.dart b/lib/wl_gen/interfaces/frost_interface.dart
new file mode 100644
index 0000000..affbda0
--- /dev/null
+++ b/lib/wl_gen/interfaces/frost_interface.dart
@@ -0,0 +1,237 @@
+import 'dart:convert';
+import 'dart:typed_data';
+
+import '../../models/isar/models/blockchain_data/utxo.dart';
+import '../../utilities/amount/amount.dart';
+import '../../utilities/extensions/extensions.dart';
+import '../../wallets/crypto_currency/crypto_currency.dart';
+import '../../wallets/models/tx_recipient.dart';
+
+export '../generated/frost_interface_impl.dart';
+
+abstract class FrostInterface {
+ const FrostInterface();
+
+ //==================== utility ===============================================
+ List<String> getParticipants({required String multisigConfig});
+
+ bool validateEncodedMultisigConfig({required String encodedConfig});
+
+ int getThreshold({required String multisigConfig});
+
+ ({
+ List<({String address, Amount amount})> recipients,
+ String changeAddress,
+ int feePerWeight,
+ List<FrostOutput> inputs,
+ })
+ extractDataFromSignConfig({
+ required String serializedKeys,
+ required String signConfig,
+ required CryptoCurrency coin,
+ });
+
+ //==================== wallet creation =======================================
+
+ String createMultisigConfig({
+ required String name,
+ required int threshold,
+ required List<String> participants,
+ });
+
+ ({
+ String seed,
+ String commitments,
+ // Pointer<MultisigConfigWithName> multisigConfigWithNamePtr,
+ OpaqueWrapper multisigConfigWithNamePtr,
+ // Pointer<SecretShareMachineWrapper> secretShareMachineWrapperPtr,
+ OpaqueWrapper secretShareMachineWrapperPtr,
+ })
+ startKeyGeneration({required String multisigConfig, required String myName});
+
+ // ({String share, Pointer<SecretSharesRes> secretSharesResPtr})
+ ({String share, OpaqueWrapper secretSharesResPtr}) generateSecretShares({
+ // required Pointer<MultisigConfigWithName> multisigConfigWithNamePtr,
+ required OpaqueWrapper multisigConfigWithNamePtr,
+ required String mySeed,
+ // required Pointer<SecretShareMachineWrapper> secretShareMachineWrapperPtr,
+ required OpaqueWrapper secretShareMachineWrapperPtr,
+ required List<String> commitments,
+ });
+
+ ({Uint8List multisigId, String recoveryString, String serializedKeys})
+ completeKeyGeneration({
+ // required Pointer<MultisigConfigWithName> multisigConfigWithNamePtr,
+ required OpaqueWrapper multisigConfigWithNamePtr,
+ // required Pointer<SecretSharesRes> secretSharesResPtr,
+ required OpaqueWrapper secretSharesResPtr,
+ required List<String> shares,
+ });
+
+ //=================== transaction creation ===================================
+
+ String createSignConfig({
+ required String serializedKeys,
+ required int network,
+ required List<
+ ({
+ UTXO utxo,
+ Uint8List scriptPubKey,
+ FrostAddressDerivationData addressDerivationData,
+ })
+ >
+ inputs,
+ required List<TxRecipient> outputs,
+ required String changeAddress,
+ required int feePerWeight,
+ });
+
+ // ({Pointer<TransactionSignMachineWrapper> machinePtr, String preprocess})
+ ({OpaqueWrapper machinePtr, String preprocess}) attemptSignConfig({
+ required int network,
+ required String config,
+ required String serializedKeys,
+ });
+
+ // ({Pointer<TransactionSignatureMachineWrapper> machinePtr, String share})
+ ({OpaqueWrapper machinePtr, String share}) continueSigning({
+ // required Pointer<TransactionSignMachineWrapper> machinePtr,
+ required OpaqueWrapper machinePtr,
+ required List<String> preprocesses,
+ });
+
+ String completeSigning({
+ // required Pointer<TransactionSignatureMachineWrapper> machinePtr,
+ required OpaqueWrapper machinePtr,
+ required List<String> shares,
+ });
+
+ // Pointer<SignConfig> decodedSignConfig({
+ OpaqueWrapper decodedSignConfig({
+ required String serializedKeys,
+ required String encodedConfig,
+ required int network,
+ });
+
+ //========================== resharing =======================================
+
+ String createResharerConfig({
+ required int newThreshold,
+ required List<int> resharers,
+ required List<String> newParticipants,
+ });
+
+ // ({String resharerStart, Pointer<StartResharerRes> machine}) beginResharer({
+ ({String resharerStart, OpaqueWrapper machine}) beginResharer({
+ required String serializedKeys,
+ required String config,
+ });
+
+ /// expects [resharerStarts] of length equal to resharers.
+ // ({String resharedStart, Pointer<StartResharedRes> prior}) beginReshared({
+ ({String resharedStart, OpaqueWrapper prior}) beginReshared({
+ required String myName,
+ required String resharerConfig,
+ required List<String> resharerStarts,
+ });
+
+ /// expects [encryptionKeysOfResharedTo] of length equal to new participants
+ String finishResharer({
+ // required StartResharerRes machine,
+ required OpaqueWrapper machine,
+ required List<String> encryptionKeysOfResharedTo,
+ });
+
+ /// expects [resharerCompletes] of length equal to resharers
+ ({String multisigConfig, String serializedKeys, String resharedId})
+ finishReshared({
+ // required StartResharedRes prior,
+ required OpaqueWrapper prior,
+ required List<String> resharerCompletes,
+ });
+
+ // Pointer<ResharerConfig> decodedResharerConfig({
+ OpaqueWrapper decodedResharerConfig({required String resharerConfig});
+
+ ({int newThreshold, Map<String, int> resharers, List<String> newParticipants})
+ extractResharerConfigData({required String rConfig});
+
+ Uint8List getMultisigSalt({required String multisigConfig});
+ int participantIndexFromKeys({required String serializedKeys});
+ int getMultisigThreshold({required String multisigConfig});
+ int thresholdFromKeys({required String serializedKeys});
+ Uint8List getResharerSalt({required String resharerConfig});
+
+ OpaqueWrapper getDeserializedKeys({required String keys});
+ String getAddressForKeys({
+ required OpaqueWrapper keys,
+ required int network,
+ required FrostAddressDerivationData addressDerivationData,
+ required bool secure,
+ });
+
+ int get mainnet;
+ int get testnet;
+
+ String encodeRConfig(String config, Map<String, int> resharers) {
+ return base64Encode("$config@${jsonEncode(resharers)}".toUint8ListFromUtf8);
+ }
+
+ String decodeRConfig(String rConfig) {
+ return base64Decode(rConfig).toUtf8String.split("@").first;
+ }
+}
+
+final class FrostInsufficientFundsException implements Exception {}
+
+final class FrostBadIndexException implements Exception {}
+
+final class OpaqueWrapper {
+ final Object _value;
+
+ const OpaqueWrapper(this._value);
+
+ T getValue<T>() {
+ if (_value is T) return _value as T;
+ throw Exception(
+ "OpaqueWrapper.getValue type of ${_value.runtimeType} is not ${T.runtimeType}",
+ );
+ }
+
+ @override
+ String toString() => "OpaqueWrapper(${_value.runtimeType})";
+}
+
+typedef FrostAddressDerivationData = ({
+ int account,
+ bool change,
+ int index,
+ bool secure,
+});
+
+class FrostOutput {
+ final Uint8List hash;
+ final int vout;
+ final int value;
+ final Uint8List scriptPubKey;
+
+ final FrostAddressDerivationData? addressDerivationData;
+
+ FrostOutput({
+ required this.hash,
+ required this.vout,
+ required this.value,
+ required this.scriptPubKey,
+ required this.addressDerivationData,
+ });
+
+ @override
+ String toString() =>
+ 'FrostOutput{'
+ 'hash: $hash, '
+ 'vout: $vout, '
+ 'value: $value, '
+ 'scriptPubKey: $scriptPubKey, '
+ 'addressDerivationData: $addressDerivationData'
+ '}';
+}
diff --git a/tool/wl_templates/FROST_frost_interface_impl.template.dart b/tool/wl_templates/FROST_frost_interface_impl.template.dart
new file mode 100644
index 0000000..072af51
--- /dev/null
+++ b/tool/wl_templates/FROST_frost_interface_impl.template.dart
@@ -0,0 +1,687 @@
+//ON
+import 'dart:convert';
+import 'dart:ffi';
+import 'dart:typed_data';
+
+import 'package:frostdart/frostdart.dart';
+import 'package:frostdart/frostdart_bindings_generated.dart';
+import 'package:frostdart/output.dart';
+import 'package:frostdart/util.dart';
+
+import '../../models/isar/models/blockchain_data/utxo.dart';
+import '../../utilities/amount/amount.dart';
+import '../../utilities/extensions/extensions.dart';
+import '../../utilities/logger.dart';
+import '../../wallets/crypto_currency/crypto_currency.dart';
+import '../../wallets/models/tx_recipient.dart';
+//END_ON
+import '../interfaces/frost_interface.dart';
+
+FrostInterface get frostInterface => _getInterface();
+
+//OFF
+FrostInterface _getInterface() => throw Exception("FROST not enabled!");
+
+//END_OFF
+//ON
+FrostInterface _getInterface() => _FrostInterfaceImpl();
+
+final class _FrostInterfaceImpl extends FrostInterface {
+ @override
+ ({OpaqueWrapper machinePtr, String preprocess}) attemptSignConfig({
+ required int network,
+ required String config,
+ required String serializedKeys,
+ }) {
+ try {
+ final keys = deserializeKeys(keys: serializedKeys);
+
+ final attemptSignRes = attemptSign(
+ thresholdKeysWrapperPointer: keys,
+ network: network,
+ signConfig: config,
+ );
+
+ return (
+ preprocess: attemptSignRes.ref.preprocess.toDartString(),
+ machinePtr: OpaqueWrapper(attemptSignRes.ref.machine),
+ );
+ } catch (e, s) {
+ Logging.instance.f("attemptSignConfig failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ ({OpaqueWrapper prior, String resharedStart}) beginReshared({
+ required String myName,
+ required String resharerConfig,
+ required List<String> resharerStarts,
+ }) {
+ try {
+ final result = startReshared(
+ newMultisigName: 'unused_property',
+ myName: myName,
+ resharerConfig: resharerConfig,
+ resharerStarts: resharerStarts,
+ );
+ return (
+ resharedStart: result.encoded,
+ prior: OpaqueWrapper(result.machine),
+ );
+ } catch (e, s) {
+ Logging.instance.f("beginReshared failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ ({OpaqueWrapper machine, String resharerStart}) beginResharer({
+ required String serializedKeys,
+ required String config,
+ }) {
+ try {
+ final result = startResharer(
+ serializedKeys: serializedKeys,
+ config: config,
+ );
+
+ return (
+ resharerStart: result.encoded,
+ machine: OpaqueWrapper(result.machine),
+ );
+ } catch (e, s) {
+ Logging.instance.f("beginResharer failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ ({Uint8List multisigId, String recoveryString, String serializedKeys})
+ completeKeyGeneration({
+ required OpaqueWrapper multisigConfigWithNamePtr,
+ required OpaqueWrapper secretSharesResPtr,
+ required List<String> shares,
+ }) {
+ try {
+ final keyGenResPtr = completeKeyGen(
+ multisigConfigWithName: multisigConfigWithNamePtr.getValue(),
+ machineAndCommitments: secretSharesResPtr.getValue(),
+ shares: shares,
+ );
+
+ final id = Uint8List.fromList(
+ List<int>.generate(
+ MULTISIG_ID_LENGTH,
+ (index) => keyGenResPtr.ref.multisig_id[index],
+ ),
+ );
+
+ final recoveryString = keyGenResPtr.ref.recovery.toDartString();
+
+ final serializedKeys = serializeKeys(keys: keyGenResPtr.ref.keys);
+
+ return (
+ multisigId: id,
+ recoveryString: recoveryString,
+ serializedKeys: serializedKeys,
+ );
+ } catch (e, s) {
+ Logging.instance.f(
+ "completeKeyGeneration failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ rethrow;
+ }
+ }
+
+ @override
+ String completeSigning({
+ required OpaqueWrapper machinePtr,
+ required List<String> shares,
+ }) {
+ try {
+ final rawTransaction = completeSign(
+ machine: machinePtr.getValue(),
+ shares: shares,
+ );
+
+ return rawTransaction;
+ } catch (e, s) {
+ Logging.instance.f("completeSigning failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ ({OpaqueWrapper machinePtr, String share}) continueSigning({
+ required OpaqueWrapper machinePtr,
+ required List<String> preprocesses,
+ }) {
+ try {
+ final continueSignRes = continueSign(
+ machine: machinePtr.getValue(),
+ preprocesses: preprocesses,
+ );
+
+ return (
+ share: continueSignRes.ref.preprocess.toDartString(),
+ machinePtr: OpaqueWrapper(continueSignRes.ref.machine),
+ );
+ } catch (e, s) {
+ Logging.instance.f("continueSigning failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ String createMultisigConfig({
+ required String name,
+ required int threshold,
+ required List<String> participants,
+ }) {
+ try {
+ final config = newMultisigConfig(
+ name: name,
+ threshold: threshold,
+ participants: participants,
+ );
+
+ return config;
+ } catch (e, s) {
+ Logging.instance.f(
+ "createMultisigConfig failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ rethrow;
+ }
+ }
+
+ @override
+ String createResharerConfig({
+ required int newThreshold,
+ required List<int> resharers,
+ required List<String> newParticipants,
+ }) {
+ try {
+ final config = newResharerConfig(
+ newThreshold: newThreshold,
+ newParticipants: newParticipants,
+ resharers: resharers,
+ );
+
+ return config;
+ } catch (e, s) {
+ Logging.instance.f(
+ "createResharerConfig failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ rethrow;
+ }
+ }
+
+ @override
+ String createSignConfig({
+ required String serializedKeys,
+ required int network,
+ required List<
+ ({
+ Uint8List scriptPubKey,
+ UTXO utxo,
+ FrostAddressDerivationData addressDerivationData,
+ })
+ >
+ inputs,
+ required List<TxRecipient> outputs,
+ required String changeAddress,
+ required int feePerWeight,
+ }) {
+ try {
+ final signConfig = newSignConfig(
+ thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
+ network: network,
+ outputs: inputs
+ .map(
+ (e) => Output(
+ hash: e.utxo.txid.toUint8ListFromHex,
+ vout: e.utxo.vout,
+ value: e.utxo.value,
+ scriptPubKey: e.scriptPubKey,
+ addressDerivationData: e.addressDerivationData,
+ ),
+ )
+ .toList(),
+ paymentAddresses: outputs.map((e) => e.address).toList(),
+ paymentAmounts: outputs.map((e) => e.amount.raw.toInt()).toList(),
+ change: changeAddress,
+ feePerWeight: feePerWeight,
+ );
+
+ return signConfig;
+ } catch (e, s) {
+ Logging.instance.f("createSignConfig failed: ", error: e, stackTrace: s);
+
+ if (e is FrostdartException && e.errorCode == NOT_ENOUGH_FUNDS_ERROR) {
+ throw FrostInsufficientFundsException();
+ }
+
+ rethrow;
+ }
+ }
+
+ @override
+ OpaqueWrapper decodedResharerConfig({required String resharerConfig}) {
+ try {
+ final config = decodeResharerConfig(resharerConfig: resharerConfig);
+
+ return OpaqueWrapper(config);
+ } catch (e, s) {
+ Logging.instance.f(
+ "decodedResharerConfig failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ rethrow;
+ }
+ }
+
+ @override
+ OpaqueWrapper decodedSignConfig({
+ required String serializedKeys,
+ required String encodedConfig,
+ required int network,
+ }) {
+ try {
+ final configPtr = decodeSignConfig(
+ thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
+ encodedSignConfig: encodedConfig,
+ network: network,
+ );
+ return OpaqueWrapper(configPtr);
+ } catch (e, s) {
+ Logging.instance.f("decodedSignConfig failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ ({
+ String changeAddress,
+ int feePerWeight,
+ List<FrostOutput> inputs,
+ List<({String address, Amount amount})> recipients,
+ })
+ extractDataFromSignConfig({
+ required String serializedKeys,
+ required String signConfig,
+ required CryptoCurrency coin,
+ }) {
+ try {
+ final network = coin.network.isTestNet
+ ? Network.Testnet
+ : Network.Mainnet;
+ final signConfigPointer = decodedSignConfig(
+ encodedConfig: signConfig,
+ network: network,
+ serializedKeys: serializedKeys,
+ );
+
+ // get various data from config
+ final feePerWeight = signFeePerWeight(
+ signConfigPointer: signConfigPointer.getValue(),
+ );
+ final changeAddress = signChange(
+ signConfigPointer: signConfigPointer.getValue(),
+ );
+ final recipientsCount = signPayments(
+ signConfigPointer: signConfigPointer.getValue(),
+ );
+
+ // get tx recipient info
+ final List<({String address, Amount amount})> recipients = [];
+ for (int i = 0; i < recipientsCount; i++) {
+ final String address = signPaymentAddress(
+ signConfigPointer: signConfigPointer.getValue(),
+ index: i,
+ );
+ final int amount = signPaymentAmount(
+ signConfigPointer: signConfigPointer.getValue(),
+ index: i,
+ );
+ recipients.add((
+ address: address,
+ amount: Amount(
+ rawValue: BigInt.from(amount),
+ fractionDigits: coin.fractionDigits,
+ ),
+ ));
+ }
+
+ // get utxos
+ final count = signInputs(signConfigPointer: signConfigPointer.getValue());
+ final List<Output> outputs = [];
+ for (int i = 0; i < count; i++) {
+ final output = signInput(
+ thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
+ signConfig: signConfig,
+ index: i,
+ network: network,
+ );
+
+ outputs.add(output);
+ }
+
+ return (
+ recipients: recipients,
+ changeAddress: changeAddress,
+ feePerWeight: feePerWeight,
+ inputs: outputs
+ .map(
+ (e) => FrostOutput(
+ hash: e.hash,
+ vout: e.vout,
+ value: e.value,
+ scriptPubKey: e.scriptPubKey,
+ addressDerivationData: e.addressDerivationData,
+ ),
+ )
+ .toList(),
+ );
+ } catch (e, s) {
+ Logging.instance.f(
+ "extractDataFromSignConfig failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ rethrow;
+ }
+ }
+
+ @override
+ ({List<String> newParticipants, int newThreshold, Map<String, int> resharers})
+ extractResharerConfigData({required String rConfig}) {
+ final decoded = _decodeRConfigWithResharers(rConfig);
+ final resharerConfig = decoded.config;
+
+ try {
+ final newThreshold = resharerNewThreshold(
+ resharerConfigPointer: decodedResharerConfig(
+ resharerConfig: resharerConfig,
+ ).getValue(),
+ );
+
+ final resharersCount = resharerResharers(
+ resharerConfigPointer: decodedResharerConfig(
+ resharerConfig: resharerConfig,
+ ).getValue(),
+ );
+ final List<int> resharers = [];
+ for (int i = 0; i < resharersCount; i++) {
+ resharers.add(
+ resharerResharer(
+ resharerConfigPointer: decodedResharerConfig(
+ resharerConfig: resharerConfig,
+ ).getValue(),
+ index: i,
+ ),
+ );
+ }
+
+ final newParticipantsCount = resharerNewParticipants(
+ resharerConfigPointer: decodedResharerConfig(
+ resharerConfig: resharerConfig,
+ ).getValue(),
+ );
+ final List<String> newParticipants = [];
+ for (int i = 0; i < newParticipantsCount; i++) {
+ newParticipants.add(
+ resharerNewParticipant(
+ resharerConfigPointer: decodedResharerConfig(
+ resharerConfig: resharerConfig,
+ ).getValue(),
+ index: i,
+ ),
+ );
+ }
+
+ final Map<String, int> resharersMap = {};
+
+ for (final resharer in resharers) {
+ resharersMap[decoded.resharers.entries
+ .firstWhere((e) => e.value == resharer)
+ .key] =
+ resharer;
+ }
+
+ return (
+ newThreshold: newThreshold,
+ resharers: resharersMap,
+ newParticipants: newParticipants,
+ );
+ } catch (e, s) {
+ Logging.instance.f(
+ "extractResharerConfigData failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ rethrow;
+ }
+ }
+
+ @override
+ ({String multisigConfig, String resharedId, String serializedKeys})
+ finishReshared({
+ required OpaqueWrapper prior,
+ required List<String> resharerCompletes,
+ }) {
+ try {
+ final result = completeReshared(
+ prior: prior.getValue(),
+ resharerCompletes: resharerCompletes,
+ );
+ return result;
+ } catch (e, s) {
+ Logging.instance.f("finishReshared failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ String finishResharer({
+ required OpaqueWrapper machine,
+ required List<String> encryptionKeysOfResharedTo,
+ }) {
+ try {
+ final result = completeResharer(
+ machine: machine.getValue(),
+ encryptionKeysOfResharedTo: encryptionKeysOfResharedTo,
+ );
+ return result;
+ } catch (e, s) {
+ Logging.instance.f("finishResharer failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ ({OpaqueWrapper secretSharesResPtr, String share}) generateSecretShares({
+ required OpaqueWrapper multisigConfigWithNamePtr,
+ required String mySeed,
+ required OpaqueWrapper secretShareMachineWrapperPtr,
+ required List<String> commitments,
+ }) {
+ try {
+ final secretSharesResPtr = getSecretShares(
+ multisigConfigWithName: multisigConfigWithNamePtr.getValue(),
+ seed: mySeed,
+ language: Language.english,
+ machine: secretShareMachineWrapperPtr.getValue(),
+ commitments: commitments,
+ );
+
+ final share = secretSharesResPtr.ref.shares.toDartString();
+
+ return (
+ share: share,
+ secretSharesResPtr: OpaqueWrapper(secretSharesResPtr),
+ );
+ } catch (e, s) {
+ Logging.instance.f(
+ "generateSecretShares failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ rethrow;
+ }
+ }
+
+ @override
+ List<String> getParticipants({required String multisigConfig}) {
+ try {
+ final numberOfParticipants = multisigParticipants(
+ multisigConfig: multisigConfig,
+ );
+
+ final List<String> participants = [];
+ for (int i = 0; i < numberOfParticipants; i++) {
+ participants.add(
+ multisigParticipant(multisigConfig: multisigConfig, index: i),
+ );
+ }
+
+ return participants;
+ } catch (e, s) {
+ Logging.instance.f("getParticipants failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ int getThreshold({required String multisigConfig}) {
+ try {
+ final threshold = multisigThreshold(multisigConfig: multisigConfig);
+
+ return threshold;
+ } catch (e, s) {
+ Logging.instance.f("getThreshold failed: ", error: e, stackTrace: s);
+ rethrow;
+ }
+ }
+
+ @override
+ ({
+ String commitments,
+ OpaqueWrapper multisigConfigWithNamePtr,
+ OpaqueWrapper secretShareMachineWrapperPtr,
+ String seed,
+ })
+ startKeyGeneration({required String multisigConfig, required String myName}) {
+ try {
+ final startKeyGenResPtr = startKeyGen(
+ multisigConfig: multisigConfig,
+ myName: myName,
+ language: Language.english,
+ );
+
+ final seed = startKeyGenResPtr.ref.seed.toDartString();
+ final commitments = startKeyGenResPtr.ref.commitments.toDartString();
+ final configWithNamePtr = startKeyGenResPtr.ref.config;
+ final machinePtr = startKeyGenResPtr.ref.machine;
+
+ return (
+ seed: seed,
+ commitments: commitments,
+ multisigConfigWithNamePtr: OpaqueWrapper(configWithNamePtr),
+ secretShareMachineWrapperPtr: OpaqueWrapper(machinePtr),
+ );
+ } catch (e, s) {
+ Logging.instance.f(
+ "startKeyGeneration failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ rethrow;
+ }
+ }
+
+ @override
+ bool validateEncodedMultisigConfig({required String encodedConfig}) {
+ try {
+ decodeMultisigConfig(multisigConfig: encodedConfig);
+ return true;
+ } catch (e, s) {
+ Logging.instance.f(
+ "validateEncodedMultisigConfig failed: ",
+ error: e,
+ stackTrace: s,
+ );
+ return false;
+ }
+ }
+
+ @override
+ Uint8List getMultisigSalt({required String multisigConfig}) =>
+ multisigSalt(multisigConfig: multisigConfig);
+
+ @override
+ int participantIndexFromKeys({required String serializedKeys}) =>
+ getParticipantIndexFromKeys(serializedKeys: serializedKeys);
+
+ @override
+ int getMultisigThreshold({required String multisigConfig}) =>
+ multisigThreshold(multisigConfig: multisigConfig);
+
+ @override
+ int thresholdFromKeys({required String serializedKeys}) =>
+ getThresholdFromKeys(serializedKeys: serializedKeys);
+
+ @override
+ Uint8List getResharerSalt({required String resharerConfig}) =>
+ resharerSalt(resharerConfig: resharerConfig);
+
+ @override
+ OpaqueWrapper getDeserializedKeys({required String keys}) =>
+ OpaqueWrapper(deserializeKeys(keys: keys));
+
+ @override
+ String getAddressForKeys({
+ required OpaqueWrapper keys,
+ required int network,
+ required FrostAddressDerivationData addressDerivationData,
+ required bool secure,
+ }) {
+ try {
+ return addressForKeys(
+ network: network,
+ keys: keys.getValue(),
+ addressDerivationData: addressDerivationData,
+ secure: secure,
+ );
+ } on FrostdartException catch (e) {
+ if (e.errorCode == 72) throw FrostBadIndexException();
+ rethrow;
+ }
+ }
+
+ @override
+ int get mainnet => Network.Mainnet;
+
+ @override
+ int get testnet => Network.Testnet;
+
+ ({Map<String, int> resharers, String config}) _decodeRConfigWithResharers(
+ String rConfig,
+ ) {
+ final parts = base64Decode(rConfig).toUtf8String.split("@");
+
+ final config = parts[0];
+ final resharers = Map<String, int>.from(jsonDecode(parts[1]) as Map);
+
+ return (resharers: resharers, config: config);
+ }
+}
+
+//END_ON
Why this scored 34/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.