This commit is contained in:
Matthew Fosse 2024-03-06 11:21:24 -08:00
parent 7dc999bdb1
commit 452ff1e82b
4 changed files with 94 additions and 42 deletions

View file

@ -8,12 +8,14 @@ import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/exchange/trade_state.dart';
import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart';
import 'package:cake_wallet/lightning/lightning.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
class TrocadorExchangeProvider extends ExchangeProvider { class TrocadorExchangeProvider extends ExchangeProvider {
TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}}) TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}})
: _lastUsedRateId = '', _provider = [], : _lastUsedRateId = '',
_provider = [],
super(pairList: supportedPairs(_notSupported)); super(pairList: supportedPairs(_notSupported));
bool useTorOnly; bool useTorOnly;
@ -24,7 +26,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
'StealthEx', 'StealthEx',
'Simpleswap', 'Simpleswap',
'Swapuz' 'Swapuz'
'ChangeNow', 'ChangeNow',
'Changehero', 'Changehero',
'FixedFloat', 'FixedFloat',
'LetsExchange', 'LetsExchange',
@ -95,6 +97,14 @@ class TrocadorExchangeProvider extends ExchangeProvider {
final coinJson = responseJSON.first as Map<String, dynamic>; final coinJson = responseJSON.first as Map<String, dynamic>;
// trocador treats btcln as just bitcoin amounts:
if (from == CryptoCurrency.btcln) {
return Limits(
min: lightning!.bitcoinDoubleToLightningDouble(amount: (coinJson['minimum'] as double)),
max: lightning!.bitcoinDoubleToLightningDouble(amount: (coinJson['maximum'] as double)),
);
}
return Limits( return Limits(
min: coinJson['minimum'] as double, min: coinJson['minimum'] as double,
max: coinJson['maximum'] as double, max: coinJson['maximum'] as double,
@ -111,14 +121,20 @@ class TrocadorExchangeProvider extends ExchangeProvider {
try { try {
if (amount == 0) return 0.0; if (amount == 0) return 0.0;
double amt = amount;
if (from == CryptoCurrency.btcln) {
amt = lightning!.lightningDoubleToBitcoinDouble(amount: amount);
}
final params = <String, String>{ final params = <String, String>{
'api_key': apiKey, 'api_key': apiKey,
'ticker_from': _normalizeCurrency(from), 'ticker_from': _normalizeCurrency(from),
'ticker_to': _normalizeCurrency(to), 'ticker_to': _normalizeCurrency(to),
'network_from': _networkFor(from), 'network_from': _networkFor(from),
'network_to': _networkFor(to), 'network_to': _networkFor(to),
if (!isFixedRateMode) 'amount_from': amount.toString(), if (!isFixedRateMode) 'amount_from': amt.toString(),
if (isFixedRateMode) 'amount_to': amount.toString(), if (isFixedRateMode) 'amount_to': amt.toString(),
'payment': isFixedRateMode ? 'True' : 'False', 'payment': isFixedRateMode ? 'True' : 'False',
'min_kycrating': 'C', 'min_kycrating': 'C',
'markup': markup, 'markup': markup,
@ -145,6 +161,14 @@ class TrocadorExchangeProvider extends ExchangeProvider {
@override @override
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async { Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
double fromAmt = double.parse(request.fromAmount);
double toAmt = double.parse(request.toAmount);
if (request.fromCurrency == CryptoCurrency.btcln) {
fromAmt = lightning!.lightningDoubleToBitcoinDouble(amount: fromAmt);
}
if (request.toCurrency == CryptoCurrency.btcln) {
toAmt = lightning!.lightningDoubleToBitcoinDouble(amount: toAmt);
}
final params = { final params = {
'api_key': apiKey, 'api_key': apiKey,
@ -155,24 +179,28 @@ class TrocadorExchangeProvider extends ExchangeProvider {
'payment': isFixedRateMode ? 'True' : 'False', 'payment': isFixedRateMode ? 'True' : 'False',
'min_kycrating': 'C', 'min_kycrating': 'C',
'markup': markup, 'markup': markup,
if (!isFixedRateMode) 'amount_from': request.fromAmount, if (!isFixedRateMode) 'amount_from': fromAmt.toString(),
if (isFixedRateMode) 'amount_to': request.toAmount, if (isFixedRateMode) 'amount_to': toAmt.toString(),
'address': request.toAddress, 'address': request.toAddress,
'refund': request.refundAddress 'refund': request.refundAddress
}; };
double amt = double.tryParse(request.toAmount) ?? 0;
if (request.fromCurrency == CryptoCurrency.btcln) {
amt = lightning!.lightningDoubleToBitcoinDouble(amount: amt);
}
if (isFixedRateMode) { if (isFixedRateMode) {
await fetchRate( await fetchRate(
from: request.fromCurrency, from: request.fromCurrency,
to: request.toCurrency, to: request.toCurrency,
amount: double.tryParse(request.toAmount) ?? 0, amount: amt,
isFixedRateMode: true, isFixedRateMode: true,
isReceiveAmount: true, isReceiveAmount: true,
); );
params['id'] = _lastUsedRateId; params['id'] = _lastUsedRateId;
} }
String firstAvailableProvider = ''; String firstAvailableProvider = '';
for (var provider in _provider) { for (var provider in _provider) {
@ -212,20 +240,29 @@ class TrocadorExchangeProvider extends ExchangeProvider {
final providerId = responseJSON['id_provider'] as String; final providerId = responseJSON['id_provider'] as String;
final providerName = responseJSON['provider'] as String; final providerName = responseJSON['provider'] as String;
String? responseAmount = responseJSON['amount_from']?.toString();
if (request.fromCurrency == CryptoCurrency.btcln && responseAmount != null) {
responseAmount = lightning!
.bitcoinDoubleToLightningDouble(amount: double.parse(responseAmount))
.toString();
}
responseAmount ??= fromAmt.toString();
return Trade( return Trade(
id: id, id: id,
from: request.fromCurrency, from: request.fromCurrency,
to: request.toCurrency, to: request.toCurrency,
provider: description, provider: description,
inputAddress: inputAddress, inputAddress: inputAddress,
refundAddress: refundAddress, refundAddress: refundAddress,
state: TradeState.deserialize(raw: status), state: TradeState.deserialize(raw: status),
password: password, password: password,
providerId: providerId, providerId: providerId,
providerName: providerName, providerName: providerName,
createdAt: DateTime.tryParse(date)?.toLocal(), createdAt: DateTime.tryParse(date)?.toLocal(),
amount: responseJSON['amount_from']?.toString() ?? request.fromAmount, amount: responseAmount,
payoutAddress: payoutAddress); payoutAddress: payoutAddress,
);
} }
@override @override

View file

@ -72,6 +72,7 @@ class CWLightning extends Lightning {
@override @override
ReceivePageOption getOptionOnchain() => LightningReceivePageOption.lightningOnchain; ReceivePageOption getOptionOnchain() => LightningReceivePageOption.lightningOnchain;
@override
String satsToLightningString(int sats) { String satsToLightningString(int sats) {
const bitcoinAmountLength = 8; const bitcoinAmountLength = 8;
const bitcoinAmountDivider = 100000000; const bitcoinAmountDivider = 100000000;
@ -84,16 +85,28 @@ class CWLightning extends Lightning {
return formattedAmount.substring(0, formattedAmount.length - 2); return formattedAmount.substring(0, formattedAmount.length - 2);
} }
@override
String bitcoinAmountToLightningString({required int amount}) { String bitcoinAmountToLightningString({required int amount}) {
final bitcoinAmountFormat = NumberFormat() final bitcoinAmountFormat = NumberFormat()
..maximumFractionDigits = bitcoinAmountLength ..maximumFractionDigits = bitcoinAmountLength
..minimumFractionDigits = 1; ..minimumFractionDigits = 1;
String formattedAmount = bitcoinAmountFormat String formattedAmount =
.format(cryptoAmountToDouble(amount: amount, divider: 1)); bitcoinAmountFormat.format(cryptoAmountToDouble(amount: amount, divider: 1));
return formattedAmount.substring(0, formattedAmount.length - 2); return formattedAmount.substring(0, formattedAmount.length - 2);
} }
@override
int bitcoinAmountToLightningAmount({required int amount}) { int bitcoinAmountToLightningAmount({required int amount}) {
return amount * 100000000; return amount * 100000000;
} }
@override
double bitcoinDoubleToLightningDouble({required double amount}) {
return amount * 100000000;
}
@override
double lightningDoubleToBitcoinDouble({required double amount}) {
return amount / 100000000;
}
} }

View file

@ -171,6 +171,7 @@ class LightningSendPage extends BasePage {
onPushPasteButton: (context) async { onPushPasteButton: (context) async {
output.resetParsedAddress(); output.resetParsedAddress();
await output.fetchParsedAddress(context); await output.fetchParsedAddress(context);
await send(context);
}, },
onPushAddressBookButton: (context) async { onPushAddressBookButton: (context) async {
output.resetParsedAddress(); output.resetParsedAddress();
@ -188,28 +189,11 @@ class LightningSendPage extends BasePage {
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
bottomSection: Column( bottomSection: Column(
children: <Widget>[ children: <Widget>[
LoadingPrimaryButton( PrimaryButton(
text: S.of(context).send, text: S.of(context).send,
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
textColor: Colors.white, textColor: Colors.white,
isLoading: lightningViewModel.loading, onPressed: () => send(context),
onPressed: () async {
try {
lightningViewModel.setLoading(true);
await processInput(context);
lightningViewModel.setLoading(false);
} catch (e) {
showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithOneAction(
alertTitle: S.of(context).error,
alertContent: e.toString(),
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
});
}
},
), ),
], ],
), ),
@ -219,6 +203,22 @@ class LightningSendPage extends BasePage {
); );
} }
Future<void> send(BuildContext context) async {
try {
await processInput(context);
} catch (e) {
showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithOneAction(
alertTitle: S.of(context).error,
alertContent: e.toString(),
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
});
}
}
Future<bool> _onNavigateBack(BuildContext context) async { Future<bool> _onNavigateBack(BuildContext context) async {
onClose(context); onClose(context);
return false; return false;

View file

@ -775,6 +775,8 @@ abstract class Lightning {
ReceivePageOption getOptionOnchain(); ReceivePageOption getOptionOnchain();
String bitcoinAmountToLightningString({required int amount}); String bitcoinAmountToLightningString({required int amount});
int bitcoinAmountToLightningAmount({required int amount}); int bitcoinAmountToLightningAmount({required int amount});
double bitcoinDoubleToLightningDouble({required double amount});
double lightningDoubleToBitcoinDouble({required double amount});
} }
"""; """;