Test Wallet Receive, Send with NBX, Coin selection

This commit is contained in:
nicolas.dorier 2020-03-23 15:46:54 +09:00
parent 40953ef2c6
commit 805e1f53b3
No known key found for this signature in database
GPG key ID: 6618763EF09186FE
6 changed files with 87 additions and 30 deletions

View file

@ -121,7 +121,7 @@ namespace BTCPayServer.Tests
return (usr, Driver.FindElement(By.Id("Id")).GetAttribute("value"));
}
public string GenerateWallet(string cryptoCode = "BTC", string seed = "", bool importkeys = false, bool privkeys = false)
public Mnemonic GenerateWallet(string cryptoCode = "BTC", string seed = "", bool importkeys = false, bool privkeys = false)
{
Driver.FindElement(By.Id($"Modify{cryptoCode}")).ForceClick();
Driver.FindElement(By.Id("import-from-btn")).ForceClick();
@ -138,7 +138,7 @@ namespace BTCPayServer.Tests
}
Driver.FindElement(By.Id("Confirm")).ForceClick();
AssertHappyMessage();
return seed;
return new Mnemonic(seed);
}
public void AddDerivationScheme(string cryptoCode = "BTC", string derivationScheme = "xpub661MyMwAqRbcGABgHMUXDzPzH1tU7eZaAaJQXhDXsSxsqyQzQeU6kznNfSuAyqAK9UaWSaZaMFdNiY5BCF4zBPAzSnwfUAwUhwttuAKwfRX-[legacy]")
@ -339,6 +339,14 @@ namespace BTCPayServer.Tests
}
public void GoToWalletSend(WalletId walletId)
{
Driver.Navigate().GoToUrl(new Uri(Server.PayTester.ServerUri, $"wallets/{walletId}/send"));
}
internal void GoToWalletReceive(WalletId walletId)
{
Driver.Navigate().GoToUrl(new Uri(Server.PayTester.ServerUri, $"wallets/{walletId}/receive"));
}
}
}

View file

