Skip to content

Commit

Permalink
Create a faucet for the signet
Browse files Browse the repository at this point in the history
  • Loading branch information
dangershony committed Dec 17, 2023
1 parent 4a7b45b commit 92fa21b
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/Angor/Client/Pages/Wallet.razor
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@using Angor.Shared.Models
@using Angor.Client.Components

@inject HttpClient _httpClient;
@inject IClientStorage storage;
@inject IWalletStorage _walletStorage;
@inject ILogger<Wallet> Logger;
Expand Down Expand Up @@ -164,6 +165,9 @@
<h4 class="card-title">Receive Address</h4>
<p id="receive-address" class="card-text">@nextReceiveAddress</p>
<button class="btn btn-primary" onclick="@CopyNextReceiveAddress">Copy Address</button>

<button class="btn btn-secondary" @onclick="GetTestCoins">Get some test coins</button>

</div>

<ShowQrCode @ref="showQrCode" Data="@nextReceiveAddress" />
Expand Down Expand Up @@ -660,4 +664,29 @@
coinControlModal = true;
StateHasChanged();
}

private async Task GetTestCoins()
{
if (localAccountInfo.TotalBalance > 10)
{
notificationComponent.ShowNotificationMessage("you already have coins!");
}

var operationResult = await notificationComponent.LongOperation(async () =>
{

var res = await _httpClient.GetAsync($"/api/faucet/send/{localAccountInfo.GetNextReceiveAddress()}");

if (res.IsSuccessStatusCode)
return new OperationResult { Success = true };

return new OperationResult { Success = false,Message = await res.Content.ReadAsStringAsync()};
});

if (operationResult is { Success: true })
{
notificationComponent.ShowNotificationMessage("Success!");
}
}

}
142 changes: 142 additions & 0 deletions src/Angor/Server/FaucetController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using Angor.Server;
using Angor.Shared;
using Angor.Shared.Models;
using Angor.Shared.ProtocolNew;
using Blockcore.Consensus.TransactionInfo;
using Blockcore.NBitcoin.BIP39;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using Angor.Client.Services;
using Angor.Shared.Services;
using Blockcore.NBitcoin;
using Blockcore.NBitcoin.BIP32;
using Blockcore.Networks;
using ExtPubKey = Blockcore.NBitcoin.BIP32.ExtPubKey;
using Network = Blockcore.Networks.Network;
using static System.Runtime.InteropServices.JavaScript.JSType;
using TransactionBuilder = Blockcore.Consensus.TransactionInfo.TransactionBuilder;
using BitcoinWitPubKeyAddress = Blockcore.NBitcoin.BitcoinWitPubKeyAddress;
using Money = Blockcore.NBitcoin.Money;
using Transaction = Blockcore.Consensus.TransactionInfo.Transaction;

namespace Blockcore.AtomicSwaps.Server.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class FaucetController : ControllerBase
{
private readonly IWalletOperations _walletOperations;
private readonly IIndexerService _indexerService;
private readonly IHdOperations _hdOperations;
private readonly INetworkConfiguration _networkConfiguration;

private List<UtxoData> PendingUtxo = new ();

public FaucetController(IWalletOperations walletOperations, IIndexerService indexerService, IHdOperations hdOperations, INetworkConfiguration networkConfiguration)
{
_walletOperations = walletOperations;
_indexerService = indexerService;
_hdOperations = hdOperations;
_networkConfiguration = networkConfiguration;
}

[HttpGet]
[Route("send/{address}/{amount?}")]
public async Task<IActionResult> Send(string address, long? amount)
{
var network = _networkConfiguration.GetNetwork();

//var mnemonic = new Mnemonic(wrods);
var words = new WalletWords { Words = "margin radio diamond leg loud street announce guitar video shiver speed eyebrow" };

var accountInfo = _walletOperations.BuildAccountInfoForWalletWords(words);

// the miners address with all the utxos
var addressInfo = GenerateAddressFromPubKey(0, _networkConfiguration.GetNetwork(), false, ExtPubKey.Parse(accountInfo.ExtPubKey, _networkConfiguration.GetNetwork()));

List<UtxoDataWithPath> list = new();

if (!PendingUtxo.Any())
{
// we assume a miner wallet so for now just ignore amounts and send a utxo to the request address
var utxos = await _indexerService.FetchUtxoAsync(addressInfo.Address, 510, 5);

lock (PendingUtxo)
{
if (!PendingUtxo.Any())
{
PendingUtxo.AddRange(utxos);
}
}
}

lock (PendingUtxo)
{
list = new() { new UtxoDataWithPath { HdPath = addressInfo.HdPath, UtxoData = PendingUtxo.First() } };
PendingUtxo.Remove(PendingUtxo.First());
}

var (coins, keys) = _walletOperations.GetUnspentOutputsForTransaction(words, list);

Transaction trx = network.CreateTransaction();
trx.AddOutput(Money.Satoshis(list.First().UtxoData.value) - Money.Satoshis(10000), BitcoinWitPubKeyAddress.Create(address, network));
trx.AddInput(new TxIn { PrevOut = list.First().UtxoData.outpoint.ToOutPoint() });

var signedTransaction = new TransactionBuilder(network)
.AddCoins(coins)
.AddKeys(keys.ToArray())
.SignTransaction(trx);

var res = await _walletOperations.PublishTransactionAsync(network, signedTransaction);

if (res.Success)
{
return Ok();
}

return BadRequest(res.Message);
}

private AddressInfo GenerateAddressFromPubKey(int scanIndex, Network network, bool isChange, ExtPubKey accountExtPubKey)
{
var pubKey = _hdOperations.GeneratePublicKey(accountExtPubKey, scanIndex, isChange);
var path = _hdOperations.CreateHdPath(84, network.Consensus.CoinType, 0, isChange, scanIndex);
var address = pubKey.GetSegwitAddress(network).ToString();

return new AddressInfo { Address = address, HdPath = path };
}
}

public class NetworkServiceMock : INetworkService
{
public Task CheckServices(bool force = false)
{
throw new NotImplementedException();
}

public SettingsUrl GetPrimaryIndexer()
{
return new SettingsUrl { Url = "https://tbtc.indexer.angor.io" };
}

public SettingsUrl GetPrimaryRelay()
{
throw new NotImplementedException();
}

public List<SettingsUrl> GetRelays()
{
throw new NotImplementedException();
}

public void CheckAndHandleError(HttpResponseMessage httpResponseMessage)
{

}

public void HandleException(Exception exception)
{
throw exception;
}
}
}
6 changes: 6 additions & 0 deletions src/Angor/Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
using Angor.Client;
using Angor.Shared;
using Blockcore.AtomicSwaps.Server.Controllers;
using Angor.Client.Services;
using Angor.Shared.Services;

var builder = WebApplication.CreateBuilder(args);

Expand All @@ -20,7 +22,11 @@

// types needed to build investor sigs
builder.Services.AddSingleton<INetworkConfiguration, NetworkConfiguration>();
builder.Services.AddSingleton<INetworkService, NetworkServiceMock>();
builder.Services.AddSingleton<IHdOperations, HdOperations>();
builder.Services.AddSingleton<IWalletOperations, WalletOperations>();
builder.Services.AddSingleton<IIndexerService, IndexerService>();
builder.Services.AddSingleton<HttpClient>();
builder.Services.AddSingleton<IDerivationOperations, DerivationOperations>();
builder.Services.AddSingleton<IFounderTransactionActions, FounderTransactionActions>();
builder.Services.AddSingleton<ISeederTransactionActions, SeederTransactionActions>();
Expand Down

0 comments on commit 92fa21b

Please sign in to comment.