Skip to content

Commit

Permalink
Merge branch 'development' of github.com:threefoldtech/threefold_conn…
Browse files Browse the repository at this point in the history
…ect into development_kyc_wallets
  • Loading branch information
AlaaElattar committed Jan 8, 2025
2 parents 655bd20 + 21f55de commit 9217f7b
Show file tree
Hide file tree
Showing 13 changed files with 809 additions and 6 deletions.
1 change: 1 addition & 0 deletions app/lib/app_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,5 @@ void setFallbackConfigs() {
Globals().spendingLimit = 0;
Globals().newsUrl = '';
Globals().idenfyServiceUrl = '';
Globals().council = false;
}
42 changes: 42 additions & 0 deletions app/lib/apps/council/council.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'package:flutter/material.dart';
import 'package:threebotlogin/app.dart';
import 'package:threebotlogin/apps/farmers/farmers_user_data.dart';
import 'package:threebotlogin/events/events.dart';
import 'package:threebotlogin/events/go_home_event.dart';
import 'package:threebotlogin/screens/council_screen.dart';

class Council implements App {
static final Council _singleton = Council._internal();
static const Widget _councilWidget = CouncilScreen();

factory Council() {
return _singleton;
}

Council._internal();

@override
Future<Widget> widget() async {
return _councilWidget;
}

@override
void clearData() {
clearAllData();
}

@override
bool emailVerificationRequired() {
return false;
}

@override
bool pinRequired() {
return true;
}

@override
void back() {
Events().emit(GoHomeEvent());
}
}
2 changes: 2 additions & 0 deletions app/lib/helpers/flags.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ class Flags {

Globals().bridgeTFTAddress =
(await Flags().getFlagValueByFeatureName('bridge-address'))!;
Globals().council =
await Flags().hasFlagValueByFeatureName('council-member');
}

Future<bool> hasFlagValueByFeatureName(String name) async {
Expand Down
1 change: 1 addition & 0 deletions app/lib/helpers/globals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Globals {
String termsAndConditionsUrl = '';
String newsUrl = '';
String idenfyServiceUrl = '';
bool council = false;

bool isCacheClearedWallet = false;
bool isCacheClearedFarmer = false;
Expand Down
9 changes: 9 additions & 0 deletions app/lib/jrouter.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:threebotlogin/app.dart';
import 'package:threebotlogin/apps/council/council.dart';
import 'package:threebotlogin/apps/dao/dao.dart';
import 'package:threebotlogin/apps/wallet/wallet.dart';
import 'package:threebotlogin/screens/identity_verification_screen.dart';
Expand Down Expand Up @@ -77,6 +78,14 @@ class JRouter {
view: const PreferenceScreen(),
),
app: null),
AppInfo(
route: Route(
path: '/council',
name: 'Council',
icon: Icons.how_to_vote_outlined,
view: await Council().widget(),
),
app: Dao()),
];
}

Expand Down
134 changes: 134 additions & 0 deletions app/lib/screens/council_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import 'package:flutter/material.dart';
import 'package:threebotlogin/widgets/council/councils.dart';
import 'package:threebotlogin/widgets/layout_drawer.dart';
import 'package:validators/validators.dart';

class CouncilScreen extends StatefulWidget {
const CouncilScreen({super.key});

@override
State<CouncilScreen> createState() => _CouncilScreenState();
}