@ -11,6 +11,7 @@ using System.Threading.Tasks;
using System.Text.RegularExpressions;
using BTCPayServer.Models;
using NBitcoin.Payment;
using BTCPayServer.Controllers;
namespace BTCPayServer.Tests
{
@ -417,7 +418,54 @@ namespace BTCPayServer.Tests
s.Driver.Quit();
}
}
[Fact(Timeout = TestTimeout)]
public async Task CanUseCoinSelection()
{
using (var s = SeleniumTester.Create())
{
await s.StartAsync();
var userId = s.RegisterNewUser(true);
var storeId = s.CreateNewStore().storeId;
s.GenerateWallet("BTC", "", false, true);
var walletId = new WalletId(storeId, "BTC");
s.GoToWalletReceive(walletId);
s.Driver.FindElement(By.Id("generateButton")).Click();
var addressStr = s.Driver.FindElement(By.Id("vue-address")).GetProperty("value");
var address = BitcoinAddress.Create(addressStr, ((BTCPayNetwork)s.Server.NetworkProvider.GetNetwork("BTC")).NBitcoinNetwork);
await s.Server.ExplorerNode.GenerateAsync(1);
for (int i = 0; i < 6; i++)
{
await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(1.0m));
}
var targetTx = await s.Server.ExplorerNode.SendToAddressAsync(address, Money.Coins(1.2m));
var tx = await s.Server.ExplorerNode.GetRawTransactionAsync(targetTx);
var spentOutpoint = new OutPoint(targetTx, tx.Outputs.FindIndex(txout => txout.Value == Money.Coins(1.2m)));
await s.Server.ExplorerNode.GenerateAsync(1);
s.GoToWalletSend(walletId);
s.Driver.FindElement(By.Id("advancedSettings")).Click();
s.Driver.FindElement(By.Id("toggleInputSelection")).Click();
s.Driver.WaitForElement(By.Id(spentOutpoint.ToString()));
await Task.Delay(1000);
var el = s.Driver.FindElement(By.Id(spentOutpoint.ToString()));
s.Driver.FindElement(By.Id(spentOutpoint.ToString())).Click();
var bob = new Key().PubKey.Hash.GetAddress(Network.RegTest);
SetTransactionOutput(s, 0, bob, 0.3m);
s.Driver.FindElement(By.Id("SendMenu")).Click();
s.Driver.FindElement(By.Id("spendWithNBxplorer")).Click();
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).ForceClick();
var happyElement = s.AssertHappyMessage();
var happyText = happyElement.Text;
var txid = Regex.Match(happyText, @"\((.*)\)").Groups[1].Value;
tx = await s.Server.ExplorerNode.GetRawTransactionAsync(new uint256(txid));
Assert.Single(tx.Inputs);
Assert.Equal(spentOutpoint, tx.Inputs[0].PrevOut);
}
}
[Fact(Timeout = TestTimeout)]
public async Task CanManageWallet()
{
@ -488,7 +536,7 @@ namespace BTCPayServer.Tests
var mnemonic = s.GenerateWallet("BTC", "", true, true);
//lets import and save private keys
var root = new Mnemonic(mnemonic).DeriveExtKey();
var root = mnemonic.DeriveExtKey();
invoiceId = s.CreateInvoice(storeId.storeId);
invoice = await s.Server.PayTester.InvoiceRepository.GetInvoice( invoiceId);
address = invoice.EntityToDTO().Addresses["BTC"];
@ -518,18 +566,18 @@ namespace BTCPayServer.Tests
Assert.Contains(tx.ToString(), s.Driver.PageSource);
void SignWith(string signingSource)
void SignWith(Mnemonic signingSource)
{
// Send to bob
s.Driver.FindElement(By.Id("WalletSend")).Click();
var bob = new Key().PubKey.Hash.GetAddress(Network.RegTest);
SetTransactionOutput(0, bob, 1);
SetTransactionOutput(s, 0, bob, 1);
s.Driver.ScrollTo(By.Id("SendMenu"));
s.Driver.FindElement(By.Id("SendMenu")).ForceClick();
s.Driver.FindElement(By.CssSelector("button[value=seed]")).Click();
// Input the seed
s.Driver.FindElement(By.Id("SeedOrKey")).SendKeys(signingSource + Keys.Enter);
s.Driver.FindElement(By.Id("SeedOrKey")).SendKeys(signingSource.ToString() + Keys.Enter);
// Broadcast
Assert.Contains(bob.ToString(), s.Driver.PageSource);
@ -537,19 +585,6 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.CssSelector("button[value=broadcast]")).ForceClick();
Assert.Equal(walletTransactionLink, s.Driver.Url);
}
void SetTransactionOutput(int index, BitcoinAddress dest, decimal amount, bool subtract = false)
{
s.Driver.FindElement(By.Id($"Outputs_{index}__DestinationAddress")).SendKeys(dest.ToString());
var amountElement = s.Driver.FindElement(By.Id($"Outputs_{index}__Amount"));
amountElement.Clear();
amountElement.SendKeys(amount.ToString());
var checkboxElement = s.Driver.FindElement(By.Id($"Outputs_{index}__SubtractFeesFromOutput"));
if (checkboxElement.Selected != subtract)
{
checkboxElement.Click();
}
}
SignWith(mnemonic);
@ -558,7 +593,7 @@ namespace BTCPayServer.Tests
s.Driver.FindElement(By.Id("WalletSend")).Click();
var jack = new Key().PubKey.Hash.GetAddress(Network.RegTest);
SetTransactionOutput(0, jack, 0.01m);
SetTransactionOutput(s, 0, jack, 0.01m);
s.Driver.ScrollTo(By.Id("SendMenu"));
s.Driver.FindElement(By.Id("SendMenu")).ForceClick();
@ -589,5 +624,17 @@ namespace BTCPayServer.Tests
}
}
void SetTransactionOutput(SeleniumTester s, int index, BitcoinAddress dest, decimal amount, bool subtract = false)
{
s.Driver.FindElement(By.Id($"Outputs_{index}__DestinationAddress")).SendKeys(dest.ToString());
var amountElement = s.Driver.FindElement(By.Id($"Outputs_{index}__Amount"));
amountElement.Clear();
amountElement.SendKeys(amount.ToString());
var checkboxElement = s.Driver.FindElement(By.Id($"Outputs_{index}__SubtractFeesFromOutput"));
if (checkboxElement.Selected != subtract)
{
checkboxElement.Click();
}
}
}
}

