diff --git a/Cargo.toml b/Cargo.toml index 3e591d1..1fcf2aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,5 +19,5 @@ debug = false [patch.crates-io] #zcash_note_encryption = { path = "librustzcash/components/zcash_note_encryption" } -zcash_note_encryption = { git = "https://github.com/hhanh00/librustzcash.git", rev = "ad4a1c61fdaf04ac4fb884976ad175196e695264" } +zcash_note_encryption = { git = "https://github.com/hhanh00/librustzcash.git", rev = "7469d70261e8e72f2bbf3163704ddf8fd825b1aa" } jubjub = { git = "https://github.com/hhanh00/jubjub.git", rev = "4a3edf3d242f368b5aa418ec659d01f191127cf3" } diff --git a/idl/data.fbs b/idl/data.fbs index df52116..63bdc78 100644 --- a/idl/data.fbs +++ b/idl/data.fbs @@ -177,3 +177,47 @@ table Progress { trial_decryptions:uint64; downloaded:uint64; } + +table KeyPack { + t_addr:string; + t_key:string; + z_addr:string; + z_key:string; +} + +table Recipient { + address:string; + amount:uint64; + fee_included:bool; + reply_to:bool; + subject:string; + memo:string; + max_amount_per_note:uint64; +} + +table RecipientSummary { + amount:uint64; + address:string; +} + +table UnsignedTxSummary { + recipients:[RecipientSummary]; +} + +table TxOutput { + id:uint32; + address:string; + amount:uint64; + pool:uint8; +} + +table TxReport { + outputs:[TxOutput]; + transparent:uint64; + sapling:uint64; + orchard:uint64; + net_sapling:int64; + net_orchard:int64; + fee:uint64; + privacy_level:uint8; +} diff --git a/lib/accounts.dart b/lib/accounts.dart index 0322fbb..43af2d3 100644 --- a/lib/accounts.dart +++ b/lib/accounts.dart @@ -1,6 +1,5 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:warp_api/data_fb_generated.dart' ; -import 'package:warp_api/types.dart'; import 'coin/coins.dart'; import 'package:mobx/mobx.dart'; import 'db.dart'; diff --git a/lib/backup.dart b/lib/backup.dart index 7a04cab..3f0b5bc 100644 --- a/lib/backup.dart +++ b/lib/backup.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:warp_api/data_fb_generated.dart'; -import 'package:warp_api/types.dart'; import 'package:warp_api/warp_api.dart'; import 'main.dart'; diff --git a/lib/home.dart b/lib/home.dart index eb3599c..981be7a 100644 --- a/lib/home.dart +++ b/lib/home.dart @@ -9,7 +9,6 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:warp_api/data_fb_generated.dart'; -import 'package:warp_api/types.dart'; import 'package:warp_api/warp_api.dart'; import 'package:badges/badges.dart' as Badges; import 'package:path/path.dart' as p; diff --git a/lib/keytool.dart b/lib/keytool.dart index f2819a4..954b3ab 100644 --- a/lib/keytool.dart +++ b/lib/keytool.dart @@ -53,13 +53,13 @@ class KeyToolState extends State { ListTile(subtitle: Text('Transparent')), TextField( decoration: InputDecoration(labelText: 'Key'), - controller: TextEditingController(text: kp.t_key), + controller: TextEditingController(text: kp.tKey), minLines: 1, maxLines: 3, readOnly: true), TextField( decoration: InputDecoration(labelText: 'Address'), - controller: TextEditingController(text: kp.t_addr), + controller: TextEditingController(text: kp.tAddr), readOnly: true), ]) ), @@ -69,13 +69,13 @@ class KeyToolState extends State { ListTile(subtitle: Text('Shielded')), TextField( decoration: InputDecoration(labelText: 'Key'), - controller: TextEditingController(text: kp.z_key), + controller: TextEditingController(text: kp.zKey), minLines: 3, maxLines: 10, readOnly: true), TextField( decoration: InputDecoration(labelText: 'Address'), - controller: TextEditingController(text: kp.z_addr), + controller: TextEditingController(text: kp.zAddr), minLines: 1, maxLines: 3, readOnly: true), diff --git a/lib/multisend.dart b/lib/multisend.dart index f406625..459741b 100644 --- a/lib/multisend.dart +++ b/lib/multisend.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:warp_api/data_fb_generated.dart'; import 'store.dart'; -import 'package:warp_api/types.dart'; import 'main.dart'; import 'generated/l10n.dart'; @@ -27,7 +27,7 @@ class MultiPayState extends State { return Dismissible( key: UniqueKey(), child: ListTile( - title: Text(recipient.address), subtitle: Text("$amount")), + title: Text(recipient.address!), subtitle: Text("$amount")), onDismissed: (_) { _remove(index); }, diff --git a/lib/send.dart b/lib/send.dart index 7e99819..46b48d0 100644 --- a/lib/send.dart +++ b/lib/send.dart @@ -8,7 +8,6 @@ import 'package:warp_api/data_fb_generated.dart' hide Account; import 'accounts.dart'; import 'contact.dart'; import 'dualmoneyinput.dart'; -import 'package:warp_api/types.dart'; import 'package:warp_api/warp_api.dart'; import 'package:decimal/decimal.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; @@ -73,11 +72,11 @@ class SendState extends State { final draftRecipient = active.draftRecipient; if (draftRecipient != null) { - _addressController.text = draftRecipient.address; + _addressController.text = draftRecipient.address!; _initialAmount = draftRecipient.amount; - _memoController.text = draftRecipient.memo; - _replyTo = draftRecipient.reply_to; - _subjectController.text = draftRecipient.subject; + _memoController.text = draftRecipient.memo ?? ''; + _replyTo = draftRecipient.replyTo; + _subjectController.text = draftRecipient.subject ?? ''; _memoInitialized = true; } @@ -396,16 +395,16 @@ class SendState extends State { final feeIncluded = amountInput?.feeIncluded ?? false; final memo = _memoController.text; final subject = _subjectController.text; - final recipient = Recipient( - _address, - amount, - feeIncluded, - _replyTo, - subject, - memo, - 0, + final recipient = RecipientObjectBuilder( + address: _address, + amount: amount, + feeIncluded: feeIncluded, + replyTo: _replyTo, + subject: subject, + memo: memo, + maxAmountPerNote: 0, ); - return recipient; + return Recipient(recipient.toBytes()); } void _onSend() async { diff --git a/lib/store.dart b/lib/store.dart index f386fd1..84d0c53 100644 --- a/lib/store.dart +++ b/lib/store.dart @@ -13,7 +13,6 @@ import 'package:shared_preferences_ios/shared_preferences_ios.dart'; import 'package:warp_api/data_fb_generated.dart'; import 'coin/coins.dart'; import 'package:warp_api/warp_api.dart'; -import 'package:warp_api/types.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; import 'dart:convert' as convert; diff --git a/lib/txplan.dart b/lib/txplan.dart index 38225fa..6706bd9 100644 --- a/lib/txplan.dart +++ b/lib/txplan.dart @@ -4,7 +4,7 @@ import 'package:YWallet/main.dart'; import 'package:YWallet/settings.dart'; import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; -import 'package:warp_api/types.dart'; +import 'package:warp_api/data_fb_generated.dart'; import 'package:warp_api/warp_api.dart'; import 'generated/l10n.dart'; @@ -17,9 +17,7 @@ class TxPlanPage extends StatelessWidget { TxPlanPage(this.plan, this.report, this.signOnly); factory TxPlanPage.fromPlan(String plan, bool signOnly) { - final reportStr = WarpApi.transactionReport(active.coin, plan); - final json = jsonDecode(reportStr); - final report = TxReport.fromJson(json); + final report = WarpApi.transactionReport(active.coin, plan); return TxPlanPage(plan, report, signOnly); } @@ -29,14 +27,14 @@ class TxPlanPage extends StatelessWidget { final t = Theme.of(context); final supportsUA = active.coinDef.supportsUA; final theme = Theme.of(context); - final rows = report.outputs + final rows = report.outputs! .map((e) => DataRow(cells: [ - DataCell(Text('...${trailing(e.address, 12)}')), + DataCell(Text('...${trailing(e.address!, 12)}')), DataCell(Text('${poolToString(e.pool)}')), DataCell(Text('${amountToString(e.amount, 3)}')), ])) .toList(); - final invalidPrivacy = report.privacy_level < settings.minPrivacyLevel; + final invalidPrivacy = report.privacyLevel < settings.minPrivacyLevel; return Scaffold( appBar: AppBar(title: Text('Transaction Plan')), @@ -57,11 +55,11 @@ class TxPlanPage extends StatelessWidget { if (supportsUA) ListTile(title: Text('Orchard Input'), trailing: Text( amountToString(report.orchard, MAX_PRECISION))), ListTile(title: Text('Net Sapling Change'), trailing: Text( - amountToString(report.net_sapling, MAX_PRECISION))), + amountToString(report.netSapling, MAX_PRECISION))), if (supportsUA) ListTile(title: Text('Net Orchard Change'), trailing: Text( - amountToString(report.net_orchard, MAX_PRECISION))), + amountToString(report.netOrchard, MAX_PRECISION))), ListTile(title: Text('Fee'), trailing: Text(amountToString(report.fee, MAX_PRECISION))), - privacyToString(context, report.privacy_level)!, + privacyToString(context, report.privacyLevel)!, if (invalidPrivacy) Padding(padding: EdgeInsets.only(top: 8), child: Text(s.privacyLevelTooLow, style: t.textTheme.bodyLarge)), ButtonBar(children: [ diff --git a/librustzcash b/librustzcash index ad4a1c6..7469d70 160000 --- a/librustzcash +++ b/librustzcash @@ -1 +1 @@ -Subproject commit ad4a1c61fdaf04ac4fb884976ad175196e695264 +Subproject commit 7469d70261e8e72f2bbf3163704ddf8fd825b1aa diff --git a/native/zcash-params b/native/zcash-params index bdb7aa4..c43d03d 160000 --- a/native/zcash-params +++ b/native/zcash-params @@ -1 +1 @@ -Subproject commit bdb7aa490b32c204307c717f5dcea18358f7be3b +Subproject commit c43d03dda4a78172fe5283168510cd41ee8f1430 diff --git a/packages/warp_api_ffi/lib/data_fb_generated.dart b/packages/warp_api_ffi/lib/data_fb_generated.dart index 7357316..f4049a5 100644 --- a/packages/warp_api_ffi/lib/data_fb_generated.dart +++ b/packages/warp_api_ffi/lib/data_fb_generated.dart @@ -3857,3 +3857,895 @@ class ProgressObjectBuilder extends fb.ObjectBuilder { return fbBuilder.buffer; } } +class KeyPack { + KeyPack._(this._bc, this._bcOffset); + factory KeyPack(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _KeyPackReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + String? get tAddr => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 4); + String? get tKey => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 6); + String? get zAddr => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 8); + String? get zKey => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 10); + + @override + String toString() { + return 'KeyPack{tAddr: ${tAddr}, tKey: ${tKey}, zAddr: ${zAddr}, zKey: ${zKey}}'; + } + + KeyPackT unpack() => KeyPackT( + tAddr: tAddr, + tKey: tKey, + zAddr: zAddr, + zKey: zKey); + + static int pack(fb.Builder fbBuilder, KeyPackT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class KeyPackT implements fb.Packable { + String? tAddr; + String? tKey; + String? zAddr; + String? zKey; + + KeyPackT({ + this.tAddr, + this.tKey, + this.zAddr, + this.zKey}); + + @override + int pack(fb.Builder fbBuilder) { + final int? tAddrOffset = tAddr == null ? null + : fbBuilder.writeString(tAddr!); + final int? tKeyOffset = tKey == null ? null + : fbBuilder.writeString(tKey!); + final int? zAddrOffset = zAddr == null ? null + : fbBuilder.writeString(zAddr!); + final int? zKeyOffset = zKey == null ? null + : fbBuilder.writeString(zKey!); + fbBuilder.startTable(4); + fbBuilder.addOffset(0, tAddrOffset); + fbBuilder.addOffset(1, tKeyOffset); + fbBuilder.addOffset(2, zAddrOffset); + fbBuilder.addOffset(3, zKeyOffset); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'KeyPackT{tAddr: ${tAddr}, tKey: ${tKey}, zAddr: ${zAddr}, zKey: ${zKey}}'; + } +} + +class _KeyPackReader extends fb.TableReader { + const _KeyPackReader(); + + @override + KeyPack createObject(fb.BufferContext bc, int offset) => + KeyPack._(bc, offset); +} + +class KeyPackBuilder { + KeyPackBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(4); + } + + int addTAddrOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + int addTKeyOffset(int? offset) { + fbBuilder.addOffset(1, offset); + return fbBuilder.offset; + } + int addZAddrOffset(int? offset) { + fbBuilder.addOffset(2, offset); + return fbBuilder.offset; + } + int addZKeyOffset(int? offset) { + fbBuilder.addOffset(3, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class KeyPackObjectBuilder extends fb.ObjectBuilder { + final String? _tAddr; + final String? _tKey; + final String? _zAddr; + final String? _zKey; + + KeyPackObjectBuilder({ + String? tAddr, + String? tKey, + String? zAddr, + String? zKey, + }) + : _tAddr = tAddr, + _tKey = tKey, + _zAddr = zAddr, + _zKey = zKey; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? tAddrOffset = _tAddr == null ? null + : fbBuilder.writeString(_tAddr!); + final int? tKeyOffset = _tKey == null ? null + : fbBuilder.writeString(_tKey!); + final int? zAddrOffset = _zAddr == null ? null + : fbBuilder.writeString(_zAddr!); + final int? zKeyOffset = _zKey == null ? null + : fbBuilder.writeString(_zKey!); + fbBuilder.startTable(4); + fbBuilder.addOffset(0, tAddrOffset); + fbBuilder.addOffset(1, tKeyOffset); + fbBuilder.addOffset(2, zAddrOffset); + fbBuilder.addOffset(3, zKeyOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} +class Recipient { + Recipient._(this._bc, this._bcOffset); + factory Recipient(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _RecipientReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + String? get address => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 4); + int get amount => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 6, 0); + bool get feeIncluded => const fb.BoolReader().vTableGet(_bc, _bcOffset, 8, false); + bool get replyTo => const fb.BoolReader().vTableGet(_bc, _bcOffset, 10, false); + String? get subject => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 12); + String? get memo => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 14); + int get maxAmountPerNote => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 16, 0); + + @override + String toString() { + return 'Recipient{address: ${address}, amount: ${amount}, feeIncluded: ${feeIncluded}, replyTo: ${replyTo}, subject: ${subject}, memo: ${memo}, maxAmountPerNote: ${maxAmountPerNote}}'; + } + + RecipientT unpack() => RecipientT( + address: address, + amount: amount, + feeIncluded: feeIncluded, + replyTo: replyTo, + subject: subject, + memo: memo, + maxAmountPerNote: maxAmountPerNote); + + static int pack(fb.Builder fbBuilder, RecipientT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class RecipientT implements fb.Packable { + String? address; + int amount; + bool feeIncluded; + bool replyTo; + String? subject; + String? memo; + int maxAmountPerNote; + + RecipientT({ + this.address, + this.amount = 0, + this.feeIncluded = false, + this.replyTo = false, + this.subject, + this.memo, + this.maxAmountPerNote = 0}); + + @override + int pack(fb.Builder fbBuilder) { + final int? addressOffset = address == null ? null + : fbBuilder.writeString(address!); + final int? subjectOffset = subject == null ? null + : fbBuilder.writeString(subject!); + final int? memoOffset = memo == null ? null + : fbBuilder.writeString(memo!); + fbBuilder.startTable(7); + fbBuilder.addOffset(0, addressOffset); + fbBuilder.addUint64(1, amount); + fbBuilder.addBool(2, feeIncluded); + fbBuilder.addBool(3, replyTo); + fbBuilder.addOffset(4, subjectOffset); + fbBuilder.addOffset(5, memoOffset); + fbBuilder.addUint64(6, maxAmountPerNote); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'RecipientT{address: ${address}, amount: ${amount}, feeIncluded: ${feeIncluded}, replyTo: ${replyTo}, subject: ${subject}, memo: ${memo}, maxAmountPerNote: ${maxAmountPerNote}}'; + } +} + +class _RecipientReader extends fb.TableReader { + const _RecipientReader(); + + @override + Recipient createObject(fb.BufferContext bc, int offset) => + Recipient._(bc, offset); +} + +class RecipientBuilder { + RecipientBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(7); + } + + int addAddressOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + int addAmount(int? amount) { + fbBuilder.addUint64(1, amount); + return fbBuilder.offset; + } + int addFeeIncluded(bool? feeIncluded) { + fbBuilder.addBool(2, feeIncluded); + return fbBuilder.offset; + } + int addReplyTo(bool? replyTo) { + fbBuilder.addBool(3, replyTo); + return fbBuilder.offset; + } + int addSubjectOffset(int? offset) { + fbBuilder.addOffset(4, offset); + return fbBuilder.offset; + } + int addMemoOffset(int? offset) { + fbBuilder.addOffset(5, offset); + return fbBuilder.offset; + } + int addMaxAmountPerNote(int? maxAmountPerNote) { + fbBuilder.addUint64(6, maxAmountPerNote); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class RecipientObjectBuilder extends fb.ObjectBuilder { + final String? _address; + final int? _amount; + final bool? _feeIncluded; + final bool? _replyTo; + final String? _subject; + final String? _memo; + final int? _maxAmountPerNote; + + RecipientObjectBuilder({ + String? address, + int? amount, + bool? feeIncluded, + bool? replyTo, + String? subject, + String? memo, + int? maxAmountPerNote, + }) + : _address = address, + _amount = amount, + _feeIncluded = feeIncluded, + _replyTo = replyTo, + _subject = subject, + _memo = memo, + _maxAmountPerNote = maxAmountPerNote; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? addressOffset = _address == null ? null + : fbBuilder.writeString(_address!); + final int? subjectOffset = _subject == null ? null + : fbBuilder.writeString(_subject!); + final int? memoOffset = _memo == null ? null + : fbBuilder.writeString(_memo!); + fbBuilder.startTable(7); + fbBuilder.addOffset(0, addressOffset); + fbBuilder.addUint64(1, _amount); + fbBuilder.addBool(2, _feeIncluded); + fbBuilder.addBool(3, _replyTo); + fbBuilder.addOffset(4, subjectOffset); + fbBuilder.addOffset(5, memoOffset); + fbBuilder.addUint64(6, _maxAmountPerNote); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} +class RecipientSummary { + RecipientSummary._(this._bc, this._bcOffset); + factory RecipientSummary(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _RecipientSummaryReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get amount => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 4, 0); + String? get address => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 6); + + @override + String toString() { + return 'RecipientSummary{amount: ${amount}, address: ${address}}'; + } + + RecipientSummaryT unpack() => RecipientSummaryT( + amount: amount, + address: address); + + static int pack(fb.Builder fbBuilder, RecipientSummaryT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class RecipientSummaryT implements fb.Packable { + int amount; + String? address; + + RecipientSummaryT({ + this.amount = 0, + this.address}); + + @override + int pack(fb.Builder fbBuilder) { + final int? addressOffset = address == null ? null + : fbBuilder.writeString(address!); + fbBuilder.startTable(2); + fbBuilder.addUint64(0, amount); + fbBuilder.addOffset(1, addressOffset); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'RecipientSummaryT{amount: ${amount}, address: ${address}}'; + } +} + +class _RecipientSummaryReader extends fb.TableReader { + const _RecipientSummaryReader(); + + @override + RecipientSummary createObject(fb.BufferContext bc, int offset) => + RecipientSummary._(bc, offset); +} + +class RecipientSummaryBuilder { + RecipientSummaryBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(2); + } + + int addAmount(int? amount) { + fbBuilder.addUint64(0, amount); + return fbBuilder.offset; + } + int addAddressOffset(int? offset) { + fbBuilder.addOffset(1, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class RecipientSummaryObjectBuilder extends fb.ObjectBuilder { + final int? _amount; + final String? _address; + + RecipientSummaryObjectBuilder({ + int? amount, + String? address, + }) + : _amount = amount, + _address = address; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? addressOffset = _address == null ? null + : fbBuilder.writeString(_address!); + fbBuilder.startTable(2); + fbBuilder.addUint64(0, _amount); + fbBuilder.addOffset(1, addressOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} +class UnsignedTxSummary { + UnsignedTxSummary._(this._bc, this._bcOffset); + factory UnsignedTxSummary(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _UnsignedTxSummaryReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + List? get recipients => const fb.ListReader(RecipientSummary.reader).vTableGetNullable(_bc, _bcOffset, 4); + + @override + String toString() { + return 'UnsignedTxSummary{recipients: ${recipients}}'; + } + + UnsignedTxSummaryT unpack() => UnsignedTxSummaryT( + recipients: recipients?.map((e) => e.unpack()).toList()); + + static int pack(fb.Builder fbBuilder, UnsignedTxSummaryT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class UnsignedTxSummaryT implements fb.Packable { + List? recipients; + + UnsignedTxSummaryT({ + this.recipients}); + + @override + int pack(fb.Builder fbBuilder) { + final int? recipientsOffset = recipients == null ? null + : fbBuilder.writeList(recipients!.map((b) => b.pack(fbBuilder)).toList()); + fbBuilder.startTable(1); + fbBuilder.addOffset(0, recipientsOffset); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'UnsignedTxSummaryT{recipients: ${recipients}}'; + } +} + +class _UnsignedTxSummaryReader extends fb.TableReader { + const _UnsignedTxSummaryReader(); + + @override + UnsignedTxSummary createObject(fb.BufferContext bc, int offset) => + UnsignedTxSummary._(bc, offset); +} + +class UnsignedTxSummaryBuilder { + UnsignedTxSummaryBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(1); + } + + int addRecipientsOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class UnsignedTxSummaryObjectBuilder extends fb.ObjectBuilder { + final List? _recipients; + + UnsignedTxSummaryObjectBuilder({ + List? recipients, + }) + : _recipients = recipients; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? recipientsOffset = _recipients == null ? null + : fbBuilder.writeList(_recipients!.map((b) => b.getOrCreateOffset(fbBuilder)).toList()); + fbBuilder.startTable(1); + fbBuilder.addOffset(0, recipientsOffset); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} +class TxOutput { + TxOutput._(this._bc, this._bcOffset); + factory TxOutput(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _TxOutputReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + int get id => const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 4, 0); + String? get address => const fb.StringReader().vTableGetNullable(_bc, _bcOffset, 6); + int get amount => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 8, 0); + int get pool => const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 10, 0); + + @override + String toString() { + return 'TxOutput{id: ${id}, address: ${address}, amount: ${amount}, pool: ${pool}}'; + } + + TxOutputT unpack() => TxOutputT( + id: id, + address: address, + amount: amount, + pool: pool); + + static int pack(fb.Builder fbBuilder, TxOutputT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class TxOutputT implements fb.Packable { + int id; + String? address; + int amount; + int pool; + + TxOutputT({ + this.id = 0, + this.address, + this.amount = 0, + this.pool = 0}); + + @override + int pack(fb.Builder fbBuilder) { + final int? addressOffset = address == null ? null + : fbBuilder.writeString(address!); + fbBuilder.startTable(4); + fbBuilder.addUint32(0, id); + fbBuilder.addOffset(1, addressOffset); + fbBuilder.addUint64(2, amount); + fbBuilder.addUint8(3, pool); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'TxOutputT{id: ${id}, address: ${address}, amount: ${amount}, pool: ${pool}}'; + } +} + +class _TxOutputReader extends fb.TableReader { + const _TxOutputReader(); + + @override + TxOutput createObject(fb.BufferContext bc, int offset) => + TxOutput._(bc, offset); +} + +class TxOutputBuilder { + TxOutputBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(4); + } + + int addId(int? id) { + fbBuilder.addUint32(0, id); + return fbBuilder.offset; + } + int addAddressOffset(int? offset) { + fbBuilder.addOffset(1, offset); + return fbBuilder.offset; + } + int addAmount(int? amount) { + fbBuilder.addUint64(2, amount); + return fbBuilder.offset; + } + int addPool(int? pool) { + fbBuilder.addUint8(3, pool); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class TxOutputObjectBuilder extends fb.ObjectBuilder { + final int? _id; + final String? _address; + final int? _amount; + final int? _pool; + + TxOutputObjectBuilder({ + int? id, + String? address, + int? amount, + int? pool, + }) + : _id = id, + _address = address, + _amount = amount, + _pool = pool; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? addressOffset = _address == null ? null + : fbBuilder.writeString(_address!); + fbBuilder.startTable(4); + fbBuilder.addUint32(0, _id); + fbBuilder.addOffset(1, addressOffset); + fbBuilder.addUint64(2, _amount); + fbBuilder.addUint8(3, _pool); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} +class TxReport { + TxReport._(this._bc, this._bcOffset); + factory TxReport(List bytes) { + final rootRef = fb.BufferContext.fromBytes(bytes); + return reader.read(rootRef, 0); + } + + static const fb.Reader reader = _TxReportReader(); + + final fb.BufferContext _bc; + final int _bcOffset; + + List? get outputs => const fb.ListReader(TxOutput.reader).vTableGetNullable(_bc, _bcOffset, 4); + int get transparent => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 6, 0); + int get sapling => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 8, 0); + int get orchard => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 10, 0); + int get netSapling => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 12, 0); + int get netOrchard => const fb.Int64Reader().vTableGet(_bc, _bcOffset, 14, 0); + int get fee => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 16, 0); + int get privacyLevel => const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 18, 0); + + @override + String toString() { + return 'TxReport{outputs: ${outputs}, transparent: ${transparent}, sapling: ${sapling}, orchard: ${orchard}, netSapling: ${netSapling}, netOrchard: ${netOrchard}, fee: ${fee}, privacyLevel: ${privacyLevel}}'; + } + + TxReportT unpack() => TxReportT( + outputs: outputs?.map((e) => e.unpack()).toList(), + transparent: transparent, + sapling: sapling, + orchard: orchard, + netSapling: netSapling, + netOrchard: netOrchard, + fee: fee, + privacyLevel: privacyLevel); + + static int pack(fb.Builder fbBuilder, TxReportT? object) { + if (object == null) return 0; + return object.pack(fbBuilder); + } +} + +class TxReportT implements fb.Packable { + List? outputs; + int transparent; + int sapling; + int orchard; + int netSapling; + int netOrchard; + int fee; + int privacyLevel; + + TxReportT({ + this.outputs, + this.transparent = 0, + this.sapling = 0, + this.orchard = 0, + this.netSapling = 0, + this.netOrchard = 0, + this.fee = 0, + this.privacyLevel = 0}); + + @override + int pack(fb.Builder fbBuilder) { + final int? outputsOffset = outputs == null ? null + : fbBuilder.writeList(outputs!.map((b) => b.pack(fbBuilder)).toList()); + fbBuilder.startTable(8); + fbBuilder.addOffset(0, outputsOffset); + fbBuilder.addUint64(1, transparent); + fbBuilder.addUint64(2, sapling); + fbBuilder.addUint64(3, orchard); + fbBuilder.addInt64(4, netSapling); + fbBuilder.addInt64(5, netOrchard); + fbBuilder.addUint64(6, fee); + fbBuilder.addUint8(7, privacyLevel); + return fbBuilder.endTable(); + } + + @override + String toString() { + return 'TxReportT{outputs: ${outputs}, transparent: ${transparent}, sapling: ${sapling}, orchard: ${orchard}, netSapling: ${netSapling}, netOrchard: ${netOrchard}, fee: ${fee}, privacyLevel: ${privacyLevel}}'; + } +} + +class _TxReportReader extends fb.TableReader { + const _TxReportReader(); + + @override + TxReport createObject(fb.BufferContext bc, int offset) => + TxReport._(bc, offset); +} + +class TxReportBuilder { + TxReportBuilder(this.fbBuilder); + + final fb.Builder fbBuilder; + + void begin() { + fbBuilder.startTable(8); + } + + int addOutputsOffset(int? offset) { + fbBuilder.addOffset(0, offset); + return fbBuilder.offset; + } + int addTransparent(int? transparent) { + fbBuilder.addUint64(1, transparent); + return fbBuilder.offset; + } + int addSapling(int? sapling) { + fbBuilder.addUint64(2, sapling); + return fbBuilder.offset; + } + int addOrchard(int? orchard) { + fbBuilder.addUint64(3, orchard); + return fbBuilder.offset; + } + int addNetSapling(int? netSapling) { + fbBuilder.addInt64(4, netSapling); + return fbBuilder.offset; + } + int addNetOrchard(int? netOrchard) { + fbBuilder.addInt64(5, netOrchard); + return fbBuilder.offset; + } + int addFee(int? fee) { + fbBuilder.addUint64(6, fee); + return fbBuilder.offset; + } + int addPrivacyLevel(int? privacyLevel) { + fbBuilder.addUint8(7, privacyLevel); + return fbBuilder.offset; + } + + int finish() { + return fbBuilder.endTable(); + } +} + +class TxReportObjectBuilder extends fb.ObjectBuilder { + final List? _outputs; + final int? _transparent; + final int? _sapling; + final int? _orchard; + final int? _netSapling; + final int? _netOrchard; + final int? _fee; + final int? _privacyLevel; + + TxReportObjectBuilder({ + List? outputs, + int? transparent, + int? sapling, + int? orchard, + int? netSapling, + int? netOrchard, + int? fee, + int? privacyLevel, + }) + : _outputs = outputs, + _transparent = transparent, + _sapling = sapling, + _orchard = orchard, + _netSapling = netSapling, + _netOrchard = netOrchard, + _fee = fee, + _privacyLevel = privacyLevel; + + /// Finish building, and store into the [fbBuilder]. + @override + int finish(fb.Builder fbBuilder) { + final int? outputsOffset = _outputs == null ? null + : fbBuilder.writeList(_outputs!.map((b) => b.getOrCreateOffset(fbBuilder)).toList()); + fbBuilder.startTable(8); + fbBuilder.addOffset(0, outputsOffset); + fbBuilder.addUint64(1, _transparent); + fbBuilder.addUint64(2, _sapling); + fbBuilder.addUint64(3, _orchard); + fbBuilder.addInt64(4, _netSapling); + fbBuilder.addInt64(5, _netOrchard); + fbBuilder.addUint64(6, _fee); + fbBuilder.addUint8(7, _privacyLevel); + return fbBuilder.endTable(); + } + + /// Convenience method to serialize to byte list. + @override + Uint8List toBytes([String? fileIdentifier]) { + final fbBuilder = fb.Builder(deduplicateTables: false); + fbBuilder.finish(finish(fbBuilder), fileIdentifier); + return fbBuilder.buffer; + } +} diff --git a/packages/warp_api_ffi/lib/types.dart b/packages/warp_api_ffi/lib/types.dart deleted file mode 100644 index 1a8f90c..0000000 --- a/packages/warp_api_ffi/lib/types.dart +++ /dev/null @@ -1,100 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'types.g.dart'; - -@JsonSerializable() -class Recipient { - // ignore: non_constant_identifier_names - final String address; - final int amount; - final bool fee_included; - // ignore: non_constant_identifier_names - final bool reply_to; - final String subject; - final String memo; - // ignore: non_constant_identifier_names - final int max_amount_per_note; - - Recipient(this.address, this.amount, this.fee_included, this.reply_to, this.subject, this.memo, this.max_amount_per_note); - - factory Recipient.fromJson(Map json) => - _$RecipientFromJson(json); - - Map toJson() => _$RecipientToJson(this); -} - -@JsonSerializable() -class UnsignedTxSummary { - final List recipients; - - UnsignedTxSummary(this.recipients); - - factory UnsignedTxSummary.fromJson(Map json) => - _$UnsignedTxSummaryFromJson(json); - - Map toJson() => _$UnsignedTxSummaryToJson(this); -} - -@JsonSerializable() -class RecipientSummary { - final int amount; - final String address; - - RecipientSummary(this.amount, this.address); - - factory RecipientSummary.fromJson(Map json) => - _$RecipientSummaryFromJson(json); - - Map toJson() => _$RecipientSummaryToJson(this); -} - -@JsonSerializable() -class KeyPack { - final String t_addr; - final String t_key; - final String z_addr; - final String z_key; - - KeyPack(this.t_addr, this.t_key, this.z_addr, this.z_key); - - factory KeyPack.fromJson(Map json) => - _$KeyPackFromJson(json); - - Map toJson() => _$KeyPackToJson(this); -} - -@JsonSerializable() -class TxOutput { - final int id; - final String address; - final int amount; - final int pool; - - TxOutput(this.id, this.address, this.amount, this.pool); - - factory TxOutput.fromJson(Map json) => - _$TxOutputFromJson(json); - - Map toJson() => _$TxOutputToJson(this); -} - -@JsonSerializable() -class TxReport { - final List outputs; - final int transparent; - final int sapling; - final int orchard; - final int net_sapling; - final int net_orchard; - final int fee; - final int privacy_level; - - TxReport(this.outputs, this.transparent, this.sapling, - this.orchard, this.net_sapling, this.net_orchard, - this.fee, this.privacy_level); - - factory TxReport.fromJson(Map json) => - _$TxReportFromJson(json); - - Map toJson() => _$TxReportToJson(this); -} diff --git a/packages/warp_api_ffi/lib/warp_api.dart b/packages/warp_api_ffi/lib/warp_api.dart index d521fe2..f680c3d 100644 --- a/packages/warp_api_ffi/lib/warp_api.dart +++ b/packages/warp_api_ffi/lib/warp_api.dart @@ -4,13 +4,11 @@ import 'dart:ffi'; import 'dart:io'; import 'dart:isolate'; -import 'package:flat_buffers/flat_buffers.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:ffi/ffi.dart'; import 'warp_api_generated.dart'; import 'data_fb_generated.dart'; -import 'types.dart'; typedef report_callback = Void Function(Int32); @@ -263,9 +261,10 @@ class WarpApi { }, null); } - static String transactionReport(int coin, String plan) { - final report = warp_api_lib.transaction_report(coin, plan.toNativeUtf8().cast()); - return unwrapResultString(report); + static TxReport transactionReport(int coin, String plan) { + final data = unwrapResultBytes(warp_api_lib.transaction_report(coin, toNative(plan))); + final report = TxReport(data); + return report; } static Future signAndBroadcast (int coin, int account, String plan) async { @@ -421,15 +420,14 @@ class WarpApi { static KeyPack deriveZip32(int coin, int idAccount, int accountIndex, int externalIndex, int? addressIndex) { - final res = unwrapResultString(warp_api_lib.derive_zip32( + final res = unwrapResultBytes(warp_api_lib.derive_zip32( coin, idAccount, accountIndex, externalIndex, addressIndex != null ? 1 : 0, addressIndex ?? 0)); - final jsonMap = jsonDecode(res); - final kp = KeyPack.fromJson(jsonMap); + final kp = KeyPack(res); return kp; } diff --git a/packages/warp_api_ffi/lib/warp_api_generated.dart b/packages/warp_api_ffi/lib/warp_api_generated.dart index 17d70f2..2e8753d 100644 --- a/packages/warp_api_ffi/lib/warp_api_generated.dart +++ b/packages/warp_api_ffi/lib/warp_api_generated.dart @@ -546,7 +546,7 @@ class NativeLibrary { late final _dart_prepare_multi_payment _prepare_multi_payment = _prepare_multi_payment_ptr.asFunction<_dart_prepare_multi_payment>(); - CResult_____c_char transaction_report( + CResult______u8 transaction_report( int coin, ffi.Pointer plan, ) { @@ -937,7 +937,7 @@ class NativeLibrary { late final _dart_import_from_zwl _import_from_zwl = _import_from_zwl_ptr.asFunction<_dart_import_from_zwl>(); - CResult_____c_char derive_zip32( + CResult______u8 derive_zip32( int coin, int id_account, int account, @@ -1551,6 +1551,34 @@ const int Progress_VT_TRIAL_DECRYPTIONS = 6; const int Progress_VT_DOWNLOADED = 8; +const int KeyPack_VT_T_ADDR = 4; + +const int KeyPack_VT_T_KEY = 6; + +const int KeyPack_VT_Z_ADDR = 8; + +const int KeyPack_VT_Z_KEY = 10; + +const int Recipient_VT_REPLY_TO = 10; + +const int Recipient_VT_MAX_AMOUNT_PER_NOTE = 16; + +const int UnsignedTxSummary_VT_RECIPIENTS = 4; + +const int TxOutput_VT_POOL = 10; + +const int TxReport_VT_OUTPUTS = 4; + +const int TxReport_VT_TRANSPARENT = 6; + +const int TxReport_VT_NET_SAPLING = 12; + +const int TxReport_VT_NET_ORCHARD = 14; + +const int TxReport_VT_FEE = 16; + +const int TxReport_VT_PRIVACY_LEVEL = 18; + typedef _c_dummy_export = ffi.Void Function(); typedef _dart_dummy_export = void Function(); @@ -1897,12 +1925,12 @@ typedef _dart_prepare_multi_payment = CResult_____c_char Function( int anchor_offset, ); -typedef _c_transaction_report = CResult_____c_char Function( +typedef _c_transaction_report = CResult______u8 Function( ffi.Uint8 coin, ffi.Pointer plan, ); -typedef _dart_transaction_report = CResult_____c_char Function( +typedef _dart_transaction_report = CResult______u8 Function( int coin, ffi.Pointer plan, ); @@ -2151,7 +2179,7 @@ typedef _dart_import_from_zwl = void Function( ffi.Pointer data, ); -typedef _c_derive_zip32 = CResult_____c_char Function( +typedef _c_derive_zip32 = CResult______u8 Function( ffi.Uint8 coin, ffi.Uint32 id_account, ffi.Uint32 account, @@ -2160,7 +2188,7 @@ typedef _c_derive_zip32 = CResult_____c_char Function( ffi.Uint32 address, ); -typedef _dart_derive_zip32 = CResult_____c_char Function( +typedef _dart_derive_zip32 = CResult______u8 Function( int coin, int id_account, int account, diff --git a/pubspec.yaml b/pubspec.yaml index aaa571f..f94bef5 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.3.6+400 +version: 1.3.6+401 environment: sdk: ">=2.12.0 <3.0.0"