|
468 | 468 | @inject INBXplorerService NBXplorerService |
469 | 469 | @inject IFMUTXORepository FMUTXORepository |
470 | 470 | @inject IWalletWithdrawalRequestDestinationRepository WalletWithdrawalRequestDestinationRepository |
| 471 | +@inject ILogger<Withdrawals> Logger |
471 | 472 | @code { |
472 | 473 |
|
473 | 474 | [CascadingParameter] private ApplicationUser? LoggedUser { get; set; } |
|
628 | 629 |
|
629 | 630 | arg.Item.Wallet = null; |
630 | 631 | var addResult = await WalletWithdrawalRequestRepository.AddAsync(arg.Item); |
631 | | - |
632 | | - |
633 | 632 | if (addResult.Item1) |
634 | 633 | { |
635 | 634 | ToastService.ShowSuccess("Success"); |
|
707 | 706 | if (await ValidateBalance(arg)) return; |
708 | 707 |
|
709 | 708 | var updateResult = WalletWithdrawalRequestRepository.Update(arg.Item); |
710 | | - |
711 | | - |
712 | 709 | if (updateResult.Item1) |
713 | 710 | { |
714 | 711 | ToastService.ShowSuccess("Success"); |
|
779 | 776 |
|
780 | 777 | private async Task ShowApprovalModal(WalletWithdrawalRequest walletWithdrawalRequest) |
781 | 778 | { |
782 | | - _selectedRequest = walletWithdrawalRequest; |
| 779 | + _selectedRequest = await WalletWithdrawalRequestRepository.GetById(walletWithdrawalRequest.Id); |
783 | 780 |
|
784 | 781 | //PSBT Generation |
785 | 782 | try |
786 | 783 | { |
787 | | - if (_selectedRequest.BumpingWalletWithdrawalRequestId != null) |
788 | | - { |
789 | | - await CopyBumpedRequestData(_selectedRequest); |
790 | | - } |
791 | | - |
792 | 784 | var templatePSBT = await BitcoinService.GenerateTemplatePSBT(walletWithdrawalRequest); |
793 | 785 |
|
794 | 786 | //TODO Save template PSBT (?) |
|
799 | 791 | { |
800 | 792 | ToastService.ShowError("No UTXOs available for withdrawals were found for this wallet"); |
801 | 793 | } |
| 794 | + catch (BumpingException e) |
| 795 | + { |
| 796 | + ToastService.ShowError(e.Message); |
| 797 | + } |
| 798 | + catch (ShowToUserException e) |
| 799 | + { |
| 800 | + ToastService.ShowError(e.Message); |
| 801 | + _selectedRequest.Status = WalletWithdrawalRequestStatus.Failed; |
| 802 | + WalletWithdrawalRequestRepository.Update(_selectedRequest); |
| 803 | + await GetData(); |
| 804 | + StateHasChanged(); |
| 805 | + } |
802 | 806 | catch (Exception) |
803 | 807 | { |
804 | 808 | ToastService.ShowError("Error while generating PSBT template for the request"); |
|
904 | 908 | _selectedRequest = await WalletWithdrawalRequestRepository.GetById(_selectedRequest.Id); |
905 | 909 | if (_selectedRequest != null) |
906 | 910 | { |
907 | | - CreateJob(); |
| 911 | + await CreateJob(); |
| 912 | + if (_selectedRequest?.BumpingWalletWithdrawalRequestId != null) |
| 913 | + { |
| 914 | + await UpdateBumpWalletWithdrawalRequest(); |
| 915 | + } |
908 | 916 | } |
909 | 917 | } |
910 | 918 | catch |
|
929 | 937 | } |
930 | 938 | else |
931 | 939 | { |
932 | | - ToastService.ShowSuccess("Error while saving the signature"); |
| 940 | + ToastService.ShowError("Error while saving the signature"); |
933 | 941 | } |
934 | 942 |
|
935 | 943 | await _psbtSignRef.HideModal(); |
|
942 | 950 | { |
943 | 951 | _selectedMempoolRecommendedFeesType = newRequest.MempoolRecommendedFeesType; |
944 | 952 | _customSatPerVbAmount = (long)newRequest.CustomFeeRate; |
| 953 | + _selectedRequest = newRequest; |
945 | 954 | if (newRequest.Wallet.IsHotWallet) |
946 | 955 | { |
947 | 956 | await GetData(); |
948 | | - _selectedRequest = newRequest; |
949 | 957 | await _confirmationModal.ShowModal(); |
950 | 958 | return; |
951 | 959 | } |
952 | 960 |
|
953 | 961 | newRequest.Wallet = null; |
954 | | - var addResult = await WalletWithdrawalRequestRepository.AddAsync(newRequest); |
955 | 962 |
|
| 963 | + try { |
| 964 | + if (_selectedRequest.Id == 0) |
| 965 | + { |
| 966 | + var createWithdrawalResult = await WalletWithdrawalRequestRepository.AddAsync(_selectedRequest); |
| 967 | + if (!createWithdrawalResult.Item1) |
| 968 | + { |
| 969 | + throw new ShowToUserException(createWithdrawalResult.Item2); |
| 970 | + } |
| 971 | + } |
| 972 | + else |
| 973 | + { |
| 974 | + var updateResult = WalletWithdrawalRequestRepository.Update(_selectedRequest); |
| 975 | + if (!updateResult.Item1) |
| 976 | + { |
| 977 | + throw new ShowToUserException(updateResult.Item2); |
| 978 | + } |
| 979 | + } |
956 | 980 |
|
957 | | - if (addResult.Item1) |
958 | | - { |
959 | 981 | ToastService.ShowSuccess("Success"); |
960 | 982 | await GetData(); |
961 | 983 |
|
|
966 | 988 |
|
967 | 989 | _utxoSelectorModalRef.ClearModal(); |
968 | 990 | } |
969 | | - else |
| 991 | + catch (ShowToUserException e) |
970 | 992 | { |
971 | | - ToastService.ShowError("Something went wrong"); |
| 993 | + ToastService.ShowError(e.Message); |
972 | 994 | _userPendingRequests.Remove(newRequest); |
973 | 995 | } |
| 996 | + catch (Exception e) |
| 997 | + { |
| 998 | + Logger.LogError("Error creating a new withdrawal request for bumping fee: {Error}", e.Message); |
| 999 | + ToastService.ShowError("Something went wrong"); |
| 1000 | + } |
974 | 1001 | } |
975 | 1002 |
|
976 | 1003 | private async Task Bumpfee(WalletWithdrawalRequest request) |
|
991 | 1018 | { |
992 | 1019 | if (newRequest != null && _bumpfeeRef != null) |
993 | 1020 | { |
994 | | - newRequest.WalletId = _selectedRequest.WalletId; |
995 | 1021 | newRequest.Wallet = await WalletRepository.GetById(newRequest.WalletId); |
996 | 1022 |
|
997 | 1023 | // Use either the custom fee rate or the recommended fee rate based on mempool fee type |
|
1044 | 1070 |
|
1045 | 1071 | await Bumpfee(newRequest); |
1046 | 1072 | await _bumpfeeRef.HideModal(); |
| 1073 | + StateHasChanged(); |
1047 | 1074 | } |
1048 | 1075 | else |
1049 | 1076 | { |
|
1081 | 1108 | _selectedRequest.Status = (WalletWithdrawalRequestStatus) _rejectCancelStatus; |
1082 | 1109 |
|
1083 | 1110 | var updateResult = WalletWithdrawalRequestRepository.Update(_selectedRequest); |
1084 | | - |
1085 | | - if (updateResult.Item1 == false) |
| 1111 | + if (!updateResult.Item1) |
1086 | 1112 | { |
| 1113 | + Logger.LogError("Error while updating the withdrawal request status to cancelled/rejected: {Error}", updateResult.Item2); |
1087 | 1114 | ToastService.ShowError("Something went wrong"); |
1088 | 1115 | } |
1089 | 1116 |
|
| 1117 | + // In case that is a bump, we return the old request status to pending confirmation. |
| 1118 | + await ResetStatusBumpedIfError(_selectedRequest); |
| 1119 | + |
1090 | 1120 | await HideRejectCancelModal(); |
1091 | 1121 | } |
1092 | 1122 | } |
|
1151 | 1181 |
|
1152 | 1182 | private async Task CloseConfirmationModal() |
1153 | 1183 | { |
| 1184 | + if (_selectedRequest != null) |
| 1185 | + { |
| 1186 | + _selectedRequest.Status = WalletWithdrawalRequestStatus.Cancelled; |
| 1187 | + _selectedRequest.RejectCancelDescription = "User cancelled the operation"; |
| 1188 | + var updateResult = WalletWithdrawalRequestRepository.Update(_selectedRequest); |
| 1189 | + if (!updateResult.Item1) |
| 1190 | + { |
| 1191 | + Logger.LogError("Error while updating the withdrawal request status to cancelled: {Error}", updateResult.Item2); |
| 1192 | + ToastService.ShowError("Something went wrong"); |
| 1193 | + } |
| 1194 | + StateHasChanged(); |
| 1195 | + } |
1154 | 1196 | await _confirmationModal.CloseModal(); |
1155 | 1197 | } |
1156 | 1198 |
|
| 1199 | + private async Task UpdateBumpWalletWithdrawalRequest() |
| 1200 | + { |
| 1201 | + if (_selectedRequest == null) throw new BumpingException("Invalid request"); |
| 1202 | + |
| 1203 | + var outpoints = _selectedRequest.UTXOs.Select(u => OutPoint.Parse($"{u.TxId}:{u.OutputIndex}")).ToList(); |
| 1204 | + _selectedUTXOs = await CoinSelectionService.GetUTXOsByOutpointAsync(_selectedRequest.Wallet.GetDerivationStrategy()!, outpoints); |
| 1205 | + |
| 1206 | + // Update the status of the old withdrawal request |
| 1207 | + if (_selectedRequest.BumpingWalletWithdrawalRequestId != null) |
| 1208 | + { |
| 1209 | + _selectedRequest.BumpingWalletWithdrawalRequest = await WalletWithdrawalRequestRepository.GetById(_selectedRequest.BumpingWalletWithdrawalRequestId.Value); |
| 1210 | + if (_selectedRequest.BumpingWalletWithdrawalRequest == null) |
| 1211 | + { |
| 1212 | + throw new BumpingException("Could not find bumping withdrawal request"); |
| 1213 | + } |
| 1214 | + _selectedRequest.BumpingWalletWithdrawalRequest.Status = WalletWithdrawalRequestStatus.Bumped; |
| 1215 | + var updateResultOldWithdrawal = WalletWithdrawalRequestRepository.Update(_selectedRequest.BumpingWalletWithdrawalRequest); |
| 1216 | + if (!updateResultOldWithdrawal.Item1) |
| 1217 | + { |
| 1218 | + throw new BumpingException("Something went wrong"); |
| 1219 | + } |
| 1220 | + } |
| 1221 | + } |
| 1222 | + |
1157 | 1223 | private async Task SubmitConfirmationModal() |
1158 | 1224 | { |
1159 | 1225 | async Task CleanUp(string errorMessage) |
|
1170 | 1236 | { |
1171 | 1237 | try |
1172 | 1238 | { |
1173 | | - _selectedRequest.Wallet = null; |
| 1239 | + _selectedRequest.Wallet = await WalletRepository.GetById(_selectedRequest.WalletId); |
1174 | 1240 | _selectedRequest.WithdrawAllFunds = _isCheckedAllFunds || _amount == _selectedRequestWalletBalance; |
1175 | 1241 | _selectedRequest.MempoolRecommendedFeesType = _selectedMempoolRecommendedFeesType; |
1176 | 1242 | _selectedRequest.CustomFeeRate = _customSatPerVbAmount; |
1177 | 1243 |
|
1178 | | - var createWithdrawalResult = await WalletWithdrawalRequestRepository.AddAsync(_selectedRequest); |
1179 | | - if (!createWithdrawalResult.Item1) |
| 1244 | + if (_selectedRequest.Id == 0) |
1180 | 1245 | { |
1181 | | - throw new ShowToUserException(createWithdrawalResult.Item2); |
| 1246 | + var createWithdrawalResult = await WalletWithdrawalRequestRepository.AddAsync(_selectedRequest); |
| 1247 | + if (!createWithdrawalResult.Item1) |
| 1248 | + { |
| 1249 | + throw new ShowToUserException(createWithdrawalResult.Item2); |
| 1250 | + } |
| 1251 | + } |
| 1252 | + else |
| 1253 | + { |
| 1254 | + var updateResult = WalletWithdrawalRequestRepository.Update(_selectedRequest); |
| 1255 | + if (!updateResult.Item1) |
| 1256 | + { |
| 1257 | + throw new ShowToUserException(updateResult.Item2); |
| 1258 | + } |
1182 | 1259 | } |
1183 | 1260 |
|
1184 | 1261 | if (_selectedRequest.BumpingWalletWithdrawalRequestId != null) |
1185 | 1262 | { |
1186 | | - await CopyBumpedRequestData(_selectedRequest); |
| 1263 | + await UpdateBumpWalletWithdrawalRequest(); |
1187 | 1264 | } |
1188 | 1265 |
|
1189 | 1266 | _selectedRequest.Changeless = _selectedUTXOs.Count > 0; |
|
1205 | 1282 | }; |
1206 | 1283 |
|
1207 | 1284 | var addResult = await WalletWithdrawalRequestPsbtRepository.AddAsync(walletWithdrawalRequestPsbt); |
1208 | | - |
1209 | 1285 | if (!addResult.Item1) |
1210 | 1286 | { |
1211 | 1287 | throw new ShowToUserException("Error while saving the signature"); |
|
1232 | 1308 | } |
1233 | 1309 | catch (NoUTXOsAvailableException e) |
1234 | 1310 | { |
1235 | | - CleanUp("No UTXOs available for withdrawals were found for this wallet"); |
| 1311 | + await CleanUp("No UTXOs available for withdrawals were found for this wallet"); |
1236 | 1312 | await ResetStatusBumpedIfError(_selectedRequest); |
1237 | 1313 | } |
1238 | 1314 | catch (ShowToUserException e) |
1239 | 1315 | { |
1240 | | - CleanUp(e.Message); |
| 1316 | + await CleanUp(e.Message); |
| 1317 | + await ResetStatusBumpedIfError(_selectedRequest); |
| 1318 | + } |
| 1319 | + catch (BumpingException e) |
| 1320 | + { |
| 1321 | + await CleanUp(e.Message); |
1241 | 1322 | await ResetStatusBumpedIfError(_selectedRequest); |
1242 | 1323 | } |
1243 | | - catch |
| 1324 | + catch (Exception e) |
1244 | 1325 | { |
1245 | | - CleanUp("Something went wrong"); |
| 1326 | + Logger.LogError(e, "Error while creating withdrawal"); |
| 1327 | + await CleanUp("Something went wrong"); |
1246 | 1328 | await ResetStatusBumpedIfError(_selectedRequest); |
1247 | 1329 | } |
1248 | 1330 | } |
|
1390 | 1472 |
|
1391 | 1473 | return false; |
1392 | 1474 | } |
1393 | | - |
1394 | | - private async Task CopyBumpedRequestData(WalletWithdrawalRequest request) |
1395 | | - { |
1396 | | - WalletWithdrawalRequest originalRequest = await WalletWithdrawalRequestRepository.GetById((int)request.BumpingWalletWithdrawalRequestId); |
1397 | | - if (originalRequest == null) |
1398 | | - { |
1399 | | - throw new ShowToUserException("Original withdrawal request not found"); |
1400 | | - } |
1401 | | - |
1402 | | - // Get destinations from the original request |
1403 | | - List<WalletWithdrawalRequestDestination> originalDestinations = await WalletWithdrawalRequestDestinationRepository.GetByWalletWithdrawalRequestId(originalRequest.Id); |
1404 | | - if (originalDestinations == null || originalDestinations.Count == 0) |
1405 | | - { |
1406 | | - throw new ShowToUserException("Original withdrawal request destinations not found"); |
1407 | | - } |
1408 | | - |
1409 | | - request.WalletWithdrawalRequestDestinations = originalDestinations.Select(d => new WalletWithdrawalRequestDestination |
1410 | | - { |
1411 | | - Address = d.Address, |
1412 | | - Amount = d.Amount, |
1413 | | - WalletWithdrawalRequestId = request.Id |
1414 | | - }).ToList(); |
1415 | | - |
1416 | | - // Get utxos from the original request |
1417 | | - List<FMUTXO> mUTXOs = await FMUTXORepository.GetLockedUTXOsByWithdrawalId(originalRequest.Id); |
1418 | | - |
1419 | | - request.UTXOs = mUTXOs; |
1420 | | - List<OutPoint> outpoints = new List<OutPoint>(); |
1421 | | - mUTXOs.ForEach(u => { |
1422 | | - OutPoint o; |
1423 | | - if (OutPoint.TryParse($"{u.TxId}:{u.OutputIndex}", out o)) |
1424 | | - outpoints.Add(o); |
1425 | | - else |
1426 | | - throw new FormatException("Failed to parse OutPoint from TxId and OutputIndex"); |
1427 | | - }); |
1428 | | - _selectedUTXOs = await CoinSelectionService.GetUTXOsByOutpointAsync(originalRequest.Wallet.GetDerivationStrategy(), outpoints); |
1429 | | - originalRequest.Status = WalletWithdrawalRequestStatus.Bumped; |
1430 | | - |
1431 | | - var updateResult = WalletWithdrawalRequestRepository.Update(request); |
1432 | | - if (!updateResult.Item1) |
1433 | | - { |
1434 | | - ToastService.ShowError("Something went wrong"); |
1435 | | - return; |
1436 | | - } |
1437 | | - |
1438 | | - updateResult = WalletWithdrawalRequestRepository.Update(originalRequest); |
1439 | | - if (!updateResult.Item1) |
1440 | | - { |
1441 | | - ToastService.ShowError("Something went wrong"); |
1442 | | - return; |
1443 | | - } |
1444 | | - } |
1445 | 1475 | } |
0 commit comments