class _CouncilScreenState extends State<CouncilScreen> {
final urlController = TextEditingController();
String? errorMessage;

@override
Widget build(BuildContext context) {
const size = 100.0;
final content = Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
color: Theme.of(context).colorScheme.onSurface,
),
controller: urlController,
onChanged: (value) {
final v = value.trim();
if (v.isEmpty) {
errorMessage = 'URL is required';
setState(() {});
return;
}
if (!v.startsWith('wss://') && !v.startsWith('ws://')) {
errorMessage = 'Not a valid websocket URL';
setState(() {});
return;
}
if (!isFQDN(v.replaceFirst('wss://', '')) &&
!isFQDN(v.replaceFirst('ws://', ''))) {
errorMessage = 'Not a valid websocket URL';
setState(() {});
return;
}
errorMessage = null;
setState(() {});
return;
},
decoration: InputDecoration(
labelText: 'TFChain URL',
errorText: errorMessage,
)),
const SizedBox(height: 50),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
fixedSize: const Size.fromWidth(size)),
onPressed: () {
urlController.text = 'wss://tfchain.dev.grid.tf';
errorMessage = null;
setState(() {});
},
child: const Text('Devnet')),
ElevatedButton(
style: ElevatedButton.styleFrom(
fixedSize: const Size.fromWidth(size)),
onPressed: () {
urlController.text = 'wss://tfchain.qa.grid.tf';
errorMessage = null;
setState(() {});
},
child: const Text('QAnet')),
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
fixedSize: const Size.fromWidth(size)),
onPressed: () {
urlController.text = 'wss://tfchain.test.grid.tf';
errorMessage = null;
setState(() {});
},
child: const Text('Testnet')),
ElevatedButton(
style: ElevatedButton.styleFrom(
fixedSize: const Size.fromWidth(size)),
onPressed: () {
urlController.text = 'wss://tfchain.grid.tf';
errorMessage = null;
setState(() {});
},
child: const Text('Mainnet')),
],
),
const SizedBox(height: 50),
ElevatedButton(
onPressed: () {
if (errorMessage == null) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
CouncilsWidget(chainUrl: urlController.text),
));
}
},
style: ElevatedButton.styleFrom(
backgroundColor: errorMessage == null
? Theme.of(context).colorScheme.primaryContainer
: Theme.of(context).colorScheme.surfaceContainerHighest),
child: SizedBox(
width: double.infinity,
child: Text(
style: Theme.of(context).textTheme.titleLarge!.copyWith(
color: errorMessage == null
? Theme.of(context).colorScheme.primary
: Colors.grey,
fontWeight: FontWeight.bold),
'Connect',
textAlign: TextAlign.center,
)))
],
),
);
return LayoutDrawer(titleText: 'Council', content: content);
}
}
55 changes: 55 additions & 0 deletions app/lib/services/tfchain_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import 'dart:convert';

import 'package:bip39/bip39.dart';
import 'package:convert/convert.dart';
import 'package:tfchain_client/generated/dev/types/pallet_collective/votes.dart';
import 'package:tfchain_client/generated/dev/types/tfchain_support/types/farm.dart';
import 'package:tfchain_client/models/council.dart';
import 'package:threebotlogin/apps/wallet/wallet_config.dart';
import 'package:threebotlogin/helpers/globals.dart';
import 'package:threebotlogin/services/shared_preference_service.dart';
Expand Down Expand Up @@ -249,3 +251,56 @@ Future<String> getMemo(String address) async {
final twinId = await getTwinIdByQueryClient(address);
return 'twin_$twinId';
}

Future<List<CouncilProposal>> getCouncilProposals(String chainUrl) async {
final client = TFChain.QueryClient(chainUrl);
try {
await client.connect();
final proposals = await client.council.get();
return proposals;
} catch (e) {
throw Exception('Failed to get council proposals due to $e');
} finally {
await client.disconnect();
}
}

Future<List<String>> getCouncilMembers(String chainUrl) async {
final client = TFChain.QueryClient(chainUrl);
try {
await client.connect();
final members = await client.council.members();
return members;
} catch (e) {
throw Exception('Failed to get council members due to $e');
} finally {
await client.disconnect();
}
}

Future<Votes> councilVote(
String chainUrl, bool vote, String hash, String seed) async {
final client = TFChain.Client(chainUrl, seed, 'sr25519');
try {
await client.connect();
final votes = await client.council.vote(hash: hash, approve: vote);
return votes;
} catch (e) {
throw Exception('Failed to vote due to $e');
} finally {
await client.disconnect();
}
}

Future<Votes> getCouncilProposalVotes(String chainUrl, String hash) async {
final client = TFChain.QueryClient(chainUrl);
try {
await client.connect();
final votes = await client.council.getProposalVotes(hash: hash);
return votes;
} catch (e) {
throw Exception('Failed to get council proposals votes due to $e');
} finally {
await client.disconnect();
}
}
Loading

0 comments on commit 9217f7b

Please sign in to comment.