Add anypay payment. Add filter by search for ionia, add get purchased items for ionia.

This commit is contained in:
M 2022-06-28 14:31:51 +01:00
parent 1447ea32ba
commit 657265a10a
15 changed files with 378 additions and 58 deletions

View file

@ -2,8 +2,9 @@ import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_core/output_info.dart'; import 'package:cw_core/output_info.dart';
class BitcoinTransactionCredentials { class BitcoinTransactionCredentials {
BitcoinTransactionCredentials(this.outputs, this.priority); BitcoinTransactionCredentials(this.outputs, {this.priority, this.feeRate});
final List<OutputInfo> outputs; final List<OutputInfo> outputs;
BitcoinTransactionPriority priority; final BitcoinTransactionPriority priority;
final int feeRate;
} }

View file

@ -208,8 +208,14 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
} }
amount = credentialsAmount; amount = credentialsAmount;
fee = calculateEstimatedFee(transactionCredentials.priority, amount,
outputsCount: outputs.length + 1); if (transactionCredentials.feeRate != null) {
fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate, amount,
outputsCount: outputs.length + 1);
} else {
fee = calculateEstimatedFee(transactionCredentials.priority, amount,
outputsCount: outputs.length + 1);
}
} else { } else {
final output = outputs.first; final output = outputs.first;
credentialsAmount = !output.sendAll credentialsAmount = !output.sendAll
@ -223,9 +229,14 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
amount = output.sendAll || allAmount - credentialsAmount < minAmount amount = output.sendAll || allAmount - credentialsAmount < minAmount
? allAmount ? allAmount
: credentialsAmount; : credentialsAmount;
fee = output.sendAll || amount == allAmount
? allAmountFee if (output.sendAll || amount == allAmount) {
: calculateEstimatedFee(transactionCredentials.priority, amount); fee = allAmountFee;
} else if (transactionCredentials.feeRate != null) {
fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate, amount);
} else {
fee = calculateEstimatedFee(transactionCredentials.priority, amount);
}
} }
if (fee == 0) { if (fee == 0) {
@ -296,7 +307,14 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
final estimatedSize = final estimatedSize =
estimatedTransactionSize(inputs.length, outputs.length + 1); estimatedTransactionSize(inputs.length, outputs.length + 1);
final feeAmount = feeRate(transactionCredentials.priority) * estimatedSize; var feeAmount = 0;
if (transactionCredentials.feeRate != null) {
feeAmount = transactionCredentials.feeRate * estimatedSize;
} else {
feeAmount = feeRate(transactionCredentials.priority) * estimatedSize;
}
final changeValue = totalInputAmount - amount - feeAmount; final changeValue = totalInputAmount - amount - feeAmount;
if (changeValue > minAmount) { if (changeValue > minAmount) {
@ -346,45 +364,57 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
int outputsCount) => int outputsCount) =>
feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount); feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount);
int feeAmountWithFeeRate(int feeRate, int inputsCount,
int outputsCount) =>
feeRate * estimatedTransactionSize(inputsCount, outputsCount);
@override @override
int calculateEstimatedFee(TransactionPriority priority, int amount, int calculateEstimatedFee(TransactionPriority priority, int amount,
{int outputsCount}) { {int outputsCount}) {
if (priority is BitcoinTransactionPriority) { if (priority is BitcoinTransactionPriority) {
int inputsCount = 0; return calculateEstimatedFeeWithFeeRate(
feeRate(priority),
if (amount != null) { amount,
int totalValue = 0; outputsCount: outputsCount);
for (final input in unspentCoins) {
if (totalValue >= amount) {
break;
}
if (input.isSending) {
totalValue += input.value;
inputsCount += 1;
}
}
if (totalValue < amount) return 0;
} else {
for (final input in unspentCoins) {
if (input.isSending) {
inputsCount += 1;
}
}
}
// If send all, then we have no change value
final _outputsCount = outputsCount ?? (amount != null ? 2 : 1);
return feeAmountForPriority(
priority, inputsCount, _outputsCount);
} }
return 0; return 0;
} }
int calculateEstimatedFeeWithFeeRate(int feeRate, int amount,
{int outputsCount}) {
int inputsCount = 0;
if (amount != null) {
int totalValue = 0;
for (final input in unspentCoins) {
if (totalValue >= amount) {
break;
}
if (input.isSending) {
totalValue += input.value;
inputsCount += 1;
}
}
if (totalValue < amount) return 0;
} else {
for (final input in unspentCoins) {
if (input.isSending) {
inputsCount += 1;
}
}
}
// If send all, then we have no change value
final _outputsCount = outputsCount ?? (amount != null ? 2 : 1);
return feeAmountWithFeeRate(
feeRate, inputsCount, _outputsCount);
}
@override @override
Future<void> save() async { Future<void> save() async {
final path = await makePath(); final path = await makePath();

View file

@ -25,7 +25,7 @@ class PendingBitcoinTransaction with PendingTransaction {
String get id => _tx.getId(); String get id => _tx.getId();
@override @override
String get hex => ''; String get hex => _tx.toHex();
@override @override
String get amountFormatted => bitcoinAmountToString(amount: amount); String get amountFormatted => bitcoinAmountToString(amount: amount);

View file

@ -0,0 +1,5 @@
class AnyPayChain {
static const xmr = 'XMR';
static const btc = 'BTC';
static const ltc = 'LTC';
}

View file

@ -22,6 +22,8 @@ class AnyPayPaymentInstruction {
outputs: outputs); outputs: outputs);
} }
static const transactionType = 'transaction';
final String type; final String type;
final int requiredFeeRate; final int requiredFeeRate;
final bool txKey; final bool txKey;

