Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
gruve-p committed Dec 12, 2024
2 parents c8fd149 + d4b7682 commit 13ace02
Show file tree
Hide file tree
Showing 84 changed files with 2,343 additions and 682 deletions.
1 change: 0 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ jobs:
docker buildx create --use
DOCKER_BUILDX_OPTS="--platform linux/amd64,linux/arm64,linux/arm/v7 --build-arg GIT_COMMIT=${GIT_COMMIT} --push"
docker buildx build $DOCKER_BUILDX_OPTS -t $DOCKERHUB_REPO:$LATEST_TAG .
docker buildx build $DOCKER_BUILDX_OPTS -t $DOCKERHUB_REPO:$LATEST_TAG-altcoins --build-arg CONFIGURATION_NAME=Altcoins-Release .
workflows:
version: 2
build_and_test:
Expand Down
5 changes: 4 additions & 1 deletion BTCPayServer.Data/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
Expand Down Expand Up @@ -61,6 +63,7 @@ public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
public DbSet<LightningAddressData> LightningAddresses { get; set; }
public DbSet<PayoutProcessorData> PayoutProcessors { get; set; }
public DbSet<FormData> Forms { get; set; }
public DbSet<PendingTransaction> PendingTransactions { get; set; }

protected override void OnModelCreating(ModelBuilder builder)
{
Expand Down Expand Up @@ -106,7 +109,7 @@ protected override void OnModelCreating(ModelBuilder builder)
WebhookData.OnModelCreating(builder, Database);
FormData.OnModelCreating(builder, Database);
StoreRole.OnModelCreating(builder, Database);
PendingTransaction.OnModelCreating(builder, Database);
}
}

}
63 changes: 63 additions & 0 deletions BTCPayServer.Data/Data/PendingTransaction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace BTCPayServer.Data;

public class PendingTransaction: IHasBlob<PendingTransactionBlob>
{
public string TransactionId { get; set; }
public string CryptoCode { get; set; }
public string StoreId { get; set; }
public StoreData Store { get; set; }
public DateTimeOffset? Expiry { get; set; }
public PendingTransactionState State { get; set; }
public string[] OutpointsUsed { get; set; }

[NotMapped][Obsolete("Use Blob2 instead")]
public byte[] Blob { get; set; }

public string Blob2 { get; set; }


internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
{
builder.Entity<PendingTransaction>()
.HasOne(o => o.Store)
.WithMany(i => i.PendingTransactions)
.HasForeignKey(i => i.StoreId)
.OnDelete(DeleteBehavior.Cascade);

builder.Entity<PendingTransaction>().HasKey(transaction => new {transaction.CryptoCode, transaction.TransactionId});

builder.Entity<PendingTransaction>()
.Property(o => o.Blob2)
.HasColumnType("JSONB");
builder.Entity<PendingTransaction>()
.Property(o => o.OutpointsUsed)
.HasColumnType("text[]");
}
}
public enum PendingTransactionState
{
Pending,
Cancelled,
Expired,
Invalidated,
Signed,
Broadcast
}

public class PendingTransactionBlob
{
public string PSBT { get; set; }
public List<CollectedSignature> CollectedSignatures { get; set; } = new();
}

public class CollectedSignature
{
public DateTimeOffset Timestamp { get; set; }
public string ReceivedPSBT { get; set; }
}
1 change: 1 addition & 0 deletions BTCPayServer.Data/Data/StoreData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class StoreData
public IEnumerable<FormData> Forms { get; set; }
public IEnumerable<StoreRole> StoreRoles { get; set; }
public bool Archived { get; set; }
public IEnumerable<PendingTransaction> PendingTransactions { get; set; }

internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace BTCPayServer.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20241029163147_AddingPendingTransactionsTable")]
public partial class AddingPendingTransactionsTable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "PendingTransactions",
columns: table => new
{
TransactionId = table.Column<string>(type: "text", nullable: false),
CryptoCode = table.Column<string>(type: "text", nullable: false),
StoreId = table.Column<string>(type: "text", nullable: true),
Expiry = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
State = table.Column<int>(type: "integer", nullable: false),
OutpointsUsed = table.Column<string[]>(type: "text[]", nullable: true),
Blob2 = table.Column<string>(type: "JSONB", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PendingTransactions", x => new { x.CryptoCode, x.TransactionId });
table.ForeignKey(
name: "FK_PendingTransactions_Stores_StoreId",
column: x => x.StoreId,
principalTable: "Stores",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateIndex(
name: "IX_PendingTransactions_StoreId",
table: "PendingTransactions",
column: "StoreId");
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PendingTransactions");
}
}
}
42 changes: 42 additions & 0 deletions BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,36 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("PayoutProcessors");
});

