From d07d07dd428f631e0a0def8222960fc7fc2b432e Mon Sep 17 00:00:00 2001 From: Hanh Date: Thu, 11 Jul 2024 21:46:29 +0200 Subject: [PATCH] Allow voting with notes that are spent *after* the snapshot height --- lib/pages/more/vote.dart | 29 ++++++++------ lib/pages/utils.dart | 6 +-- lib/store2.dart | 2 +- lib/store2.freezed.dart | 50 +++++++++++++------------ native/zcash-sync | 2 +- native/zcash-vote | 2 +- packages/warp_api_ffi/lib/warp_api.dart | 4 +- pubspec.yaml | 2 +- 8 files changed, 52 insertions(+), 45 deletions(-) diff --git a/lib/pages/more/vote.dart b/lib/pages/more/vote.dart index 3b034aaf..89de83c0 100644 --- a/lib/pages/more/vote.dart +++ b/lib/pages/more/vote.dart @@ -1,14 +1,16 @@ import 'dart:convert'; -import 'package:YWallet/pages/utils.dart'; +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:http/http.dart' as http; import 'package:go_router/go_router.dart'; import 'package:settings_ui/settings_ui.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:warp_api/data_fb_generated.dart'; import 'package:warp_api/warp_api.dart'; +import '../../pages/utils.dart'; import '../../accounts.dart'; import '../../generated/intl/messages.dart'; import '../../store2.dart'; @@ -109,7 +111,7 @@ class VoteState extends State with WithLoadingAnimation { final electionJson = jsonDecode(electionString); final election = Election.fromJson(electionJson); setState(() { - vote = Vote(election: election, ids: []); + vote = Vote(election: election, notes: []); }); } @@ -117,8 +119,8 @@ class VoteState extends State with WithLoadingAnimation { final e = vote?.election; if (e != null) { WarpApi.populateVoteNotes(aa.coin, aa.id, e.start_height, e.end_height); - final ids = WarpApi.listVoteNotes(aa.coin, aa.id, e.end_height); - final vote = Vote(election: e, ids: ids); + final notes = WarpApi.listVoteNotes(aa.coin, aa.id, e.end_height); + final vote = Vote(election: e, notes: notes); GoRouter.of(context).push('/more/vote/notes', extra: vote); } else { final electionURL = urlController.text; @@ -152,11 +154,7 @@ class VoteNotesState extends State { void initState() { super.initState(); Future(() async { - final ids = widget.vote.ids; - final allNotes = await WarpApi.getNotes(aa.coin, aa.id); - for (var id in ids) { - final sn = allNotes.where((n) => n.id == id).firstOrNull; - if (sn != null) + for (var sn in widget.vote.notes) { notes.add(Note.fromShieldedNote(sn)); }; setState(() {}); @@ -180,8 +178,15 @@ class VoteNotesState extends State { } _next() { - final ids = notes.where((n) => n.selected).map((n) => n.id).toList(); - final vote = Vote(election: widget.vote.election, ids: ids); + List selectedNotes = []; + for (final pairs in + IterableZip([notes, widget.vote.notes])) { + final n1 = pairs[0] as Note; + final n2 = pairs[1] as ShieldedNoteT; + if (n1.selected) + selectedNotes.add(n2); + } + final vote = Vote(election: widget.vote.election, notes: selectedNotes); GoRouter.of(context).push('/more/vote/candidate', extra: vote); } } @@ -267,7 +272,7 @@ class VoteCandidateState extends State _ok() async { final election = widget.vote.election; - final ids = widget.vote.ids; + final ids = widget.vote.notes.map((n) => n.id).toList(); await load(() async { final vote = await WarpApi.vote( aa.coin, aa.id, ids, candidate, jsonEncode(election)); diff --git a/lib/pages/utils.dart b/lib/pages/utils.dart index c4c6b8a1..599ed5ed 100644 --- a/lib/pages/utils.dart +++ b/lib/pages/utils.dart @@ -435,8 +435,8 @@ class Note extends HasHeight { final confirmations = latestHeight?.let((h) => h - height + 1); return Note(id, height, confirmations, timestamp, value, orchard, excluded, selected); } - factory Note.fromShieldedNote(ShieldedNote n) => - Note(n.id, n.height, 0, toDateTime(n.timestamp), n.value / ZECUNIT, + factory Note.fromShieldedNote(ShieldedNoteT n) => + Note(n.id, n.height, 0, toDateTime(n.timestamp), n.value / ZECUNIT, n.orchard, n.excluded, false); Note(this.id, this.height, this.confirmations, this.timestamp, this.value, @@ -446,7 +446,7 @@ class Note extends HasHeight { Note(id, height, confirmations, timestamp, value, orchard, !excluded, selected); Note clone() => Note(id, height, confirmations, timestamp, value, orchard, excluded, selected); - + } @reflector diff --git a/lib/store2.dart b/lib/store2.dart index 9ed500d6..09aeecac 100644 --- a/lib/store2.dart +++ b/lib/store2.dart @@ -476,7 +476,7 @@ class Election with _$Election { class Vote with _$Vote { const factory Vote({ required Election election, - required List ids, + required List notes, int? candidate, }) = _Vote; } diff --git a/lib/store2.freezed.dart b/lib/store2.freezed.dart index 902b52da..978c9387 100644 --- a/lib/store2.freezed.dart +++ b/lib/store2.freezed.dart @@ -1668,7 +1668,7 @@ abstract class _Election implements Election { /// @nodoc mixin _$Vote { Election get election => throw _privateConstructorUsedError; - List get ids => throw _privateConstructorUsedError; + List get notes => throw _privateConstructorUsedError; int? get candidate => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -1680,7 +1680,7 @@ abstract class $VoteCopyWith<$Res> { factory $VoteCopyWith(Vote value, $Res Function(Vote) then) = _$VoteCopyWithImpl<$Res, Vote>; @useResult - $Res call({Election election, List ids, int? candidate}); + $Res call({Election election, List notes, int? candidate}); $ElectionCopyWith<$Res> get election; } @@ -1699,7 +1699,7 @@ class _$VoteCopyWithImpl<$Res, $Val extends Vote> @override $Res call({ Object? election = null, - Object? ids = null, + Object? notes = null, Object? candidate = freezed, }) { return _then(_value.copyWith( @@ -1707,10 +1707,10 @@ class _$VoteCopyWithImpl<$Res, $Val extends Vote> ? _value.election : election // ignore: cast_nullable_to_non_nullable as Election, - ids: null == ids - ? _value.ids - : ids // ignore: cast_nullable_to_non_nullable - as List, + notes: null == notes + ? _value.notes + : notes // ignore: cast_nullable_to_non_nullable + as List, candidate: freezed == candidate ? _value.candidate : candidate // ignore: cast_nullable_to_non_nullable @@ -1734,7 +1734,7 @@ abstract class _$$VoteImplCopyWith<$Res> implements $VoteCopyWith<$Res> { __$$VoteImplCopyWithImpl<$Res>; @override @useResult - $Res call({Election election, List ids, int? candidate}); + $Res call({Election election, List notes, int? candidate}); @override $ElectionCopyWith<$Res> get election; @@ -1751,7 +1751,7 @@ class __$$VoteImplCopyWithImpl<$Res> @override $Res call({ Object? election = null, - Object? ids = null, + Object? notes = null, Object? candidate = freezed, }) { return _then(_$VoteImpl( @@ -1759,10 +1759,10 @@ class __$$VoteImplCopyWithImpl<$Res> ? _value.election : election // ignore: cast_nullable_to_non_nullable as Election, - ids: null == ids - ? _value._ids - : ids // ignore: cast_nullable_to_non_nullable - as List, + notes: null == notes + ? _value._notes + : notes // ignore: cast_nullable_to_non_nullable + as List, candidate: freezed == candidate ? _value.candidate : candidate // ignore: cast_nullable_to_non_nullable @@ -1775,17 +1775,19 @@ class __$$VoteImplCopyWithImpl<$Res> class _$VoteImpl implements _Vote { const _$VoteImpl( - {required this.election, required final List ids, this.candidate}) - : _ids = ids; + {required this.election, + required final List notes, + this.candidate}) + : _notes = notes; @override final Election election; - final List _ids; + final List _notes; @override - List get ids { - if (_ids is EqualUnmodifiableListView) return _ids; + List get notes { + if (_notes is EqualUnmodifiableListView) return _notes; // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_ids); + return EqualUnmodifiableListView(_notes); } @override @@ -1793,7 +1795,7 @@ class _$VoteImpl implements _Vote { @override String toString() { - return 'Vote(election: $election, ids: $ids, candidate: $candidate)'; + return 'Vote(election: $election, notes: $notes, candidate: $candidate)'; } @override @@ -1803,14 +1805,14 @@ class _$VoteImpl implements _Vote { other is _$VoteImpl && (identical(other.election, election) || other.election == election) && - const DeepCollectionEquality().equals(other._ids, _ids) && + const DeepCollectionEquality().equals(other._notes, _notes) && (identical(other.candidate, candidate) || other.candidate == candidate)); } @override int get hashCode => Object.hash(runtimeType, election, - const DeepCollectionEquality().hash(_ids), candidate); + const DeepCollectionEquality().hash(_notes), candidate); @JsonKey(ignore: true) @override @@ -1822,13 +1824,13 @@ class _$VoteImpl implements _Vote { abstract class _Vote implements Vote { const factory _Vote( {required final Election election, - required final List ids, + required final List notes, final int? candidate}) = _$VoteImpl; @override Election get election; @override - List get ids; + List get notes; @override int? get candidate; @override diff --git a/native/zcash-sync b/native/zcash-sync index f6837f8d..72b92294 160000 --- a/native/zcash-sync +++ b/native/zcash-sync @@ -1 +1 @@ -Subproject commit f6837f8ddf3dc3893bdcf17202136847dcda3b5b +Subproject commit 72b92294acd5b88a1ae4a5680a92b6821d22e70b diff --git a/native/zcash-vote b/native/zcash-vote index fa134680..57ab7855 160000 --- a/native/zcash-vote +++ b/native/zcash-vote @@ -1 +1 @@ -Subproject commit fa134680460b5c6214eb05b35f93600c463010bd +Subproject commit 57ab7855948ec263069efa594f29fbeebff28b19 diff --git a/packages/warp_api_ffi/lib/warp_api.dart b/packages/warp_api_ffi/lib/warp_api.dart index 66379a02..79d4a089 100644 --- a/packages/warp_api_ffi/lib/warp_api.dart +++ b/packages/warp_api_ffi/lib/warp_api.dart @@ -573,9 +573,9 @@ class WarpApi { warp_api_lib.populate_vote_notes(coin, account, startHeight, endHeight); } - static List listVoteNotes(int coin, int account, int endHeight) { + static List listVoteNotes(int coin, int account, int endHeight) { final res = unwrapResultBytes(warp_api_lib.list_vote_notes(coin, account, endHeight)); - return IdList(res).unpack().ids!; + return ShieldedNoteVec(res).unpack().notes!; } static Future> vote( diff --git a/pubspec.yaml b/pubspec.yaml index c5ebec4f..6bd22ff7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.7.0+549 +version: 1.7.0+550 environment: sdk: ">=3.0.0 <4.0.0"