transfer method
Transfers funds directly between two configured wallets.
BOLT11-capable wallets exchange a fresh invoice. A BOLT12-only receiver exposes its reusable offer and requires a BIP-321-capable sender.
Implementation
Future<WalletTransferResult> transfer({
required String sourceWalletId,
required String destinationWalletId,
int? amountMsat,
Duration? timeout,
}) async {
await _initializationFuture;
final source = await _getWalletForOperation(sourceWalletId);
final destination = await _getWalletForOperation(destinationWalletId);
final protocol = compatibleTransferProtocol(
source: source,
destination: destination,
);
if (protocol == null) {
throw UnsupportedError(
'The selected wallets have no compatible payment protocol',
);
}
if (amountMsat != null && amountMsat <= 0) {
throw ArgumentError.value(
amountMsat,
'amountMsat',
'Transfer amount must be positive',
);
}
if (protocol == WalletPaymentProtocol.bolt11 &&
(amountMsat == null || amountMsat % 1000 != 0)) {
throw ArgumentError.value(
amountMsat,
'amountMsat',
'BOLT11 wallet transfers require a positive whole-satoshi amount',
);
}
ReceiveResponse? receiveResponse;
late final String payment;
if (destination.supportsBip321Receive) {
receiveResponse = await receiveBip321(
walletId: destination.id,
amountMsat: amountMsat,
timeout: timeout,
);
payment = receiveResponse.bip321;
} else {
final invoice = await receive(
walletId: destination.id,
amountSats: amountMsat! ~/ 1000,
);
payment = Bip321.fromBolt11(invoice);
}
if (source.supportsBip321Pay) {
final payResponse = await payBip321(
walletId: source.id,
payment: payment,
amountMsat: amountMsat,
timeout: timeout,
);
if (payResponse.errorCode != null || payResponse.state == 'failed') {
throw StateError(
payResponse.errorMessage ??
payResponse.failureReason ??
'Wallet transfer failed',
);
}
final selectedProtocol = payResponse.instructionType == 'bolt12'
? WalletPaymentProtocol.bolt12
: WalletPaymentProtocol.bolt11;
await _refreshTransferredWalletData(source.id, destination.id);
return WalletTransferResult(
sourceWalletId: source.id,
destinationWalletId: destination.id,
protocol: selectedProtocol,
payment: payment,
receiveResponse: receiveResponse,
payResponse: payResponse,
);
}
final invoice = Bip321.getBolt11(payment);
final payInvoiceResponse = await send(
walletId: source.id,
invoice: invoice,
timeout: timeout,
);
if (payInvoiceResponse.errorCode != null) {
throw StateError(
payInvoiceResponse.errorMessage ?? 'Wallet transfer failed',
);
}
await _refreshTransferredWalletData(source.id, destination.id);
return WalletTransferResult(
sourceWalletId: source.id,
destinationWalletId: destination.id,
protocol: WalletPaymentProtocol.bolt11,
payment: payment,
receiveResponse: receiveResponse,
payInvoiceResponse: payInvoiceResponse,
);
}