modelBuilder.Entity("BTCPayServer.Data.PendingTransaction", b =>
{
b.Property<string>("CryptoCode")
.HasColumnType("text");

b.Property<string>("TransactionId")
.HasColumnType("text");

b.Property<string>("Blob2")
.HasColumnType("JSONB");

b.Property<DateTimeOffset?>("Expiry")
.HasColumnType("timestamp with time zone");

b.Property<string[]>("OutpointsUsed")
.HasColumnType("text[]");

b.Property<int>("State")
.HasColumnType("integer");

b.Property<string>("StoreId")
.HasColumnType("text");

b.HasKey("CryptoCode", "TransactionId");

b.HasIndex("StoreId");

b.ToTable("PendingTransactions");
});

modelBuilder.Entity("BTCPayServer.Data.PlannedTransaction", b =>
{
b.Property<string>("Id")
Expand Down Expand Up @@ -1324,6 +1354,16 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Navigation("Store");
});

modelBuilder.Entity("BTCPayServer.Data.PendingTransaction", b =>
{
b.HasOne("BTCPayServer.Data.StoreData", "Store")
.WithMany("PendingTransactions")
.HasForeignKey("StoreId")
.OnDelete(DeleteBehavior.Cascade);

b.Navigation("Store");
});

modelBuilder.Entity("BTCPayServer.Data.PullPaymentData", b =>
{
b.HasOne("BTCPayServer.Data.StoreData", "StoreData")
Expand Down Expand Up @@ -1582,6 +1622,8 @@ protected override void BuildModel(ModelBuilder modelBuilder)

b.Navigation("Payouts");

b.Navigation("PendingTransactions");

b.Navigation("PullPayments");

b.Navigation("Settings");
Expand Down
13 changes: 6 additions & 7 deletions BTCPayServer.Rating/Providers/BareBitcoinRateProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class BareBitcoinRateProvider : IRateProvider
{
private readonly HttpClient _httpClient;

public RateSourceInfo RateSourceInfo => new("barebitcoin", "Bare Bitcoin", "https://api.bb.no/price");
public RateSourceInfo RateSourceInfo => new("barebitcoin", "Bare Bitcoin", "https://api.bb.no/v1/price/nok");

public BareBitcoinRateProvider(HttpClient httpClient)
{
Expand All @@ -24,16 +24,15 @@ public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)

var jobj = await response.Content.ReadAsAsync<JObject>(cancellationToken);

// Extract market and otc prices
var market = jobj["market"].Value<decimal>();
var buy = jobj["buy"].Value<decimal>();
var sell = jobj["sell"].Value<decimal>();
// Extract bid/ask prices from JSON response
var bid = (decimal)jobj["bid"];
var ask = (decimal)jobj["ask"];

// Create currency pair for BTC/NOK
var pair = new CurrencyPair("BTC", "NOK");

// Return single pair rate with sell/buy as bid/ask
return new[] { new PairRate(pair, new BidAsk(sell, buy)) };
// Return single pair rate with bid/ask
return new[] { new PairRate(pair, new BidAsk(bid, ask)) };
}
}
}
1 change: 1 addition & 0 deletions BTCPayServer.Tests/BTCPayServerTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using BTCPayServer.Rating;
using BTCPayServer.Services;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Mails;
using BTCPayServer.Services.Rates;
using BTCPayServer.Services.Stores;
using BTCPayServer.Tests.Logging;
Expand Down
14 changes: 9 additions & 5 deletions BTCPayServer.Tests/FastTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,13 @@ public void CheckDockerComposeUpToDate()
{
var compose1 = File.ReadAllText(Path.Combine(TestUtils.TryGetSolutionDirectoryInfo().FullName, "BTCPayServer.Tests", "docker-compose.yml"));
var compose2 = File.ReadAllText(Path.Combine(TestUtils.TryGetSolutionDirectoryInfo().FullName, "BTCPayServer.Tests", "docker-compose.altcoins.yml"));
var compose3 = File.ReadAllText(Path.Combine(TestUtils.TryGetSolutionDirectoryInfo().FullName, "BTCPayServer.Tests", "docker-compose.mutinynet.yml"));
var compose4 = File.ReadAllText(Path.Combine(TestUtils.TryGetSolutionDirectoryInfo().FullName, "BTCPayServer.Tests", "docker-compose.testnet.yml"));

List<DockerImage> GetImages(string content)
{
List<DockerImage> images = new List<DockerImage>();
foreach (var line in content.Split(new[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries))
var images = new List<DockerImage>();
foreach (var line in content.Split(["\n", "\r\n"], StringSplitOptions.RemoveEmptyEntries))
{
var l = line.Trim();
if (l.StartsWith("image:", StringComparison.OrdinalIgnoreCase))
Expand All @@ -120,13 +122,15 @@ List<DockerImage> GetImages(string content)

var img1 = GetImages(compose1);
var img2 = GetImages(compose2);
var groups = img1.Concat(img2).GroupBy(g => g.Name);
var img3 = GetImages(compose3);
var img4 = GetImages(compose4);
var groups = img1.Concat(img2).Concat(img3).Concat(img4).GroupBy(g => g.Name);
foreach (var g in groups)
{
var tags = new HashSet<String>(g.Select(o => o.Tag));
var tags = new HashSet<string>(g.Select(o => o.Tag));
if (tags.Count != 1)
{
Assert.Fail($"All docker images '{g.Key}' in docker-compose.yml and docker-compose.altcoins.yml should have the same tags. (Found {string.Join(',', tags)})");
Assert.Fail($"All docker images '{g.Key}' across the docker-compose.yml files should have the same tags. (Found {string.Join(',', tags)})");
}
}
}
Expand Down
1 change: 0 additions & 1 deletion BTCPayServer.Tests/GreenfieldAPITests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3829,7 +3829,6 @@ await client.ShowOnChainWalletTransactions(walletId.StoreId, walletId.CryptoCode

await tester.WaitForEvent<NewBlockEvent>(async () =>
{

await tester.ExplorerNode.GenerateAsync(1);
}, bevent => bevent.PaymentMethodId == PaymentTypes.CHAIN.GetPaymentMethodId("BTC"));

Expand Down
11 changes: 10 additions & 1 deletion BTCPayServer.Tests/SeleniumTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ public async Task CanUseForms()

s.Driver.FindElement(By.CssSelector("button[type='submit']")).Click();

Assert.Contains("Enter your email", s.Driver.PageSource);
s.Driver.FindElement(By.Name("buyerEmail")).SendKeys("[email protected]");
s.Driver.FindElement(By.CssSelector("input[type='submit']")).Click();

Expand Down Expand Up @@ -2904,6 +2903,16 @@ public async Task CanUsePOSKeypad()
// Unauthenticated user can't access recent transactions
s.GoToUrl(keypadUrl);
s.Driver.ElementDoesNotExist(By.Id("RecentTransactionsToggle"));

// But they can generate invoices
s.Driver.FindElement(By.CssSelector(".keypad [data-key='1']")).Click();
s.Driver.FindElement(By.CssSelector(".keypad [data-key='2']")).Click();
s.Driver.FindElement(By.CssSelector(".keypad [data-key='3']")).Click();
s.Driver.FindElement(By.Id("pay-button")).Click();
s.Driver.WaitUntilAvailable(By.Id("Checkout"));
s.Driver.FindElement(By.Id("DetailsToggle")).Click();
s.Driver.WaitForElement(By.Id("PaymentDetails-TotalFiat"));
Assert.Contains("1,23 €", s.Driver.FindElement(By.Id("PaymentDetails-TotalFiat")).Text);
}

[Fact]
Expand Down
9 changes: 8 additions & 1 deletion BTCPayServer.Tests/docker-compose.altcoins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ services:
custom:

nbxplorer:
image: nicolasdorier/nbxplorer:2.5.14
image: nicolasdorier/nbxplorer:2.5.16
restart: unless-stopped
ports:
- "32838:32838"
Expand Down Expand Up @@ -180,6 +180,7 @@ services:
dev-bitcoind-poll=1
ports:
- "30992:9835" # api port
- "30892:9735" # server port
expose:
- "9735" # server port
- "9835" # api port
Expand Down Expand Up @@ -208,6 +209,7 @@ services:
dev-bitcoind-poll=1
ports:
- "30993:9835" # api port
- "30893:9735" # server port
expose:
- "9735" # server port
- "9835" # api port
Expand Down Expand Up @@ -252,9 +254,12 @@ services:
no-rest-tls=1
ports:
- "35531:8080"
- "30894:9735"
- "53280:10009"
expose:
- "8080"
- "9735"
- "10009"
volumes:
- "merchant_lnd_datadir:/data"
- "bitcoin_datadir:/deps/.bitcoin"
Expand Down Expand Up @@ -287,8 +292,10 @@ services:
no-rest-tls=1
ports:
- "35532:8080"
- "30895:9735"
expose:
- "8080"
- "9735"
- "10009"
volumes:
- "customer_lnd_datadir:/root/.lnd"
Expand Down
Loading

0 comments on commit 13ace02

Please sign in to comment.