Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
334abdc9d1 |
@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
echo "Checking if it is possible to build Bitcoin only..."
|
||||
cd ../BTCPayServer.Tests
|
||||
docker-compose -f "docker-compose.yml" build
|
@ -1,151 +1,98 @@
|
||||
version: 2
|
||||
jobs:
|
||||
fast_tests:
|
||||
build:
|
||||
machine:
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
test:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "Fast=Fast|ThirdParty=ThirdParty" && ./can-build.sh
|
||||
selenium_tests:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "Selenium=Selenium"
|
||||
integration_tests:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "Integration=Integration"
|
||||
trigger_docs_build:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
steps:
|
||||
- run:
|
||||
command: |
|
||||
curl -X POST -H "Authorization: token $GH_PAT" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/btcpayserver/btcpayserver-doc/dispatches --data '{"event_type": "build_docs"}'
|
||||
cd BTCPayServer.Tests
|
||||
docker-compose down --v
|
||||
docker-compose build
|
||||
docker-compose run tests
|
||||
|
||||
# publish jobs require $DOCKERHUB_REPO, $DOCKERHUB_USER, $DOCKERHUB_PASS defined
|
||||
amd64:
|
||||
publish_docker_linuxamd64:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
|
||||
#
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-amd64 -f amd64.Dockerfile .
|
||||
sudo docker build --pull --build-arg CONFIGURATION_NAME=Altcoins-Release -t $DOCKERHUB_REPO:$LATEST_TAG-altcoins-amd64 -f amd64.Dockerfile .
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-amd64 -f Dockerfile.linuxamd64 .
|
||||
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-amd64
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-altcoins-amd64
|
||||
|
||||
arm32v7:
|
||||
publish_docker_linuxarm:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
|
||||
#
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-arm32v7 -f arm32v7.Dockerfile .
|
||||
sudo docker build --pull --build-arg CONFIGURATION_NAME=Altcoins-Release -t $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm32v7 -f arm32v7.Dockerfile .
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-arm32v7 -f Dockerfile.linuxarm32v7 .
|
||||
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-arm32v7
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm32v7
|
||||
|
||||
arm64v8:
|
||||
publish_docker_multiarch:
|
||||
machine:
|
||||
image: ubuntu-2004:202111-02
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
|
||||
#
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-arm64v8 -f arm64v8.Dockerfile .
|
||||
sudo docker build --build-arg CONFIGURATION_NAME=Altcoins-Release --pull -t $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm64v8 -f arm64v8.Dockerfile .
|
||||
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-arm64v8
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm64v8
|
||||
|
||||
multiarch:
|
||||
machine:
|
||||
image: ubuntu-2004:202201-02
|
||||
enabled: true
|
||||
image: circleci/classic:201808-01
|
||||
steps:
|
||||
- run:
|
||||
command: |
|
||||
# Turn on Experimental features
|
||||
sudo mkdir $HOME/.docker
|
||||
sudo sh -c 'echo "{ \"experimental\": \"enabled\" }" >> $HOME/.docker/config.json'
|
||||
#
|
||||
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
#
|
||||
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
|
||||
sudo docker manifest create --amend $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-amd64 $DOCKERHUB_REPO:$LATEST_TAG-arm32v7 $DOCKERHUB_REPO:$LATEST_TAG-arm64v8
|
||||
sudo docker manifest create --amend $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-amd64 $DOCKERHUB_REPO:$LATEST_TAG-arm32v7
|
||||
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-amd64 --os linux --arch amd64
|
||||
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-arm32v7 --os linux --arch arm --variant v7
|
||||
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-arm64v8 --os linux --arch arm64 --variant v8
|
||||
sudo docker manifest push $DOCKERHUB_REPO:$LATEST_TAG -p
|
||||
|
||||
sudo docker manifest create --amend $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-amd64 $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm32v7 $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm64v8
|
||||
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-amd64 --os linux --arch amd64
|
||||
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm32v7 --os linux --arch arm --variant v7
|
||||
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm64v8 --os linux --arch arm64 --variant v8
|
||||
sudo docker manifest push $DOCKERHUB_REPO:$LATEST_TAG-altcoins -p
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
jobs:
|
||||
- fast_tests
|
||||
- selenium_tests
|
||||
- integration_tests
|
||||
- test
|
||||
|
||||
publish:
|
||||
jobs:
|
||||
- trigger_docs_build:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
# only act on version tags
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
|
||||
- amd64:
|
||||
- publish_docker_linuxamd64:
|
||||
filters:
|
||||
# ignore any commit on any branch by default
|
||||
branches:
|
||||
ignore: /.*/
|
||||
# only act on version tags v1.0.0.88 or v1.0.2-1
|
||||
# OR feature tags like vlndseedbackup
|
||||
# OR features on specific versions like v1.0.0.88-lndseedbackup-1
|
||||
# only act on version tags
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
|
||||
- arm32v7:
|
||||
only: /v[1-9]+(\.[0-9]+)*/
|
||||
- publish_docker_linuxarm:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
|
||||
- arm64v8:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
|
||||
- multiarch:
|
||||
only: /v[1-9]+(\.[0-9]+)*/
|
||||
- publish_docker_multiarch:
|
||||
requires:
|
||||
- amd64
|
||||
- arm32v7
|
||||
- arm64v8
|
||||
- publish_docker_linuxamd64
|
||||
- publish_docker_linuxarm
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
|
||||
only: /v[1-9]+(\.[0-9]+)*/
|
||||
|
@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cd ../BTCPayServer.Tests
|
||||
docker-compose -v
|
||||
docker-compose -f "docker-compose.altcoins.yml" down --v
|
||||
|
||||
# For some reason, docker-compose pull fails time to time, so we try several times
|
||||
n=0
|
||||
until [ "$n" -ge 10 ]
|
||||
do
|
||||
docker-compose -f "docker-compose.altcoins.yml" pull && break
|
||||
n=$((n+1))
|
||||
sleep 5
|
||||
done
|
||||
|
||||
docker-compose -f "docker-compose.altcoins.yml" build
|
||||
docker-compose -f "docker-compose.altcoins.yml" run -e "TEST_FILTERS=$1" tests
|
@ -10,9 +10,8 @@ root = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
charset = utf-8
|
||||
|
||||
[launchSettings.json]
|
||||
[project.json]
|
||||
indent_size = 2
|
||||
|
||||
# C# files
|
||||
@ -121,11 +120,8 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
csharp_style_prefer_null_check_over_type_check = true:warning
|
||||
csharp_prefer_simple_using_statement = true:warning
|
||||
|
||||
# C++ Files
|
||||
|
||||
[*.{cpp,h,in}]
|
||||
curly_bracket_next_line = true
|
||||
indent_brace_style = Allman
|
||||
@ -150,4 +146,4 @@ indent_size = 2
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
[*.{cmd, bat}]
|
||||
end_of_line = crlf
|
||||
end_of_line = crlf
|
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,2 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
custom: https://foundation.btcpayserver.org
|
68
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
68
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,68 +0,0 @@
|
||||
name: 🐛 Bug Report
|
||||
description: File a bug report
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! Please provide as much information as you can. It helps us better understand the problem and fix it faster.
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: What is your BTCPay version?
|
||||
description: You can see the version in the footer's bottom right corner
|
||||
placeholder: I'm running BTCPay v1.X.X.X
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: deployment
|
||||
attributes:
|
||||
label: How did you deploy BTCPay Server?
|
||||
description: Docker, manual, third-party host? Read more on deployment methods [here](https://docs.btcpayserver.org/Deployment/)
|
||||
placeholder: I'm running BTCPay Server on a...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: How did you encounter this bug?
|
||||
description: Step by step describe how did you encounter the bug?
|
||||
placeholder: 1. I clicked X 2. Then I clicked Y 3. See error
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logoutput
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. Logs can be found in Server Settings > Logs. Here's how you can [troubleshoot an issue](https://docs.btcpayserver.org/Troubleshooting/)
|
||||
render: shell
|
||||
- type: textarea
|
||||
id: browser
|
||||
attributes:
|
||||
label: What browser do you use?
|
||||
description: Provide your browser and it's version. If you replicated issues on multiple browsers, let us know which ones.
|
||||
placeholder: For example Safari 15.00, Chrome 10.0, Tor, Edge, etc
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: additonal
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: Feel free to provide additional information. Screenshots are always helpful.
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Are you sure this is a bug report?
|
||||
description: By submitting this report, you agree that this is not a support or a feature request. For general questions please read our [documentation](https://docs.btcpayserver.org). You can ask questions in [discussions](https://github.com/btcpayserver/btcpayserver/discussions) and [on our community chat](https://chat.btcpayserver.org)
|
||||
options:
|
||||
- label: I confirm this is a bug report
|
||||
required: true
|
11
.github/ISSUE_TEMPLATE/config.yml
vendored
11
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,11 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 🚀 Discussions
|
||||
url: https://github.com/btcpayserver/btcpayserver/discussions
|
||||
about: Technical discussions, questions and feature requests
|
||||
- name: 📝 Official Documentation
|
||||
url: https://docs.btcpayserver.org
|
||||
about: Check our documentation for answers to common questions
|
||||
- name: 💬 Community Support Chat
|
||||
url: https://chat.btcpayserver.org/
|
||||
about: Ask general questions and get community support in real-time
|
11
.gitignore
vendored
11
.gitignore
vendored
@ -292,13 +292,4 @@ __pycache__/
|
||||
BTCPayServer/wwwroot/bundles/*
|
||||
!BTCPayServer/wwwroot/bundles/.gitignore
|
||||
|
||||
.vscode/*
|
||||
!.vscode/launch.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/extensions.json
|
||||
BTCPayServer/testpwd
|
||||
.DS_Store
|
||||
Packed Plugins
|
||||
Plugins/packed
|
||||
|
||||
BTCPayServer/wwwroot/swagger/v1/openapi.json
|
||||
.vscode
|
||||
|
@ -1,21 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Pack Test Plugin" type="DotNetProject" factoryName=".NET Project" singleton="false">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/bin/Debug/netcoreapp3.1/BTCPayServer.PluginPacker.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="../../../../BTCPayServer.Plugins.Test\bin\Debug\netcoreapp3.1 BTCPayServer.Plugins.Test "../../../../Packed Plugins"" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/bin/Debug/netcoreapp3.1" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/BTCPayServer.PluginPacker.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
||||
<method v="2">
|
||||
<option name="Build" default="false" projectName="BTCPayServer.Plugins.Test" projectPath="C:\Git\btcpayserver\BTCPayServer.Plugins.Test\BTCPayServer.Plugins.Test.csproj" />
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -1,3 +0,0 @@
|
||||
{
|
||||
"recommendations": ["ms-dotnettools.csharp"]
|
||||
}
|
33
.vscode/launch.json
vendored
33
.vscode/launch.json
vendored
@ -1,33 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||
// Use hover for the description of the existing attributes
|
||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (web)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/BTCPayServer/bin/Debug/net6.0/BTCPayServer.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/BTCPayServer",
|
||||
"stopAtEntry": false,
|
||||
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
|
||||
"serverReadyAction": {
|
||||
"action": "openExternally",
|
||||
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
|
||||
},
|
||||
"env": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"sourceFileMap": {
|
||||
"/Views": "${workspaceFolder}/Views"
|
||||
},
|
||||
"logging": {
|
||||
"moduleLoad": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
42
.vscode/tasks.json
vendored
42
.vscode/tasks.json
vendored
@ -1,42 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/BTCPayServer/BTCPayServer.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/BTCPayServer/BTCPayServer.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/BTCPayServer/BTCPayServer.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../Build/Version.csproj" Condition="Exists('../Build/Version.csproj')" />
|
||||
<Import Project="../Build/Common.csproj" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Company>BTCPay Server</Company>
|
||||
<Copyright>Copyright © BTCPay Server 2020</Copyright>
|
||||
<Description>A library for BTCPay Server plugin development</Description>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageTags>btcpay,btcpayserver</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/btcpayserver/btcpayserver/tree/master/BTCPayServer.Abstractions</PackageProjectUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryUrl>https://github.com/btcpayserver/btcpayserver</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>1591;1573;1572;1584;1570;3021</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="icon.png" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HtmlSanitizer" Version="5.0.372" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.7" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.5" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BTCPayServer.Client\BTCPayServer.Client.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,11 +0,0 @@
|
||||
namespace BTCPayServer.Configuration
|
||||
{
|
||||
public class DataDirectories
|
||||
{
|
||||
public string DataDir { get; set; }
|
||||
public string PluginDir { get; set; }
|
||||
public string TempStorageDir { get; set; }
|
||||
public string StorageDir { get; set; }
|
||||
public string TempDir { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Constants
|
||||
{
|
||||
public class AuthenticationSchemes
|
||||
{
|
||||
public const string Cookie = "Identity.Application";
|
||||
public const string Bitpay = "Bitpay";
|
||||
public const string Greenfield = "Greenfield.APIKeys,Greenfield.Basic";
|
||||
public const string GreenfieldAPIKeys = "Greenfield.APIKeys";
|
||||
public const string GreenfieldBasic = "Greenfield.Basic";
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Constants;
|
||||
|
||||
public class WellKnownTempData
|
||||
{
|
||||
public const string SuccessMessage = nameof(SuccessMessage);
|
||||
public const string ErrorMessage = nameof(ErrorMessage);
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public abstract class BaseDbContextFactory<T> where T : DbContext
|
||||
{
|
||||
private readonly IOptions<DatabaseOptions> _options;
|
||||
private readonly string _schemaPrefix;
|
||||
|
||||
public BaseDbContextFactory(IOptions<DatabaseOptions> options, string schemaPrefix)
|
||||
{
|
||||
_options = options;
|
||||
_schemaPrefix = schemaPrefix;
|
||||
}
|
||||
|
||||
public abstract T CreateContext();
|
||||
|
||||
class CustomNpgsqlMigrationsSqlGenerator : NpgsqlMigrationsSqlGenerator
|
||||
{
|
||||
#pragma warning disable EF1001 // Internal EF Core API usage.
|
||||
public CustomNpgsqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.INpgsqlSingletonOptions opts) : base(dependencies, opts)
|
||||
#pragma warning restore EF1001 // Internal EF Core API usage.
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Generate(NpgsqlCreateDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder)
|
||||
{
|
||||
builder
|
||||
.Append("CREATE DATABASE ")
|
||||
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name));
|
||||
|
||||
// POSTGRES gotcha: Indexed Text column (even if PK) are not used if we are not using C locale
|
||||
builder
|
||||
.Append(" TEMPLATE ")
|
||||
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier("template0"));
|
||||
|
||||
builder
|
||||
.Append(" LC_CTYPE ")
|
||||
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier("C"));
|
||||
|
||||
builder
|
||||
.Append(" LC_COLLATE ")
|
||||
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier("C"));
|
||||
|
||||
builder
|
||||
.Append(" ENCODING ")
|
||||
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier("UTF8"));
|
||||
|
||||
if (operation.Tablespace != null)
|
||||
{
|
||||
builder
|
||||
.Append(" TABLESPACE ")
|
||||
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Tablespace));
|
||||
}
|
||||
|
||||
builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
|
||||
|
||||
EndStatement(builder, suppressTransaction: true);
|
||||
}
|
||||
}
|
||||
|
||||
public void ConfigureBuilder(DbContextOptionsBuilder builder)
|
||||
{
|
||||
switch (_options.Value.DatabaseType)
|
||||
{
|
||||
case DatabaseType.Sqlite:
|
||||
builder.UseSqlite(_options.Value.ConnectionString, o =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_schemaPrefix))
|
||||
{
|
||||
o.MigrationsHistoryTable(_schemaPrefix);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case DatabaseType.Postgres:
|
||||
builder
|
||||
.UseNpgsql(_options.Value.ConnectionString, o =>
|
||||
{
|
||||
o.EnableRetryOnFailure(10);
|
||||
if (!string.IsNullOrEmpty(_schemaPrefix))
|
||||
{
|
||||
o.MigrationsHistoryTable(_schemaPrefix);
|
||||
}
|
||||
})
|
||||
.ReplaceService<IMigrationsSqlGenerator, CustomNpgsqlMigrationsSqlGenerator>();
|
||||
break;
|
||||
case DatabaseType.MySQL:
|
||||
builder.UseMySql(_options.Value.ConnectionString, ServerVersion.AutoDetect(_options.Value.ConnectionString), o =>
|
||||
{
|
||||
o.EnableRetryOnFailure(10);
|
||||
|
||||
if (!string.IsNullOrEmpty(_schemaPrefix))
|
||||
{
|
||||
o.MigrationsHistoryTable(_schemaPrefix);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface IBTCPayServerClientFactory
|
||||
{
|
||||
Task<BTCPayServerClient> Create(string userId, params string[] storeIds);
|
||||
Task<BTCPayServerClient> Create(string userId, string[] storeIds, HttpContext httpRequest);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using BTCPayServer.Abstractions.Converters;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface IBTCPayServerPlugin
|
||||
{
|
||||
public string Identifier { get; }
|
||||
string Name { get; }
|
||||
[JsonConverter(typeof(VersionConverter))]
|
||||
Version Version { get; }
|
||||
string Description { get; }
|
||||
bool SystemPlugin { get; set; }
|
||||
PluginDependency[] Dependencies { get; }
|
||||
void Execute(IApplicationBuilder applicationBuilder, IServiceProvider applicationBuilderApplicationServices);
|
||||
void Execute(IServiceCollection applicationBuilder);
|
||||
|
||||
public class PluginDependency
|
||||
{
|
||||
public string Identifier { get; set; }
|
||||
public string Condition { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Identifier}: {Condition}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
public interface IFileService
|
||||
{
|
||||
Task<bool> IsAvailable();
|
||||
Task<IStoredFile> AddFile(IFormFile file, string userId);
|
||||
Task<IStoredFile> AddFile(Uri file, string userId);
|
||||
Task<string?> GetFileUrl(Uri baseUri, string fileId);
|
||||
Task<string?> GetTemporaryFileUrl(Uri baseUri, string fileId, DateTimeOffset expiry,
|
||||
bool isDownload);
|
||||
Task RemoveFile(string fileId, string userId);
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public abstract class BaseNotification
|
||||
{
|
||||
public abstract string Identifier { get; }
|
||||
public abstract string NotificationType { get; }
|
||||
}
|
||||
|
||||
public interface INotificationHandler
|
||||
{
|
||||
string NotificationType { get; }
|
||||
Type NotificationBlobType { get; }
|
||||
public (string identifier, string name)[] Meta { get; }
|
||||
void FillViewModel(object notification, NotificationViewModel vm);
|
||||
}
|
||||
|
||||
public class NotificationViewModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public string Body { get; set; }
|
||||
public string ActionLink { get; set; }
|
||||
public bool Seen { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface IPluginHookAction
|
||||
{
|
||||
public string Hook { get; }
|
||||
Task Execute(object args);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface IPluginHookFilter
|
||||
{
|
||||
public string Hook { get; }
|
||||
|
||||
Task<object> Execute(object args);
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface IPluginHookService
|
||||
{
|
||||
Task ApplyAction(string hook, object args);
|
||||
Task<object> ApplyFilter(string hook, object args);
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
#nullable enable
|
||||
namespace BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
public interface IScopeProvider
|
||||
{
|
||||
string? GetCurrentStoreId();
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#nullable enable
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface ISettingsRepository
|
||||
{
|
||||
Task<T?> GetSettingAsync<T>(string? name = null) where T : class;
|
||||
Task UpdateSetting<T>(T obj, string? name = null) where T : class;
|
||||
Task<T> WaitSettingsChanged<T>(CancellationToken cancellationToken = default) where T : class;
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface IStartupTask
|
||||
{
|
||||
Task ExecuteAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
public interface IStoreRepository
|
||||
{
|
||||
Task<T?> GetSettingAsync<T>(string storeId, string name) where T : class;
|
||||
Task<Dictionary<string, T?>> GetSettingsAsync<T>(string name) where T : class;
|
||||
Task UpdateSetting<T>(string storeId, string name, T obj) where T : class;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
public interface IStoredFile
|
||||
{
|
||||
string Id { get; set; }
|
||||
string FileName { get; set; }
|
||||
string StorageFileName { get; set; }
|
||||
DateTime Timestamp { get; set; }
|
||||
string ApplicationUserId { get; set; }
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
public interface ISwaggerProvider
|
||||
{
|
||||
Task<JObject> Fetch();
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface ISyncSummaryProvider
|
||||
{
|
||||
bool AllAvailable();
|
||||
|
||||
string Partial { get; }
|
||||
IEnumerable<ISyncStatus> GetStatuses();
|
||||
}
|
||||
|
||||
public interface ISyncStatus
|
||||
{
|
||||
public string CryptoCode { get; set; }
|
||||
public bool Available { get; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Contracts
|
||||
{
|
||||
public interface IUIExtension
|
||||
{
|
||||
string Partial { get; }
|
||||
|
||||
string Location { get; }
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Payments.PayJoin;
|
||||
|
||||
public interface IUTXOLocker
|
||||
{
|
||||
Task<bool> TryLock(OutPoint outpoint);
|
||||
Task<bool> TryUnlock(params OutPoint[] outPoints);
|
||||
Task<bool> TryLockInputs(OutPoint[] outPoints);
|
||||
Task<HashSet<OutPoint>> FindLocks(OutPoint[] outpoints);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Converters
|
||||
{
|
||||
public class VersionConverter : JsonConverter<Version>
|
||||
{
|
||||
public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return Version.Parse(reader.GetString());
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians.Client;
|
||||
|
||||
public class AssetQuoteResult
|
||||
{
|
||||
public string FromAsset { get; set; }
|
||||
public string ToAsset { get; set; }
|
||||
public decimal Bid { get; set; }
|
||||
public decimal Ask { get; set; }
|
||||
|
||||
public AssetQuoteResult() { }
|
||||
|
||||
public AssetQuoteResult(string fromAsset, string toAsset,decimal bid, decimal ask)
|
||||
{
|
||||
FromAsset = fromAsset;
|
||||
ToAsset = toAsset;
|
||||
Bid = bid;
|
||||
Ask = ask;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class AssetBalancesUnavailableException : CustodianApiException
|
||||
{
|
||||
|
||||
public AssetBalancesUnavailableException(System.Exception e) : base(500, "asset-balances-unavailable", $"Cannot fetch the asset balances: {e.Message}", e)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class AssetQuoteUnavailableException : CustodianApiException
|
||||
{
|
||||
public AssetPairData AssetPair { get; }
|
||||
|
||||
public AssetQuoteUnavailableException(AssetPairData assetPair) : base(400, "asset-price-unavailable", "Cannot find a quote for pair " + assetPair)
|
||||
{
|
||||
this.AssetPair = assetPair;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class BadConfigException : CustodianApiException
|
||||
{
|
||||
public string[] BadConfigKeys { get; set; }
|
||||
|
||||
public BadConfigException(string[] badConfigKeys) : base(500, "bad-custodian-account-config", "Wrong config values: " + String.Join(", ", badConfigKeys))
|
||||
{
|
||||
this.BadConfigKeys = badConfigKeys;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class CannotWithdrawException : CustodianApiException
|
||||
|
||||
{
|
||||
public CannotWithdrawException(ICustodian custodian, string paymentMethod, string message) : base(403, "cannot-withdraw", message)
|
||||
{
|
||||
}
|
||||
|
||||
public CannotWithdrawException(ICustodian custodian, string paymentMethod, string targetAddress, CustodianApiException originalException) : base(403, "cannot-withdraw", $"{custodian.Name} cannot withdraw {paymentMethod} to '{targetAddress}': {originalException.Message}")
|
||||
{
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using System;
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
public class CustodianApiException: Exception {
|
||||
public int HttpStatus { get; }
|
||||
public string Code { get; }
|
||||
|
||||
public CustodianApiException(int httpStatus, string code, string message, System.Exception ex) : base(message, ex)
|
||||
{
|
||||
HttpStatus = httpStatus;
|
||||
Code = code;
|
||||
}
|
||||
public CustodianApiException( int httpStatus, string code, string message) : this(httpStatus, code, message, null)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class CustodianFeatureNotImplementedException: CustodianApiException
|
||||
{
|
||||
public CustodianFeatureNotImplementedException(string message) : base(400, "not-implemented", message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class DepositsUnavailableException : CustodianApiException
|
||||
{
|
||||
public DepositsUnavailableException(string message) : base(404, "deposits-unavailable", message)
|
||||
{
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class InsufficientFundsException : CustodianApiException
|
||||
{
|
||||
public InsufficientFundsException(string message) : base(400, "insufficient-funds", message)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class InvalidWithdrawalTargetException : CustodianApiException
|
||||
|
||||
{
|
||||
public InvalidWithdrawalTargetException(ICustodian custodian, string paymentMethod, string targetAddress, CustodianApiException originalException) : base(403, "invalid-withdrawal-target", $"{custodian.Name} cannot withdraw {paymentMethod} to '{targetAddress}': {originalException.Message}")
|
||||
{
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class PermissionDeniedCustodianApiException : CustodianApiException
|
||||
|
||||
{
|
||||
public PermissionDeniedCustodianApiException(ICustodian custodian) : base(403, "custodian-api-permission-denied", $"{custodian.Name}'s API reported that you don't have permission.")
|
||||
{
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class TradeNotFoundException : CustodianApiException
|
||||
{
|
||||
private string tradeId { get; }
|
||||
|
||||
public TradeNotFoundException(string tradeId) : base(404,"trade-not-found","Could not find trade ID " + tradeId)
|
||||
{
|
||||
this.tradeId = tradeId;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class WithdrawalNotFoundException : CustodianApiException
|
||||
{
|
||||
private string WithdrawalId { get; }
|
||||
|
||||
public WithdrawalNotFoundException(string withdrawalId) : base(404, "withdrawal-not-found", $"Could not find withdrawal ID {withdrawalId}.")
|
||||
{
|
||||
WithdrawalId = withdrawalId;
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class WrongTradingPairException: CustodianApiException
|
||||
{
|
||||
public const int HttpCode = 404;
|
||||
public WrongTradingPairException(string fromAsset, string toAsset) : base(HttpCode, "wrong-trading-pair", $"Cannot find a trading pair for converting {fromAsset} into {toAsset}.")
|
||||
{
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians.Client;
|
||||
|
||||
/**
|
||||
* The result of a market trade. Used as a return type for custodians implementing ICanTrade
|
||||
*/
|
||||
public class MarketTradeResult
|
||||
{
|
||||
public string FromAsset { get; }
|
||||
public string ToAsset { get; }
|
||||
/**
|
||||
* The ledger entries that show the balances that were affected by the trade.
|
||||
*/
|
||||
public List<LedgerEntryData> LedgerEntries { get; }
|
||||
/**
|
||||
* The unique ID of the trade that was executed.
|
||||
*/
|
||||
public string TradeId { get; }
|
||||
|
||||
public MarketTradeResult(string fromAsset, string toAsset, List<LedgerEntryData> ledgerEntries, string tradeId)
|
||||
{
|
||||
this.FromAsset = fromAsset;
|
||||
this.ToAsset = toAsset;
|
||||
this.LedgerEntries = ledgerEntries;
|
||||
this.TradeId = tradeId;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians.Client;
|
||||
|
||||
public class WithdrawResult
|
||||
{
|
||||
public string PaymentMethod { get; }
|
||||
public string Asset { get; set; }
|
||||
public List<LedgerEntryData> LedgerEntries { get; }
|
||||
public string WithdrawalId { get; }
|
||||
public WithdrawalResponseData.WithdrawalStatus Status { get; }
|
||||
public DateTimeOffset CreatedTime { get; }
|
||||
public string TargetAddress { get; }
|
||||
public string TransactionId { get; }
|
||||
|
||||
public WithdrawResult(string paymentMethod, string asset, List<LedgerEntryData> ledgerEntries, string withdrawalId, WithdrawalResponseData.WithdrawalStatus status, DateTimeOffset createdTime, string targetAddress, string transactionId)
|
||||
{
|
||||
PaymentMethod = paymentMethod;
|
||||
Asset = asset;
|
||||
LedgerEntries = ledgerEntries;
|
||||
WithdrawalId = withdrawalId;
|
||||
CreatedTime = createdTime;
|
||||
Status = status;
|
||||
TargetAddress = targetAddress;
|
||||
TransactionId = transactionId;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public interface ICanDeposit
|
||||
{
|
||||
/**
|
||||
* Get the address where we can deposit for the chosen payment method (crypto code + network).
|
||||
* The result can be a string in different formats like a bitcoin address or even a LN invoice.
|
||||
*/
|
||||
public Task<DepositAddressData> GetDepositAddressAsync(string paymentMethod, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
public string[] GetDepositablePaymentMethods();
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Custodians.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public interface ICanTrade
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* A list of tradable asset pairs, or NULL if the custodian cannot trade/convert assets. if thr asset pair contains fiat, fiat is always put last. If both assets are a cyrptocode or both are fiat, the pair is written alphabetically. Always in uppercase. Example: ["BTC/EUR","BTC/USD", "EUR/USD", "BTC/ETH",...]
|
||||
*/
|
||||
public List<AssetPairData> GetTradableAssetPairs();
|
||||
|
||||
/**
|
||||
* Execute a market order right now.
|
||||
*/
|
||||
public Task<MarketTradeResult> TradeMarketAsync(string fromAsset, string toAsset, decimal qty, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
/**
|
||||
* Get the details about a previous market trade.
|
||||
*/
|
||||
public Task<MarketTradeResult> GetTradeInfoAsync(string tradeId, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
public Task<AssetQuoteResult> GetQuoteForAssetAsync(string fromAsset, string toAsset, JObject config, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Custodians.Client;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public interface ICanWithdraw
|
||||
{
|
||||
public Task<WithdrawResult> WithdrawAsync(string paymentMethod, decimal amount, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
public Task<WithdrawResult> GetWithdrawalInfoAsync(string paymentMethod, string withdrawalId, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
public string[] GetWithdrawablePaymentMethods();
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public interface ICustodian
|
||||
{
|
||||
/**
|
||||
* Get the unique code that identifies this custodian.
|
||||
*/
|
||||
string Code { get; }
|
||||
|
||||
string Name { get; }
|
||||
|
||||
/**
|
||||
* Get a list of assets and their qty in custody.
|
||||
*/
|
||||
Task<Dictionary<string, decimal>> GetAssetBalancesAsync(JObject config, CancellationToken cancellationToken);
|
||||
|
||||
public Task<Form.Form> GetConfigForm(JObject config, string locale,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Extensions;
|
||||
|
||||
public static class CustodianExtensions
|
||||
{
|
||||
public static ICustodian? GetCustodianByCode(this IEnumerable<ICustodian> custodians, string code)
|
||||
{
|
||||
return custodians.FirstOrDefault(custodian => custodian.Code == code);
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using BTCPayServer.Client.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Extensions;
|
||||
|
||||
public static class GreenfieldExtensions
|
||||
{
|
||||
public static IActionResult CreateValidationError(this ControllerBase controller, ModelStateDictionary modelState)
|
||||
{
|
||||
return controller.UnprocessableEntity(modelState.ToGreenfieldValidationError());
|
||||
}
|
||||
|
||||
public static List<GreenfieldValidationError> ToGreenfieldValidationError(this ModelStateDictionary modelState)
|
||||
{
|
||||
List<GreenfieldValidationError> errors = new List<GreenfieldValidationError>();
|
||||
foreach (var error in modelState)
|
||||
{
|
||||
foreach (var errorMessage in error.Value.Errors)
|
||||
{
|
||||
errors.Add(new GreenfieldValidationError(error.Key, errorMessage.ErrorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static IActionResult CreateAPIError(this ControllerBase controller, string errorCode, string errorMessage)
|
||||
{
|
||||
return controller.BadRequest(new GreenfieldAPIError(errorCode, errorMessage));
|
||||
}
|
||||
|
||||
public static IActionResult CreateAPIError(this ControllerBase controller, int httpCode, string errorCode, string errorMessage)
|
||||
{
|
||||
return controller.StatusCode(httpCode, new GreenfieldAPIError(errorCode, errorMessage));
|
||||
}
|
||||
|
||||
public static IActionResult CreateAPIPermissionError(this ControllerBase controller, string missingPermission, string message = null)
|
||||
{
|
||||
return controller.StatusCode(403, new GreenfieldPermissionAPIError(missingPermission, message));
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Extensions;
|
||||
|
||||
public static class HttpRequestExtensions
|
||||
{
|
||||
public static bool IsOnion(this HttpRequest request)
|
||||
{
|
||||
if (request?.Host.Host == null)
|
||||
return false;
|
||||
return request.Host.Host.EndsWith(".onion", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static string GetAbsoluteRoot(this HttpRequest request)
|
||||
{
|
||||
return string.Concat(
|
||||
request.Scheme,
|
||||
"://",
|
||||
request.Host.ToUriComponent(),
|
||||
request.PathBase.ToUriComponent());
|
||||
}
|
||||
|
||||
public static Uri GetAbsoluteRootUri(this HttpRequest request)
|
||||
{
|
||||
return new Uri(request.GetAbsoluteRoot());
|
||||
}
|
||||
|
||||
public static string GetCurrentUrl(this HttpRequest request)
|
||||
{
|
||||
return string.Concat(
|
||||
request.Scheme,
|
||||
"://",
|
||||
request.Host.ToUriComponent(),
|
||||
request.PathBase.ToUriComponent(),
|
||||
request.Path.ToUriComponent());
|
||||
}
|
||||
|
||||
public static string GetCurrentPath(this HttpRequest request)
|
||||
{
|
||||
return string.Concat(
|
||||
request.PathBase.ToUriComponent(),
|
||||
request.Path.ToUriComponent());
|
||||
}
|
||||
|
||||
public static string GetCurrentPathWithQueryString(this HttpRequest request)
|
||||
{
|
||||
return request.PathBase + request.Path + request.QueryString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If 'toto' and RootPath is 'rootpath' returns '/rootpath/toto'
|
||||
/// If 'toto' and RootPath is empty returns '/toto'
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetRelativePath(this HttpRequest request, string path)
|
||||
{
|
||||
if (path.Length > 0 && path[0] != '/')
|
||||
path = $"/{path}";
|
||||
return string.Concat(
|
||||
request.PathBase.ToUriComponent(),
|
||||
path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If 'https://example.com/toto' returns 'https://example.com/toto'
|
||||
/// If 'toto' and RootPath is 'rootpath' returns '/rootpath/toto'
|
||||
/// If 'toto' and RootPath is empty returns '/toto'
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetRelativePathOrAbsolute(this HttpRequest request, string path)
|
||||
{
|
||||
if (!Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out var uri) ||
|
||||
uri.IsAbsoluteUri)
|
||||
return path;
|
||||
|
||||
if (path.Length > 0 && path[0] != '/')
|
||||
path = $"/{path}";
|
||||
return string.Concat(
|
||||
request.PathBase.ToUriComponent(),
|
||||
path);
|
||||
}
|
||||
|
||||
public static string GetAbsoluteUri(this HttpRequest request, string redirectUrl)
|
||||
{
|
||||
bool isRelative =
|
||||
(redirectUrl.Length > 0 && redirectUrl[0] == '/')
|
||||
|| !new Uri(redirectUrl, UriKind.RelativeOrAbsolute).IsAbsoluteUri;
|
||||
return isRelative ? request.GetAbsoluteRoot() + redirectUrl : redirectUrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will return an absolute URL.
|
||||
/// If `relativeOrAsbolute` is absolute, returns it.
|
||||
/// If `relativeOrAsbolute` is relative, send absolute url based on the HOST of this request (without PathBase)
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="relativeOrAbsolte"></param>
|
||||
/// <returns></returns>
|
||||
public static Uri GetAbsoluteUriNoPathBase(this HttpRequest request, Uri relativeOrAbsolute = null)
|
||||
{
|
||||
if (relativeOrAbsolute == null)
|
||||
{
|
||||
return new Uri(string.Concat(
|
||||
request.Scheme,
|
||||
"://",
|
||||
request.Host.ToUriComponent()), UriKind.Absolute);
|
||||
}
|
||||
if (relativeOrAbsolute.IsAbsoluteUri)
|
||||
return relativeOrAbsolute;
|
||||
return new Uri(string.Concat(
|
||||
request.Scheme,
|
||||
"://",
|
||||
request.Host.ToUriComponent()) + relativeOrAbsolute.ToString().WithStartingSlash(), UriKind.Absolute);
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
using System.Text.Json;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Extensions;
|
||||
|
||||
public static class SetStatusMessageModelExtensions
|
||||
{
|
||||
public static void SetStatusMessageModel(this ITempDataDictionary tempData, StatusMessageModel statusMessage)
|
||||
{
|
||||
if (statusMessage == null)
|
||||
{
|
||||
tempData.Remove("StatusMessageModel");
|
||||
return;
|
||||
}
|
||||
|
||||
tempData["StatusMessageModel"] = JsonSerializer.Serialize(statusMessage, new JsonSerializerOptions());
|
||||
}
|
||||
|
||||
public static StatusMessageModel GetStatusMessageModel(this ITempDataDictionary tempData)
|
||||
{
|
||||
tempData.TryGetValue(WellKnownTempData.SuccessMessage, out var successMessage);
|
||||
tempData.TryGetValue(WellKnownTempData.ErrorMessage, out var errorMessage);
|
||||
tempData.TryGetValue("StatusMessageModel", out var model);
|
||||
if (successMessage != null || errorMessage != null)
|
||||
{
|
||||
var parsedModel = new StatusMessageModel();
|
||||
parsedModel.Message = (string)successMessage ?? (string)errorMessage;
|
||||
if (successMessage != null)
|
||||
{
|
||||
parsedModel.Severity = StatusMessageModel.StatusSeverity.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
parsedModel.Severity = StatusMessageModel.StatusSeverity.Error;
|
||||
}
|
||||
return parsedModel;
|
||||
}
|
||||
else if (model != null && model is string str)
|
||||
{
|
||||
return JObject.Parse(str).ToObject<StatusMessageModel>();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool HasStatusMessage(this ITempDataDictionary tempData)
|
||||
{
|
||||
return (tempData.Peek(WellKnownTempData.SuccessMessage) ??
|
||||
tempData.Peek(WellKnownTempData.ErrorMessage) ??
|
||||
tempData.Peek("StatusMessageModel")) != null;
|
||||
}
|
||||
|
||||
public static bool HasErrorMessage(this ITempDataDictionary tempData)
|
||||
{
|
||||
return GetStatusMessageModel(tempData)?.Severity == StatusMessageModel.StatusSeverity.Error;
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Extensions
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddStartupTask<T>(this IServiceCollection services)
|
||||
where T : class, IStartupTask
|
||||
=> services.AddTransient<IStartupTask, T>();
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Extensions;
|
||||
|
||||
public static class StringExtensions
|
||||
{
|
||||
|
||||
public static bool IsValidFileName(this string fileName)
|
||||
{
|
||||
return !fileName.ToCharArray().Any(c => Path.GetInvalidFileNameChars().Contains(c)
|
||||
|| c == Path.AltDirectorySeparatorChar
|
||||
|| c == Path.DirectorySeparatorChar
|
||||
|| c == Path.PathSeparator
|
||||
|| c == '\\');
|
||||
}
|
||||
|
||||
public static string Truncate(this string value, int maxLength)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return value;
|
||||
return value.Length <= maxLength ? value : value.Substring(0, maxLength);
|
||||
}
|
||||
|
||||
public static string WithTrailingSlash(this string str)
|
||||
{
|
||||
if (str.EndsWith("/", StringComparison.InvariantCulture))
|
||||
return str;
|
||||
return str + "/";
|
||||
}
|
||||
public static string WithStartingSlash(this string str)
|
||||
{
|
||||
if (str.StartsWith("/", StringComparison.InvariantCulture))
|
||||
return str;
|
||||
return $"/{str}";
|
||||
}
|
||||
public static string WithoutEndingSlash(this string str)
|
||||
{
|
||||
if (str.EndsWith("/", StringComparison.InvariantCulture))
|
||||
return str.Substring(0, str.Length - 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Extensions
|
||||
{
|
||||
public static class ViewsRazor
|
||||
{
|
||||
private const string ACTIVE_CATEGORY_KEY = "ActiveCategory";
|
||||
private const string ACTIVE_PAGE_KEY = "ActivePage";
|
||||
private const string ACTIVE_ID_KEY = "ActiveId";
|
||||
|
||||
public static void SetActivePage<T>(this ViewDataDictionary viewData, T activePage, string title = null, string activeId = null)
|
||||
where T : IConvertible
|
||||
{
|
||||
SetActivePage(viewData, activePage.ToString(), activePage.GetType().ToString(), title, activeId);
|
||||
}
|
||||
|
||||
public static void SetActivePage(this ViewDataDictionary viewData, string activePage, string category, string title = null, string activeId = null)
|
||||
{
|
||||
// Page Title
|
||||
viewData["Title"] = title ?? activePage;
|
||||
// Navigation
|
||||
viewData[ACTIVE_PAGE_KEY] = activePage;
|
||||
viewData[ACTIVE_ID_KEY] = activeId;
|
||||
SetActiveCategory(viewData, category);
|
||||
}
|
||||
|
||||
public static void SetActiveCategory<T>(this ViewDataDictionary viewData, T activeCategory)
|
||||
{
|
||||
SetActiveCategory(viewData, activeCategory.ToString());
|
||||
}
|
||||
|
||||
public static void SetActiveCategory(this ViewDataDictionary viewData, string activeCategory)
|
||||
{
|
||||
viewData[ACTIVE_CATEGORY_KEY] = activeCategory;
|
||||
}
|
||||
|
||||
public static string IsActiveCategory<T>(this ViewDataDictionary viewData, T category, object id = null)
|
||||
{
|
||||
return IsActiveCategory(viewData, category.ToString(), id);
|
||||
}
|
||||
|
||||
public static string IsActiveCategory(this ViewDataDictionary viewData, string category, object id = null)
|
||||
{
|
||||
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var activeId = viewData[ACTIVE_ID_KEY];
|
||||
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
|
||||
var categoryMatch = category.Equals(activeCategory, StringComparison.InvariantCultureIgnoreCase);
|
||||
var idMatch = id == null || activeId == null || id.Equals(activeId);
|
||||
return categoryMatch && idMatch ? "active" : null;
|
||||
}
|
||||
|
||||
public static string IsActivePage<T>(this ViewDataDictionary viewData, T page, object id = null)
|
||||
where T : IConvertible
|
||||
{
|
||||
return IsActivePage(viewData, page.ToString(), page.GetType().ToString(), id);
|
||||
}
|
||||
|
||||
public static string IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
|
||||
{
|
||||
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var activeId = viewData[ACTIVE_ID_KEY];
|
||||
var activePage = viewData[ACTIVE_PAGE_KEY]?.ToString();
|
||||
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
|
||||
var categoryAndPageMatch = (category == null || activeCategory.Equals(category, StringComparison.InvariantCultureIgnoreCase)) && page.Equals(activePage, StringComparison.InvariantCultureIgnoreCase);
|
||||
var idMatch = id == null || activeId == null || id.Equals(activeId);
|
||||
return categoryAndPageMatch && idMatch ? "active" : null;
|
||||
}
|
||||
|
||||
public static HtmlString ToBrowserDate(this DateTimeOffset date)
|
||||
{
|
||||
var displayDate = date.ToString("o", CultureInfo.InvariantCulture);
|
||||
return new HtmlString($"<span class='localizeDate'>{displayDate}</span>");
|
||||
}
|
||||
|
||||
public static HtmlString ToBrowserDate(this DateTime date)
|
||||
{
|
||||
var displayDate = date.ToString("o", CultureInfo.InvariantCulture);
|
||||
return new HtmlString($"<span class='localizeDate'>{displayDate}</span>");
|
||||
}
|
||||
|
||||
public static string ToTimeAgo(this DateTimeOffset date)
|
||||
{
|
||||
var diff = DateTimeOffset.UtcNow - date;
|
||||
var formatted = diff.TotalSeconds > 0
|
||||
? $"{diff.TimeString()} ago"
|
||||
: $"in {diff.Negate().TimeString()}";
|
||||
return formatted;
|
||||
}
|
||||
|
||||
public static string TimeString(this TimeSpan timeSpan)
|
||||
{
|
||||
if (timeSpan.TotalMinutes < 1)
|
||||
{
|
||||
return $"{(int)timeSpan.TotalSeconds} second{Plural((int)timeSpan.TotalSeconds)}";
|
||||
}
|
||||
if (timeSpan.TotalHours < 1)
|
||||
{
|
||||
return $"{(int)timeSpan.TotalMinutes} minute{Plural((int)timeSpan.TotalMinutes)}";
|
||||
}
|
||||
if (timeSpan.Days < 1)
|
||||
{
|
||||
return $"{(int)timeSpan.TotalHours} hour{Plural((int)timeSpan.TotalHours)}";
|
||||
}
|
||||
return $"{(int)timeSpan.TotalDays} day{Plural((int)timeSpan.TotalDays)}";
|
||||
}
|
||||
|
||||
private static string Plural(int value)
|
||||
{
|
||||
return value > 1 ? "s" : string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Form;
|
||||
|
||||
public class AlertMessage
|
||||
{
|
||||
// Corresponds to the Bootstrap CSS "alert alert-xxx" messages:
|
||||
// Success = green
|
||||
// Warning = orange
|
||||
// Danger = red
|
||||
// Info = blue
|
||||
public enum AlertMessageType
|
||||
{
|
||||
Success,
|
||||
Warning,
|
||||
Danger,
|
||||
Info
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public AlertMessageType Type;
|
||||
|
||||
// The translated message to be shown to the user
|
||||
public string Message;
|
||||
|
||||
public AlertMessage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AlertMessage(AlertMessageType type, string message)
|
||||
{
|
||||
this.Type = type;
|
||||
this.Message = message;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Form;
|
||||
|
||||
public abstract class Field
|
||||
{
|
||||
// HTML5 compatible type string like "text", "textarea", "email", "password", etc. Each type is a class and may contain more fields (i.e. "select" would have options).
|
||||
public string Type;
|
||||
|
||||
// The name of the HTML5 node. Should be used as the key for the posted data.
|
||||
public string Name;
|
||||
|
||||
// The translated label of the field.
|
||||
public string Label;
|
||||
|
||||
// The value field is what is currently in the DB or what the user entered, but possibly not saved yet due to validation errors.
|
||||
// If this is the first the user sees the form, then value and original value are the same. Value changes as the user starts interacting with the form.
|
||||
public string Value;
|
||||
|
||||
// The original value is the value that is currently saved in the backend. A "reset" button can be used to revert back to this. Should only be set from the constructor.
|
||||
public string OriginalValue;
|
||||
|
||||
// A useful note shown below the field or via a tooltip / info icon. Should be translated for the user.
|
||||
public string HelpText;
|
||||
|
||||
// The field is considered "valid" if there are no validation errors
|
||||
public List<string> ValidationErrors = new List<string>();
|
||||
|
||||
public bool Required = false;
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
return ValidationErrors.Count == 0;
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Form;
|
||||
|
||||
public class Fieldset
|
||||
{
|
||||
public Fieldset()
|
||||
{
|
||||
this.Fields = new List<Field>();
|
||||
}
|
||||
|
||||
public string Label { get; set; }
|
||||
public List<Field> Fields { get; set; }
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Form;
|
||||
|
||||
public class Form
|
||||
{
|
||||
|
||||
// Messages to be shown at the top of the form indicating user feedback like "Saved successfully" or "Please change X because of Y." or a warning, etc...
|
||||
public List<AlertMessage> TopMessages { get; set; } = new();
|
||||
|
||||
// Groups of fields in the form
|
||||
public List<Fieldset> Fieldsets { get; set; } = new();
|
||||
|
||||
|
||||
// Are all the fields valid in the form?
|
||||
public bool IsValid()
|
||||
{
|
||||
foreach (var fieldset in Fieldsets)
|
||||
{
|
||||
foreach (var field in fieldset.Fields)
|
||||
{
|
||||
if (!field.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Field GetFieldByName(string name)
|
||||
{
|
||||
foreach (var fieldset in Fieldsets)
|
||||
{
|
||||
foreach (var field in fieldset.Fields)
|
||||
{
|
||||
if (name.Equals(field.Name))
|
||||
{
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<string> GetAllNames()
|
||||
{
|
||||
var names = new List<string>();
|
||||
foreach (var fieldset in Fieldsets)
|
||||
{
|
||||
foreach (var field in fieldset.Fields)
|
||||
{
|
||||
names.Add(field.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Form;
|
||||
|
||||
public class TextField : Field
|
||||
{
|
||||
public TextField(string label, string name, string value, bool required, string helpText)
|
||||
{
|
||||
this.Label = label;
|
||||
this.Name = name;
|
||||
this.Value = value;
|
||||
this.OriginalValue = value;
|
||||
this.Required = required;
|
||||
this.HelpText = helpText;
|
||||
this.Type = "text";
|
||||
}
|
||||
|
||||
// TODO JSON parsing from string to objects again probably won't work out of the box because of the different field types.
|
||||
|
||||
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Models
|
||||
{
|
||||
public abstract class BaseBTCPayServerPlugin : IBTCPayServerPlugin
|
||||
{
|
||||
public abstract string Identifier { get; }
|
||||
public abstract string Name { get; }
|
||||
|
||||
public virtual Version Version
|
||||
{
|
||||
get
|
||||
{
|
||||
return Assembly.GetAssembly(GetType())?.GetName().Version ?? new Version(1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract string Description { get; }
|
||||
public bool SystemPlugin { get; set; }
|
||||
public virtual IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } = Array.Empty<IBTCPayServerPlugin.PluginDependency>();
|
||||
|
||||
public virtual void Execute(IApplicationBuilder applicationBuilder,
|
||||
IServiceProvider applicationBuilderApplicationServices)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Execute(IServiceCollection applicationBuilder)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Models
|
||||
{
|
||||
public class ConfirmModel
|
||||
{
|
||||
private const string ButtonClassDefault = "btn-danger";
|
||||
|
||||
public ConfirmModel() { }
|
||||
|
||||
public ConfirmModel(string title, string desc, string action = null, string buttonClass = ButtonClassDefault, string actionName = null, string controllerName = null)
|
||||
{
|
||||
Title = title;
|
||||
Description = desc;
|
||||
Action = action;
|
||||
ActionName = actionName;
|
||||
ControllerName = controllerName;
|
||||
ButtonClass = buttonClass;
|
||||
|
||||
if (Description.Contains("<strong>", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
DescriptionHtml = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public bool DescriptionHtml { get; set; }
|
||||
public string Action { get; set; }
|
||||
public string ActionName { get; set; }
|
||||
public string ControllerName { get; set; }
|
||||
public string ButtonClass { get; set; } = ButtonClassDefault;
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Models
|
||||
{
|
||||
public class DatabaseOptions
|
||||
{
|
||||
public DatabaseType DatabaseType { get; set; }
|
||||
public string ConnectionString { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace BTCPayServer.Abstractions.Models
|
||||
{
|
||||
public enum DatabaseType
|
||||
{
|
||||
Sqlite,
|
||||
Postgres,
|
||||
MySQL,
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Models
|
||||
{
|
||||
public class StatusMessageModel
|
||||
{
|
||||
public StatusMessageModel()
|
||||
{
|
||||
}
|
||||
public string Message { get; set; }
|
||||
public string Html { get; set; }
|
||||
public StatusSeverity Severity { get; set; }
|
||||
public bool AllowDismiss { get; set; } = true;
|
||||
|
||||
public string SeverityCSS => ToString(Severity);
|
||||
|
||||
private void ParseNonJsonStatus(string s)
|
||||
{
|
||||
Message = s;
|
||||
Severity = s.StartsWith("Error", StringComparison.InvariantCultureIgnoreCase)
|
||||
? StatusSeverity.Error
|
||||
: StatusSeverity.Success;
|
||||
}
|
||||
|
||||
public static string ToString(StatusSeverity severity)
|
||||
{
|
||||
switch (severity)
|
||||
{
|
||||
case StatusSeverity.Info:
|
||||
return "info";
|
||||
case StatusSeverity.Error:
|
||||
return "danger";
|
||||
case StatusSeverity.Success:
|
||||
return "success";
|
||||
case StatusSeverity.Warning:
|
||||
return "warning";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public enum StatusSeverity
|
||||
{
|
||||
Info,
|
||||
Error,
|
||||
Success,
|
||||
Warning
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
rm "bin\release\" -Recurse -Force
|
||||
dotnet pack --configuration Release --include-symbols -p:SymbolPackageFormat=snupkg
|
||||
$package=(ls .\bin\Release\*.nupkg).FullName
|
||||
dotnet nuget push $package --source "https://api.nuget.org/v3/index.json"
|
||||
$ver = ((ls .\bin\release\*.nupkg)[0].Name -replace '.*(\d+\.\d+\.\d+)\.nupkg','$1')
|
||||
git tag -a "BTCPayServer.Abstractions/v$ver" -m "BTCPayServer.Abstractions/$ver"
|
||||
git push origin "BTCPayServer.Abstractions/v$ver"
|
@ -1,27 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace BTCPayServer.Security;
|
||||
|
||||
public class AuthorizationFilterHandle
|
||||
{
|
||||
public AuthorizationHandlerContext Context { get; }
|
||||
public PolicyRequirement Requirement { get; }
|
||||
public HttpContext HttpContext { get; }
|
||||
public bool Success { get; private set; }
|
||||
|
||||
public AuthorizationFilterHandle(
|
||||
AuthorizationHandlerContext context,
|
||||
PolicyRequirement requirement,
|
||||
HttpContext httpContext)
|
||||
{
|
||||
Context = context;
|
||||
Requirement = requirement;
|
||||
HttpContext = httpContext;
|
||||
}
|
||||
|
||||
public void MarkSuccessful()
|
||||
{
|
||||
Success = true;
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace BTCPayServer.Security
|
||||
{
|
||||
public class PolicyRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public PolicyRequirement(string policy)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(policy);
|
||||
Policy = policy;
|
||||
}
|
||||
public string Policy { get; }
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Services
|
||||
{
|
||||
public abstract class PluginAction<T> : IPluginHookAction
|
||||
{
|
||||
public abstract string Hook { get; }
|
||||
public Task Execute(object args)
|
||||
{
|
||||
return Execute(args is T args1 ? args1 : default);
|
||||
}
|
||||
|
||||
public abstract Task Execute(T arg);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Services
|
||||
{
|
||||
public abstract class PluginHookFilter<T> : IPluginHookFilter
|
||||
{
|
||||
public abstract string Hook { get; }
|
||||
|
||||
public Task<object> Execute(object args)
|
||||
{
|
||||
return Execute(args is T args1 ? args1 : default).ContinueWith(task => task.Result as object);
|
||||
}
|
||||
|
||||
public abstract Task<T> Execute(T arg);
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
using Ganss.XSS;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Services
|
||||
{
|
||||
public class Safe
|
||||
{
|
||||
private readonly IHtmlHelper _htmlHelper;
|
||||
private readonly IJsonHelper _jsonHelper;
|
||||
private readonly HtmlSanitizer _htmlSanitizer;
|
||||
|
||||
public Safe(IHtmlHelper htmlHelper, IJsonHelper jsonHelper, HtmlSanitizer htmlSanitizer)
|
||||
{
|
||||
_htmlHelper = htmlHelper;
|
||||
_jsonHelper = jsonHelper;
|
||||
_htmlSanitizer = htmlSanitizer;
|
||||
}
|
||||
|
||||
public IHtmlContent Raw(string value)
|
||||
{
|
||||
return _htmlHelper.Raw(_htmlSanitizer.Sanitize(value));
|
||||
}
|
||||
|
||||
public IHtmlContent Json(object model)
|
||||
{
|
||||
return _htmlHelper.Raw(_jsonHelper.Serialize(model));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Services
|
||||
{
|
||||
public class UIExtension : IUIExtension
|
||||
{
|
||||
public UIExtension(string partial, string location)
|
||||
{
|
||||
Partial = partial;
|
||||
Location = location;
|
||||
}
|
||||
|
||||
public string Partial { get; }
|
||||
public string Location { get; }
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Security;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
||||
namespace BTCPayServer.Abstractions.TagHelpers;
|
||||
|
||||
/// <summary>
|
||||
/// Add sha256- to allow inline event handlers in a:href=javascript:
|
||||
/// </summary>
|
||||
[HtmlTargetElement("a", Attributes = "csp-allow")]
|
||||
public class CSPA : TagHelper
|
||||
{
|
||||
private readonly ContentSecurityPolicies _csp;
|
||||
public CSPA(ContentSecurityPolicies csp)
|
||||
{
|
||||
_csp = csp;
|
||||
}
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
output.Attributes.RemoveAll("csp-allow");
|
||||
if (output.Attributes.TryGetAttribute("href", out var attr))
|
||||
{
|
||||
var v = attr.Value.ToString();
|
||||
if (v.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_csp.AllowUnsafeHashes(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BTCPayServer.Security;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
||||
namespace BTCPayServer.Abstractions.TagHelpers;
|
||||
|
||||
/// <summary>
|
||||
/// Add 'unsafe-hashes' and sha256- to allow inline event handlers in CSP
|
||||
/// </summary>
|
||||
[HtmlTargetElement(Attributes = "onclick")]
|
||||
[HtmlTargetElement(Attributes = "onkeypress")]
|
||||
[HtmlTargetElement(Attributes = "onchange")]
|
||||
[HtmlTargetElement(Attributes = "onsubmit")]
|
||||
public class CSPEventTagHelper : TagHelper
|
||||
{
|
||||
public const string EventNames = "onclick,onkeypress,onchange,onsubmit";
|
||||
private readonly ContentSecurityPolicies _csp;
|
||||
|
||||
readonly static HashSet<string> EventSet = EventNames.Split(',')
|
||||
.ToHashSet();
|
||||
public CSPEventTagHelper(ContentSecurityPolicies csp)
|
||||
{
|
||||
_csp = csp;
|
||||
}
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
foreach (var attr in output.Attributes)
|
||||
{
|
||||
var n = attr.Name.ToLowerInvariant();
|
||||
if (EventSet.Contains(n))
|
||||
{
|
||||
_csp.AllowUnsafeHashes(attr.Value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using BTCPayServer.Security;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Abstractions.TagHelpers;
|
||||
|
||||
/// <summary>
|
||||
/// Add a nonce-* so the inline-script can pass CSP rule when they are rendered server-side
|
||||
/// </summary>
|
||||
[HtmlTargetElement("script")]
|
||||
public class CSPInlineScriptTagHelper : TagHelper
|
||||
{
|
||||
private readonly ContentSecurityPolicies _csp;
|
||||
|
||||
public CSPInlineScriptTagHelper(ContentSecurityPolicies csp)
|
||||
{
|
||||
_csp = csp;
|
||||
}
|
||||
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
if (output.Attributes.ContainsName("src"))
|
||||
return;
|
||||
if (output.Attributes.TryGetAttribute("type", out var attr))
|
||||
{
|
||||
if (attr.Value?.ToString() != "text/javascript")
|
||||
return;
|
||||
}
|
||||
var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32);
|
||||
output.Attributes.Add(new TagHelperAttribute("nonce", nonce));
|
||||
_csp.Add("script-src", $"'nonce-{nonce}'");
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Security;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
||||
namespace BTCPayServer.Abstractions.TagHelpers;
|
||||
|
||||
/// <summary>
|
||||
/// Add sha256- to allow inline event handlers in CSP
|
||||
/// </summary>
|
||||
[HtmlTargetElement("template", Attributes = "csp-allow")]
|
||||
public class CSPTemplate : TagHelper
|
||||
{
|
||||
private readonly ContentSecurityPolicies _csp;
|
||||
public CSPTemplate(ContentSecurityPolicies csp)
|
||||
{
|
||||
_csp = csp;
|
||||
}
|
||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
output.Attributes.RemoveAll("csp-allow");
|
||||
var childContent = await output.GetChildContentAsync();
|
||||
var content = childContent.GetContent();
|
||||
_csp.AllowInline(content);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BTCPayServer.Abstractions.TagHelpers;
|
||||
|
||||
[HtmlTargetElement(Attributes = nameof(Permission))]
|
||||
public class PermissionTagHelper : TagHelper
|
||||
{
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly ILogger<PermissionTagHelper> _logger;
|
||||
|
||||
public PermissionTagHelper(IAuthorizationService authorizationService, IHttpContextAccessor httpContextAccessor, ILogger<PermissionTagHelper> logger)
|
||||
{
|
||||
_authorizationService = authorizationService;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string Permission { get; set; }
|
||||
public string PermissionResource { get; set; }
|
||||
|
||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Permission))
|
||||
return;
|
||||
if (_httpContextAccessor.HttpContext is null)
|
||||
return;
|
||||
|
||||
var key = $"{Permission}_{PermissionResource}";
|
||||
if (!_httpContextAccessor.HttpContext.Items.TryGetValue(key, out var o) ||
|
||||
o is not AuthorizationResult res)
|
||||
{
|
||||
res = await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User,
|
||||
PermissionResource,
|
||||
Permission);
|
||||
_httpContextAccessor.HttpContext.Items.Add(key, res);
|
||||
}
|
||||
if (!res.Succeeded)
|
||||
{
|
||||
output.SuppressOutput();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
|
||||
namespace BTCPayServer.Abstractions.TagHelpers;
|
||||
|
||||
// Make sure that <svg><use href=/ are correctly working if rootpath is present
|
||||
[HtmlTargetElement("use", Attributes = "href")]
|
||||
public class SVGUse : UrlResolutionTagHelper
|
||||
{
|
||||
private readonly IFileVersionProvider _fileVersionProvider;
|
||||
|
||||
public SVGUse(IUrlHelperFactory urlHelperFactory, HtmlEncoder htmlEncoder, IFileVersionProvider fileVersionProvider) : base(urlHelperFactory, htmlEncoder)
|
||||
{
|
||||
_fileVersionProvider = fileVersionProvider;
|
||||
}
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
var attr = output.Attributes["href"].Value.ToString();
|
||||
attr = _fileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, attr);
|
||||
output.Attributes.SetAttribute("href", attr);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using BTCPayServer.Abstractions.Services;
|
||||
using BTCPayServer.Security;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Abstractions.TagHelpers;
|
||||
|
||||
[HtmlTargetElement("srv-model")]
|
||||
public class SrvModel : TagHelper
|
||||
{
|
||||
private readonly Safe _safe;
|
||||
private readonly ContentSecurityPolicies _csp;
|
||||
|
||||
public SrvModel(Safe safe, ContentSecurityPolicies csp)
|
||||
{
|
||||
_safe = safe;
|
||||
_csp = csp;
|
||||
}
|
||||
public string VarName { get; set; } = "srvModel";
|
||||
public object Model { get; set; }
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
output.TagName = "script";
|
||||
output.TagMode = TagMode.StartTagAndEndTag;
|
||||
output.Attributes.Add(new TagHelperAttribute("type", "text/javascript"));
|
||||
var nonce = RandomUtils.GetUInt256().ToString().Substring(0, 32);
|
||||
output.Attributes.Add(new TagHelperAttribute("nonce", nonce));
|
||||
_csp.Add("script-src", $"'nonce-{nonce}'");
|
||||
output.Content.SetHtmlContent($"var {VarName} = {_safe.Json(Model)};");
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
@ -1,38 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<Company>BTCPay Server</Company>
|
||||
<Copyright>Copyright © BTCPay Server 2020</Copyright>
|
||||
<Description>A client library for BTCPay Server Greenfield API</Description>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageTags>btcpay,btcpayserver</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/btcpayserver/btcpayserver/tree/master/BTCPayServer.Client</PackageProjectUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryUrl>https://github.com/btcpayserver/btcpayserver</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(Version)' == '' ">1.7.0</Version>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>1591;1573;1572;1584;1570;3021</NoWarn>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.8" />
|
||||
<PackageReference Include="NBitcoin" Version="7.0.10" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="icon.png" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<ApiKeyData> GetCurrentAPIKeyInfo(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/api-keys/current"), token);
|
||||
return await HandleResponse<ApiKeyData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<ApiKeyData> CreateAPIKey(CreateApiKeyRequest request, CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/api-keys", bodyPayload: request, method: HttpMethod.Post), token);
|
||||
return await HandleResponse<ApiKeyData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task RevokeCurrentAPIKeyInfo(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/api-keys/current", null, HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task RevokeAPIKey(string apikey, CancellationToken token = default)
|
||||
{
|
||||
if (apikey == null)
|
||||
throw new ArgumentNullException(nameof(apikey));
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/api-keys/{apikey}", null, HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
|
||||
public virtual async Task<PointOfSaleAppData> CreatePointOfSaleApp(string storeId,
|
||||
CreatePointOfSaleAppRequest request, CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/apps/pos", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
return await HandleResponse<PointOfSaleAppData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<AppDataBase> GetApp(string appId, CancellationToken token = default)
|
||||
{
|
||||
if (appId == null)
|
||||
throw new ArgumentNullException(nameof(appId));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/apps/{appId}",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<AppDataBase>(response);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteApp(string appId, CancellationToken token = default)
|
||||
{
|
||||
if (appId == null)
|
||||
throw new ArgumentNullException(nameof(appId));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/apps/{appId}",
|
||||
method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
|
||||
public static Uri GenerateAuthorizeUri(Uri btcpayHost, string[] permissions, bool strict = true,
|
||||
bool selectiveStores = false, (string ApplicationIdentifier, Uri Redirect) applicationDetails = default)
|
||||
{
|
||||
var result = new UriBuilder(btcpayHost);
|
||||
result.Path = "api-keys/authorize";
|
||||
|
||||
AppendPayloadToQuery(result,
|
||||
new Dictionary<string, object>()
|
||||
{
|
||||
{"strict", strict}, {"selectiveStores", selectiveStores}, {"permissions", permissions}
|
||||
});
|
||||
|
||||
if (applicationDetails.Redirect != null)
|
||||
{
|
||||
AppendPayloadToQuery(result, new KeyValuePair<string, object>("redirect", applicationDetails.Redirect));
|
||||
if (!string.IsNullOrEmpty(applicationDetails.ApplicationIdentifier))
|
||||
{
|
||||
AppendPayloadToQuery(result, new KeyValuePair<string, object>("applicationIdentifier", applicationDetails.ApplicationIdentifier));
|
||||
}
|
||||
}
|
||||
|
||||
return result.Uri;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<IEnumerable<CustodianAccountData>> GetCustodianAccounts(string storeId, bool includeAssetBalances = false, CancellationToken token = default)
|
||||
{
|
||||
var queryPayload = new Dictionary<string, object>();
|
||||
if (includeAssetBalances)
|
||||
{
|
||||
queryPayload.Add("assetBalances", "true");
|
||||
}
|
||||
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts", queryPayload), token);
|
||||
return await HandleResponse<IEnumerable<CustodianAccountData>>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<CustodianAccountResponse> GetCustodianAccount(string storeId, string accountId, bool includeAssetBalances = false, CancellationToken token = default)
|
||||
{
|
||||
var queryPayload = new Dictionary<string, object>();
|
||||
if (includeAssetBalances)
|
||||
{
|
||||
queryPayload.Add("assetBalances", "true");
|
||||
}
|
||||
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}", queryPayload), token);
|
||||
return await HandleResponse<CustodianAccountResponse>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<CustodianAccountData> CreateCustodianAccount(string storeId, CreateCustodianAccountRequest request, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts", bodyPayload: request, method: HttpMethod.Post), token);
|
||||
return await HandleResponse<CustodianAccountData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<CustodianAccountData> UpdateCustodianAccount(string storeId, string accountId, CreateCustodianAccountRequest request, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}", bodyPayload: request, method: HttpMethod.Put), token);
|
||||
return await HandleResponse<CustodianAccountData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteCustodianAccount(string storeId, string accountId, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}", method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<DepositAddressData> GetDepositAddress(string storeId, string accountId, string paymentMethod, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/addresses/{paymentMethod}"), token);
|
||||
return await HandleResponse<DepositAddressData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<MarketTradeResponseData> MarketTradeCustodianAccountAsset(string storeId, string accountId, TradeRequestData request, CancellationToken token = default)
|
||||
{
|
||||
|
||||
//var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/users", null, request, HttpMethod.Post), token);
|
||||
//return await HandleResponse<ApplicationUserData>(response);
|
||||
var internalRequest = CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/market", null,
|
||||
request, HttpMethod.Post);
|
||||
var response = await _httpClient.SendAsync(internalRequest, token);
|
||||
return await HandleResponse<MarketTradeResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<MarketTradeResponseData> GetTradeInfo(string storeId, string accountId, string tradeId, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/{tradeId}", method: HttpMethod.Get), token);
|
||||
return await HandleResponse<MarketTradeResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<TradeQuoteResponseData> GetTradeQuote(string storeId, string accountId, string fromAsset, string toAsset, CancellationToken token = default)
|
||||
{
|
||||
var queryPayload = new Dictionary<string, object>();
|
||||
queryPayload.Add("fromAsset", fromAsset);
|
||||
queryPayload.Add("toAsset", toAsset);
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/quote", queryPayload), token);
|
||||
return await HandleResponse<TradeQuoteResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<WithdrawalResponseData> CreateWithdrawal(string storeId, string accountId, WithdrawRequestData request, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/withdrawals", bodyPayload: request, method: HttpMethod.Post), token);
|
||||
return await HandleResponse<WithdrawalResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<WithdrawalResponseData> GetWithdrawalInfo(string storeId, string accountId, string paymentMethod, string withdrawalId, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/withdrawals/{paymentMethod}/{withdrawalId}", method: HttpMethod.Get), token);
|
||||
return await HandleResponse<WithdrawalResponseData>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<IEnumerable<CustodianData>> GetCustodians(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/custodians"), token);
|
||||
return await HandleResponse<IEnumerable<CustodianData>>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<ApiHealthData> GetHealth(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/health"), token);
|
||||
return await HandleResponse<ApiHealthData>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<IEnumerable<InvoiceData>> GetInvoices(string storeId, string[] orderId = null,
|
||||
InvoiceStatus[] status = null,
|
||||
DateTimeOffset? startDate = null,
|
||||
DateTimeOffset? endDate = null,
|
||||
string textSearch = null,
|
||||
bool includeArchived = false,
|
||||
int? skip = null,
|
||||
int? take = null,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, object> queryPayload = new Dictionary<string, object>();
|
||||
queryPayload.Add(nameof(includeArchived), includeArchived);
|
||||
|
||||
if (startDate is DateTimeOffset s)
|
||||
queryPayload.Add(nameof(startDate), Utils.DateTimeToUnixTime(s));
|
||||
|
||||
if (endDate is DateTimeOffset e)
|
||||
queryPayload.Add(nameof(endDate), Utils.DateTimeToUnixTime(e));
|
||||
|
||||
if (orderId != null)
|
||||
queryPayload.Add(nameof(orderId), orderId);
|
||||
if (textSearch != null)
|
||||
queryPayload.Add(nameof(textSearch), textSearch);
|
||||
if (status != null)
|
||||
queryPayload.Add(nameof(status), status.Select(s => s.ToString().ToLower()).ToArray());
|
||||
|
||||
if (skip != null)
|
||||
{
|
||||
queryPayload.Add(nameof(skip), skip);
|
||||
}
|
||||
|
||||
if (take != null)
|
||||
{
|
||||
queryPayload.Add(nameof(take), take);
|
||||
}
|
||||
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices",
|
||||
queryPayload), token);
|
||||
return await HandleResponse<IEnumerable<InvoiceData>>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<InvoiceData> GetInvoice(string storeId, string invoiceId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}"), token);
|
||||
return await HandleResponse<InvoiceData>(response);
|
||||
}
|
||||
public virtual async Task<InvoicePaymentMethodDataModel[]> GetInvoicePaymentMethods(string storeId, string invoiceId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods"), token);
|
||||
return await HandleResponse<InvoicePaymentMethodDataModel[]>(response);
|
||||
}
|
||||
|
||||
public virtual async Task ArchiveInvoice(string storeId, string invoiceId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}",
|
||||
method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<InvoiceData> CreateInvoice(string storeId,
|
||||
CreateInvoiceRequest request, CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
return await HandleResponse<InvoiceData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<InvoiceData> UpdateInvoice(string storeId, string invoiceId,
|
||||
UpdateInvoiceRequest request, CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}", bodyPayload: request,
|
||||
method: HttpMethod.Put), token);
|
||||
return await HandleResponse<InvoiceData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<InvoiceData> MarkInvoiceStatus(string storeId, string invoiceId,
|
||||
MarkInvoiceStatusRequest request, CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
if (request.Status != InvoiceStatus.Settled && request.Status != InvoiceStatus.Invalid)
|
||||
throw new ArgumentOutOfRangeException(nameof(request.Status), "Status can only be Invalid or Complete");
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/status", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
return await HandleResponse<InvoiceData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<InvoiceData> UnarchiveInvoice(string storeId, string invoiceId, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/unarchive",
|
||||
method: HttpMethod.Post), token);
|
||||
return await HandleResponse<InvoiceData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task ActivateInvoicePaymentMethod(string storeId, string invoiceId, string paymentMethod, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods/{paymentMethod}/activate",
|
||||
method: HttpMethod.Post), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<IEnumerable<LNURLPayPaymentMethodData>>
|
||||
GetStoreLNURLPayPaymentMethods(string storeId, bool? enabled = null,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var query = new Dictionary<string, object>();
|
||||
if (enabled != null)
|
||||
{
|
||||
query.Add(nameof(enabled), enabled);
|
||||
}
|
||||
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LNURLPay",
|
||||
query), token);
|
||||
return await HandleResponse<IEnumerable<LNURLPayPaymentMethodData>>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LNURLPayPaymentMethodData> GetStoreLNURLPayPaymentMethod(
|
||||
string storeId,
|
||||
string cryptoCode, CancellationToken token = default)
|
||||
{
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LNURLPay/{cryptoCode}"), token);
|
||||
return await HandleResponse<LNURLPayPaymentMethodData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task RemoveStoreLNURLPayPaymentMethod(string storeId,
|
||||
string cryptoCode, CancellationToken token = default)
|
||||
{
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LNURLPay/{cryptoCode}",
|
||||
method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LNURLPayPaymentMethodData> UpdateStoreLNURLPayPaymentMethod(
|
||||
string storeId,
|
||||
string cryptoCode, LNURLPayPaymentMethodData paymentMethod,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LNURLPay/{cryptoCode}",
|
||||
bodyPayload: paymentMethod, method: HttpMethod.Put), token);
|
||||
return await HandleResponse<LNURLPayPaymentMethodData>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<LightningNodeInformationData> GetLightningNodeInfo(string cryptoCode,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/info",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningNodeInformationData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningNodeBalanceData> GetLightningNodeBalance(string cryptoCode,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/balance",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningNodeBalanceData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/connect", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<IEnumerable<LightningChannelData>> GetLightningNodeChannels(string cryptoCode,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/channels",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<IEnumerable<LightningChannelData>>(response);
|
||||
}
|
||||
|
||||
public virtual async Task OpenLightningChannel(string cryptoCode, OpenLightningChannelRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/channels", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<string> GetLightningDepositAddress(string cryptoCode, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/address", method: HttpMethod.Post), token);
|
||||
return await HandleResponse<string>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningPaymentData> PayLightningInvoice(string cryptoCode, PayLightningInvoiceRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/invoices/pay", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
return await HandleResponse<LightningPaymentData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningPaymentData> GetLightningPayment(string cryptoCode,
|
||||
string paymentHash, CancellationToken token = default)
|
||||
{
|
||||
if (paymentHash == null)
|
||||
throw new ArgumentNullException(nameof(paymentHash));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/payments/{paymentHash}",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningPaymentData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningInvoiceData> GetLightningInvoice(string cryptoCode,
|
||||
string invoiceId, CancellationToken token = default)
|
||||
{
|
||||
if (invoiceId == null)
|
||||
throw new ArgumentNullException(nameof(invoiceId));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/invoices/{invoiceId}",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningInvoiceData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningInvoiceData> CreateLightningInvoice(string cryptoCode, CreateLightningInvoiceRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/invoices", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
return await HandleResponse<LightningInvoiceData>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<LightningNodeInformationData> GetLightningNodeInfo(string storeId, string cryptoCode,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/info",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningNodeInformationData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningNodeBalanceData> GetLightningNodeBalance(string storeId, string cryptoCode,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/balance",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningNodeBalanceData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task ConnectToLightningNode(string storeId, string cryptoCode, ConnectToNodeRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/connect", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<IEnumerable<LightningChannelData>> GetLightningNodeChannels(string storeId, string cryptoCode,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/channels",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<IEnumerable<LightningChannelData>>(response);
|
||||
}
|
||||
|
||||
public virtual async Task OpenLightningChannel(string storeId, string cryptoCode, OpenLightningChannelRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/channels", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<string> GetLightningDepositAddress(string storeId, string cryptoCode,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/address", method: HttpMethod.Post),
|
||||
token);
|
||||
return await HandleResponse<string>(response);
|
||||
}
|
||||
|
||||
public virtual async Task PayLightningInvoice(string storeId, string cryptoCode, PayLightningInvoiceRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/invoices/pay", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningPaymentData> GetLightningPayment(string storeId, string cryptoCode,
|
||||
string paymentHash, CancellationToken token = default)
|
||||
{
|
||||
if (paymentHash == null)
|
||||
throw new ArgumentNullException(nameof(paymentHash));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/payments/{paymentHash}",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningPaymentData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningInvoiceData> GetLightningInvoice(string storeId, string cryptoCode,
|
||||
string invoiceId, CancellationToken token = default)
|
||||
{
|
||||
if (invoiceId == null)
|
||||
throw new ArgumentNullException(nameof(invoiceId));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/invoices/{invoiceId}",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningInvoiceData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningInvoiceData> CreateLightningInvoice(string storeId, string cryptoCode,
|
||||
CreateLightningInvoiceRequest request, CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/invoices", bodyPayload: request,
|
||||
method: HttpMethod.Post), token);
|
||||
return await HandleResponse<LightningInvoiceData>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<IEnumerable<LightningNetworkPaymentMethodData>>
|
||||
GetStoreLightningNetworkPaymentMethods(string storeId, bool? enabled = null,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var query = new Dictionary<string, object>();
|
||||
if (enabled != null)
|
||||
{
|
||||
query.Add(nameof(enabled), enabled);
|
||||
}
|
||||
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LightningNetwork",
|
||||
query), token);
|
||||
return await HandleResponse<IEnumerable<LightningNetworkPaymentMethodData>>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningNetworkPaymentMethodData> GetStoreLightningNetworkPaymentMethod(
|
||||
string storeId,
|
||||
string cryptoCode, CancellationToken token = default)
|
||||
{
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LightningNetwork/{cryptoCode}"), token);
|
||||
return await HandleResponse<LightningNetworkPaymentMethodData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task RemoveStoreLightningNetworkPaymentMethod(string storeId,
|
||||
string cryptoCode, CancellationToken token = default)
|
||||
{
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LightningNetwork/{cryptoCode}",
|
||||
method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningNetworkPaymentMethodData> UpdateStoreLightningNetworkPaymentMethod(
|
||||
string storeId,
|
||||
string cryptoCode, UpdateLightningNetworkPaymentMethodRequest paymentMethod,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/LightningNetwork/{cryptoCode}",
|
||||
bodyPayload: paymentMethod, method: HttpMethod.Put), token);
|
||||
return await HandleResponse<LightningNetworkPaymentMethodData>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<PermissionMetadata[]> GetPermissionMetadata(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("misc/permissions"), token);
|
||||
return await HandleResponse<PermissionMetadata[]>(response);
|
||||
}
|
||||
public virtual async Task<Language[]> GetAvailableLanguages(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("misc/lang"), token);
|
||||
return await HandleResponse<Language[]>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client.Models;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<IEnumerable<NotificationData>> GetNotifications(bool? seen = null, int? skip = null,
|
||||
int? take = null, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, object> queryPayload = new Dictionary<string, object>();
|
||||
|
||||
if (seen != null)
|
||||
queryPayload.Add(nameof(seen), seen);
|
||||
if (skip != null)
|
||||
queryPayload.Add(nameof(skip), skip);
|
||||
if (take != null)
|
||||
queryPayload.Add(nameof(take), take);
|
||||
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/users/me/notifications",
|
||||
queryPayload), token);
|
||||
|
||||
return await HandleResponse<IEnumerable<NotificationData>>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<NotificationData> GetNotification(string notificationId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/users/me/notifications/{notificationId}"), token);
|
||||
return await HandleResponse<NotificationData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<NotificationData> UpdateNotification(string notificationId, bool? seen,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/users/me/notifications/{notificationId}",
|
||||
method: HttpMethod.Put, bodyPayload: new UpdateNotification() { Seen = seen }), token);
|
||||
return await HandleResponse<NotificationData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task RemoveNotification(string notificationId, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/users/me/notifications/{notificationId}",
|
||||
method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user