|
1 | 1 | using System;
|
| 2 | +using System.Collections.Generic; |
| 3 | +using System.Linq; |
| 4 | +using System.Reflection; |
| 5 | +using System.Threading; |
| 6 | +using System.Threading.Tasks; |
| 7 | +using NBitcoin; |
| 8 | +using Newtonsoft.Json; |
| 9 | +using Newtonsoft.Json.Linq; |
| 10 | +using WalletWasabi.Helpers; |
| 11 | +using WalletWasabi.JsonConverters; |
| 12 | +using WalletWasabi.Wallets; |
| 13 | + |
2 | 14 | namespace Chaincase.Common.Services
|
3 | 15 | {
|
4 |
| - public class P2EPRequestHandler |
5 |
| - { |
6 |
| - public P2EPRequestHandler() |
7 |
| - { |
8 |
| - } |
9 |
| - } |
| 16 | + public class P2EPRequestHandler |
| 17 | + { |
| 18 | + public P2EPRequestHandler(Network network, WalletManager walletManager, int privacyLevelThreshold) |
| 19 | + { |
| 20 | + Network = network; |
| 21 | + WalletManager = walletManager; |
| 22 | + PrivacyLevelThreshold = privacyLevelThreshold; |
| 23 | + } |
| 24 | + |
| 25 | + public Network Network { get; } |
| 26 | + public WalletManager WalletManager { get; } |
| 27 | + public int PrivacyLevelThreshold { get; } |
| 28 | + |
| 29 | + public Task<string> HandleAsync(string body, CancellationToken cancellationToken) |
| 30 | + { |
| 31 | + if (!PSBT.TryParse(body, Network, out var psbt)) |
| 32 | + { |
| 33 | + throw new Exception("What the heck are you trying to do?"); |
| 34 | + } |
| 35 | + if (!psbt.IsAllFinalized()) |
| 36 | + { |
| 37 | + throw new Exception("The PSBT should be finalized"); |
| 38 | + } |
| 39 | + |
| 40 | + var toUse = WalletManager.GetWallets() |
| 41 | + .Where(x => x.State == WalletState.Started && !x.KeyManager.IsWatchOnly && !x.KeyManager.IsHardwareWallet) |
| 42 | + .SelectMany(wallet => wallet.Coins.Select(coin => new { wallet.KeyManager, coin })) |
| 43 | + .Where(x => x.coin.AnonymitySet >= PrivacyLevelThreshold && !x.coin.Unavailable) |
| 44 | + .OrderBy(x => x.coin.IsBanned) |
| 45 | + .ThenBy(x => x.coin.Confirmed) |
| 46 | + .ThenBy(x => x.coin.Height) |
| 47 | + .First(); |
| 48 | + |
| 49 | + var originalFeeRate = psbt.GetEstimatedFeeRate(); |
| 50 | + var paymentTx = psbt.ExtractTransaction(); |
| 51 | + foreach (var input in paymentTx.Inputs) |
| 52 | + { |
| 53 | + input.WitScript = WitScript.Empty; |
| 54 | + } |
| 55 | + var serverCoinKey = toUse.KeyManager.GetSecrets("", toUse.coin.ScriptPubKey).First(); |
| 56 | + var serverCoin = toUse.coin.GetCoin(); |
| 57 | + paymentTx.Inputs.Add(serverCoin.Outpoint); |
| 58 | + var paymentOutput = paymentTx.Outputs.First(); |
| 59 | + var inputSizeInVBytes = (int)Math.Ceiling(((3 * Constants.P2wpkhInputSizeInBytes) + Constants.P2pkhInputSizeInBytes) / 4m); |
| 60 | + paymentOutput.Value += (Money)serverCoin.Amount - originalFeeRate.GetFee(inputSizeInVBytes); |
| 61 | + var newPsbt = PSBT.FromTransaction(paymentTx, Network.Main); |
| 62 | + var serverCoinToSign = newPsbt.Inputs.FindIndexedInput(serverCoin.Outpoint); |
| 63 | + serverCoinToSign.UpdateFromCoin(serverCoin); |
| 64 | + serverCoinToSign.Sign(serverCoinKey.PrivateKey); |
| 65 | + serverCoinToSign.FinalizeInput(); |
| 66 | + |
| 67 | + return Task.FromResult(newPsbt.ToHex()); |
| 68 | + } |
| 69 | + } |
10 | 70 | }
|
0 commit comments