View file

@ -67,6 +67,8 @@ namespace BTCPayServer.Data
public static IEnumerable<ISupportedPaymentMethod> GetSupportedPaymentMethods(this StoreData storeData, BTCPayNetworkProvider networks)
{
if (storeData == null)
throw new ArgumentNullException(nameof(storeData));
networks = networks.UnfilteredNetworks;
#pragma warning disable CS0618
bool btcReturned = false;

View file

@ -25,12 +25,12 @@
:key="item.outpoint"
v-bind:class="{ 'alert-success': item.selected }"
v-on:click="toggleItem($event, item, !item.selected)">
<a
v-on:click="toggleItem($event, item, !item.selected)" class="text-truncate" v-tooltip="item.outpoint" style="max-width:50%" v-bind:href="item.link" target="_blank">{{item.outpoint}}</a>
<div class="d-flex justify-content-between align-items-center">
<a v-on:click="toggleItem($event, item, !item.selected)" class="text-truncate" v-tooltip="item.outpoint" style="max-width:50%" v-bind:href="item.link" target="_blank">{{item.outpoint}}</a>
<div :id="item.outpoint" class="d-flex justify-content-between align-items-center">
<div>
<span v-if="item.comment" data-toggle="tooltip" v-tooltip="item.comment" class="badge badge-info badge-pill" style="font-style: italic">i</span>
<span v-if="item.labels"
<span
v-if="item.labels"
class="badge badge-primary badge-pill ml-1"
v-for="label of item.labels"
v-bind:style="{ 'background-color': label.color}"

View file

@ -21,7 +21,7 @@
{
<h3 class="card-title mb-3">Receive @Model.CryptoCode</h3>
<button class="btn btn-lg btn-primary" type="submit" name="command" value="generate-new-address">Generate @Model.CryptoCode address</button>
<button id="generateButton" class="btn btn-lg btn-primary" type="submit" name="command" value="generate-new-address">Generate @Model.CryptoCode address</button>
}
else
{

View file

@ -43,7 +43,7 @@
<select multiple="multiple" asp-for="SelectedInputs" >
@foreach (var input in Model.InputsAvailable)
{
<option value="@input.Outpoint" asp-selected="@(Model.SelectedInputs?.Contains(input.Outpoint)??false)">@input.Outpoint <span>@input.Amount</span> </option>
<option value="@input.Outpoint" asp-selected="@(Model.SelectedInputs?.Contains(input.Outpoint)??false)">@input.Outpoint (@input.Amount)</option>
}
</select>
</div>
@ -144,7 +144,7 @@
}
<div class="card">
<button class="btn btn-light collapsed" type="button" data-toggle="collapse" data-target="#accordian-advanced" aria-expanded="false" aria-controls="accordian-advanced">
<button id="advancedSettings" class="btn btn-light collapsed" type="button" data-toggle="collapse" data-target="#accordian-advanced" aria-expanded="false" aria-controls="accordian-advanced">
Advanced settings
</button>
<div id="accordian-advanced" class="collapse" aria-labelledby="accordian-advanced-header" data-parent="#accordian-advanced">
@ -167,7 +167,7 @@
</div>
}
<div class="form-group">
<button type="submit" name="command" value="toggle-input-selection" class="btn btn-sm btn-secondary">Toggle coin selection</button>
<button id="toggleInputSelection" type="submit" name="command" value="toggle-input-selection" class="btn btn-sm btn-secondary">Toggle coin selection</button>
</div>
</div>
</div>
@ -186,7 +186,7 @@
}
@if (Model.NBXSeedAvailable)
{
<button name="command" type="submit" class="dropdown-item" value="nbx-seed">... the seed saved in NBXplorer</button>
<button id="spendWithNBxplorer" name="command" type="submit" class="dropdown-item" value="nbx-seed">... the seed saved in NBXplorer</button>
}
</div>
</div>