feat(grants-create): add configurable grant authorization fields
This commit is contained in:
@@ -5,6 +5,10 @@ import 'package:arbiter/screens/dashboard/evm/grants/create/grants/ether_transfe
|
|||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart';
|
import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart';
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart';
|
import 'package:arbiter/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart';
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart';
|
import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart';
|
||||||
|
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/chain_id_field.dart';
|
||||||
|
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart';
|
||||||
|
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart';
|
||||||
|
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/validity_window_field.dart';
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/shared_grant_fields.dart';
|
import 'package:arbiter/screens/dashboard/evm/grants/create/shared_grant_fields.dart';
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart';
|
import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart';
|
||||||
import 'package:arbiter/theme/palette.dart';
|
import 'package:arbiter/theme/palette.dart';
|
||||||
@@ -101,8 +105,64 @@ class CreateEvmGrantScreen extends HookConsumerWidget {
|
|||||||
const _IntroCard(),
|
const _IntroCard(),
|
||||||
SizedBox(height: 1.8.h),
|
SizedBox(height: 1.8.h),
|
||||||
const _Section(
|
const _Section(
|
||||||
title: 'Shared grant options',
|
title: 'Authorization',
|
||||||
child: SharedGrantFields(),
|
tooltip: 'Select which SDK client receives this grant and '
|
||||||
|
'which of its wallet accesses it applies to.',
|
||||||
|
child: AuthorizationFields(),
|
||||||
|
),
|
||||||
|
SizedBox(height: 1.8.h),
|
||||||
|
IntrinsicHeight(
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: _Section(
|
||||||
|
title: 'Chain',
|
||||||
|
tooltip: 'Restrict this grant to a specific EVM chain ID. '
|
||||||
|
'Leave empty to allow any chain.',
|
||||||
|
optional: true,
|
||||||
|
child: ChainIdField(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 1.8.w),
|
||||||
|
const Expanded(
|
||||||
|
child: _Section(
|
||||||
|
title: 'Timing',
|
||||||
|
tooltip: 'Set an optional validity window. '
|
||||||
|
'Signing requests outside this period will be rejected.',
|
||||||
|
optional: true,
|
||||||
|
child: ValidityWindowField(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 1.8.h),
|
||||||
|
IntrinsicHeight(
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: _Section(
|
||||||
|
title: 'Gas limits',
|
||||||
|
tooltip: 'Cap the gas fees this grant may authorize. '
|
||||||
|
'Transactions exceeding these values will be rejected.',
|
||||||
|
optional: true,
|
||||||
|
child: GasFeeOptionsField(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 1.8.w),
|
||||||
|
const Expanded(
|
||||||
|
child: _Section(
|
||||||
|
title: 'Transaction limits',
|
||||||
|
tooltip: 'Limit how many transactions can be signed '
|
||||||
|
'within a rolling time window.',
|
||||||
|
optional: true,
|
||||||
|
child: TransactionRateLimitField(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 1.8.h),
|
SizedBox(height: 1.8.h),
|
||||||
_GrantTypeSelector(
|
_GrantTypeSelector(
|
||||||
@@ -112,6 +172,8 @@ class CreateEvmGrantScreen extends HookConsumerWidget {
|
|||||||
SizedBox(height: 1.8.h),
|
SizedBox(height: 1.8.h),
|
||||||
_Section(
|
_Section(
|
||||||
title: 'Grant-specific options',
|
title: 'Grant-specific options',
|
||||||
|
tooltip: 'Rules specific to the selected transfer type. '
|
||||||
|
'Switch between Ether and token above to change these fields.',
|
||||||
child: handler.buildForm(context, ref),
|
child: handler.buildForm(context, ref),
|
||||||
),
|
),
|
||||||
SizedBox(height: 2.2.h),
|
SizedBox(height: 2.2.h),
|
||||||
@@ -175,13 +237,21 @@ class _IntroCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _Section extends StatelessWidget {
|
class _Section extends StatelessWidget {
|
||||||
const _Section({required this.title, required this.child});
|
const _Section({
|
||||||
|
required this.title,
|
||||||
|
required this.tooltip,
|
||||||
|
required this.child,
|
||||||
|
this.optional = false,
|
||||||
|
});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
|
final String tooltip;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
final bool optional;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final subtleColor = Theme.of(context).colorScheme.outline;
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.all(2.h),
|
padding: EdgeInsets.all(2.h),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -192,11 +262,33 @@ class _Section extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Row(
|
||||||
title,
|
children: [
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
Text(
|
||||||
fontWeight: FontWeight.w800,
|
title,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 0.4.w),
|
||||||
|
Tooltip(
|
||||||
|
message: tooltip,
|
||||||
|
child: Icon(
|
||||||
|
Icons.info_outline_rounded,
|
||||||
|
size: 16,
|
||||||
|
color: subtleColor,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
if (optional) ...[
|
||||||
|
SizedBox(width: 0.6.w),
|
||||||
|
Text(
|
||||||
|
'(optional)',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
|
color: subtleColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 1.4.h),
|
SizedBox(height: 1.4.h),
|
||||||
child,
|
child,
|
||||||
|
|||||||
@@ -1,19 +1,11 @@
|
|||||||
// lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart
|
// lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/chain_id_field.dart';
|
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/client_picker_field.dart';
|
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/client_picker_field.dart';
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart';
|
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart';
|
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/validity_window_field.dart';
|
|
||||||
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart';
|
import 'package:arbiter/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:sizer/sizer.dart';
|
import 'package:sizer/sizer.dart';
|
||||||
|
|
||||||
/// All shared grant fields in a single vertical layout.
|
class AuthorizationFields extends StatelessWidget {
|
||||||
///
|
const AuthorizationFields({super.key});
|
||||||
/// Every [FormBuilderField] descendant auto-registers with the nearest
|
|
||||||
/// [FormBuilder] ancestor via [BuildContext] — no controllers passed.
|
|
||||||
class SharedGrantFields extends StatelessWidget {
|
|
||||||
const SharedGrantFields({super.key});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -23,15 +15,8 @@ class SharedGrantFields extends StatelessWidget {
|
|||||||
const ClientPickerField(),
|
const ClientPickerField(),
|
||||||
SizedBox(height: 1.6.h),
|
SizedBox(height: 1.6.h),
|
||||||
const WalletAccessPickerField(),
|
const WalletAccessPickerField(),
|
||||||
SizedBox(height: 1.6.h),
|
|
||||||
const ChainIdField(),
|
|
||||||
SizedBox(height: 1.6.h),
|
|
||||||
const ValidityWindowField(),
|
|
||||||
SizedBox(height: 1.6.h),
|
|
||||||
const GasFeeOptionsField(),
|
|
||||||
SizedBox(height: 1.6.h),
|
|
||||||
const TransactionRateLimitField(),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user