WIP: integration with ledger
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/models/payment/asset.dart';
|
||||
import 'package:pshared/models/payment/chain_network.dart';
|
||||
import 'package:pshared/models/payment/currency_pair.dart';
|
||||
@@ -9,66 +8,109 @@ import 'package:pshared/models/payment/kind.dart';
|
||||
import 'package:pshared/models/payment/methods/card.dart';
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/methods/iban.dart';
|
||||
import 'package:pshared/models/payment/methods/ledger.dart';
|
||||
import 'package:pshared/models/payment/methods/managed_wallet.dart';
|
||||
import 'package:pshared/models/payment/methods/russian_bank.dart';
|
||||
import 'package:pshared/models/payment/source.dart';
|
||||
import 'package:pshared/models/payment/methods/type.dart';
|
||||
import 'package:pshared/models/money.dart';
|
||||
import 'package:pshared/models/payment/settlement_mode.dart';
|
||||
import 'package:pshared/models/payment/intent.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/controllers/payment/source.dart';
|
||||
import 'package:pshared/provider/payment/amount.dart';
|
||||
import 'package:pshared/provider/payment/flow.dart';
|
||||
import 'package:pshared/provider/recipient/provider.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
|
||||
|
||||
class QuotationIntentBuilder {
|
||||
PaymentIntent? build({
|
||||
required PaymentAmountProvider payment,
|
||||
required WalletsController wallets,
|
||||
required PaymentSourceController sources,
|
||||
required PaymentFlowProvider flow,
|
||||
required RecipientsProvider recipients,
|
||||
}) {
|
||||
final selectedWallet = wallets.selectedWallet;
|
||||
final selectedSource = sources.selectedSource;
|
||||
final paymentData = flow.selectedPaymentData;
|
||||
final selectedMethod = flow.selectedMethod;
|
||||
if (selectedWallet == null || paymentData == null) return null;
|
||||
if (selectedSource == null || paymentData == null) return null;
|
||||
|
||||
final customer = _buildCustomer(
|
||||
recipient: recipients.currentObject,
|
||||
method: selectedMethod,
|
||||
data: paymentData,
|
||||
);
|
||||
final sourceCurrency = _resolveSourceCurrency(selectedSource);
|
||||
if (sourceCurrency == null) return null;
|
||||
final targetCurrency = _resolveTargetCurrency(paymentData);
|
||||
final fxIntent = _buildFxIntent(
|
||||
baseCurrency: sourceCurrency,
|
||||
quoteCurrency: targetCurrency,
|
||||
);
|
||||
final amount = Money(
|
||||
amount: payment.amount.toString(),
|
||||
// TODO: adapt to possible other sources
|
||||
currency: currencyCodeToString(selectedWallet.currency),
|
||||
);
|
||||
final fxIntent = FxIntent(
|
||||
pair: CurrencyPair(
|
||||
base: currencyCodeToString(selectedWallet.currency),
|
||||
quote: 'RUB', // TODO: exentd target currencies
|
||||
),
|
||||
side: FxSide.sellBaseBuyQuote,
|
||||
currency: sourceCurrency,
|
||||
);
|
||||
return PaymentIntent(
|
||||
kind: PaymentKind.payout,
|
||||
amount: amount,
|
||||
destination: paymentData,
|
||||
source: ManagedWalletPaymentMethod(
|
||||
managedWalletRef: selectedWallet.id,
|
||||
asset: PaymentAsset(
|
||||
tokenSymbol: selectedWallet.tokenSymbol ?? '',
|
||||
chain: selectedWallet.network ?? ChainNetwork.unspecified,
|
||||
)
|
||||
),
|
||||
source: _buildSourceEndpoint(selectedSource),
|
||||
fx: fxIntent,
|
||||
settlementMode: payment.payerCoversFee ? SettlementMode.fixReceived : SettlementMode.fixSource,
|
||||
settlementCurrency: _resolveSettlementCurrency(amount: amount, fx: fxIntent),
|
||||
settlementMode: payment.payerCoversFee
|
||||
? SettlementMode.fixReceived
|
||||
: SettlementMode.fixSource,
|
||||
settlementCurrency: _resolveSettlementCurrency(
|
||||
amount: amount,
|
||||
fx: fxIntent,
|
||||
),
|
||||
customer: customer,
|
||||
);
|
||||
}
|
||||
|
||||
String _resolveTargetCurrency(PaymentMethodData destination) {
|
||||
// Current payout flow is RUB-settlement oriented.
|
||||
// Avoid requesting unsupported self-pairs (e.g. RUB/RUB).
|
||||
return 'RUB';
|
||||
}
|
||||
|
||||
FxIntent? _buildFxIntent({
|
||||
required String baseCurrency,
|
||||
required String quoteCurrency,
|
||||
}) {
|
||||
final base = baseCurrency.trim().toUpperCase();
|
||||
final quote = quoteCurrency.trim().toUpperCase();
|
||||
if (base.isEmpty || quote.isEmpty || base == quote) {
|
||||
return null;
|
||||
}
|
||||
return FxIntent(
|
||||
pair: CurrencyPair(base: base, quote: quote),
|
||||
side: FxSide.sellBaseBuyQuote,
|
||||
);
|
||||
}
|
||||
|
||||
String? _resolveSourceCurrency(PaymentSource source) {
|
||||
return switch (source.type) {
|
||||
PaymentSourceType.wallet => currencyCodeToString(source.wallet!.currency),
|
||||
PaymentSourceType.ledger => source.ledgerAccount?.currency,
|
||||
};
|
||||
}
|
||||
|
||||
PaymentMethodData _buildSourceEndpoint(PaymentSource source) {
|
||||
return switch (source.type) {
|
||||
PaymentSourceType.wallet => ManagedWalletPaymentMethod(
|
||||
managedWalletRef: source.wallet!.id,
|
||||
asset: PaymentAsset(
|
||||
tokenSymbol: source.wallet?.tokenSymbol ?? '',
|
||||
chain: source.wallet?.network ?? ChainNetwork.unspecified,
|
||||
),
|
||||
),
|
||||
PaymentSourceType.ledger => LedgerPaymentMethod(
|
||||
ledgerAccountRef: source.ledgerAccount!.ledgerAccountRef,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
String _resolveSettlementCurrency({
|
||||
required Money amount,
|
||||
required FxIntent? fx,
|
||||
@@ -85,8 +127,12 @@ class QuotationIntentBuilder {
|
||||
case FxSide.unspecified:
|
||||
break;
|
||||
}
|
||||
if (amount.currency == pair.base && pair.quote.isNotEmpty) return pair.quote;
|
||||
if (amount.currency == pair.quote && pair.base.isNotEmpty) return pair.base;
|
||||
if (amount.currency == pair.base && pair.quote.isNotEmpty) {
|
||||
return pair.quote;
|
||||
}
|
||||
if (amount.currency == pair.quote && pair.base.isNotEmpty) {
|
||||
return pair.base;
|
||||
}
|
||||
if (pair.quote.isNotEmpty) return pair.quote;
|
||||
if (pair.base.isNotEmpty) return pair.base;
|
||||
}
|
||||
@@ -111,8 +157,9 @@ class QuotationIntentBuilder {
|
||||
: name.trim().split(RegExp(r'\s+'));
|
||||
final firstName = parts.isNotEmpty ? parts.first : null;
|
||||
final lastName = parts.length >= 2 ? parts.last : null;
|
||||
final middleName =
|
||||
parts.length > 2 ? parts.sublist(1, parts.length - 1).join(' ') : null;
|
||||
final middleName = parts.length > 2
|
||||
? parts.sublist(1, parts.length - 1).join(' ')
|
||||
: null;
|
||||
|
||||
return Customer(
|
||||
id: id,
|
||||
@@ -139,7 +186,9 @@ class QuotationIntentBuilder {
|
||||
return iban.accountHolder.trim();
|
||||
}
|
||||
|
||||
final bank = method?.bankAccountData ?? (data is RussianBankAccountPaymentMethod ? data : null);
|
||||
final bank =
|
||||
method?.bankAccountData ??
|
||||
(data is RussianBankAccountPaymentMethod ? data : null);
|
||||
if (bank != null && bank.recipientName.trim().isNotEmpty) {
|
||||
return bank.recipientName.trim();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user