diff --git a/packages/tfchain_client/lib/models/council.dart b/packages/tfchain_client/lib/models/council.dart new file mode 100644 index 0000000..62bea25 --- /dev/null +++ b/packages/tfchain_client/lib/models/council.dart @@ -0,0 +1,23 @@ +import 'package:moment_dart/moment_dart.dart'; + +class CouncilProposal { + int index; + int threshold; + Moment end; + String hash; + String module; + String method; + Map args; + bool active; + + CouncilProposal({ + required this.index, + required this.threshold, + required this.end, + required this.hash, + required this.module, + required this.method, + required this.args, + required this.active, + }); +} diff --git a/packages/tfchain_client/lib/src/client.dart b/packages/tfchain_client/lib/src/client.dart index 38726b3..a5e0a11 100644 --- a/packages/tfchain_client/lib/src/client.dart +++ b/packages/tfchain_client/lib/src/client.dart @@ -14,6 +14,7 @@ class QueryClient { QueryBridge? _bridge; QueryTFTPrice? _price; Dao.QueryDao? _dao; + Council.QueryCouncil? _council; QueryClient(this.url) {} @@ -62,6 +63,11 @@ class QueryClient { return _dao!; } + Council.QueryCouncil get council { + if (_council == null) _council = Council.QueryCouncil(this); + return _council!; + } + void _checkInputs() { if (url.isEmpty) { throw FormatException("URL should be provided"); @@ -146,6 +152,12 @@ class Client extends QueryClient { return _dao as Dao.Dao; } + @override + Council.Council get council { + if (_council == null) _council = Council.Council(this); + return _council as Council.Council; + } + KVStore get kvStore { if (_kvStore == null) _kvStore = KVStore(this); return _kvStore as KVStore; diff --git a/packages/tfchain_client/lib/src/council.dart b/packages/tfchain_client/lib/src/council.dart new file mode 100644 index 0000000..5d0a1e7 --- /dev/null +++ b/packages/tfchain_client/lib/src/council.dart @@ -0,0 +1,85 @@ +import 'package:moment_dart/moment_dart.dart'; +import 'package:polkadart/multisig/multisig_base.dart'; +import 'package:polkadart_keyring/polkadart_keyring.dart'; +import 'package:tfchain_client/generated/dev/types/pallet_collective/votes.dart'; +import 'package:tfchain_client/models/council.dart'; +import 'package:tfchain_client/models/dao.dart'; +import 'package:tfchain_client/tfchain_client.dart'; + +class QueryCouncil { + final QueryClient client; + QueryCouncil(this.client); + + Future> getProposals() async { + final hashesJson = await client.api.query.council.proposals(); + List hashes = + hashesJson.map((hashList) => hashList.toHex()).toList(); + return hashes; + } + + Future getProposal({required String hash}) async { + try { + final proposal = + await client.api.query.council.proposalOf(hash.hexToListInt()); + final ProposalJson = proposal!.toJson(); + return ProposalInfo.fromJson(ProposalJson); + } catch (error) { + print(error); + return null; + } + } + + Future getProposalVotes({required String hash}) async { + final votes = await client.api.query.council.voting(hash.hexToListInt()); + return votes!; + } + + Future> members() async { + final keyring = Keyring(); + final members = await client.api.query.council.members(); + return members.map((member) => keyring.encodeAddress(member)).toList(); + } + + Future> get() async { + List hashes = await getProposals(); + + List proposals = []; + + for (int i = 0; i < hashes.length; i++) { + final proposal = await getProposal(hash: hashes[i]); + final proposalVotes = await getProposalVotes(hash: hashes[i]); + final nowBlock = await client.api.query.system.number(); + final timeUntilEnd = (proposalVotes.end - nowBlock) * 6; + if (proposal != null) { + final p = CouncilProposal( + index: proposalVotes.index, + threshold: proposalVotes.threshold, + end: Moment(DateTime.now()).add(Duration(seconds: timeUntilEnd)), + hash: hashes[i], + module: proposal.module, + method: proposal.method, + args: proposal.args, + active: proposalVotes.end > nowBlock); + proposals.add(p); + } + } + + return proposals; + } +} + +class Council extends QueryCouncil { + Council(Client this.client) : super(client); + final Client client; + + Future vote({required String hash, required bool approve}) async { + final votes = await getProposalVotes(hash: hash); + final extrinsic = client.api.tx.council.vote( + index: BigInt.from(votes.index), + proposal: hash.hexToListInt(), + approve: approve); + await client.apply(extrinsic); + + return getProposalVotes(hash: hash); + } +} diff --git a/packages/tfchain_client/lib/tfchain_client.dart b/packages/tfchain_client/lib/tfchain_client.dart index b2a0000..0156b17 100644 --- a/packages/tfchain_client/lib/tfchain_client.dart +++ b/packages/tfchain_client/lib/tfchain_client.dart @@ -16,6 +16,7 @@ import 'package:polkadart/scale_codec.dart'; import 'package:polkadart_keyring/polkadart_keyring.dart'; import 'package:signer/signer.dart' as Signer; import 'package:tfchain_client/generated/dev/types/tfchain_runtime/runtime_call.dart'; +import 'package:tfchain_client/src/council.dart' as Council; import 'package:tfchain_client/src/error_mapper.dart'; import 'package:tfchain_client/src/balances.dart' as balance; import 'package:tfchain_client/src/contracts.dart';