Skip to content

Commit cbc0977

Browse files
committed
Refactor contracts, update grid proxy ref, edit state in getContractsByTwinId
1 parent 0e39d6d commit cbc0977

3 files changed

Lines changed: 69 additions & 96 deletions

File tree

app/lib/screens/wallets/contracts.dart

Lines changed: 67 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import 'package:threebotlogin/services/gridproxy_service.dart';
77
import 'package:threebotlogin/services/tfchain_service.dart';
88
import 'package:gridproxy_client/models/contracts.dart';
99
import 'package:threebotlogin/widgets/wallets/contract_details.dart';
10-
import 'dart:convert';
1110

1211
class WalletContractsWidget extends ConsumerStatefulWidget {
1312
const WalletContractsWidget({super.key, required this.wallet});
1413
final Wallet wallet;
1514

1615
@override
17-
ConsumerState<WalletContractsWidget> createState() => _WalletContractsWidgetState();
16+
ConsumerState<WalletContractsWidget> createState() =>
17+
_WalletContractsWidgetState();
1818
}
1919

2020
class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
@@ -33,42 +33,9 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
3333
loading = true;
3434
failed = false;
3535
});
36-
3736
try {
38-
int? twinId;
39-
try {
40-
twinId = await getTwinId(widget.wallet.tfchainSecret);
41-
logger.i('Found twin ID: $twinId for wallet: ${widget.wallet.tfchainAddress}');
42-
} catch (e) {
43-
logger.w('Could not get twin ID: $e');
44-
}
45-
46-
if (twinId != null) {
47-
try {
48-
final contractsList = await getContractsByTwinId(twinId);
49-
contracts = contractsList.cast<ContractInfo>();
50-
logger.i('Loaded ${contracts.length} contracts for twin ID: $twinId');
51-
} catch (e) {
52-
logger.w('Error fetching contracts by twin ID: $e');
53-
if (context.mounted) {
54-
ScaffoldMessenger.of(context).showSnackBar(
55-
SnackBar(
56-
content: Text('Error: ${e.toString().split(': ').last}'),
57-
duration: const Duration(seconds: 3),
58-
),
59-
);
60-
}
61-
}
62-
} else {
63-
if (context.mounted) {
64-
ScaffoldMessenger.of(context).showSnackBar(
65-
const SnackBar(
66-
content: Text('Could not find a twin ID for this wallet. No contracts can be displayed.'),
67-
duration: Duration(seconds: 5),
68-
),
69-
);
70-
}
71-
}
37+
final twinId = await getTwinId(widget.wallet.tfchainSecret);
38+
contracts = await getContractsByTwinId(twinId);
7239
} catch (e) {
7340
logger.e('Failed to load contracts: $e');
7441
setState(() {
@@ -77,7 +44,7 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
7744
if (context.mounted) {
7845
final loadingContractsFailure = SnackBar(
7946
content: Text(
80-
'Failed to load contracts: ${e.toString().split(': ').last}',
47+
'Failed to load contracts',
8148
style: Theme.of(context)
8249
.textTheme
8350
.bodyMedium!
@@ -98,7 +65,7 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
9865
@override
9966
Widget build(BuildContext context) {
10067
Widget content;
101-
68+
10269
if (loading) {
10370
content = Center(
10471
child: Column(
@@ -124,8 +91,10 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
12491
const SizedBox(height: 15),
12592
Text(
12693
'Failed to load contracts',
127-
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
128-
color: Theme.of(context).colorScheme.error),
94+
style: Theme.of(context)
95+
.textTheme
96+
.bodyLarge!
97+
.copyWith(color: Theme.of(context).colorScheme.error),
12998
),
13099
const SizedBox(height: 15),
131100
ElevatedButton.icon(
@@ -144,14 +113,17 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
144113
Icon(
145114
Icons.description_outlined,
146115
size: 64,
147-
color: Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.5),
116+
color: Theme.of(context)
117+
.colorScheme
118+
.onSurfaceVariant
119+
.withOpacity(0.5),
148120
),
149121
const SizedBox(height: 16),
150122
Text(
151123
'No contracts found for this wallet',
152124
style: Theme.of(context).textTheme.titleMedium!.copyWith(
153-
color: Theme.of(context).colorScheme.onSurface,
154-
),
125+
color: Theme.of(context).colorScheme.onSurface,
126+
),
155127
textAlign: TextAlign.center,
156128
),
157129
const SizedBox(height: 8),
@@ -160,8 +132,8 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
160132
child: Text(
161133
'Contracts will appear here when you deploy workloads on the ThreeFold Grid',
162134
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
163-
color: Theme.of(context).colorScheme.onSurfaceVariant,
164-
),
135+
color: Theme.of(context).colorScheme.onSurfaceVariant,
136+
),
165137
textAlign: TextAlign.center,
166138
),
167139
),
@@ -181,36 +153,21 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
181153
),
182154
);
183155
}
184-
156+
185157
return content;
186158
}
187-
159+
188160
Widget _buildContractListItem(BuildContext context, ContractInfo contract) {
189-
final contractId = contract.contract_id.toString();
161+
final contractId = contract.contract_id;
190162
final contractType = contract.type;
191163
final state = contract.state;
192-
164+
193165
String name = '';
194-
195-
if (contract.details != null && contract.details is Map) {
196-
final details = contract.details as Map;
197-
198-
if (contractType.toLowerCase() == 'name' && details.containsKey('name')) {
199-
name = details['name']?.toString() ?? '';
200-
}
201-
else if (contractType.toLowerCase() == 'node' &&
202-
details.containsKey('deployment_data') &&
203-
details['deployment_data'] is String &&
204-
details['deployment_data'].isNotEmpty) {
205-
try {
206-
final Map<String, dynamic> decoded = json.decode(details['deployment_data']);
207-
name = decoded['name']?.toString() ?? '';
208-
} catch (e) {
209-
logger.d('Could not parse deployment_data JSON: $e');
210-
}
211-
}
166+
167+
if (contract.details != null && contractType.toLowerCase() == 'name') {
168+
name = (contract.details as Map)['name'];
212169
}
213-
170+
214171
// Get icon based on contract type
215172
IconData typeIcon = Icons.description_outlined;
216173
if (contractType.toLowerCase() == 'name') {
@@ -220,7 +177,7 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
220177
} else if (contractType.toLowerCase() == 'rent') {
221178
typeIcon = Icons.storage_outlined;
222179
}
223-
180+
224181
return Card(
225182
margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
226183
elevation: 2,
@@ -267,37 +224,53 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
267224
children: [
268225
Text(
269226
'Contract $contractId',
270-
style: Theme.of(context).textTheme.titleMedium!.copyWith(
271-
fontWeight: FontWeight.bold,
272-
color: Theme.of(context).colorScheme.onSurface,
273-
),
227+
style: Theme.of(context)
228+
.textTheme
229+
.titleMedium!
230+
.copyWith(
231+
fontWeight: FontWeight.bold,
232+
color: Theme.of(context).colorScheme.onSurface,
233+
),
274234
overflow: TextOverflow.ellipsis,
275235
),
276236
const SizedBox(height: 4),
277237
Row(
278238
children: [
279239
Container(
280-
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
240+
padding: const EdgeInsets.symmetric(
241+
horizontal: 8, vertical: 2),
281242
decoration: BoxDecoration(
282-
color: Theme.of(context).colorScheme.surfaceVariant,
243+
color: Theme.of(context)
244+
.colorScheme
245+
.surfaceVariant,
283246
borderRadius: BorderRadius.circular(4),
284247
),
285248
child: Text(
286249
contractType,
287-
style: Theme.of(context).textTheme.bodySmall!.copyWith(
288-
color: Theme.of(context).colorScheme.onSurfaceVariant,
289-
fontWeight: FontWeight.w500,
290-
),
250+
style: Theme.of(context)
251+
.textTheme
252+
.bodySmall!
253+
.copyWith(
254+
color: Theme.of(context)
255+
.colorScheme
256+
.onSurfaceVariant,
257+
fontWeight: FontWeight.w500,
258+
),
291259
),
292260
),
293261
if (name.isNotEmpty) ...[
294262
const SizedBox(width: 8),
295263
Expanded(
296264
child: Text(
297265
name,
298-
style: Theme.of(context).textTheme.bodySmall!.copyWith(
299-
color: Theme.of(context).colorScheme.onSurfaceVariant,
300-
),
266+
style: Theme.of(context)
267+
.textTheme
268+
.bodySmall!
269+
.copyWith(
270+
color: Theme.of(context)
271+
.colorScheme
272+
.onSurfaceVariant,
273+
),
301274
overflow: TextOverflow.ellipsis,
302275
),
303276
),
@@ -320,9 +293,9 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
320293
Text(
321294
'View Details',
322295
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
323-
color: Theme.of(context).colorScheme.primary,
324-
fontWeight: FontWeight.w500,
325-
),
296+
color: Theme.of(context).colorScheme.primary,
297+
fontWeight: FontWeight.w500,
298+
),
326299
),
327300
Icon(
328301
Icons.arrow_forward_ios,
@@ -338,20 +311,20 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
338311
),
339312
);
340313
}
341-
314+
342315
Widget _buildStatusBadge(BuildContext context, String status) {
343316
final lowerStatus = status.toLowerCase();
344317
Color backgroundColor;
345318
Color textColor;
346-
319+
347320
if (lowerStatus == 'created') {
348321
backgroundColor = Theme.of(context).colorScheme.primaryContainer;
349-
textColor = Theme.of(context).colorScheme.onPrimary;
322+
textColor = Theme.of(context).colorScheme.onPrimaryContainer;
350323
} else {
351324
backgroundColor = Theme.of(context).colorScheme.warningContainer;
352325
textColor = Theme.of(context).colorScheme.warning;
353326
}
354-
327+
355328
return Container(
356329
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
357330
decoration: BoxDecoration(
@@ -361,13 +334,13 @@ class _WalletContractsWidgetState extends ConsumerState<WalletContractsWidget> {
361334
child: Text(
362335
_capitalizeFirstLetter(lowerStatus),
363336
style: Theme.of(context).textTheme.labelSmall!.copyWith(
364-
color: textColor,
365-
fontWeight: FontWeight.bold,
366-
),
337+
color: textColor,
338+
fontWeight: FontWeight.bold,
339+
),
367340
),
368341
);
369342
}
370-
343+
371344
String _capitalizeFirstLetter(String text) {
372345
if (text.isEmpty) return text;
373346
return text[0].toUpperCase() + text.substring(1);

app/lib/services/gridproxy_service.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Future<List<ContractInfo>> getContractsByTwinId(int twinId) async {
2424

2525
final client = GridProxyClient(gridproxyUrl);
2626
final contracts =
27-
await client.contracts.list(ContractInfoQueryParams(twin_id: twinId, state: ContractState.GracePeriod));
27+
await client.contracts.list(ContractInfoQueryParams(twin_id: twinId, state: [ContractState.Created, ContractState.GracePeriod]));
2828
return contracts;
2929
} catch (e) {
3030
throw Exception('Error fetching contracts: $e');

app/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ packages:
811811
description:
812812
path: "packages/gridproxy_client"
813813
ref: development
814-
resolved-ref: "4ef4d3bc2550017d987f27fd8c2264854c5cf683"
814+
resolved-ref: a2e6e9d8a560d93474c77edacb0b8e8f04187cef
815815
url: "https://github.com/threefoldtech/tfgrid-sdk-dart"
816816
source: git
817817
version: "1.0.0"

0 commit comments

Comments
 (0)