-
Notifications
You must be signed in to change notification settings - Fork 116
Epicbox Cancellation Requests & Multi-Party Reflection [DO NOT MERGE] #1429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: staging
Are you sure you want to change the base?
Changes from all commits
0e6ba24
b254068
62874c4
da43da7
b23e9c4
d2f4b76
120497b
a8a7776
fae8ad4
0fdb218
583cd19
eacd7e2
b5ab399
37d8f28
caa9e55
96b3ec3
df6c9e6
75c5b76
e0036c2
502fa2a
5d7515d
642f699
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,10 @@ | ||
| [submodule "crypto_plugins/flutter_libepiccash"] | ||
| path = crypto_plugins/flutter_libepiccash | ||
| url = https://github.com/cypherstack/flutter_libepiccash.git | ||
| [submodule "crypto_plugins/frostdart"] | ||
| path = crypto_plugins/frostdart | ||
| url = https://github.com/cypherstack/frostdart | ||
| [submodule "crypto_plugins/flutter_libmwc"] | ||
| path = crypto_plugins/flutter_libmwc | ||
| url = https://github.com/cypherstack/flutter_libmwc | ||
| [submodule "crypto_plugins/flutter_libepiccash"] | ||
| path = crypto_plugins/flutter_libepiccash | ||
| url = https://github.com/who-biz/flutter_libepiccash.git | ||
| branch = ebox-cancel-tx |
| +8 −1 | ios/Classes/FlutterLibepiccashPlugin.h | |
| +8 −2 | ios/Classes/SwiftFlutterLibepiccashPlugin.swift | |
| +133 −169 | lib/epic_cash.dart | |
| +56 −10 | lib/epic_wallet.dart | |
| +47 −15 | lib/lib.dart | |
| +5 −0 | lib/models/transaction.dart | |
| +22 −1 | lib/src/epic_task.dart | |
| +8 −4 | lib/src/epic_worker.dart | |
| +12 −5 | macos/Classes/FlutterLibepiccashPlugin.h | |
| +8 −1 | macos/Classes/FlutterLibepiccashPlugin.swift | |
| +31 −43 | rust/Cargo.lock | |
| +10 −14 | rust/Cargo.toml | |
| +380 −465 | rust/src/ffi.rs | |
| +4 −4 | rust/src/lib.rs | |
| +39 −33 | rust/src/listener.rs | |
| +6 −24 | rust/src/mnemonic.rs | |
| +185 −18 | rust/src/wallet.rs | |
| +7 −2 | rust/target/epic_cash_wallet.h | |
| +1 −1 | scripts/macos/download.sh |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,45 +44,46 @@ class AddressUtils { | |
| static Map<String, String> _parseUri(String uri) { | ||
| final Map<String, String> result = {}; | ||
| try { | ||
| final u = Uri.parse(uri); | ||
| if (u.hasScheme) { | ||
| result["scheme"] = u.scheme.toLowerCase(); | ||
| final Uri parsedUri = Uri.parse(uri); | ||
|
|
||
| if (parsedUri.hasScheme) { | ||
| final String scheme = parsedUri.scheme.toLowerCase(); | ||
| result["scheme"] = scheme; | ||
|
|
||
| // Handle different URI formats. | ||
| if (result["scheme"] == "bitcoin" || | ||
| result["scheme"] == "bitcoincash") { | ||
| result["address"] = u.path; | ||
| result["address"] = parsedUri.path; | ||
| } else if (result["scheme"] == "monero") { | ||
| // Monero addresses can contain '?' which Uri.parse interprets as query start. | ||
| final addressEnd = uri.indexOf( | ||
| '?', | ||
| 7, | ||
| ); // 7 is the length of "monero:". | ||
| if (addressEnd != -1) { | ||
| result["address"] = uri.substring(7, addressEnd); | ||
| } else { | ||
| result["address"] = uri.substring(7); | ||
| } | ||
| final int addressEnd = uri.indexOf( | ||
| "?", | ||
| 7, // 7 is the length of "monero:". | ||
| ); | ||
| } else { | ||
| // Default case, treat path as address. | ||
| result["address"] = u.path; | ||
| result["address"] = parsedUri.path; | ||
| } | ||
| } else { | ||
| // Plain address, including an Epicbox/Grinbox address containing '@'. | ||
| result["address"] = parsedUri.path; | ||
| } | ||
|
|
||
| // Parse query parameters. | ||
| result.addAll(_parseQueryParameters(u.queryParameters)); | ||
| // Parse query parameters. | ||
| result.addAll(_parseQueryParameters(parsedUri.queryParameters)); | ||
|
|
||
| // Handle Monero-specific fragment (tx_description). | ||
| if (u.fragment.isNotEmpty && result["scheme"] == "monero") { | ||
| result["tx_description"] = Uri.decodeComponent(u.fragment); | ||
| } | ||
| // Handle Monero-specific fragment (tx_description). | ||
| if (parsedUri.fragment.isNotEmpty && result["scheme"] == "monero") { | ||
| result["tx_description"] = Uri.decodeComponent(parsedUri.fragment); | ||
| } | ||
| } catch (e, s) { | ||
| Logging.instance.d( | ||
| "Exception caught in parseUri($uri): $e", | ||
| "Exception caught in _parseUri($uri): $e", | ||
| error: e, | ||
| stackTrace: s, | ||
| ); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
|
|
@@ -137,6 +138,7 @@ class AddressUtils { | |
| static PaymentUriData? parsePaymentUri(String uri, {Logging? logging}) { | ||
| // hacky check its not just a bcash, ecash, or xel address | ||
| final parts = uri.split(":"); | ||
|
|
||
| if (parts.length == 2) { | ||
| if ([ | ||
| "xel", | ||
|
|
@@ -153,20 +155,25 @@ class AddressUtils { | |
| final Map<String, String> parsedData = _parseUri(uri); | ||
|
|
||
| // Normalize the URI scheme. | ||
| final String scheme = parsedData['scheme'] ?? ''; | ||
| parsedData.remove('scheme'); | ||
| final String scheme = parsedData["scheme"] ?? ""; | ||
| parsedData.remove("scheme"); | ||
|
|
||
| // Filter out unrecognized parameters. | ||
| final filteredParams = _filterParams(parsedData); | ||
| final String? address = parsedData["address"]; | ||
|
|
||
| if (address == null || address.trim().isEmpty) { | ||
| return null; | ||
| } | ||
|
|
||
| final Map<String, String> filteredParams = _filterParams(parsedData); | ||
|
|
||
| return PaymentUriData( | ||
| scheme: scheme, | ||
| address: parsedData['address']!.trim(), | ||
| amount: filteredParams['amount'] ?? filteredParams['tx_amount'], | ||
| label: filteredParams['label'] ?? filteredParams['recipient_name'], | ||
| message: filteredParams['message'] ?? filteredParams['tx_description'], | ||
| paymentId: filteredParams['tx_payment_id'], | ||
| // Specific to Monero | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1.) check that the |
||
| address: address.trim(), | ||
| amount: filteredParams["amount"] ?? filteredParams["tx_amount"], | ||
| label: filteredParams["label"] ?? filteredParams["recipient_name"], | ||
| message: filteredParams["message"] ?? filteredParams["tx_description"], | ||
| paymentId: filteredParams["tx_payment_id"], | ||
| additionalParams: filteredParams, | ||
| ); | ||
| } catch (e, s) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -138,9 +138,12 @@ class EpiccashWallet extends Bip39Wallet { | |
| throw Exception('Wallet not initialized'); | ||
| } | ||
|
|
||
| final result = await libEpic.cancelTransaction( | ||
| final epicboxConfig = await getEpicBoxConfig(); | ||
| final result = await libEpic.cancelEpicboxTransaction( | ||
| wallet: _wallet!, | ||
| transactionId: txSlateId, | ||
| methodIsEpicbox: true, | ||
| epicboxConfig: epicboxConfig.toString(), | ||
| txSlateId: txSlateId, | ||
| ); | ||
| Logging.instance.d("cancel $txSlateId result: $result"); | ||
| return result; | ||
|
|
@@ -1386,10 +1389,22 @@ class EpiccashWallet extends Bip39Wallet { | |
| final slatesToCommits = info.epicData?.slatesToCommits ?? {}; | ||
|
|
||
| for (final tx in transactions) { | ||
|
|
||
| Logging.instance.w( | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs removed before prod. |
||
| "EPIC TX " | ||
| "id=${tx.id} " | ||
| "slate=${tx.txSlateId} " | ||
| "epicbox_tx_id=${tx.txEpicboxId} " | ||
| "type=${tx.txType} " | ||
| "sentCancelled=${libEpic.txTypeIsSentCancelled(tx.txType)} " | ||
| "receiveCancelled=${libEpic.txTypeIsReceiveCancelled(tx.txType)}", | ||
| ); | ||
|
|
||
| final isIncoming = | ||
| libEpic.txTypeIsReceived(tx.txType) || | ||
| libEpic.txTypeIsReceiveCancelled(tx.txType); | ||
| final slateId = tx.txSlateId; | ||
| final epicboxId = tx.txEpicboxId; | ||
| final commitId = slatesToCommits[slateId]?['commitId'] as String?; | ||
| final numberOfMessages = tx.messages?.length; | ||
| final onChainNote = tx.messages?.first.message; | ||
|
|
@@ -1451,6 +1466,7 @@ class EpiccashWallet extends Bip39Wallet { | |
| "isEpiccashTransaction": true, | ||
| "numberOfMessages": numberOfMessages, | ||
| "slateId": slateId, | ||
| "epicboxId": epicboxId, | ||
| "onChainNote": onChainNote, | ||
| "isCancelled": | ||
| libEpic.txTypeIsSentCancelled(tx.txType) || | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,12 +21,25 @@ final class _LibEpicCashInterfaceImpl extends LibEpicCashInterface { | |
| const _LibEpicCashInterfaceImpl(); | ||
|
|
||
| @override | ||
| Future<String> cancelTransaction({ | ||
| Future<String> cancelEpicboxTransaction({ | ||
| required DynamicObject wallet, | ||
| required String transactionId, | ||
| }) { | ||
| return wallet.get<EpicWallet>().cancelTransaction( | ||
| transactionId: transactionId, | ||
| required bool methodIsEpicbox, | ||
| String? epicboxConfig, | ||
| int? txId, | ||
| String? txSlateId, | ||
| String? txEpicboxId, | ||
| }) async { | ||
| final epicWallet = wallet.get<EpicWallet>(); | ||
|
|
||
| if (epicboxConfig != null) { | ||
| epicWallet.updateEpicboxConfig(epicboxConfig); | ||
| } | ||
|
|
||
| return epicWallet.cancelEpicboxTransaction( | ||
| methodIsEpicbox: methodIsEpicbox, | ||
| txId: txId, | ||
| txSlateId: txSlateId, | ||
| txEpicboxId: txEpicboxId, | ||
| ); | ||
| } | ||
|
|
||
|
|
@@ -124,6 +137,17 @@ final class _LibEpicCashInterfaceImpl extends LibEpicCashInterface { | |
| refreshFromNode: refreshFromNode, | ||
| ); | ||
|
|
||
| // Log the flutter_libepiccash Transaction BEFORE converting it. | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be removed before prod. |
||
| for (final e in transactions) { | ||
| print( | ||
| "EPIC INTERFACE TX " | ||
| "id=${e.id} " | ||
| "txSlateId=${e.txSlateId} " | ||
| "txEpicboxId=${e.txEpicboxId} " | ||
| "type=${e.txType}", | ||
| ); | ||
| } | ||
|
|
||
| return transactions | ||
| .map( | ||
| (e) => EpicTransaction( | ||
|
|
@@ -138,6 +162,7 @@ final class _LibEpicCashInterfaceImpl extends LibEpicCashInterface { | |
| amountCredited: e.amountCredited, | ||
| amountDebited: e.amountDebited, | ||
| txSlateId: e.txSlateId, | ||
| txEpicboxId: e.txEpicboxId, | ||
| fee: e.fee, | ||
| ttlCutoffHeight: e.ttlCutoffHeight, | ||
| messages: e.messages?.messages | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do proper null-checking up here now - See comment on L169, item 1.