View file

@ -0,0 +1,9 @@
import 'package:flutter/foundation.dart';
class AnyPayTransaction {
const AnyPayTransaction(this.tx, {@required this.id, @required this.key});
final String tx;
final String id;
final String key;
}

View file

@ -1,16 +1,23 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/anypay/any_pay_payment.dart'; import 'package:cake_wallet/anypay/any_pay_payment.dart';
import 'package:cake_wallet/anypay/any_pay_trasnaction.dart';
class AnyPayApi { class AnyPayApi {
static const contentTypePaymentRequest = 'application/payment-request'; static const contentTypePaymentRequest = 'application/payment-request';
static const contentTypePayment = 'application/payment';
static const xPayproVersion = '2'; static const xPayproVersion = '2';
static String chainByScheme(String scheme) { static String chainByScheme(String scheme) {
switch (scheme.toLowerCase()) { switch (scheme.toLowerCase()) {
case 'monero': case 'monero':
return CryptoCurrency.xmr.title; return CryptoCurrency.xmr.title;
case 'bitcoin':
return CryptoCurrency.btc.title;
case 'litecoin':
return CryptoCurrency.ltc.title;
default: default:
return ''; return '';
} }
@ -20,12 +27,16 @@ class AnyPayApi {
switch (scheme.toLowerCase()) { switch (scheme.toLowerCase()) {
case 'monero': case 'monero':
return CryptoCurrency.xmr; return CryptoCurrency.xmr;
case 'bitcoin':
return CryptoCurrency.btc;
case 'litecoin':
return CryptoCurrency.ltc;
default: default:
return null; return null;
} }
} }
Future<AnyPayPayment> pay(String uri) async { Future<AnyPayPayment> paymentRequest(String uri) async {
final fragments = uri.split(':?r='); final fragments = uri.split(':?r=');
final scheme = fragments.first; final scheme = fragments.first;
final url = fragments[1]; final url = fragments[1];
@ -45,4 +56,24 @@ class AnyPayApi {
final decodedBody = json.decode(response.body) as Map<String, dynamic>; final decodedBody = json.decode(response.body) as Map<String, dynamic>;
return AnyPayPayment.fromMap(decodedBody); return AnyPayPayment.fromMap(decodedBody);
} }
Future<void> payment(
String uri,
{@required String chain,
@required String currency,
@required List<AnyPayTransaction> transactions}) async {
final headers = <String, String>{
'Content-Type': contentTypePayment,
'X-Paypro-Version': xPayproVersion,
'Accept': '*/*',};
final body = <String, dynamic>{
'chain': chain,
'currency': currency,
'transactions': transactions.map((tx) => {'tx': tx.tx, 'tx_hash': tx.id, 'tx_key': tx.key}).toList()};
final response = await post(uri, headers: headers, body: utf8.encode(json.encode(body)));
if (response.statusCode != 200) {
return null;
}
}
} }

View file

@ -55,7 +55,7 @@ class CWBitcoin extends Bitcoin {
} }
@override @override
Object createBitcoinTransactionCredentials(List<Output> outputs, TransactionPriority priority) Object createBitcoinTransactionCredentials(List<Output> outputs, {TransactionPriority priority, int feeRate})
=> BitcoinTransactionCredentials( => BitcoinTransactionCredentials(
outputs.map((out) => OutputInfo( outputs.map((out) => OutputInfo(
fiatAmount: out.fiatAmount, fiatAmount: out.fiatAmount,
@ -67,7 +67,15 @@ class CWBitcoin extends Bitcoin {
isParsedAddress: out.isParsedAddress, isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount)) formattedCryptoAmount: out.formattedCryptoAmount))
.toList(), .toList(),
priority as BitcoinTransactionPriority); priority: priority != null ? priority as BitcoinTransactionPriority : null,
feeRate: feeRate);
@override
Object createBitcoinTransactionCredentialsRaw(List<OutputInfo> outputs, {TransactionPriority priority, int feeRate})
=> BitcoinTransactionCredentials(
outputs,
priority: priority != null ? priority as BitcoinTransactionPriority : null,
feeRate: feeRate);
@override @override
List<String> getAddresses(Object wallet) { List<String> getAddresses(Object wallet) {

View file

@ -131,6 +131,7 @@ import 'package:cake_wallet/exchange/exchange_template.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart';
import 'package:cake_wallet/ionia/ionia_token_service.dart'; import 'package:cake_wallet/ionia/ionia_token_service.dart';
import 'package:cake_wallet/anypay/anypay_api.dart';
final getIt = GetIt.instance; final getIt = GetIt.instance;
@ -651,6 +652,8 @@ Future setup(
getIt.registerFactory(() => IoniaApi()); getIt.registerFactory(() => IoniaApi());
getIt.registerFactory(() => AnyPayApi());
getIt.registerFactory<IoniaService>( getIt.registerFactory<IoniaService>(
() => IoniaService(getIt.get<FlutterSecureStorage>(), getIt.get<IoniaApi>())); () => IoniaService(getIt.get<FlutterSecureStorage>(), getIt.get<IoniaApi>()));

View file

@ -0,0 +1,89 @@
import 'package:flutter/foundation.dart';
import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_core/monero_transaction_priority.dart';
import 'package:cw_core/output_info.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cake_wallet/anypay/any_pay_payment.dart';
import 'package:cake_wallet/anypay/any_pay_payment_instruction.dart';
import 'package:cake_wallet/ionia/ionia_service.dart';
import 'package:cake_wallet/anypay/anypay_api.dart';
import 'package:cake_wallet/anypay/any_pay_chain.dart';
import 'package:cake_wallet/anypay/any_pay_trasnaction.dart';
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/monero/monero.dart';
class IoniaAnyPay {
IoniaAnyPay(this.ioniaService, this.anyPayApi, this.wallet);
final IoniaService ioniaService;
final AnyPayApi anyPayApi;
final WalletBase wallet;
Future<AnyPayPayment> purchase({
@required String merchId,
@required double amount,
@required String currency}) async {
final invoice = await ioniaService.purchaseGiftCard(
merchId: merchId,
amount: amount,
currency: currency);
return anyPayApi.paymentRequest(invoice.uri);
}
Future<void> commitInvoice(AnyPayPayment payment) async {
final transactionCredentials = payment.instructions
.where((instruction) => instruction.type == AnyPayPaymentInstruction.transactionType)
.map((AnyPayPaymentInstruction instruction) {
switch(payment.chain.toUpperCase()) {
case AnyPayChain.xmr:
return monero.createMoneroTransactionCreationCredentialsRaw(
outputs: instruction.outputs.map((out) =>
OutputInfo(
isParsedAddress: false,
address: out.address,
cryptoAmount: moneroAmountToString(amount: out.amount),
sendAll: false)).toList(),
priority: MoneroTransactionPriority.medium); // FIXME: HARDCODED PRIORITY
case AnyPayChain.btc:
return bitcoin.createBitcoinTransactionCredentialsRaw(
instruction.outputs.map((out) =>
OutputInfo(
isParsedAddress: false,
address: out.address,
formattedCryptoAmount: out.amount,
sendAll: false)).toList(),
feeRate: instruction.requiredFeeRate);
case AnyPayChain.ltc:
return bitcoin.createBitcoinTransactionCredentialsRaw(
instruction.outputs.map((out) =>
OutputInfo(
isParsedAddress: false,
address: out.address,
formattedCryptoAmount: out.amount,
sendAll: false)).toList(),
feeRate: instruction.requiredFeeRate);
default:
throw Exception('Incorrect transaction chain: ${payment.chain.toUpperCase()}');
}
});
final transactions = (await Future.wait(transactionCredentials
.map((Object credentials) async => await wallet.createTransaction(credentials))))
.map((PendingTransaction pendingTransaction) {
switch (payment.chain.toUpperCase()){
case AnyPayChain.xmr:
final ptx = monero.pendingTransactionInfo(pendingTransaction);
return AnyPayTransaction(ptx['hex'], id: ptx['id'], key: ptx['key']);
default:
return AnyPayTransaction(pendingTransaction.hex, id: pendingTransaction.id, key: null);
}
})
.toList();
await anyPayApi.payment(
payment.paymentUrl,
chain: payment.chain,
currency: payment.chain,
transactions: transactions);
}
}

View file

@ -14,6 +14,7 @@ class IoniaApi {
static final createCardUri = Uri.https(baseUri, '/$pathPrefix/CreateCard'); static final createCardUri = Uri.https(baseUri, '/$pathPrefix/CreateCard');
static final getCardsUri = Uri.https(baseUri, '/$pathPrefix/GetCards'); static final getCardsUri = Uri.https(baseUri, '/$pathPrefix/GetCards');
static final getMerchantsUrl = Uri.https(baseUri, '/$pathPrefix/GetMerchants'); static final getMerchantsUrl = Uri.https(baseUri, '/$pathPrefix/GetMerchants');
static final getMerchantsByFilterUrl = Uri.https(baseUri, '/$pathPrefix/GetMerchantsByFilter');
static final getPurchaseMerchantsUrl = Uri.https(baseUri, '/$pathPrefix/PurchaseGiftCard'); static final getPurchaseMerchantsUrl = Uri.https(baseUri, '/$pathPrefix/PurchaseGiftCard');
// Create user // Create user
@ -157,6 +158,52 @@ class IoniaApi {
}).toList(); }).toList();
} }
// Get Merchants By Filter
Future<List<IoniaMerchant>> getMerchantsByFilter({
@required String username,
@required String password,
@required String clientId,
String search,
List<int> categories,
int merchantFilterType = 0}) async {
// MerchantFilterType: {All = 0, Nearby = 1, Popular = 2, Online = 3, MyFaves = 4, Search = 5}
final headers = <String, String>{
'clientId': clientId,
'username': username,
'password': password,
'Content-Type': 'application/json'};
final body = <String, dynamic>{'MerchantFilterType': merchantFilterType};
if (search != null) {
body['SearchCriteria'] = search;
}
if (categories != null) {
body['Categories'] = categories;
}
final response = await post(getMerchantsByFilterUrl, headers: headers, body: json.encode(body));
if (response.statusCode != 200) {
return [];
}
final decodedBody = json.decode(response.body) as Map<String, dynamic>;
final isSuccessful = decodedBody['Successful'] as bool ?? false;
if (!isSuccessful) {
return [];
}
final data = decodedBody['Data'] as List<dynamic>;
return data.map((dynamic e) {
final element = e as Map<String, dynamic>;
return IoniaMerchant.fromJsonMap(element);
}).toList();
}
// Purchase Gift Card // Purchase Gift Card
Future<IoniaOrder> purchaseGiftCard({ Future<IoniaOrder> purchaseGiftCard({
@ -173,8 +220,8 @@ class IoniaApi {
'Content-Type': 'application/json'}; 'Content-Type': 'application/json'};
final body = <String, dynamic>{ final body = <String, dynamic>{
'Amount': amount, 'Amount': amount,
'Currency': currency, 'Currency': currency,
'MerchantId': merchId}; 'MerchantId': merchId};
final response = await post(getPurchaseMerchantsUrl, headers: headers, body: json.encode(body)); final response = await post(getPurchaseMerchantsUrl, headers: headers, body: json.encode(body));
if (response.statusCode != 200) { if (response.statusCode != 200) {
@ -191,4 +238,34 @@ class IoniaApi {
final data = decodedBody['Data'] as Map<String, dynamic>; final data = decodedBody['Data'] as Map<String, dynamic>;
return IoniaOrder.fromMap(data); return IoniaOrder.fromMap(data);
} }
// Get Current User Gift Card Summaries
Future<List<IoniaMerchant>> getCurrentUserGiftCardSummaries({
@required String username,
@required String password,
@required String clientId}) async {
final headers = <String, String>{
'clientId': clientId,
'username': username,
'password': password};
final response = await post(getMerchantsUrl, headers: headers);
if (response.statusCode != 200) {
return [];
}
final decodedBody = json.decode(response.body) as Map<String, dynamic>;
final isSuccessful = decodedBody['Successful'] as bool ?? false;
if (!isSuccessful) {
return [];
}
final data = decodedBody['Data'] as List<dynamic>;
return data.map((dynamic e) {
final element = e as Map<String, dynamic>;
return IoniaMerchant.fromJsonMap(element);
}).toList();
}
} }

View file

@ -71,6 +71,23 @@ class IoniaService {
return ioniaApi.getMerchants(username: username, password: password, clientId: clientId); return ioniaApi.getMerchants(username: username, password: password, clientId: clientId);
} }
// Get Merchants By Filter
Future<List<IoniaMerchant>> getMerchantsByFilter({
String search,
List<int> categories,
int merchantFilterType = 0}) async {
final username = await secureStorage.read(key: ioniaUsernameStorageKey);
final password = await secureStorage.read(key: ioniaPasswordStorageKey);
return ioniaApi.getMerchantsByFilter(
username: username,
password: password,
clientId: clientId,
search: search,
categories: categories,
merchantFilterType: merchantFilterType);
}
// Purchase Gift Card // Purchase Gift Card
Future<IoniaOrder> purchaseGiftCard({ Future<IoniaOrder> purchaseGiftCard({
@ -87,4 +104,12 @@ class IoniaService {
password: password, password: password,
clientId: clientId); clientId: clientId);
} }
// Get Current User Gift Card Summaries
Future<List<IoniaMerchant>> getCurrentUserGiftCardSummaries() async {
final username = await secureStorage.read(key: ioniaUsernameStorageKey);
final password = await secureStorage.read(key: ioniaPasswordStorageKey);
return ioniaApi.getCurrentUserGiftCardSummaries(username: username, password: password, clientId: clientId);
}
} }

View file

@ -2,7 +2,7 @@ part of 'monero.dart';
class CWMoneroAccountList extends MoneroAccountList { class CWMoneroAccountList extends MoneroAccountList {
CWMoneroAccountList(this._wallet); CWMoneroAccountList(this._wallet);
Object _wallet; final Object _wallet;
@override @override
@computed @computed
@ -39,13 +39,13 @@ class CWMoneroAccountList extends MoneroAccountList {
@override @override
Future<void> addAccount(Object wallet, {String label}) async { Future<void> addAccount(Object wallet, {String label}) async {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.accountList.addAccount(label: label); await moneroWallet.walletAddresses.accountList.addAccount(label: label);
} }
@override @override
Future<void> setLabelAccount(Object wallet, {int accountIndex, String label}) async { Future<void> setLabelAccount(Object wallet, {int accountIndex, String label}) async {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.accountList await moneroWallet.walletAddresses.accountList
.setLabelAccount( .setLabelAccount(
accountIndex: accountIndex, accountIndex: accountIndex,
label: label); label: label);
@ -95,7 +95,7 @@ class CWMoneroSubaddressList extends MoneroSubaddressList {
@override @override
Future<void> addSubaddress(Object wallet, {int accountIndex, String label}) async { Future<void> addSubaddress(Object wallet, {int accountIndex, String label}) async {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.subaddressList await moneroWallet.walletAddresses.subaddressList
.addSubaddress( .addSubaddress(
accountIndex: accountIndex, accountIndex: accountIndex,
label: label); label: label);
@ -105,7 +105,7 @@ class CWMoneroSubaddressList extends MoneroSubaddressList {
Future<void> setLabelSubaddress(Object wallet, Future<void> setLabelSubaddress(Object wallet,
{int accountIndex, int addressIndex, String label}) async { {int accountIndex, int addressIndex, String label}) async {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.subaddressList await moneroWallet.walletAddresses.subaddressList
.setLabelSubaddress( .setLabelSubaddress(
accountIndex: accountIndex, accountIndex: accountIndex,
addressIndex: addressIndex, addressIndex: addressIndex,
@ -140,35 +140,43 @@ class CWMonero extends Monero {
return CWMoneroAccountList(wallet); return CWMoneroAccountList(wallet);
} }
@override
MoneroSubaddressList getSubaddressList(Object wallet) { MoneroSubaddressList getSubaddressList(Object wallet) {
return CWMoneroSubaddressList(wallet); return CWMoneroSubaddressList(wallet);
} }
@override
TransactionHistoryBase getTransactionHistory(Object wallet) { TransactionHistoryBase getTransactionHistory(Object wallet) {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
return moneroWallet.transactionHistory; return moneroWallet.transactionHistory;
} }
@override
MoneroWalletDetails getMoneroWalletDetails(Object wallet) { MoneroWalletDetails getMoneroWalletDetails(Object wallet) {
return CWMoneroWalletDetails(wallet); return CWMoneroWalletDetails(wallet);
} }
@override
int getHeigthByDate({DateTime date}) { int getHeigthByDate({DateTime date}) {
return getMoneroHeigthByDate(date: date); return getMoneroHeigthByDate(date: date);
} }
@override
TransactionPriority getDefaultTransactionPriority() { TransactionPriority getDefaultTransactionPriority() {
return MoneroTransactionPriority.slow; return MoneroTransactionPriority.slow;
} }
@override
TransactionPriority deserializeMoneroTransactionPriority({int raw}) { TransactionPriority deserializeMoneroTransactionPriority({int raw}) {
return MoneroTransactionPriority.deserialize(raw: raw); return MoneroTransactionPriority.deserialize(raw: raw);
} }
@override
List<TransactionPriority> getTransactionPriorities() { List<TransactionPriority> getTransactionPriorities() {
return MoneroTransactionPriority.all; return MoneroTransactionPriority.all;
} }
@override
List<String> getMoneroWordList(String language) { List<String> getMoneroWordList(String language) {
switch (language.toLowerCase()) { switch (language.toLowerCase()) {
case 'english': case 'english':
@ -196,14 +204,15 @@ class CWMonero extends Monero {
} }
} }
@override
WalletCredentials createMoneroRestoreWalletFromKeysCredentials({ WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
String name, String name,
String spendKey, String spendKey,
String viewKey, String viewKey,
String address, String address,
String password, String password,
String language, String language,
int height}) { int height}) {
return MoneroRestoreWalletFromKeysCredentials( return MoneroRestoreWalletFromKeysCredentials(
name: name, name: name,
spendKey: spendKey, spendKey: spendKey,
@ -214,6 +223,7 @@ class CWMonero extends Monero {
height: height); height: height);
} }
@override
WalletCredentials createMoneroRestoreWalletFromSeedCredentials({String name, String password, int height, String mnemonic}) { WalletCredentials createMoneroRestoreWalletFromSeedCredentials({String name, String password, int height, String mnemonic}) {
return MoneroRestoreWalletFromSeedCredentials( return MoneroRestoreWalletFromSeedCredentials(
name: name, name: name,
@ -222,6 +232,7 @@ class CWMonero extends Monero {
mnemonic: mnemonic); mnemonic: mnemonic);
} }
@override
WalletCredentials createMoneroNewWalletCredentials({String name, String password, String language}) { WalletCredentials createMoneroNewWalletCredentials({String name, String password, String language}) {
return MoneroNewWalletCredentials( return MoneroNewWalletCredentials(
name: name, name: name,
@ -229,6 +240,7 @@ class CWMonero extends Monero {
language: language); language: language);
} }
@override
Map<String, String> getKeys(Object wallet) { Map<String, String> getKeys(Object wallet) {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
final keys = moneroWallet.keys; final keys = moneroWallet.keys;
@ -239,6 +251,7 @@ class CWMonero extends Monero {
'publicViewKey': keys.publicViewKey}; 'publicViewKey': keys.publicViewKey};
} }
@override
Object createMoneroTransactionCreationCredentials({List<Output> outputs, TransactionPriority priority}) { Object createMoneroTransactionCreationCredentials({List<Output> outputs, TransactionPriority priority}) {
return MoneroTransactionCreationCredentials( return MoneroTransactionCreationCredentials(
outputs: outputs.map((out) => OutputInfo( outputs: outputs.map((out) => OutputInfo(
@ -254,49 +267,72 @@ class CWMonero extends Monero {
priority: priority as MoneroTransactionPriority); priority: priority as MoneroTransactionPriority);
} }
@override
Object createMoneroTransactionCreationCredentialsRaw({List<OutputInfo> outputs, TransactionPriority priority}) {
return MoneroTransactionCreationCredentials(
outputs: outputs,
priority: priority as MoneroTransactionPriority);
}
@override
String formatterMoneroAmountToString({int amount}) { String formatterMoneroAmountToString({int amount}) {
return moneroAmountToString(amount: amount); return moneroAmountToString(amount: amount);
} }
@override
double formatterMoneroAmountToDouble({int amount}) { double formatterMoneroAmountToDouble({int amount}) {
return moneroAmountToDouble(amount: amount); return moneroAmountToDouble(amount: amount);
} }
@override
int formatterMoneroParseAmount({String amount}) { int formatterMoneroParseAmount({String amount}) {
return moneroParseAmount(amount: amount); return moneroParseAmount(amount: amount);
} }
@override
Account getCurrentAccount(Object wallet) { Account getCurrentAccount(Object wallet) {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
final acc = moneroWallet.walletAddresses.account; final acc = moneroWallet.walletAddresses.account;
return Account(id: acc.id, label: acc.label); return Account(id: acc.id, label: acc.label);
} }
@override
void setCurrentAccount(Object wallet, int id, String label) { void setCurrentAccount(Object wallet, int id, String label) {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.account = monero_account.Account(id: id, label: label); moneroWallet.walletAddresses.account = monero_account.Account(id: id, label: label);
} }
@override
void onStartup() { void onStartup() {
monero_wallet_api.onStartup(); monero_wallet_api.onStartup();
} }
@override
int getTransactionInfoAccountId(TransactionInfo tx) { int getTransactionInfoAccountId(TransactionInfo tx) {
final moneroTransactionInfo = tx as MoneroTransactionInfo; final moneroTransactionInfo = tx as MoneroTransactionInfo;
return moneroTransactionInfo.accountIndex; return moneroTransactionInfo.accountIndex;
} }
@override
WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource) { WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource) {
return MoneroWalletService(walletInfoSource); return MoneroWalletService(walletInfoSource);
} }
@override
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) { String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
return moneroWallet.getTransactionAddress(accountIndex, addressIndex); return moneroWallet.getTransactionAddress(accountIndex, addressIndex);
} }
@override
String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) { String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) {
final moneroWallet = wallet as MoneroWallet; final moneroWallet = wallet as MoneroWallet;
return moneroWallet.getSubaddressLabel(accountIndex, addressIndex); return moneroWallet.getSubaddressLabel(accountIndex, addressIndex);
} }
@override
Map<String, String> pendingTransactionInfo(Object transaction) {
final ptx = transaction as PendingMoneroTransaction;
return {'id': ptx.id, 'hex': ptx.hex, 'key': ptx.txKey};
}
} }

View file

@ -222,11 +222,11 @@ abstract class SendViewModelBase with Store {
case WalletType.bitcoin: case WalletType.bitcoin:
final priority = _settingsStore.priority[_wallet.type]; final priority = _settingsStore.priority[_wallet.type];
return bitcoin.createBitcoinTransactionCredentials(outputs, priority); return bitcoin.createBitcoinTransactionCredentials(outputs, priority: priority);
case WalletType.litecoin: case WalletType.litecoin:
final priority = _settingsStore.priority[_wallet.type]; final priority = _settingsStore.priority[_wallet.type];
return bitcoin.createBitcoinTransactionCredentials(outputs, priority); return bitcoin.createBitcoinTransactionCredentials(outputs, priority: priority);
case WalletType.monero: case WalletType.monero:
final priority = _settingsStore.priority[_wallet.type]; final priority = _settingsStore.priority[_wallet.type];

View file

@ -77,7 +77,8 @@ abstract class Bitcoin {
TransactionPriority deserializeBitcoinTransactionPriority(int raw); TransactionPriority deserializeBitcoinTransactionPriority(int raw);
int getFeeRate(Object wallet, TransactionPriority priority); int getFeeRate(Object wallet, TransactionPriority priority);
Future<void> generateNewAddress(Object wallet); Future<void> generateNewAddress(Object wallet);
Object createBitcoinTransactionCredentials(List<Output> outputs, TransactionPriority priority); Object createBitcoinTransactionCredentials(List<Output> outputs, {TransactionPriority priority, int feeRate});
Object createBitcoinTransactionCredentialsRaw(List<OutputInfo> outputs, {TransactionPriority priority, int feeRate});
List<String> getAddresses(Object wallet); List<String> getAddresses(Object wallet);
String getAddress(Object wallet); String getAddress(Object wallet);
@ -146,6 +147,7 @@ import 'package:cw_monero/mnemonics/spanish.dart';
import 'package:cw_monero/mnemonics/portuguese.dart'; import 'package:cw_monero/mnemonics/portuguese.dart';
import 'package:cw_monero/mnemonics/french.dart'; import 'package:cw_monero/mnemonics/french.dart';
import 'package:cw_monero/mnemonics/italian.dart'; import 'package:cw_monero/mnemonics/italian.dart';
import 'package:cw_monero/pending_monero_transaction.dart';
"""; """;
const moneroCwPart = "part 'cw_monero.dart';"; const moneroCwPart = "part 'cw_monero.dart';";
const moneroContent = """ const moneroContent = """
@ -229,6 +231,7 @@ abstract class Monero {
WalletCredentials createMoneroNewWalletCredentials({String name, String password, String language}); WalletCredentials createMoneroNewWalletCredentials({String name, String password, String language});
Map<String, String> getKeys(Object wallet); Map<String, String> getKeys(Object wallet);
Object createMoneroTransactionCreationCredentials({List<Output> outputs, TransactionPriority priority}); Object createMoneroTransactionCreationCredentials({List<Output> outputs, TransactionPriority priority});
Object createMoneroTransactionCreationCredentialsRaw({List<OutputInfo> outputs, TransactionPriority priority});
String formatterMoneroAmountToString({int amount}); String formatterMoneroAmountToString({int amount});
double formatterMoneroAmountToDouble({int amount}); double formatterMoneroAmountToDouble({int amount});
int formatterMoneroParseAmount({String amount}); int formatterMoneroParseAmount({String amount});
@ -237,6 +240,7 @@ abstract class Monero {
void onStartup(); void onStartup();
int getTransactionInfoAccountId(TransactionInfo tx); int getTransactionInfoAccountId(TransactionInfo tx);
WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource); WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource);
Map<String, String> pendingTransactionInfo(Object transaction);
} }
abstract class MoneroSubaddressList { abstract class MoneroSubaddressList {