Compare commits
1 Commits
v1.0.3.165
...
v1.0.2.25
Author | SHA1 | Date | |
---|---|---|---|
437daff63e |
.circleci
.github
.gitignoreBTCPayServer.Client
BTCPayServer.Client.csprojBTCPayServerClient.APIKeys.csBTCPayServerClient.Authorization.csBTCPayServerClient.Users.csBTCPayServerClient.cs
JsonConverters
Models
Permissions.csBTCPayServer.Common
Altcoins
BTCPayNetworkProvider.Bitcoin.csBTCPayNetworkProvider.Bitcoinplus.csBTCPayNetworkProvider.Bitcore.csBTCPayNetworkProvider.Dash.csBTCPayNetworkProvider.Groestlcoin.csBTCPayNetworkProvider.Litecoin.csBTCPayNetworkProvider.Polis.csBTCPayNetworkProvider.Viacoin.csBTCPayNetworkProvider.cs
BTCPayNetwork.csBTCPayServer.Common.csprojExtensions.csShims.csLiquid
Monero
BTCPayNetworkProvider.Monero.csMoneroLikeSpecificBtcPayNetwork.cs
RPC
JsonRpcClient.cs
Models
CreateAccountRequest.csCreateAccountResponse.csCreateAddressRequest.csCreateAddressResponse.csGetAccountsRequest.csGetAccountsResponse.csGetFeeEstimateRequest.csGetFeeEstimateResponse.csGetHeightResponse.csGetTransferByTransactionIdRequest.csGetTransferByTransactionIdResponse.csGetTransfersRequest.csGetTransfersResponse.csInfo.csMakeUriRequest.csMakeUriResponse.csParseStringConverter.csPeer.csSubaddrIndex.csSubaddressAccount.csSyncInfoResponse.cs
Utils
BTCPayServer.Data
BTCPayServer.Data.csproj
Data
APIKeyData.csAddressInvoiceData.csApplicationDbContext.csApplicationDbContextFactory.csOffchainTransactionData.csPayjoinLock.csPaymentRequestData.csPlannedTransaction.csStoreData.csStoredFile.csU2FDevice.csWalletData.csWalletTransactionData.cs
Migrations
20180719095626_CanDeleteStores.cs20190121133309_AddPaymentRequests.cs20190219032533_AppsTagging.cs20190225091644_AddOpenIddict.cs20190324141717_AddFiles.cs20190425081749_AddU2fDevices.cs20190701082105_sort_paymentrequests.cs20190802142637_WalletData.cs20200110064617_OpenIddictUpdate.cs20200119130108_ExtendApiKeys.cs20200224134444_Remove_OpenIddict.cs20200225133433_AddApiKeyLabel.cs20200402065615_AddApiKeyBlob.cs20200413052418_PlannedTransactions.csApplicationDbContextModelSnapshot.cs
MigrationsExtensions.csBTCPayServer.Rating
AvailableRateProvider.csBTCPayServer.Rating.csprojExchangeRates.cs
Providers
BackgroundFetcherRateProvider.csBitbankRateProvider.csBitflyerRateProvider.csBitpayRateProvider.csByllsRateProvider.csCoinGeckoRateProvider.csExchangeSharpRateProvider.csHttpClientRequestMaker.csKrakenExchangeRateProvider.csNullRateProvider.csPolisRateProvider.cs
Services
BTCPayServer.Tests
ApiKeysTests.csBTCPayServer.Tests.csprojBTCPayServerTester.csChangellyTests.csChargeTester.csCheckoutUITests.csCoinSwitchTests.csCrowdfundTests.csCustomerHttpServer.csDockerfileElementsTests.csExtensions.csGreenfieldAPITests.csLightningDTester.csTestUtils.csU2FTests.csUnitTest1.csUtilitiesTests.csUtils.csdocker-bitcoin-cli.ps1docker-bitcoin-cli.shdocker-bitcoin-generate.ps1docker-bitcoin-generate.shdocker-compose.monero.ymldocker-compose.ymldocker-customer-lightning-cli.ps1docker-customer-lightning-cli.shdocker-entrypoint.shdocker-litecoin-cli.ps1docker-litecoin-cli.shdocker-merchant-lightning-cli.ps1docker-merchant-lightning-cli.shsshd.Dockerfilexunit.runner.json
Lnd
Logging
MockDelay.csMocks
PSBTTests.csPayJoinTests.csPaymentHandlerTest.csPaymentRequestTests.csREADME.mdRateRulesTest.csSeleniumTester.csSeleniumTests.csServerTester.csStorageTests.csTestAccount.csTestData
LndSeedBackup
Tor
BTCPayServer
Authentication
BTCPayNetwork.csBTCPayNetworkProvider.Bitcoin.csBTCPayNetworkProvider.BitcoinGold.csBTCPayNetworkProvider.Dogecoin.csBTCPayNetworkProvider.Litecoin.csBTCPayNetworkProvider.Monacoin.csBTCPayNetworkProvider.csBTCPayServer.csprojConfiguration
BTCPayServerOptions.csConfigurationExtensions.csDefaultConfiguration.csExternalConnectionString.csExternalService.cs
Contracts
Controllers
AccessTokenController.csAccountController.csAppsController.Crowdfund.csAppsController.PointOfSale.csAppsController.csAppsPublicController.csChangellyController.csErrorController.cs
CorsPolicies.csCurrencies.txtCurrencyValue.csCustomThreadPool.csGreenField
HomeController.csInvoiceController.API.csInvoiceController.PaymentProtocol.csInvoiceController.UI.csInvoiceController.csMacaroons.csManageController.2FA.csManageController.APIKeys.csManageController.U2F.csManageController.csPaymentRequestActionResult.csPaymentRequestController.csPublicController.csPublicLightningNodeInfoController.csRateController.csServerController.Storage.csServerController.csStorageController.csStoresController.BTCLike.csStoresController.Changelly.csStoresController.CoinSwitch.csStoresController.Email.csStoresController.LightningLike.csStoresController.csUserStoresController.csVaultController.csWalletsController.PSBT.csWalletsController.csData
APIKeyData.csAPIKeyDataExtensions.csAddressInvoiceData.csAddressInvoiceDataExtensions.csAppData.csApplicationDbContext.csApplicationDbContextFactory.csHistoricalAddressInvoiceData.csHistoricalAddressInvoiceDataExtensions.csInvoiceData.csInvoiceDataExtensions.csInvoiceEventData.csPairedSINData.csPairingCodeData.csPaymentData.csPaymentRequestDataExtensions.csPendingInvoiceData.csRefundData.csSettingData.csStoreBlob.csStoreData.csStoreDataExtensions.csUserStore.csWalletDataExtensions.csWalletTransactionDataExtensions.cs
DerivationSchemeParser.csDerivationSchemeSettings.csDerivationStrategy.csEventAggregator.csEvents
InvoiceDataChangedEvent.csInvoiceEvent.csInvoiceNewAddressEvent.csNBXplorerStateChangedEvent.csNewOnChainTransactionEvent.csSettingsChanged.csUserRegisteredEvent.csWalletChangedEvent.cs
ExplorerClientProvider.csExtensions.csExtensions
EmailSenderExtensions.csModelStateExtensions.csMoneyExtensions.csSSHClientExtensions.csUrlHelperExtensions.cs
Filters
ContentSecurityPolicyAttribute.csOnlyIfSupportAttribute.csOnlyMediaTypeAttribute.csReferrerPolicyAttribute.csXContentTypeOptionsAttribute.csXFrameOptionsAttribute.csXXSSProtectionAttribute.cs
HostedServices
AppInventoryUpdaterHostedService.csBackgroundJobSchedulerHostedService.csBaseAsyncService.csCheckConfigurationHostedService.csCssThemeManager.csDelayedTransactionBroadcasterHostedService.csDynamicDnsHostedService.csEventHostedServiceBase.csInvoiceNotificationManager.csInvoiceWatcher.csNBXplorerWaiter.csRatesHostedService.csSocks5HttpProxyServer.csTorServicesHostedService.csUserEventHostedService.csWalletReceiveCacheUpdater.cs
Hosting
BTCPayServerServices.csBTCpayMiddleware.csHeadersOverrideMiddleware.csResourceBundleProvider.csStartup.cs
HwiWebSocketTransport.csIDelay.csIStartupTask.csJsonConverters
Logging
MigrationStartupTask.csMigrations
20170913143004_Init.Designer.cs20170913143004_Init.cs20170926073744_Settings.Designer.cs20170926073744_Settings.cs20170926084408_RequiresEmailConfirmation.Designer.cs20170926084408_RequiresEmailConfirmation.cs20171006013443_AddressMapping.Designer.cs20171006013443_AddressMapping.cs20171010082424_Tokens.Designer.cs20171010082424_Tokens.cs20171012020112_PendingInvoices.Designer.cs20171012020112_PendingInvoices.cs20171023101754_StoreBlob.Designer.cs20171023101754_StoreBlob.cs20171024163354_RenewUsedAddresses.Designer.cs20171024163354_RenewUsedAddresses.cs20171105235734_PaymentAccounted.Designer.cs20171105235734_PaymentAccounted.cs20171221054550_AltcoinSupport.Designer.cs20171221054550_AltcoinSupport.cs20180106095215_DerivationStrategies.Designer.cs20180106095215_DerivationStrategies.cs20180109021122_defaultcrypto.Designer.cs20180109021122_defaultcrypto.cs20180114123253_events.Designer.cs20180114123253_events.cs20180402095640_appdata.Designer.cs20180402095640_appdata.cs20180429083930_legacyapikey.Designer.cs20180429083930_legacyapikey.csApplicationDbContextModelSnapshot.cs
ModelBinders
Models
AccountViewModels
AppViewModels
ListAppsViewModel.csUpdateCrowdfundViewModel.csUpdatePointOfSaleViewModel.csViewCrowdfundViewModel.csViewPointOfSaleViewModel.cs
ApplicationUser.csAuthorization
BitpayTranslatorViewModel.csConfirmModel.csCreateInvoiceRequest.csErrorViewModel.csGetTokensResponse.csInvoiceResponse.csInvoicingModels
ManageViewModels
ChangePasswordViewModel.csEnableAuthenticatorViewModel.csExternalLoginsViewModel.csIndexViewModel.csSetPasswordViewModel.cs
PaymentRequestViewModels
PostRedictViewModel.csServerViewModels
ChargeServiceViewModel.csDynamicDnsViewModel.csEmailsViewModel.csLightningWalletServices.csLndSeedBackupViewModel.csLndServicesViewModel.csLogsViewModel.csMaintenanceViewModel.csRatesViewModel.csSSHServiceViewModel.csServicesViewModel.csUserViewModel.csUsersViewModel.csViewFilesViewModel.cs
StatusMessageModel.csStoreViewModels
CheckoutExperienceViewModel.csDerivationSchemeViewModel.csLightningNodeViewModel.csPairingModel.csPayButtonViewModel.csRatesViewModel.csStoreViewModel.csStoresViewModel.csTokensViewModel.csUpdateChangellySettingsViewModel.csUpdateCoinSwitchSettingsViewModel.csWalletModel.cs
TokenRequest.csWalletViewModels
PaymentRequest
Payments
Bitcoin
BitcoinLikeOnChainPaymentMethod.csBitcoinLikePaymentData.csBitcoinLikePaymentHandler.csNBXplorerListener.cs
Changelly
Changelly.csChangellyCalculationHelper.csChangellyClientProvider.csChangellyException.csChangellySettings.cs
Models
Coinswitch
IPaymentFilter.csIPaymentMethodDetails.csIPaymentMethodHandler.csISupportedPaymentMethod.csLightning
CLightning
Charge
ILightningInvoiceClient.csLightMoney.csLightningClientFactory.csLightningConnectionString.csLightningLikePaymentData.csLightningLikePaymentHandler.csLightningLikePaymentMethodDetails.csLightningListener.csLightningSupportedPaymentMethod.csPayJoin
PaymentMethodExtensions.csPaymentMethodId.csPaymentTypes.Bitcoin.csPaymentTypes.Lightning.csPaymentTypes.csProperties
Rating
SSH
SearchString.csSecurity
AuthenticationExtensions.csAuthenticationSchemes.csBTCPayClaimsFilter.cs
Bitpay
BitpayAuthenticationHandler.csBitpayAuthenticationOptions.csBitpayAuthenticationTypes.csBitpayAuthorizationHandler.csBitpayClaims.cs
BitpayClaimsFilter.csContentSecurityPolicies.csCookieAuthorizationHandler.csGreenField
APIKeyExtensions.csAPIKeyRepository.csAPIKeysAuthenticationHandler.csBasicAuthenticationHandler.csGreenFieldAuthenticationOptions.csGreenFieldAuthorizationHandler.csGreenFieldConstants.cs
Policies.csPolicyRequirement.csSecurityExtensions.csServerPolicies.csServices
Altcoins/Monero
Configuration
MoneroLikeExtensions.csMoneroStoreNavExtension.csPayments
MoneroLikeOnChainPaymentMethodDetails.csMoneroLikePaymentData.csMoneroLikePaymentMethodHandler.csMoneroPaymentType.csMoneroSupportedPaymentMethod.cs
RPC
Services
UI
Apps
BTCPayServerEnvironment.csClaims.csDelayedTransactionBroadcaster.csDynamicDnsSettings.csFees
HardwareWalletService.csInvoices
Export
InvoiceEntity.csInvoiceRepository.csPaymentMethodDictionary.csPaymentMethodHandlerDictionary.csMails
EmailSender.csEmailSenderFactory.csEmailSettings.csIEmailSender.csServerEmailSender.csStoreEmailSender.cs
MigrationSettings.csPayjoinClient.csPaymentRequests
PoliciesSettings.csRates
BTCPayRateProviderFactory.csBitpayRateProvider.csCachedRateProvider.csCoinAverageRateProvider.csCoinAverageSettings.csCurrencyNameTable.csExchangeSharpRateProvider.csFallbackRateProvider.csIRateProvider.csQuadrigacxRateProvider.cs
Safe.csSettingsRepository.csSocketFactory.csSocks5HttpClientHandler.csStores
ThemesSettings.csTorServices.csTorrc.csWalletRepository.csWallets
Storage
Models
Services
FileService.csStoredFileRepository.cs
StorageExtensions.csProviders
AmazonS3Storage
AzureBlobStorage
AzureBlobStorageFileProviderService.cs
BaseTwentyTwentyStorageFileProviderServiceBase.csConfiguration
FileSystemStorage
Configuration
FileSystemFileProviderService.csTemporaryLocalFileDescriptor.csTemporaryLocalFileProvider.csGoogleCloudStorage
IStorageProviderService.csModels
ViewModels
U2F
Models
AddU2FDeviceViewModel.csLoginWithU2FViewModel.csServerChallenge.csServerRegisterResponse.csU2FAuthenticationViewModel.csU2FDeviceAuthenticationRequest.cs
U2FService.csValidation
Validations
Views
Account
AccessDenied.cshtmlExternalLogin.cshtmlForgotPassword.cshtmlLockout.cshtmlLogin.cshtmlLoginWith2fa.cshtmlLoginWithRecoveryCode.cshtmlLoginWithU2F.cshtmlRegister.cshtmlResetPassword.cshtmlResetPasswordConfirmation.cshtmlSecondaryLogin.cshtml
Apps
AppsPublic
Error
Home
Invoice
Checkout-Body.cshtmlCheckout.cshtmlCheckoutNoScript.cshtmlCreateInvoice.cshtmlInvoice.cshtmlListInvoices.cshtmlListInvoicesPaymentsPartial.cshtmlPosData.cshtml_ViewImports.cshtml
Manage
APIKeys.cshtmlAddApiKey.cshtmlAddU2FDevice.cshtmlAuthorizeAPIKey.cshtmlChangePassword.cshtmlDisable2fa.cshtmlEnableAuthenticator.cshtmlExternalLogins.cshtmlGenerateRecoveryCodes.cshtmlIndex.cshtmlManageNavPages.csResetAuthenticator.cshtmlSetPassword.cshtmlTwoFactorAuthentication.cshtmlU2FAuthentication.cshtml_Nav.cshtml
MoneroLikeStore
PaymentRequest
EditPaymentRequest.cshtmlGetPaymentRequests.cshtmlMinimalPaymentRequest.cshtmlViewPaymentRequest.cshtml
Public
PublicLightningNodeInfo
Server
CLightningRestServices.cshtmlConfiguratorService.cshtmlCreateTemporaryFileUrl.cshtmlDynamicDnsService.cshtmlDynamicDnsServices.cshtmlEditAmazonS3StorageProvider.cshtmlEditAzureBlobStorageStorageProvider.cshtmlEditFilesystemStorageProvider.cshtmlEditGoogleCloudStorageStorageProvider.cshtmlEmails.cshtmlFiles.cshtmlLightningChargeServices.cshtmlLightningWalletServices.cshtmlListUsers.cshtmlLndSeedBackup.cshtmlLndServices.cshtmlLogs.cshtmlMaintenance.cshtmlP2PService.cshtmlPolicies.cshtmlRPCService.cshtmlRates.cshtmlSSHService.cshtmlServerNavPages.csServices.cshtmlStorage.cshtmlTheme.cshtmlUser.cshtml_Nav.cshtml
Shared
Bitcoin_Lightning_LikeMethodCheckout.cshtmlBitcoin_Lightning_LikeMethodCheckoutNoScript.cshtmlConfirm.cshtmlEmailsBody.cshtmlError.cshtmlHeader.cshtml
Monero
NotificationEmailWarning.cshtmlPostRedirect.cshtmlSyncModal.cshtmlVaultElements.cshtmlViewBitcoinLikePaymentData.cshtmlViewLightningLikePaymentData.cshtml_BTCPaySupporters.cshtml_Layout.cshtml_LayoutWelcome.cshtml_NavLayout.cshtml_StatusMessage.cshtml_ValidationScriptsPartial.cshtmlStores
AddDerivationScheme.cshtmlAddDerivationSchemes_HardwareWalletDialogs.cshtmlAddDerivationSchemes_NBXWalletGenerate.cshtmlAddLightningNode.cshtmlCheckoutExperience.cshtmlCreateToken.cshtmlEmails.cshtmlListTokens.cshtmlPayButton.cshtmlPayButtonEnable.cshtmlRates.cshtmlRequestPairing.cshtmlShowToken.cshtmlStoreNavPages.csStoreUsers.cshtmlUpdateChangellySettings.cshtmlUpdateCoinSwitchSettings.cshtmlUpdateStore.cshtmlWallet.cshtml_Nav.cshtml_ViewImports.cshtml
UserStores
ViewsRazor.csWallets
CoinSelection.cshtmlListWallets.cshtmlSignWithSeed.cshtmlWalletCameraScanner.cshtmlWalletPSBT.cshtmlWalletPSBTCombine.cshtmlWalletPSBTReady.cshtmlWalletReceive.cshtmlWalletRescan.cshtmlWalletSend.cshtmlWalletSendLedger.cshtmlWalletSendVault.cshtmlWalletSettings.cshtmlWalletTransactions.cshtmlWalletsNavPages.cs_Nav.cshtml_ViewImports.cshtml_ViewStart.cshtml
_ViewImports.cshtmlwwwroot
_bootstrap_kitchensink.html
cart
checkout
coinswitch.html
css
js
crowdfund-admin
crowdfund
fonts
img
GreenWallet.pngacinq-logo.svgbtcpay-logo-white-txt.svgbtcpay-logo.svgbtse.svgdglab.gifdglab.svgdonation.jpg
errorpages
fullynoded.pnggithub.svgibuki.pngicons
Onion_Color.svgicon-128x128.pngicon-144x144.pngicon-152x152.pngicon-192x192.pngicon-384x384.pngicon-512x512.pngicon-72x72.pngicon-96x96.pngonion.svg
joule.pngledger-help-xpub.pnglogo-white.pnglogo.svglunanode.svgmattermost.pngmattermost.svgmetaco.jpgpaybutton
pebblewallet.jpgslack.svgsplash.pngsquarecrypto.svgtwitter.svgwalletofsatoshi.svgwasabi.pngyoutube.pngzapwallet.jpgzeus.jpgimlegacy
LCAD.pngbitcoin-symbol.svgbitcoin.svgbitcoinplus.pngbitcore-lightning.pngbitcore-lightning.svgbitcore.svgbtc-lightning.svgbtg-lightning.svgbtg-symbol.svgdash.pngetb.pngfeathercoin.pnggroestlcoin-lightning.svggroestlcoin.pngliquid-tether.svgliquid.pnglitecoin-symbol.svglitecoin.svgltc-lightning.svgmonero.svgpolis.pngufo.pngviacoin.pngviacoin.svg
js
StoreAddDerivationScheme.jsStoreWallet.jsWalletSendLedger.jsledgerwebsocket.jsqrcode.jsqrcode.min.jsvaultbridge.jsvaultbridge.ui.js
wallet
locales
am-ET.jsonbs-BA.jsonca-ES.jsoncs-CZ.jsonda-DK.jsonde-DE.jsonel-GR.jsonen.jsones-ES.jsonfi-FI.jsonfr-FR.jsonhi.jsonhr-HR.jsonhu-HU.jsonid.jsonis-IS.jsonit-IT.jsonja-JP.jsonkk-KZ.jsonlv.jsonnl-NL.jsonnp-NP.jsonpl.jsonpt-BR.jsonpt-PT.jsonru-RU.jsonsk-SK.jsonsl-SI.jsonsr.jsonsv.jsontr.jsonuk-UA.jsonvi-VN.jsonzh-SP.json
main
manifest.jsonmodal
paybutton
payment-request-admin
payment-request
pos-admin
products/js
swagger/v1
swagger.template.api-keys.jsonswagger.template.authorization.jsonswagger.template.jsonswagger.template.users.json
tests
vendor
animejs
babel-polyfill
bootstrap-vue
bootstrap4-creativestart
bootstrap4
css
js
flatpickr
highlightjs
i18next
moment
popper
signalr
summernote
u2f
vex
css
vex-theme-bottom-right-corner.cssvex-theme-default.cssvex-theme-flat-attack.cssvex-theme-os.cssvex-theme-plain.cssvex-theme-top.cssvex-theme-wireframe.cssvex.css
js
vue-qrcode-reader
vue-qrcode
vue-toasted
vuejs-vee-validate
vuejs
Build
Changelog.mdDockerfileLICENSENuget.ConfigREADME.mdSECURITY.mdamd64.Dockerfilearm32v7.Dockerfilearm64v8.Dockerfilebtcpayserver.slndocker-entrypoint.shnuget.configpublish-docker.ps1@ -1,147 +0,0 @@
|
||||
version: 2
|
||||
jobs:
|
||||
fast_tests:
|
||||
machine:
|
||||
enabled: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "Fast=Fast"
|
||||
selenium_tests:
|
||||
machine:
|
||||
enabled: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "Selenium=Selenium"
|
||||
integration_tests:
|
||||
machine:
|
||||
enabled: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "Integration=Integration"
|
||||
external_tests:
|
||||
machine:
|
||||
enabled: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
if [ "$CIRCLE_PROJECT_USERNAME" == "btcpayserver" ] && [ "$CIRCLE_PROJECT_REPONAME" == "btcpayserver" ]; then
|
||||
cd .circleci && ./run-tests.sh "ExternalIntegration=ExternalIntegration"
|
||||
else
|
||||
echo "Skipping running ExternalIntegration tests outside of context of main user and repository that have access to secrets"
|
||||
fi
|
||||
|
||||
|
||||
# publish jobs require $DOCKERHUB_REPO, $DOCKERHUB_USER, $DOCKERHUB_PASS defined
|
||||
amd64:
|
||||
machine:
|
||||
enabled: true
|
||||
steps:
|
||||
- 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 login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-amd64
|
||||
|
||||
arm32v7:
|
||||
machine:
|
||||
enabled: true
|
||||
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-arm32v7 -f arm32v7.Dockerfile .
|
||||
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-arm32v7
|
||||
|
||||
arm64v8:
|
||||
machine:
|
||||
enabled: true
|
||||
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 login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-arm64v8
|
||||
|
||||
multiarch:
|
||||
machine:
|
||||
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 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
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
jobs:
|
||||
- fast_tests
|
||||
- selenium_tests
|
||||
- integration_tests
|
||||
- external_tests:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
|
||||
publish:
|
||||
jobs:
|
||||
- amd64:
|
||||
filters:
|
||||
# ignore any commit on any branch by default
|
||||
branches:
|
||||
ignore: /.*/
|
||||
# only act on version tags v1.0.0.88
|
||||
# OR feature tags like vlndseedbackup
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*)|(v[a-z]+)/
|
||||
- arm32v7:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*)|(v[a-z]+)/
|
||||
- arm64v8:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*)|(v[a-z]+)/
|
||||
- multiarch:
|
||||
requires:
|
||||
- amd64
|
||||
- arm32v7
|
||||
- arm64v8
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /(v[1-9]+(\.[0-9]+)*)|(v[a-z]+)/
|
@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cd ../BTCPayServer.Tests
|
||||
docker-compose -v
|
||||
docker-compose down --v
|
||||
docker-compose pull
|
||||
docker-compose build
|
||||
docker-compose run -e "TEST_FILTERS=$1" tests
|
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
|
37
.github/ISSUE_TEMPLATE/bug_report.md
vendored
37
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,37 +0,0 @@
|
||||
---
|
||||
name: Report a problem
|
||||
about: File a technical problem or report a bug
|
||||
---
|
||||
|
||||
**Describe the problem/bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Your environment**
|
||||
* Version of BTCPay Server:
|
||||
* Deployment method:
|
||||
* Other relevant environment details:
|
||||
|
||||
**Logs (if applicable)**
|
||||
Basic logs can be found in Server Settings > Logs.
|
||||
|
||||
**Setup Parameters**
|
||||
If you're reporting a deployment issue run `. btcpay-setup.sh -i` and paste your the paremeters by obscuring private information.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Actual behavior**
|
||||
Tell us what happens instead
|
||||
|
||||
**Screenshots/Links**
|
||||
If applicable, add screenshots or links to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Ideas and feature requests
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Provide examples**
|
||||
If applicable provide examples, wireframes, sketches or images to better explain your idea.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -293,4 +293,3 @@ BTCPayServer/wwwroot/bundles/*
|
||||
!BTCPayServer/wwwroot/bundles/.gitignore
|
||||
|
||||
.vscode
|
||||
BTCPayServer/testpwd
|
||||
|
@ -1,12 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NBitcoin" Version="5.0.29" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</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);
|
||||
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);
|
||||
HandleResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
|
||||
public static Uri GenerateAuthorizeUri(Uri btcpayHost, string[] permissions, bool strict = true,
|
||||
bool selectiveStores = false)
|
||||
{
|
||||
var result = new UriBuilder(btcpayHost);
|
||||
result.Path = "api-keys/authorize";
|
||||
|
||||
AppendPayloadToQuery(result,
|
||||
new Dictionary<string, object>()
|
||||
{
|
||||
{"strict", strict}, {"selectiveStores", selectiveStores}, {"permissions", permissions}
|
||||
});
|
||||
|
||||
return result.Uri;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
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<ApplicationUserData> GetCurrentUser(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/users/me"), token);
|
||||
return await HandleResponse<ApplicationUserData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<ApplicationUserData> CreateUser(CreateApplicationUserRequest request,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/users", null, request, HttpMethod.Post), token);
|
||||
return await HandleResponse<ApplicationUserData>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
private readonly Uri _btcpayHost;
|
||||
private readonly string _username;
|
||||
private readonly string _password;
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public string APIKey => _apiKey;
|
||||
|
||||
public BTCPayServerClient(Uri btcpayHost, HttpClient httpClient = null)
|
||||
{
|
||||
if (btcpayHost == null)
|
||||
throw new ArgumentNullException(nameof(btcpayHost));
|
||||
_btcpayHost = btcpayHost;
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
public BTCPayServerClient(Uri btcpayHost, string APIKey, HttpClient httpClient = null)
|
||||
{
|
||||
_apiKey = APIKey;
|
||||
_btcpayHost = btcpayHost;
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
|
||||
public BTCPayServerClient(Uri btcpayHost, string username, string password, HttpClient httpClient = null)
|
||||
{
|
||||
_apiKey = APIKey;
|
||||
_btcpayHost = btcpayHost;
|
||||
_username = username;
|
||||
_password = password;
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
|
||||
protected void HandleResponse(HttpResponseMessage message)
|
||||
{
|
||||
message.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
protected async Task<T> HandleResponse<T>(HttpResponseMessage message)
|
||||
{
|
||||
HandleResponse(message);
|
||||
return JsonConvert.DeserializeObject<T>(await message.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
protected virtual HttpRequestMessage CreateHttpRequest(string path,
|
||||
Dictionary<string, object> queryPayload = null,
|
||||
HttpMethod method = null)
|
||||
{
|
||||
UriBuilder uriBuilder = new UriBuilder(_btcpayHost) {Path = path};
|
||||
if (queryPayload != null && queryPayload.Any())
|
||||
{
|
||||
AppendPayloadToQuery(uriBuilder, queryPayload);
|
||||
}
|
||||
|
||||
var httpRequest = new HttpRequestMessage(method ?? HttpMethod.Get, uriBuilder.Uri);
|
||||
if (_apiKey != null)
|
||||
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("token", _apiKey);
|
||||
else if (!string.IsNullOrEmpty(_username))
|
||||
{
|
||||
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", System.Convert.ToBase64String(Encoding.ASCII.GetBytes(_username + ":" + _password)));
|
||||
}
|
||||
|
||||
|
||||
return httpRequest;
|
||||
}
|
||||
|
||||
protected virtual HttpRequestMessage CreateHttpRequest<T>(string path,
|
||||
Dictionary<string, object> queryPayload = null,
|
||||
T bodyPayload = default, HttpMethod method = null)
|
||||
{
|
||||
var request = CreateHttpRequest(path, queryPayload, method);
|
||||
if (typeof(T).IsPrimitive || !EqualityComparer<T>.Default.Equals(bodyPayload, default(T)))
|
||||
{
|
||||
request.Content = new StringContent(JsonConvert.SerializeObject(bodyPayload), Encoding.UTF8, "application/json");
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private static void AppendPayloadToQuery(UriBuilder uri, Dictionary<string, object> payload)
|
||||
{
|
||||
if (uri.Query.Length > 1)
|
||||
uri.Query += "&";
|
||||
foreach (KeyValuePair<string, object> keyValuePair in payload)
|
||||
{
|
||||
UriBuilder uriBuilder = uri;
|
||||
if (keyValuePair.Value.GetType().GetInterfaces().Contains((typeof(IEnumerable))))
|
||||
{
|
||||
foreach (var item in (IEnumerable)keyValuePair.Value)
|
||||
{
|
||||
uriBuilder.Query = uriBuilder.Query + Uri.EscapeDataString(keyValuePair.Key) + "=" +
|
||||
Uri.EscapeDataString(item.ToString()) + "&";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uriBuilder.Query = uriBuilder.Query + Uri.EscapeDataString(keyValuePair.Key) + "=" +
|
||||
Uri.EscapeDataString(keyValuePair.Value.ToString()) + "&";
|
||||
}
|
||||
}
|
||||
|
||||
uri.Query = uri.Query.Trim('&');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using NBitcoin.JsonConverters;
|
||||
|
||||
namespace BTCPayServer.Client.JsonConverters
|
||||
{
|
||||
public class PermissionJsonConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return typeof(Permission).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
return null;
|
||||
if (reader.TokenType != JsonToken.String)
|
||||
throw new JsonObjectException("Type 'Permission' is expected to be a 'String'", reader);
|
||||
if (reader.Value is String s && Permission.TryParse(s, out var permission))
|
||||
return permission;
|
||||
throw new JsonObjectException("Invalid 'Permission' String", reader);
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
if (value is Permission v)
|
||||
writer.WriteValue(v.ToString());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using BTCPayServer.Client.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public class ApiKeyData
|
||||
{
|
||||
public string ApiKey { get; set; }
|
||||
public string Label { get; set; }
|
||||
[JsonProperty(ItemConverterType = typeof(PermissionJsonConverter))]
|
||||
public Permission[] Permissions { get; set; }
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public class ApplicationUserData
|
||||
{
|
||||
/// <summary>
|
||||
/// the id of the user
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
/// the email AND username of the user
|
||||
/// </summary>
|
||||
public string Email { get; set; }
|
||||
/// <summary>
|
||||
/// Whether the user has verified their email
|
||||
/// </summary>
|
||||
public bool EmailConfirmed { get; set; }
|
||||
/// <summary>
|
||||
/// whether the user needed to verify their email on account creation
|
||||
/// </summary>
|
||||
public bool RequiresEmailConfirmation { get; set; }
|
||||
}
|
||||
|
||||
public class CreateApplicationUserRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// the email AND username of the new user
|
||||
/// </summary>
|
||||
public string Email { get; set; }
|
||||
/// <summary>
|
||||
/// password of the new user
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
/// <summary>
|
||||
/// Whether this user is an administrator. If left null and there are no admins in the system, the user will be created as an admin.
|
||||
/// </summary>
|
||||
public bool? IsAdministrator { get; set; }
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using BTCPayServer.Client.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public class CreateApiKeyRequest
|
||||
{
|
||||
public string Label { get; set; }
|
||||
[JsonProperty(ItemConverterType = typeof(PermissionJsonConverter))]
|
||||
public Permission[] Permissions { get; set; }
|
||||
}
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace BTCPayServer.Client
|
||||
{
|
||||
public class Policies
|
||||
{
|
||||
public const string CanModifyServerSettings = "btcpay.server.canmodifyserversettings";
|
||||
public const string CanModifyStoreSettings = "btcpay.store.canmodifystoresettings";
|
||||
public const string CanViewStoreSettings = "btcpay.store.canviewstoresettings";
|
||||
public const string CanCreateInvoice = "btcpay.store.cancreateinvoice";
|
||||
public const string CanModifyProfile = "btcpay.user.canmodifyprofile";
|
||||
public const string CanViewProfile = "btcpay.user.canviewprofile";
|
||||
public const string CanCreateUser = "btcpay.server.cancreateuser";
|
||||
public const string Unrestricted = "unrestricted";
|
||||
public static IEnumerable<string> AllPolicies
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return CanCreateInvoice;
|
||||
yield return CanModifyServerSettings;
|
||||
yield return CanModifyStoreSettings;
|
||||
yield return CanViewStoreSettings;
|
||||
yield return CanModifyProfile;
|
||||
yield return CanViewProfile;
|
||||
yield return CanCreateUser;
|
||||
yield return Unrestricted;
|
||||
}
|
||||
}
|
||||
public static bool IsValidPolicy(string policy)
|
||||
{
|
||||
return AllPolicies.Any(p => p.Equals(policy, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public static bool IsStorePolicy(string policy)
|
||||
{
|
||||
return policy.StartsWith("btcpay.store", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static bool IsServerPolicy(string policy)
|
||||
{
|
||||
return policy.StartsWith("btcpay.server", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
public class Permission
|
||||
{
|
||||
public static Permission Create(string policy, string storeId = null)
|
||||
{
|
||||
if (TryCreatePermission(policy, storeId, out var r))
|
||||
return r;
|
||||
throw new ArgumentException("Invalid Permission");
|
||||
}
|
||||
|
||||
public static bool TryCreatePermission(string policy, string storeId, out Permission permission)
|
||||
{
|
||||
permission = null;
|
||||
if (policy == null)
|
||||
throw new ArgumentNullException(nameof(policy));
|
||||
policy = policy.Trim().ToLowerInvariant();
|
||||
if (!Policies.IsValidPolicy(policy))
|
||||
return false;
|
||||
if (storeId != null && !Policies.IsStorePolicy(policy))
|
||||
return false;
|
||||
permission = new Permission(policy, storeId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryParse(string str, out Permission permission)
|
||||
{
|
||||
permission = null;
|
||||
if (str == null)
|
||||
throw new ArgumentNullException(nameof(str));
|
||||
str = str.Trim();
|
||||
var separator = str.IndexOf(':');
|
||||
if (separator == -1)
|
||||
{
|
||||
str = str.ToLowerInvariant();
|
||||
if (!Policies.IsValidPolicy(str))
|
||||
return false;
|
||||
permission = new Permission(str, null);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var policy = str.Substring(0, separator).ToLowerInvariant();
|
||||
if (!Policies.IsValidPolicy(policy))
|
||||
return false;
|
||||
if (!Policies.IsStorePolicy(policy))
|
||||
return false;
|
||||
var storeId = str.Substring(separator + 1);
|
||||
if (storeId.Length == 0)
|
||||
return false;
|
||||
permission = new Permission(policy, storeId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal Permission(string policy, string storeId)
|
||||
{
|
||||
Policy = policy;
|
||||
StoreId = storeId;
|
||||
}
|
||||
|
||||
public bool Contains(Permission subpermission)
|
||||
{
|
||||
if (subpermission is null)
|
||||
throw new ArgumentNullException(nameof(subpermission));
|
||||
|
||||
if (!ContainsPolicy(subpermission.Policy))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!Policies.IsStorePolicy(subpermission.Policy))
|
||||
return true;
|
||||
return StoreId == null || subpermission.StoreId == this.StoreId;
|
||||
}
|
||||
|
||||
public static IEnumerable<Permission> ToPermissions(string[] permissions)
|
||||
{
|
||||
if (permissions == null)
|
||||
throw new ArgumentNullException(nameof(permissions));
|
||||
foreach (var p in permissions)
|
||||
{
|
||||
if (TryParse(p, out var pp))
|
||||
yield return pp;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ContainsPolicy(string subpolicy)
|
||||
{
|
||||
if (this.Policy == Policies.Unrestricted)
|
||||
return true;
|
||||
if (this.Policy == subpolicy)
|
||||
return true;
|
||||
if (subpolicy == Policies.CanViewStoreSettings && this.Policy == Policies.CanModifyStoreSettings)
|
||||
return true;
|
||||
if (subpolicy == Policies.CanCreateInvoice && this.Policy == Policies.CanModifyStoreSettings)
|
||||
return true;
|
||||
if (subpolicy == Policies.CanViewProfile && this.Policy == Policies.CanModifyProfile)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public string StoreId { get; }
|
||||
public string Policy { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (StoreId != null)
|
||||
{
|
||||
return $"{Policy}:{StoreId}";
|
||||
}
|
||||
return Policy;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
Permission item = obj as Permission;
|
||||
if (item == null)
|
||||
return false;
|
||||
return ToString().Equals(item.ToString());
|
||||
}
|
||||
public static bool operator ==(Permission a, Permission b)
|
||||
{
|
||||
if (System.Object.ReferenceEquals(a, b))
|
||||
return true;
|
||||
if (((object)a == null) || ((object)b == null))
|
||||
return false;
|
||||
return a.ToString() == b.ToString();
|
||||
}
|
||||
|
||||
public static bool operator !=(Permission a, Permission b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ToString().GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitBitcoin()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("BTC");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Bitcoin",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/tx/{0}" : "https://blockstream.info/testnet/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "bitcoin",
|
||||
CryptoImagePath = "imlegacy/bitcoin.svg",
|
||||
LightningImagePath = "imlegacy/bitcoin-lightning.svg",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("0'") : new KeyPath("1'"),
|
||||
SupportRBF = true,
|
||||
SupportPayJoin = true,
|
||||
//https://github.com/spesmilo/electrum/blob/11733d6bc271646a00b69ff07657119598874da4/electrum/constants.py
|
||||
ElectrumMapping = NetworkType == NetworkType.Mainnet
|
||||
? new Dictionary<uint, DerivationType>()
|
||||
{
|
||||
{0x0488b21eU, DerivationType.Legacy }, // xpub
|
||||
{0x049d7cb2U, DerivationType.SegwitP2SH }, // ypub
|
||||
{0x4b24746U, DerivationType.Segwit }, //zpub
|
||||
}
|
||||
: new Dictionary<uint, DerivationType>()
|
||||
{
|
||||
{0x043587cfU, DerivationType.Legacy},
|
||||
{0x044a5262U, DerivationType.SegwitP2SH},
|
||||
{0x045f1cf6U, DerivationType.Segwit}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitBitcoinplus()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("XBC");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Bitcoinplus",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://chainz.cryptoid.info/xbc/tx.dws?{0}" : "https://chainz.cryptoid.info/xbc/tx.dws?{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "bitcoinplus",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"XBC_X = XBC_BTC * BTC_X",
|
||||
"XBC_BTC = cryptopia(XBC_BTC)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/bitcoinplus.png",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("65'") : new KeyPath("1'")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitBitcore()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("BTX");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Bitcore",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://insight.bitcore.cc/tx/{0}" : "https://insight.bitcore.cc/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "bitcore",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"BTX_X = BTX_BTC * BTC_X",
|
||||
"BTX_BTC = hitbtc(BTX_BTC)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/bitcore.svg",
|
||||
LightningImagePath = "imlegacy/bitcore-lightning.svg",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("160'") : new KeyPath("1'")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitDash()
|
||||
{
|
||||
//not needed: NBitcoin.Altcoins.Dash.Instance.EnsureRegistered();
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("DASH");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Dash",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
||||
? "https://insight.dash.org/insight/tx/{0}"
|
||||
: "https://testnet-insight.dashevo.org/insight/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "dash",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"DASH_X = DASH_BTC * BTC_X",
|
||||
"DASH_BTC = bittrex(DASH_BTC)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/dash.png",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
//https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("5'")
|
||||
: new KeyPath("1'")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitGroestlcoin()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("GRS");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Groestlcoin",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
||||
? "https://chainz.cryptoid.info/grs/tx.dws?{0}.htm"
|
||||
: "https://chainz.cryptoid.info/grs-test/tx.dws?{0}.htm",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "groestlcoin",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"GRS_X = GRS_BTC * BTC_X",
|
||||
"GRS_BTC = bittrex(GRS_BTC)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/groestlcoin.png",
|
||||
LightningImagePath = "imlegacy/groestlcoin-lightning.svg",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("17'") : new KeyPath("1'"),
|
||||
SupportRBF = true,
|
||||
SupportPayJoin = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitLitecoin()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("LTC");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Litecoin",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet
|
||||
? "https://live.blockcypher.com/ltc/tx/{0}/"
|
||||
: "http://explorer.litecointools.com/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "litecoin",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"LTC_X = LTC_BTC * BTC_X",
|
||||
"LTC_BTC = coingecko(LTC_BTC)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/litecoin.svg",
|
||||
LightningImagePath = "imlegacy/litecoin-lightning.svg",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("2'") : new KeyPath("1'"),
|
||||
//https://github.com/pooler/electrum-ltc/blob/0d6989a9d2fb2edbea421c116e49d1015c7c5a91/electrum_ltc/constants.py
|
||||
ElectrumMapping = NetworkType == NetworkType.Mainnet
|
||||
? new Dictionary<uint, DerivationType>()
|
||||
{
|
||||
{0x0488b21eU, DerivationType.Legacy },
|
||||
{0x049d7cb2U, DerivationType.SegwitP2SH },
|
||||
{0x04b24746U, DerivationType.Segwit },
|
||||
}
|
||||
: new Dictionary<uint, DerivationType>()
|
||||
{
|
||||
{0x043587cfU, DerivationType.Legacy },
|
||||
{0x044a5262U, DerivationType.SegwitP2SH },
|
||||
{0x045f1cf6U, DerivationType.Segwit }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitPolis()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("POLIS");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Polis",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockbook.polispay.org/tx/{0}" : "https://blockbook.polispay.org/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "polis",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"POLIS_X = POLIS_BTC * BTC_X",
|
||||
"POLIS_BTC = polispay(POLIS_BTC)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/polis.png",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1997'") : new KeyPath("1'")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitViacoin()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("VIA");
|
||||
Add(new BTCPayNetwork()
|
||||
{
|
||||
CryptoCode = nbxplorerNetwork.CryptoCode,
|
||||
DisplayName = "Viacoin",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://explorer.viacoin.org/tx/{0}" : "https://explorer.viacoin.org/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "viacoin",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"VIA_X = VIA_BTC * BTC_X",
|
||||
"VIA_BTC = bittrex(VIA_BTC)"
|
||||
},
|
||||
CryptoImagePath = "imlegacy/viacoin.png",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("14'") : new KeyPath("1'")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
Dictionary<string, BTCPayNetworkBase> _Networks = new Dictionary<string, BTCPayNetworkBase>();
|
||||
|
||||
|
||||
private readonly NBXplorerNetworkProvider _NBXplorerNetworkProvider;
|
||||
public NBXplorerNetworkProvider NBXplorerNetworkProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
return _NBXplorerNetworkProvider;
|
||||
}
|
||||
}
|
||||
|
||||
BTCPayNetworkProvider(BTCPayNetworkProvider unfiltered, string[] cryptoCodes)
|
||||
{
|
||||
UnfilteredNetworks = unfiltered.UnfilteredNetworks ?? unfiltered;
|
||||
NetworkType = unfiltered.NetworkType;
|
||||
_NBXplorerNetworkProvider = new NBXplorerNetworkProvider(unfiltered.NetworkType);
|
||||
_Networks = new Dictionary<string, BTCPayNetworkBase>();
|
||||
cryptoCodes = cryptoCodes.Select(c => c.ToUpperInvariant()).ToArray();
|
||||
foreach (var network in unfiltered._Networks)
|
||||
{
|
||||
if(cryptoCodes.Contains(network.Key))
|
||||
{
|
||||
_Networks.Add(network.Key, network.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BTCPayNetworkProvider UnfilteredNetworks { get; }
|
||||
|
||||
public NetworkType NetworkType { get; private set; }
|
||||
public BTCPayNetworkProvider(NetworkType networkType)
|
||||
{
|
||||
UnfilteredNetworks = this;
|
||||
_NBXplorerNetworkProvider = new NBXplorerNetworkProvider(networkType);
|
||||
NetworkType = networkType;
|
||||
InitBitcoin();
|
||||
InitLiquid();
|
||||
InitLiquidAssets();
|
||||
InitLitecoin();
|
||||
InitBitcore();
|
||||
InitDogecoin();
|
||||
InitBitcoinGold();
|
||||
InitMonacoin();
|
||||
InitDash();
|
||||
InitFeathercoin();
|
||||
InitGroestlcoin();
|
||||
InitViacoin();
|
||||
InitMonero();
|
||||
InitPolis();
|
||||
|
||||
// Assume that electrum mappings are same as BTC if not specified
|
||||
foreach (var network in _Networks.Values.OfType<BTCPayNetwork>())
|
||||
{
|
||||
if(network.ElectrumMapping.Count == 0)
|
||||
{
|
||||
network.ElectrumMapping = GetNetwork<BTCPayNetwork>("BTC").ElectrumMapping;
|
||||
if (!network.NBitcoinNetwork.Consensus.SupportSegwit)
|
||||
{
|
||||
network.ElectrumMapping =
|
||||
network.ElectrumMapping
|
||||
.Where(kv => kv.Value == DerivationType.Legacy)
|
||||
.ToDictionary(k => k.Key, k => k.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disabled because of https://twitter.com/Cryptopia_NZ/status/1085084168852291586
|
||||
//InitBitcoinplus();
|
||||
//InitUfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keep only the specified crypto
|
||||
/// </summary>
|
||||
/// <param name="cryptoCodes">Crypto to support</param>
|
||||
/// <returns></returns>
|
||||
public BTCPayNetworkProvider Filter(string[] cryptoCodes)
|
||||
{
|
||||
return new BTCPayNetworkProvider(this, cryptoCodes);
|
||||
}
|
||||
|
||||
[Obsolete("To use only for legacy stuff")]
|
||||
public BTCPayNetwork BTC => GetNetwork<BTCPayNetwork>("BTC");
|
||||
|
||||
public void Add(BTCPayNetwork network)
|
||||
{
|
||||
if (network.NBitcoinNetwork == null)
|
||||
return;
|
||||
Add(network as BTCPayNetworkBase);
|
||||
}
|
||||
public void Add(BTCPayNetworkBase network)
|
||||
{
|
||||
_Networks.Add(network.CryptoCode.ToUpperInvariant(), network);
|
||||
}
|
||||
|
||||
public IEnumerable<BTCPayNetworkBase> GetAll()
|
||||
{
|
||||
return _Networks.Values.ToArray();
|
||||
}
|
||||
|
||||
public bool Support(string cryptoCode)
|
||||
{
|
||||
return _Networks.ContainsKey(cryptoCode.ToUpperInvariant());
|
||||
}
|
||||
public BTCPayNetworkBase GetNetwork(string cryptoCode)
|
||||
{
|
||||
return GetNetwork<BTCPayNetworkBase>(cryptoCode.ToUpperInvariant());
|
||||
}
|
||||
public T GetNetwork<T>(string cryptoCode) where T: BTCPayNetworkBase
|
||||
{
|
||||
if (cryptoCode == null)
|
||||
throw new ArgumentNullException(nameof(cryptoCode));
|
||||
if(!_Networks.TryGetValue(cryptoCode.ToUpperInvariant(), out BTCPayNetworkBase network))
|
||||
{
|
||||
if (cryptoCode == "XBT")
|
||||
return GetNetwork<T>("BTC");
|
||||
}
|
||||
return network as T;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
using NBitcoin.Altcoins;
|
||||
using NBitcoin.Altcoins.Elements;
|
||||
using NBXplorer;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitLiquid()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("LBTC");
|
||||
Add(new ElementsBTCPayNetwork()
|
||||
{
|
||||
AssetId = NetworkType == NetworkType.Mainnet ? ElementsParams<Liquid>.PeggedAssetId: ElementsParams<Liquid.LiquidRegtest>.PeggedAssetId,
|
||||
CryptoCode = "LBTC",
|
||||
NetworkCryptoCode = "LBTC",
|
||||
DisplayName = "Liquid Bitcoin",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"LBTC_X = LBTC_BTC * BTC_X",
|
||||
"LBTC_BTC = 1",
|
||||
},
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/liquid/tx/{0}" : "https://blockstream.info/testnet/liquid/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "liquidnetwork",
|
||||
CryptoImagePath = "imlegacy/liquid.png",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
|
||||
SupportRBF = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitLiquidAssets()
|
||||
{
|
||||
var nbxplorerNetwork = NBXplorerNetworkProvider.GetFromCryptoCode("LBTC");
|
||||
Add(new ElementsBTCPayNetwork()
|
||||
{
|
||||
CryptoCode = "USDt",
|
||||
NetworkCryptoCode = "LBTC",
|
||||
ShowSyncSummary = false,
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"USDT_UST = 1",
|
||||
"USDT_X = USDT_BTC * BTC_X",
|
||||
"USDT_BTC = bitfinex(UST_BTC)",
|
||||
},
|
||||
AssetId = new uint256("ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2"),
|
||||
DisplayName = "Liquid Tether",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/liquid/tx/{0}" : "https://blockstream.info/testnet/liquid/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "liquidnetwork",
|
||||
CryptoImagePath = "imlegacy/liquid-tether.svg",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
|
||||
SupportRBF = true
|
||||
});
|
||||
|
||||
Add(new ElementsBTCPayNetwork()
|
||||
{
|
||||
CryptoCode = "ETB",
|
||||
NetworkCryptoCode = "LBTC",
|
||||
ShowSyncSummary = false,
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
|
||||
"ETB_X = ETB_BTC * BTC_X",
|
||||
"ETB_BTC = bitpay(ETB_BTC)"
|
||||
},
|
||||
Divisibility = 2,
|
||||
AssetId = new uint256("aa775044c32a7df391902b3659f46dfe004ccb2644ce2ddc7dba31e889391caf"),
|
||||
DisplayName = "Ethiopian Birr",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/liquid/tx/{0}" : "https://blockstream.info/testnet/liquid/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "liquidnetwork",
|
||||
CryptoImagePath = "imlegacy/etb.png",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
|
||||
SupportRBF = true
|
||||
});
|
||||
|
||||
Add(new ElementsBTCPayNetwork()
|
||||
{
|
||||
CryptoCode = "LCAD",
|
||||
NetworkCryptoCode = "LBTC",
|
||||
ShowSyncSummary = false,
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"LCAD_CAD = 1",
|
||||
"LCAD_X = CAD_BTC * BTC_X",
|
||||
"LCAD_BTC = bylls(CAD_BTC)",
|
||||
},
|
||||
AssetId = new uint256("0e99c1a6da379d1f4151fb9df90449d40d0608f6cb33a5bcbfc8c265f42bab0a"),
|
||||
DisplayName = "Liquid CAD",
|
||||
BlockExplorerLink = NetworkType == NetworkType.Mainnet ? "https://blockstream.info/liquid/tx/{0}" : "https://blockstream.info/testnet/liquid/tx/{0}",
|
||||
NBXplorerNetwork = nbxplorerNetwork,
|
||||
UriScheme = "liquidnetwork",
|
||||
CryptoImagePath = "imlegacy/lcad.png",
|
||||
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
|
||||
CoinType = NetworkType == NetworkType.Mainnet ? new KeyPath("1776'") : new KeyPath("1'"),
|
||||
SupportRBF = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
using NBXplorer.Models;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public class ElementsBTCPayNetwork : BTCPayNetwork
|
||||
{
|
||||
public string NetworkCryptoCode { get; set; }
|
||||
public uint256 AssetId { get; set; }
|
||||
public override bool ReadonlyWallet { get; set; } = true;
|
||||
|
||||
public override IEnumerable<(MatchedOutput matchedOutput, OutPoint outPoint)> GetValidOutputs(
|
||||
NewTransactionEvent evtOutputs)
|
||||
{
|
||||
return evtOutputs.Outputs.Where(output =>
|
||||
output.Value is AssetMoney assetMoney && assetMoney.AssetId == AssetId).Select(output =>
|
||||
{
|
||||
var outpoint = new OutPoint(evtOutputs.TransactionData.TransactionHash, output.Index);
|
||||
return (output, outpoint);
|
||||
});
|
||||
}
|
||||
|
||||
public override string GenerateBIP21(string cryptoInfoAddress, Money cryptoInfoDue)
|
||||
{
|
||||
//precision 0: 10 = 0.00000010
|
||||
//precision 2: 10 = 0.00001000
|
||||
//precision 8: 10 = 10
|
||||
var money = new Money(cryptoInfoDue.ToDecimal(MoneyUnit.BTC) / decimal.Parse("1".PadRight(1 + 8 - Divisibility, '0')), MoneyUnit.BTC);
|
||||
return $"{base.GenerateBIP21(cryptoInfoAddress, money)}&assetid={AssetId}";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
using NBitcoin;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public partial class BTCPayNetworkProvider
|
||||
{
|
||||
public void InitMonero()
|
||||
{
|
||||
Add(new MoneroLikeSpecificBtcPayNetwork()
|
||||
{
|
||||
CryptoCode = "XMR",
|
||||
DisplayName = "Monero",
|
||||
Divisibility = 12,
|
||||
BlockExplorerLink =
|
||||
NetworkType == NetworkType.Mainnet
|
||||
? "https://www.exploremonero.com/transaction/{0}"
|
||||
: "https://testnet.xmrchain.net/tx/{0}",
|
||||
DefaultRateRules = new[]
|
||||
{
|
||||
"XMR_X = XMR_BTC * BTC_X",
|
||||
"XMR_BTC = kraken(XMR_BTC)"
|
||||
},
|
||||
CryptoImagePath = "/imlegacy/monero.svg"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public class MoneroLikeSpecificBtcPayNetwork : BTCPayNetworkBase
|
||||
{
|
||||
public int MaxTrackedConfirmation = 10;
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC
|
||||
{
|
||||
public class JsonRpcClient
|
||||
{
|
||||
private readonly Uri _address;
|
||||
private readonly string _username;
|
||||
private readonly string _password;
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public JsonRpcClient(Uri address, string username, string password, HttpClient client = null)
|
||||
{
|
||||
_address = address;
|
||||
_username = username;
|
||||
_password = password;
|
||||
_httpClient = client ?? new HttpClient();
|
||||
}
|
||||
|
||||
|
||||
public async Task<TResponse> SendCommandAsync<TRequest, TResponse>(string method, TRequest data,
|
||||
CancellationToken cts = default(CancellationToken))
|
||||
{
|
||||
var jsonSerializer = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
};
|
||||
var httpRequest = new HttpRequestMessage()
|
||||
{
|
||||
Method = HttpMethod.Post,
|
||||
RequestUri = new Uri(_address, "json_rpc"),
|
||||
Content = new StringContent(
|
||||
JsonConvert.SerializeObject(new JsonRpcCommand<TRequest>(method, data), jsonSerializer),
|
||||
Encoding.UTF8, "application/json")
|
||||
};
|
||||
httpRequest.Headers.Accept.Clear();
|
||||
httpRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic",
|
||||
Convert.ToBase64String(Encoding.Default.GetBytes($"{_username}:{_password}")));
|
||||
|
||||
var rawResult = await _httpClient.SendAsync(httpRequest, cts);
|
||||
|
||||
var rawJson = await rawResult.Content.ReadAsStringAsync();
|
||||
rawResult.EnsureSuccessStatusCode();
|
||||
JsonRpcResult<TResponse> response;
|
||||
try
|
||||
{
|
||||
response = JsonConvert.DeserializeObject<JsonRpcResult<TResponse>>(rawJson, jsonSerializer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
Console.WriteLine(rawJson);
|
||||
throw;
|
||||
}
|
||||
|
||||
if (response.Error != null)
|
||||
{
|
||||
throw new JsonRpcApiException()
|
||||
{
|
||||
Error = response.Error
|
||||
};
|
||||
}
|
||||
|
||||
return response.Result;
|
||||
}
|
||||
|
||||
public class NoRequestModel
|
||||
{
|
||||
public static NoRequestModel Instance = new NoRequestModel();
|
||||
}
|
||||
|
||||
internal class JsonRpcApiException : Exception
|
||||
{
|
||||
public JsonRpcResultError Error { get; set; }
|
||||
|
||||
public override string Message => Error?.Message;
|
||||
}
|
||||
|
||||
public class JsonRpcResultError
|
||||
{
|
||||
[JsonProperty("code")] public int Code { get; set; }
|
||||
[JsonProperty("message")] public string Message { get; set; }
|
||||
[JsonProperty("data")] dynamic Data { get; set; }
|
||||
}
|
||||
internal class JsonRpcResult<T>
|
||||
{
|
||||
|
||||
|
||||
[JsonProperty("result")] public T Result { get; set; }
|
||||
[JsonProperty("error")] public JsonRpcResultError Error { get; set; }
|
||||
[JsonProperty("id")] public string Id { get; set; }
|
||||
}
|
||||
|
||||
internal class JsonRpcCommand<T>
|
||||
{
|
||||
[JsonProperty("jsonRpc")] public string JsonRpc { get; set; } = "2.0";
|
||||
[JsonProperty("id")] public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
[JsonProperty("method")] public string Method { get; set; }
|
||||
|
||||
[JsonProperty("params")] public T Parameters { get; set; }
|
||||
|
||||
public JsonRpcCommand()
|
||||
{
|
||||
}
|
||||
|
||||
public JsonRpcCommand(string method, T parameters)
|
||||
{
|
||||
Method = method;
|
||||
Parameters = parameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class CreateAccountRequest
|
||||
{
|
||||
[JsonProperty("label")] public string Label { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class CreateAccountResponse
|
||||
{
|
||||
[JsonProperty("account_index")] public long AccountIndex { get; set; }
|
||||
[JsonProperty("address")] public string Address { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class CreateAddressRequest
|
||||
{
|
||||
[JsonProperty("account_index")] public long AccountIndex { get; set; }
|
||||
[JsonProperty("label")] public string Label { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class CreateAddressResponse
|
||||
{
|
||||
[JsonProperty("address")] public string Address { get; set; }
|
||||
[JsonProperty("address_index")] public long AddressIndex { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class GetAccountsRequest
|
||||
{
|
||||
[JsonProperty("tag")] public string Tag { get; set; }
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class GetAccountsResponse
|
||||
{
|
||||
[JsonProperty("subaddress_accounts")] public List<SubaddressAccount> SubaddressAccounts { get; set; }
|
||||
[JsonProperty("total_balance")] public decimal TotalBalance { get; set; }
|
||||
|
||||
[JsonProperty("total_unlocked_balance")]
|
||||
public decimal TotalUnlockedBalance { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public class GetFeeEstimateRequest
|
||||
{
|
||||
[JsonProperty("grace_blocks")] public int? GraceBlocks { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public class GetFeeEstimateResponse
|
||||
{
|
||||
[JsonProperty("fee")] public long Fee { get; set; }
|
||||
[JsonProperty("status")] public string Status { get; set; }
|
||||
[JsonProperty("untrusted")] public bool Untrusted { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class GetHeightResponse
|
||||
{
|
||||
[JsonProperty("height")] public long Height { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public class GetTransferByTransactionIdRequest
|
||||
{
|
||||
[JsonProperty("txid")] public string TransactionId { get; set; }
|
||||
|
||||
[JsonProperty("account_index")] public long AccountIndex { get; set; }
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class GetTransferByTransactionIdResponse
|
||||
{
|
||||
[JsonProperty("transfer")] public TransferItem Transfer { get; set; }
|
||||
[JsonProperty("transfers")] public IEnumerable<TransferItem> Transfers { get; set; }
|
||||
|
||||
public partial class TransferItem
|
||||
{
|
||||
[JsonProperty("address")] public string Address { get; set; }
|
||||
[JsonProperty("amount")] public long Amount { get; set; }
|
||||
[JsonProperty("confirmations")] public long Confirmations { get; set; }
|
||||
[JsonProperty("double_spend_seen")] public bool DoubleSpendSeen { get; set; }
|
||||
[JsonProperty("height")] public long Height { get; set; }
|
||||
[JsonProperty("note")] public string Note { get; set; }
|
||||
[JsonProperty("payment_id")] public string PaymentId { get; set; }
|
||||
[JsonProperty("subaddr_index")] public SubaddrIndex SubaddrIndex { get; set; }
|
||||
|
||||
[JsonProperty("suggested_confirmations_threshold")]
|
||||
public long SuggestedConfirmationsThreshold { get; set; }
|
||||
|
||||
[JsonProperty("timestamp")] public long Timestamp { get; set; }
|
||||
[JsonProperty("txid")] public string Txid { get; set; }
|
||||
[JsonProperty("type")] public string Type { get; set; }
|
||||
[JsonProperty("unlock_time")] public long UnlockTime { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class GetTransfersRequest
|
||||
{
|
||||
[JsonProperty("in")] public bool In { get; set; }
|
||||
[JsonProperty("out")] public bool Out { get; set; }
|
||||
[JsonProperty("pending")] public bool Pending { get; set; }
|
||||
[JsonProperty("failed")] public bool Failed { get; set; }
|
||||
[JsonProperty("pool")] public bool Pool { get; set; }
|
||||
[JsonProperty("filter_by_height ")] public bool FilterByHeight { get; set; }
|
||||
[JsonProperty("min_height")] public long MinHeight { get; set; }
|
||||
[JsonProperty("max_height")] public long MaxHeight { get; set; }
|
||||
[JsonProperty("account_index")] public long AccountIndex { get; set; }
|
||||
[JsonProperty("subaddr_indices")] public List<long> SubaddrIndices { get; set; }
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class GetTransfersResponse
|
||||
{
|
||||
[JsonProperty("in")] public List<GetTransfersResponseItem> In { get; set; }
|
||||
[JsonProperty("out")] public List<GetTransfersResponseItem> Out { get; set; }
|
||||
[JsonProperty("pending")] public List<GetTransfersResponseItem> Pending { get; set; }
|
||||
[JsonProperty("failed")] public List<GetTransfersResponseItem> Failed { get; set; }
|
||||
[JsonProperty("pool")] public List<GetTransfersResponseItem> Pool { get; set; }
|
||||
|
||||
public partial class GetTransfersResponseItem
|
||||
|
||||
{
|
||||
[JsonProperty("address")] public string Address { get; set; }
|
||||
[JsonProperty("amount")] public long Amount { get; set; }
|
||||
[JsonProperty("confirmations")] public long Confirmations { get; set; }
|
||||
[JsonProperty("double_spend_seen")] public bool DoubleSpendSeen { get; set; }
|
||||
[JsonProperty("height")] public long Height { get; set; }
|
||||
[JsonProperty("note")] public string Note { get; set; }
|
||||
[JsonProperty("payment_id")] public string PaymentId { get; set; }
|
||||
[JsonProperty("subaddr_index")] public SubaddrIndex SubaddrIndex { get; set; }
|
||||
|
||||
[JsonProperty("suggested_confirmations_threshold")]
|
||||
public long SuggestedConfirmationsThreshold { get; set; }
|
||||
|
||||
[JsonProperty("timestamp")] public long Timestamp { get; set; }
|
||||
[JsonProperty("txid")] public string Txid { get; set; }
|
||||
[JsonProperty("type")] public string Type { get; set; }
|
||||
[JsonProperty("unlock_time")] public long UnlockTime { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class Info
|
||||
{
|
||||
[JsonProperty("address")] public string Address { get; set; }
|
||||
[JsonProperty("avg_download")] public long AvgDownload { get; set; }
|
||||
[JsonProperty("avg_upload")] public long AvgUpload { get; set; }
|
||||
[JsonProperty("connection_id")] public string ConnectionId { get; set; }
|
||||
[JsonProperty("current_download")] public long CurrentDownload { get; set; }
|
||||
[JsonProperty("current_upload")] public long CurrentUpload { get; set; }
|
||||
[JsonProperty("height")] public long Height { get; set; }
|
||||
[JsonProperty("host")] public string Host { get; set; }
|
||||
[JsonProperty("incoming")] public bool Incoming { get; set; }
|
||||
[JsonProperty("ip")] public string Ip { get; set; }
|
||||
[JsonProperty("live_time")] public long LiveTime { get; set; }
|
||||
[JsonProperty("local_ip")] public bool LocalIp { get; set; }
|
||||
[JsonProperty("localhost")] public bool Localhost { get; set; }
|
||||
[JsonProperty("peer_id")] public string PeerId { get; set; }
|
||||
|
||||
[JsonProperty("port")]
|
||||
[JsonConverter(typeof(ParseStringConverter))]
|
||||
public long Port { get; set; }
|
||||
|
||||
[JsonProperty("recv_count")] public long RecvCount { get; set; }
|
||||
[JsonProperty("recv_idle_time")] public long RecvIdleTime { get; set; }
|
||||
[JsonProperty("send_count")] public long SendCount { get; set; }
|
||||
[JsonProperty("send_idle_time")] public long SendIdleTime { get; set; }
|
||||
[JsonProperty("state")] public string State { get; set; }
|
||||
[JsonProperty("support_flags")] public long SupportFlags { get; set; }
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class MakeUriRequest
|
||||
{
|
||||
[JsonProperty("address")] public string Address { get; set; }
|
||||
[JsonProperty("amount")] public long Amount { get; set; }
|
||||
[JsonProperty("payment_id")] public string PaymentId { get; set; }
|
||||
[JsonProperty("tx_description")] public string TxDescription { get; set; }
|
||||
[JsonProperty("recipient_name")] public string RecipientName { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class MakeUriResponse
|
||||
{
|
||||
[JsonProperty("uri")] public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
internal class ParseStringConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?);
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null) return null;
|
||||
var value = serializer.Deserialize<string>(reader);
|
||||
long l;
|
||||
if (Int64.TryParse(value, out l))
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
throw new Exception("Cannot unmarshal type long");
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
|
||||
{
|
||||
if (untypedValue == null)
|
||||
{
|
||||
serializer.Serialize(writer, null);
|
||||
return;
|
||||
}
|
||||
|
||||
var value = (long)untypedValue;
|
||||
serializer.Serialize(writer, value.ToString(CultureInfo.InvariantCulture));
|
||||
return;
|
||||
}
|
||||
|
||||
public static readonly ParseStringConverter Singleton = new ParseStringConverter();
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class Peer
|
||||
{
|
||||
[JsonProperty("info")] public Info Info { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class SubaddrIndex
|
||||
{
|
||||
[JsonProperty("major")] public long Major { get; set; }
|
||||
[JsonProperty("minor")] public long Minor { get; set; }
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class SubaddressAccount
|
||||
{
|
||||
[JsonProperty("account_index")] public long AccountIndex { get; set; }
|
||||
[JsonProperty("balance")] public decimal Balance { get; set; }
|
||||
[JsonProperty("base_address")] public string BaseAddress { get; set; }
|
||||
[JsonProperty("label")] public string Label { get; set; }
|
||||
[JsonProperty("tag")] public string Tag { get; set; }
|
||||
[JsonProperty("unlocked_balance")] public decimal UnlockedBalance { get; set; }
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
|
||||
{
|
||||
public partial class SyncInfoResponse
|
||||
{
|
||||
[JsonProperty("height")] public long Height { get; set; }
|
||||
[JsonProperty("peers")] public List<Peer> Peers { get; set; }
|
||||
[JsonProperty("status")] public string Status { get; set; }
|
||||
[JsonProperty("target_height")] public long? TargetHeight { get; set; }
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace BTCPayServer.Services.Altcoins.Monero.Utils
|
||||
{
|
||||
public class MoneroMoney
|
||||
{
|
||||
public static decimal Convert(long piconero)
|
||||
{
|
||||
var amt = piconero.ToString(CultureInfo.InvariantCulture).PadLeft(12, '0');
|
||||
amt = amt.Length == 12 ? $"0.{amt}" : amt.Insert(amt.Length - 12, ".");
|
||||
|
||||
return decimal.Parse(amt, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static long Convert(decimal monero)
|
||||
{
|
||||
return System.Convert.ToInt64(monero * 1000000000000);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using NBitcoin;
|
||||
using NBXplorer;
|
||||
using NBXplorer.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public enum DerivationType
|
||||
{
|
||||
Legacy,
|
||||
SegwitP2SH,
|
||||
Segwit
|
||||
}
|
||||
public class BTCPayDefaultSettings
|
||||
{
|
||||
static BTCPayDefaultSettings()
|
||||
{
|
||||
_Settings = new Dictionary<NetworkType, BTCPayDefaultSettings>();
|
||||
foreach (var chainType in new[] { NetworkType.Mainnet, NetworkType.Testnet, NetworkType.Regtest })
|
||||
{
|
||||
var settings = new BTCPayDefaultSettings();
|
||||
_Settings.Add(chainType, settings);
|
||||
settings.DefaultDataDirectory = StandardConfiguration.DefaultDataDirectory.GetDirectory("BTCPayServer", NBXplorerDefaultSettings.GetFolderName(chainType));
|
||||
settings.DefaultConfigurationFile = Path.Combine(settings.DefaultDataDirectory, "settings.config");
|
||||
settings.DefaultPort = (chainType == NetworkType.Mainnet ? 23000 :
|
||||
chainType == NetworkType.Regtest ? 23002 :
|
||||
chainType == NetworkType.Testnet ? 23001 : throw new NotSupportedException(chainType.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary<NetworkType, BTCPayDefaultSettings> _Settings;
|
||||
|
||||
public static BTCPayDefaultSettings GetDefaultSettings(NetworkType chainType)
|
||||
{
|
||||
return _Settings[chainType];
|
||||
}
|
||||
|
||||
public string DefaultDataDirectory { get; set; }
|
||||
public string DefaultConfigurationFile { get; set; }
|
||||
public int DefaultPort { get; set; }
|
||||
}
|
||||
|
||||
public class BTCPayNetwork:BTCPayNetworkBase
|
||||
{
|
||||
public Network NBitcoinNetwork { get { return NBXplorerNetwork?.NBitcoinNetwork; } }
|
||||
public NBXplorer.NBXplorerNetwork NBXplorerNetwork { get; set; }
|
||||
public bool SupportRBF { get; internal set; }
|
||||
public string LightningImagePath { get; set; }
|
||||
public BTCPayDefaultSettings DefaultSettings { get; set; }
|
||||
public KeyPath CoinType { get; internal set; }
|
||||
|
||||
public Dictionary<uint, DerivationType> ElectrumMapping = new Dictionary<uint, DerivationType>();
|
||||
|
||||
public virtual bool WalletSupported { get; set; } = true;
|
||||
public virtual bool ReadonlyWallet{ get; set; } = false;
|
||||
|
||||
public int MaxTrackedConfirmation { get; internal set; } = 6;
|
||||
public string UriScheme { get; internal set; }
|
||||
public bool SupportPayJoin { get; set; } = false;
|
||||
|
||||
public KeyPath GetRootKeyPath(DerivationType type)
|
||||
{
|
||||
KeyPath baseKey;
|
||||
if (!NBitcoinNetwork.Consensus.SupportSegwit)
|
||||
{
|
||||
baseKey = new KeyPath("44'");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DerivationType.Legacy:
|
||||
baseKey = new KeyPath("44'");
|
||||
break;
|
||||
case DerivationType.SegwitP2SH:
|
||||
baseKey = new KeyPath("49'");
|
||||
break;
|
||||
case DerivationType.Segwit:
|
||||
baseKey = new KeyPath("84'");
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
}
|
||||
}
|
||||
return baseKey
|
||||
.Derive(CoinType);
|
||||
}
|
||||
|
||||
public KeyPath GetRootKeyPath()
|
||||
{
|
||||
return new KeyPath(NBitcoinNetwork.Consensus.SupportSegwit ? "49'" : "44'")
|
||||
.Derive(CoinType);
|
||||
}
|
||||
|
||||
public override T ToObject<T>(string json)
|
||||
{
|
||||
return NBXplorerNetwork.Serializer.ToObject<T>(json);
|
||||
}
|
||||
|
||||
public override string ToString<T>(T obj)
|
||||
{
|
||||
return NBXplorerNetwork.Serializer.ToString(obj);
|
||||
}
|
||||
public virtual IEnumerable<(MatchedOutput matchedOutput, OutPoint outPoint)> GetValidOutputs(NewTransactionEvent evtOutputs)
|
||||
{
|
||||
return evtOutputs.Outputs.Select(output =>
|
||||
{
|
||||
var outpoint = new OutPoint(evtOutputs.TransactionData.TransactionHash, output.Index);
|
||||
return (output, outpoint);
|
||||
});
|
||||
}
|
||||
|
||||
public virtual string GenerateBIP21(string cryptoInfoAddress, Money cryptoInfoDue)
|
||||
{
|
||||
return $"{UriScheme}:{cryptoInfoAddress}?amount={cryptoInfoDue.ToString(false, true)}";
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class BTCPayNetworkBase
|
||||
{
|
||||
public bool ShowSyncSummary { get; set; } = true;
|
||||
public string CryptoCode { get; internal set; }
|
||||
public string BlockExplorerLink { get; internal set; }
|
||||
public string DisplayName { get; set; }
|
||||
public int Divisibility { get; set; } = 8;
|
||||
[Obsolete("Should not be needed")]
|
||||
public bool IsBTC
|
||||
{
|
||||
get
|
||||
{
|
||||
return CryptoCode == "BTC";
|
||||
}
|
||||
}
|
||||
|
||||
public string CryptoImagePath { get; set; }
|
||||
public string[] DefaultRateRules { get; internal set; } = Array.Empty<string>();
|
||||
public override string ToString()
|
||||
{
|
||||
return CryptoCode;
|
||||
}
|
||||
|
||||
public virtual T ToObject<T>(string json)
|
||||
{
|
||||
return NBitcoin.JsonConverters.Serializer.ToObject<T>(json, null);
|
||||
}
|
||||
|
||||
public virtual string ToString<T>(T obj)
|
||||
{
|
||||
return NBitcoin.JsonConverters.Serializer.ToString(obj, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../Build/Version.csproj" Condition="Exists('../Build/Version.csproj')" />
|
||||
<Import Project="../Build/Common.csproj" />
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="NBXplorer.Client" Version="3.0.9" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public static class UtilitiesExtensions
|
||||
{
|
||||
public static void AddRange<T>(this HashSet<T> hashSet, IEnumerable<T> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
hashSet.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Console.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// For non-Windows platform consoles which understand the ANSI escape code sequences to represent color
|
||||
/// </summary>
|
||||
internal class AnsiLogConsole : IConsole
|
||||
{
|
||||
private readonly StringBuilder _outputBuilder;
|
||||
private readonly IAnsiSystemConsole _systemConsole;
|
||||
|
||||
public AnsiLogConsole(IAnsiSystemConsole systemConsole)
|
||||
{
|
||||
_outputBuilder = new StringBuilder();
|
||||
_systemConsole = systemConsole;
|
||||
}
|
||||
|
||||
public void Write(string message, ConsoleColor? background, ConsoleColor? foreground)
|
||||
{
|
||||
// Order: backgroundcolor, foregroundcolor, Message, reset foregroundcolor, reset backgroundcolor
|
||||
if (background.HasValue)
|
||||
{
|
||||
_outputBuilder.Append(GetBackgroundColorEscapeCode(background.Value));
|
||||
}
|
||||
|
||||
if (foreground.HasValue)
|
||||
{
|
||||
_outputBuilder.Append(GetForegroundColorEscapeCode(foreground.Value));
|
||||
}
|
||||
|
||||
_outputBuilder.Append(message);
|
||||
|
||||
if (foreground.HasValue)
|
||||
{
|
||||
_outputBuilder.Append("\x1B[39m\x1B[22m"); // reset to default foreground color
|
||||
}
|
||||
|
||||
if (background.HasValue)
|
||||
{
|
||||
_outputBuilder.Append("\x1B[49m"); // reset to the background color
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteLine(string message, ConsoleColor? background, ConsoleColor? foreground)
|
||||
{
|
||||
Write(message, background, foreground);
|
||||
_outputBuilder.AppendLine();
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
_systemConsole.Write(_outputBuilder.ToString());
|
||||
_outputBuilder.Clear();
|
||||
}
|
||||
|
||||
private static string GetForegroundColorEscapeCode(ConsoleColor color)
|
||||
{
|
||||
switch (color)
|
||||
{
|
||||
case ConsoleColor.Black:
|
||||
return "\x1B[30m";
|
||||
case ConsoleColor.DarkRed:
|
||||
return "\x1B[31m";
|
||||
case ConsoleColor.DarkGreen:
|
||||
return "\x1B[32m";
|
||||
case ConsoleColor.DarkYellow:
|
||||
return "\x1B[33m";
|
||||
case ConsoleColor.DarkBlue:
|
||||
return "\x1B[34m";
|
||||
case ConsoleColor.DarkMagenta:
|
||||
return "\x1B[35m";
|
||||
case ConsoleColor.DarkCyan:
|
||||
return "\x1B[36m";
|
||||
case ConsoleColor.Gray:
|
||||
return "\x1B[37m";
|
||||
case ConsoleColor.Red:
|
||||
return "\x1B[1m\x1B[31m";
|
||||
case ConsoleColor.Green:
|
||||
return "\x1B[1m\x1B[32m";
|
||||
case ConsoleColor.Yellow:
|
||||
return "\x1B[1m\x1B[33m";
|
||||
case ConsoleColor.Blue:
|
||||
return "\x1B[1m\x1B[34m";
|
||||
case ConsoleColor.Magenta:
|
||||
return "\x1B[1m\x1B[35m";
|
||||
case ConsoleColor.Cyan:
|
||||
return "\x1B[1m\x1B[36m";
|
||||
case ConsoleColor.White:
|
||||
return "\x1B[1m\x1B[37m";
|
||||
default:
|
||||
return "\x1B[39m\x1B[22m"; // default foreground color
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetBackgroundColorEscapeCode(ConsoleColor color)
|
||||
{
|
||||
switch (color)
|
||||
{
|
||||
case ConsoleColor.Black:
|
||||
return "\x1B[40m";
|
||||
case ConsoleColor.Red:
|
||||
return "\x1B[41m";
|
||||
case ConsoleColor.Green:
|
||||
return "\x1B[42m";
|
||||
case ConsoleColor.Yellow:
|
||||
return "\x1B[43m";
|
||||
case ConsoleColor.Blue:
|
||||
return "\x1B[44m";
|
||||
case ConsoleColor.Magenta:
|
||||
return "\x1B[45m";
|
||||
case ConsoleColor.Cyan:
|
||||
return "\x1B[46m";
|
||||
case ConsoleColor.White:
|
||||
return "\x1B[47m";
|
||||
default:
|
||||
return "\x1B[49m"; // Use default background color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class AnsiSystemConsole : IAnsiSystemConsole
|
||||
{
|
||||
private readonly TextWriter _textWriter;
|
||||
|
||||
/// <inheritdoc />
|
||||
public AnsiSystemConsole(bool stdErr = false)
|
||||
{
|
||||
_textWriter = stdErr ? System.Console.Error : System.Console.Out;
|
||||
}
|
||||
|
||||
public void Write(string message)
|
||||
{
|
||||
_textWriter.Write(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Console
|
||||
{
|
||||
internal interface IAnsiSystemConsole
|
||||
{
|
||||
void Write(string message);
|
||||
}
|
||||
public interface IConsole
|
||||
{
|
||||
void Write(string message, ConsoleColor? background, ConsoleColor? foreground);
|
||||
void WriteLine(string message, ConsoleColor? background, ConsoleColor? foreground);
|
||||
void Flush();
|
||||
}
|
||||
internal class WindowsLogConsole : IConsole
|
||||
{
|
||||
private readonly TextWriter _textWriter;
|
||||
|
||||
/// <inheritdoc />
|
||||
public WindowsLogConsole(bool stdErr = false)
|
||||
{
|
||||
_textWriter = stdErr ? System.Console.Error : System.Console.Out;
|
||||
}
|
||||
|
||||
private bool SetColor(ConsoleColor? background, ConsoleColor? foreground)
|
||||
{
|
||||
if (background.HasValue)
|
||||
{
|
||||
System.Console.BackgroundColor = background.Value;
|
||||
}
|
||||
|
||||
if (foreground.HasValue)
|
||||
{
|
||||
System.Console.ForegroundColor = foreground.Value;
|
||||
}
|
||||
|
||||
return background.HasValue || foreground.HasValue;
|
||||
}
|
||||
|
||||
private void ResetColor()
|
||||
{
|
||||
System.Console.ResetColor();
|
||||
}
|
||||
|
||||
public void Write(string message, ConsoleColor? background, ConsoleColor? foreground)
|
||||
{
|
||||
var colorChanged = SetColor(background, foreground);
|
||||
_textWriter.Write(message);
|
||||
if (colorChanged)
|
||||
{
|
||||
ResetColor();
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteLine(string message, ConsoleColor? background, ConsoleColor? foreground)
|
||||
{
|
||||
var colorChanged = SetColor(background, foreground);
|
||||
_textWriter.WriteLine(message);
|
||||
if (colorChanged)
|
||||
{
|
||||
ResetColor();
|
||||
}
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
// No action required as for every write, data is sent directly to the console
|
||||
// output stream
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Microsoft.Extensions.Logging.Abstractions.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty scope without any logic
|
||||
/// </summary>
|
||||
internal class NullScope : IDisposable
|
||||
{
|
||||
public static NullScope Instance { get; } = new NullScope();
|
||||
|
||||
private NullScope()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../Build/Version.csproj" Condition="Exists('../Build/Version.csproj')" />
|
||||
<Import Project="../Build/Common.csproj" />
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.1" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.1.2" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,43 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class APIKeyData
|
||||
{
|
||||
[MaxLength(50)]
|
||||
public string Id
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[MaxLength(50)] public string StoreId { get; set; }
|
||||
|
||||
[MaxLength(50)] public string UserId { get; set; }
|
||||
|
||||
public APIKeyType Type { get; set; } = APIKeyType.Legacy;
|
||||
|
||||
public byte[] Blob { get; set; }
|
||||
public StoreData StoreData { get; set; }
|
||||
public ApplicationUser User { get; set; }
|
||||
public string Label { get; set; }
|
||||
}
|
||||
|
||||
public class APIKeyBlob
|
||||
{
|
||||
public string[] Permissions { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public enum APIKeyType
|
||||
{
|
||||
Legacy,
|
||||
Permanent
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class AddressInvoiceData
|
||||
{
|
||||
/// <summary>
|
||||
/// Some crypto currencies share same address prefix
|
||||
/// For not having exceptions thrown by two address on different network, we suffix by "#CRYPTOCODE"
|
||||
/// </summary>
|
||||
[Obsolete("Use GetHash instead")]
|
||||
public string Address
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public InvoiceData InvoiceData
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string InvoiceDataId
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DateTimeOffset? CreatedTime
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,291 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
|
||||
{
|
||||
public ApplicationDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
|
||||
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
|
||||
builder.UseSqlite("Data Source=temp.db");
|
||||
|
||||
return new ApplicationDbContext(builder.Options, true);
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
|
||||
{
|
||||
private readonly bool _designTime;
|
||||
|
||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, bool designTime = false)
|
||||
: base(options)
|
||||
{
|
||||
_designTime = designTime;
|
||||
}
|
||||
|
||||
public DbSet<InvoiceData> Invoices
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<PlannedTransaction> PlannedTransactions { get; set; }
|
||||
public DbSet<PayjoinLock> PayjoinLocks { get; set; }
|
||||
|
||||
public DbSet<AppData> Apps
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<InvoiceEventData> InvoiceEvents
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<OffchainTransactionData> OffchainTransactions { get; set; }
|
||||
|
||||
public DbSet<HistoricalAddressInvoiceData> HistoricalAddressInvoices
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<PendingInvoiceData> PendingInvoices
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public DbSet<RefundAddressesData> RefundAddresses
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<PaymentData> Payments
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<PaymentRequestData> PaymentRequests
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<WalletData> Wallets { get; set; }
|
||||
public DbSet<WalletTransactionData> WalletTransactions { get; set; }
|
||||
|
||||
public DbSet<StoreData> Stores
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<UserStore> UserStore
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<AddressInvoiceData> AddressInvoices
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<SettingData> Settings
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
|
||||
public DbSet<PairingCodeData> PairingCodes
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<PairedSINData> PairedSINData
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<APIKeyData> ApiKeys
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public DbSet<StoredFile> Files
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
|
||||
public DbSet<U2FDevice> U2FDevices { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
var isConfigured = optionsBuilder.Options.Extensions.OfType<RelationalOptionsExtension>().Any();
|
||||
if (!isConfigured)
|
||||
optionsBuilder.UseSqlite("Data Source=temp.db");
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
builder.Entity<InvoiceData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
.WithMany(a => a.Invoices).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<InvoiceData>().HasIndex(o => o.StoreDataId);
|
||||
|
||||
|
||||
builder.Entity<PaymentData>()
|
||||
.HasOne(o => o.InvoiceData)
|
||||
.WithMany(i => i.Payments).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<PaymentData>()
|
||||
.HasIndex(o => o.InvoiceDataId);
|
||||
|
||||
|
||||
builder.Entity<RefundAddressesData>()
|
||||
.HasOne(o => o.InvoiceData)
|
||||
.WithMany(i => i.RefundAddresses).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<RefundAddressesData>()
|
||||
.HasIndex(o => o.InvoiceDataId);
|
||||
|
||||
builder.Entity<UserStore>()
|
||||
.HasOne(o => o.StoreData)
|
||||
.WithMany(i => i.UserStores).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<UserStore>()
|
||||
.HasKey(t => new
|
||||
{
|
||||
t.ApplicationUserId,
|
||||
t.StoreDataId
|
||||
});
|
||||
|
||||
builder.Entity<APIKeyData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
.WithMany(i => i.APIKeys)
|
||||
.HasForeignKey(i => i.StoreId).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.Entity<APIKeyData>()
|
||||
.HasOne(o => o.User)
|
||||
.WithMany(i => i.APIKeys)
|
||||
.HasForeignKey(i => i.UserId).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.Entity<APIKeyData>()
|
||||
.HasIndex(o => o.StoreId);
|
||||
|
||||
builder.Entity<AppData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
.WithMany(i => i.Apps).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<AppData>()
|
||||
.HasOne(a => a.StoreData);
|
||||
|
||||
builder.Entity<UserStore>()
|
||||
.HasOne(pt => pt.ApplicationUser)
|
||||
.WithMany(p => p.UserStores)
|
||||
.HasForeignKey(pt => pt.ApplicationUserId);
|
||||
|
||||
builder.Entity<UserStore>()
|
||||
.HasOne(pt => pt.StoreData)
|
||||
.WithMany(t => t.UserStores)
|
||||
.HasForeignKey(pt => pt.StoreDataId);
|
||||
|
||||
|
||||
builder.Entity<AddressInvoiceData>()
|
||||
.HasOne(o => o.InvoiceData)
|
||||
.WithMany(i => i.AddressInvoices).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<AddressInvoiceData>()
|
||||
#pragma warning disable CS0618
|
||||
.HasKey(o => o.Address);
|
||||
#pragma warning restore CS0618
|
||||
|
||||
builder.Entity<PairingCodeData>()
|
||||
.HasKey(o => o.Id);
|
||||
|
||||
builder.Entity<PendingInvoiceData>()
|
||||
.HasOne(o => o.InvoiceData)
|
||||
.WithMany(o => o.PendingInvoices)
|
||||
.HasForeignKey(o => o.Id).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
|
||||
builder.Entity<PairedSINData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
.WithMany(i => i.PairedSINs).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<PairedSINData>(b =>
|
||||
{
|
||||
b.HasIndex(o => o.SIN);
|
||||
b.HasIndex(o => o.StoreDataId);
|
||||
});
|
||||
|
||||
builder.Entity<HistoricalAddressInvoiceData>()
|
||||
.HasOne(o => o.InvoiceData)
|
||||
.WithMany(i => i.HistoricalAddressInvoices).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<HistoricalAddressInvoiceData>()
|
||||
.HasKey(o => new
|
||||
{
|
||||
o.InvoiceDataId,
|
||||
#pragma warning disable CS0618
|
||||
o.Address
|
||||
#pragma warning restore CS0618
|
||||
});
|
||||
|
||||
|
||||
builder.Entity<InvoiceEventData>()
|
||||
.HasOne(o => o.InvoiceData)
|
||||
.WithMany(i => i.Events).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<InvoiceEventData>()
|
||||
.HasKey(o => new
|
||||
{
|
||||
o.InvoiceDataId,
|
||||
#pragma warning disable CS0618
|
||||
o.UniqueId
|
||||
#pragma warning restore CS0618
|
||||
});
|
||||
|
||||
|
||||
builder.Entity<PaymentRequestData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
.WithMany(i => i.PaymentRequests)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<PaymentRequestData>()
|
||||
.Property(e => e.Created)
|
||||
.HasDefaultValue(new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero));
|
||||
|
||||
builder.Entity<PaymentRequestData>()
|
||||
.HasIndex(o => o.Status);
|
||||
|
||||
builder.Entity<WalletTransactionData>()
|
||||
.HasKey(o => new
|
||||
{
|
||||
o.WalletDataId,
|
||||
#pragma warning disable CS0618
|
||||
o.TransactionId
|
||||
#pragma warning restore CS0618
|
||||
});
|
||||
builder.Entity<WalletTransactionData>()
|
||||
.HasOne(o => o.WalletData)
|
||||
.WithMany(w => w.WalletTransactions).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
if (Database.IsSqlite() && !_designTime)
|
||||
{
|
||||
// SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations
|
||||
// here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations
|
||||
// To work around this, when the Sqlite database provider is used, all model properties of type DateTimeOffset
|
||||
// use the DateTimeOffsetToBinaryConverter
|
||||
// Based on: https://github.com/aspnet/EntityFrameworkCore/issues/10784#issuecomment-415769754
|
||||
// This only supports millisecond precision, but should be sufficient for most use cases.
|
||||
foreach (var entityType in builder.Model.GetEntityTypes())
|
||||
{
|
||||
var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(DateTimeOffset));
|
||||
foreach (var property in properties)
|
||||
{
|
||||
builder
|
||||
.Entity(entityType.Name)
|
||||
.Property(property.Name)
|
||||
.HasConversion(new Microsoft.EntityFrameworkCore.Storage.ValueConversion.DateTimeOffsetToBinaryConverter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations;
|
||||
using JetBrains.Annotations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public enum DatabaseType
|
||||
{
|
||||
Sqlite,
|
||||
Postgres,
|
||||
MySQL,
|
||||
}
|
||||
public class ApplicationDbContextFactory
|
||||
{
|
||||
string _ConnectionString;
|
||||
DatabaseType _Type;
|
||||
public ApplicationDbContextFactory(DatabaseType type, string connectionString)
|
||||
{
|
||||
_ConnectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
|
||||
_Type = type;
|
||||
}
|
||||
|
||||
|
||||
public DatabaseType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Type;
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationDbContext CreateContext()
|
||||
{
|
||||
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
ConfigureBuilder(builder);
|
||||
return new ApplicationDbContext(builder.Options);
|
||||
}
|
||||
|
||||
class CustomNpgsqlMigrationsSqlGenerator : NpgsqlMigrationsSqlGenerator
|
||||
{
|
||||
public CustomNpgsqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IMigrationsAnnotationProvider annotations, Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.INpgsqlOptions opts) : base(dependencies, annotations, opts)
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (_Type == DatabaseType.Sqlite)
|
||||
builder.UseSqlite(_ConnectionString, o => o.MigrationsAssembly("BTCPayServer.Data"));
|
||||
else if (_Type == DatabaseType.Postgres)
|
||||
builder
|
||||
.UseNpgsql(_ConnectionString, o => o.MigrationsAssembly("BTCPayServer.Data").EnableRetryOnFailure(10))
|
||||
.ReplaceService<IMigrationsSqlGenerator, CustomNpgsqlMigrationsSqlGenerator>();
|
||||
else if (_Type == DatabaseType.MySQL)
|
||||
builder.UseMySql(_ConnectionString, o => o.MigrationsAssembly("BTCPayServer.Data").EnableRetryOnFailure(10));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class OffchainTransactionData
|
||||
{
|
||||
[Key]
|
||||
[MaxLength(32*2)]
|
||||
public string Id { get; set; }
|
||||
public byte[] Blob { get; set; }
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// We represent the locks of the PayjoinRepository
|
||||
/// with this table. (Both, our utxo we locked as part of a payjoin
|
||||
/// and the utxo of the payer which were used to pay us)
|
||||
/// </summary>
|
||||
public class PayjoinLock
|
||||
{
|
||||
[Key]
|
||||
[MaxLength(100)]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class PaymentRequestData
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public DateTimeOffset Created
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public string StoreDataId { get; set; }
|
||||
|
||||
public StoreData StoreData { get; set; }
|
||||
|
||||
public PaymentRequestStatus Status { get; set; }
|
||||
|
||||
public byte[] Blob { get; set; }
|
||||
|
||||
public class PaymentRequestBlob
|
||||
{
|
||||
public decimal Amount { get; set; }
|
||||
public string Currency { get; set; }
|
||||
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Email { get; set; }
|
||||
|
||||
public string EmbeddedCSS { get; set; }
|
||||
public string CustomCSSLink { get; set; }
|
||||
public bool AllowCustomPaymentAmounts { get; set; }
|
||||
}
|
||||
|
||||
public enum PaymentRequestStatus
|
||||
{
|
||||
Pending = 0,
|
||||
Completed = 1,
|
||||
Expired = 2
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class PlannedTransaction
|
||||
{
|
||||
[Key]
|
||||
[MaxLength(100)]
|
||||
// Id in the format [cryptocode]-[txid]
|
||||
public string Id { get; set; }
|
||||
public DateTimeOffset BroadcastAt { get; set; }
|
||||
public byte[] Blob { get; set; }
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public enum SpeedPolicy
|
||||
{
|
||||
HighSpeed = 0,
|
||||
MediumSpeed = 1,
|
||||
LowSpeed = 2,
|
||||
LowMediumSpeed = 3
|
||||
}
|
||||
public class StoreData
|
||||
{
|
||||
public string Id
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public List<UserStore> UserStores
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
public List<AppData> Apps
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public List<PaymentRequestData> PaymentRequests
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public List<InvoiceData> Invoices { get; set; }
|
||||
|
||||
[Obsolete("Use GetDerivationStrategies instead")]
|
||||
public string DerivationStrategy
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[Obsolete("Use GetDerivationStrategies instead")]
|
||||
public string DerivationStrategies
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string StoreName
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public SpeedPolicy SpeedPolicy
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string StoreWebsite
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public byte[] StoreCertificate
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public string Role
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public byte[] StoreBlob
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
[Obsolete("Use GetDefaultPaymentId instead")]
|
||||
public string DefaultCrypto { get; set; }
|
||||
public List<PairedSINData> PairedSINs { get; set; }
|
||||
public IEnumerable<APIKeyData> APIKeys { get; set; }
|
||||
}
|
||||
|
||||
public enum NetworkFeeMode
|
||||
{
|
||||
MultiplePaymentsOnly,
|
||||
Always,
|
||||
Never
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class StoredFile
|
||||
{
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public string Id { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
public string StorageFileName { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public string ApplicationUserId { get; set; }
|
||||
public ApplicationUser ApplicationUser
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class U2FDevice
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
[Required] public byte[] KeyHandle { get; set; }
|
||||
|
||||
[Required] public byte[] PublicKey { get; set; }
|
||||
|
||||
[Required] public byte[] AttestationCert { get; set; }
|
||||
|
||||
[Required] public int Counter { get; set; }
|
||||
|
||||
public string ApplicationUserId { get; set; }
|
||||
public ApplicationUser ApplicationUser { get; set; }
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class WalletData
|
||||
{
|
||||
[System.ComponentModel.DataAnnotations.Key]
|
||||
public string Id { get; set; }
|
||||
|
||||
public List<WalletTransactionData> WalletTransactions { get; set; }
|
||||
|
||||
public byte[] Blob { get; set; }
|
||||
}
|
||||
|
||||
public class Label
|
||||
{
|
||||
public Label(string value, string color)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
if (color == null)
|
||||
throw new ArgumentNullException(nameof(color));
|
||||
Value = value;
|
||||
Color = color;
|
||||
}
|
||||
|
||||
public string Value { get; }
|
||||
public string Color { get; }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
Label item = obj as Label;
|
||||
if (item == null)
|
||||
return false;
|
||||
return Value.Equals(item.Value, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
public static bool operator ==(Label a, Label b)
|
||||
{
|
||||
if (System.Object.ReferenceEquals(a, b))
|
||||
return true;
|
||||
if (((object)a == null) || ((object)b == null))
|
||||
return false;
|
||||
return a.Value == b.Value;
|
||||
}
|
||||
|
||||
public static bool operator !=(Label a, Label b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Value.GetHashCode(StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public class WalletBlobInfo
|
||||
{
|
||||
public Dictionary<string, string> LabelColors { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
public IEnumerable<Label> GetLabels(WalletTransactionInfo transactionInfo)
|
||||
{
|
||||
foreach (var label in transactionInfo.Labels)
|
||||
{
|
||||
if (LabelColors.TryGetValue(label, out var color))
|
||||
{
|
||||
yield return new Label(label, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Label> GetLabels()
|
||||
{
|
||||
foreach (var kv in LabelColors)
|
||||
{
|
||||
yield return new Label(kv.Key, kv.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class WalletTransactionData
|
||||
{
|
||||
public string WalletDataId { get; set; }
|
||||
public WalletData WalletData { get; set; }
|
||||
public string TransactionId { get; set; }
|
||||
public string Labels { get; set; }
|
||||
public byte[] Blob { get; set; }
|
||||
}
|
||||
|
||||
public class WalletTransactionInfo
|
||||
{
|
||||
public string Comment { get; set; } = string.Empty;
|
||||
[JsonIgnore]
|
||||
public HashSet<string> Labels { get; set; } = new HashSet<string>();
|
||||
}
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20180719095626_CanDeleteStores")]
|
||||
public partial class CanDeleteStores : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
if (this.SupportDropForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_AddressInvoices_Invoices_InvoiceDataId",
|
||||
table: "AddressInvoices");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Apps_Stores_StoreDataId",
|
||||
table: "Apps");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Invoices_Stores_StoreDataId",
|
||||
table: "Invoices");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Payments_Invoices_InvoiceDataId",
|
||||
table: "Payments");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_RefundAddresses_Invoices_InvoiceDataId",
|
||||
table: "RefundAddresses");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_AddressInvoices_Invoices_InvoiceDataId",
|
||||
table: "AddressInvoices",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ApiKeys_Stores_StoreId",
|
||||
table: "ApiKeys",
|
||||
column: "StoreId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Apps_Stores_StoreDataId",
|
||||
table: "Apps",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Invoices_Stores_StoreDataId",
|
||||
table: "Invoices",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_PairedSINData_Stores_StoreDataId",
|
||||
table: "PairedSINData",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Payments_Invoices_InvoiceDataId",
|
||||
table: "Payments",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_PendingInvoices_Invoices_Id",
|
||||
table: "PendingInvoices",
|
||||
column: "Id",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_RefundAddresses_Invoices_InvoiceDataId",
|
||||
table: "RefundAddresses",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_AddressInvoices_Invoices_InvoiceDataId",
|
||||
table: "AddressInvoices");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ApiKeys_Stores_StoreId",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Apps_Stores_StoreDataId",
|
||||
table: "Apps");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Invoices_Stores_StoreDataId",
|
||||
table: "Invoices");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_PairedSINData_Stores_StoreDataId",
|
||||
table: "PairedSINData");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Payments_Invoices_InvoiceDataId",
|
||||
table: "Payments");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_PendingInvoices_Invoices_Id",
|
||||
table: "PendingInvoices");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_RefundAddresses_Invoices_InvoiceDataId",
|
||||
table: "RefundAddresses");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_AddressInvoices_Invoices_InvoiceDataId",
|
||||
table: "AddressInvoices",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Apps_Stores_StoreDataId",
|
||||
table: "Apps",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Invoices_Stores_StoreDataId",
|
||||
table: "Invoices",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Payments_Invoices_InvoiceDataId",
|
||||
table: "Payments",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_RefundAddresses_Invoices_InvoiceDataId",
|
||||
table: "RefundAddresses",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20190121133309_AddPaymentRequests")]
|
||||
public partial class AddPaymentRequests : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PaymentRequests",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
Status = table.Column<int>(nullable: false),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PaymentRequests", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_PaymentRequests_Stores_StoreDataId",
|
||||
column: x => x.StoreDataId,
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PaymentRequests_Status",
|
||||
table: "PaymentRequests",
|
||||
column: "Status");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PaymentRequests_StoreDataId",
|
||||
table: "PaymentRequests",
|
||||
column: "StoreDataId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PaymentRequests");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20190219032533_AppsTagging")]
|
||||
public partial class AppsTagging : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "TagAllInvoices",
|
||||
table: "Apps",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TagAllInvoices",
|
||||
table: "Apps");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20190225091644_AddOpenIddict")]
|
||||
public partial class AddOpenIddict : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictApplications",
|
||||
columns: table => new
|
||||
{
|
||||
ClientId = table.Column<string>(maxLength: 100, nullable: false),
|
||||
ClientSecret = table.Column<string>(nullable: true),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
ConsentType = table.Column<string>(nullable: true),
|
||||
DisplayName = table.Column<string>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Permissions = table.Column<string>(nullable: true),
|
||||
PostLogoutRedirectUris = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
RedirectUris = table.Column<string>(nullable: true),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictApplications", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictApplications_AspNetUsers_ApplicationUserId",
|
||||
column: x => x.ApplicationUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictScopes",
|
||||
columns: table => new
|
||||
{
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
Description = table.Column<string>(nullable: true),
|
||||
DisplayName = table.Column<string>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Name = table.Column<string>(maxLength: 200, nullable: false),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
Resources = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictScopes", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictAuthorizations",
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
Scopes = table.Column<string>(nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: false),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictTokens",
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
AuthorizationId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
CreationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
ExpirationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Payload = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
ReferenceId = table.Column<string>(maxLength: 100, nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: false),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictTokens", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId",
|
||||
column: x => x.AuthorizationId,
|
||||
principalTable: "OpenIddictAuthorizations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictApplications_ApplicationUserId",
|
||||
table: "OpenIddictApplications",
|
||||
column: "ApplicationUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictApplications_ClientId",
|
||||
table: "OpenIddictApplications",
|
||||
column: "ClientId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type",
|
||||
table: "OpenIddictAuthorizations",
|
||||
columns: new[] { "ApplicationId", "Status", "Subject", "Type" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictScopes_Name",
|
||||
table: "OpenIddictScopes",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictTokens_AuthorizationId",
|
||||
table: "OpenIddictTokens",
|
||||
column: "AuthorizationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictTokens_ReferenceId",
|
||||
table: "OpenIddictTokens",
|
||||
column: "ReferenceId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type",
|
||||
table: "OpenIddictTokens",
|
||||
columns: new[] { "ApplicationId", "Status", "Subject", "Type" });
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictScopes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictAuthorizations");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictApplications");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20190324141717_AddFiles")]
|
||||
public partial class AddFiles : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Files",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
FileName = table.Column<string>(nullable: true),
|
||||
StorageFileName = table.Column<string>(nullable: true),
|
||||
Timestamp = table.Column<DateTime>(nullable: false),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Files", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Files_AspNetUsers_ApplicationUserId",
|
||||
column: x => x.ApplicationUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Files_ApplicationUserId",
|
||||
table: "Files",
|
||||
column: "ApplicationUserId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Files");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20190425081749_AddU2fDevices")]
|
||||
public partial class AddU2fDevices : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Facade",
|
||||
table: "PairedSINData");
|
||||
}
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "U2FDevices",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
KeyHandle = table.Column<byte[]>(nullable: false),
|
||||
PublicKey = table.Column<byte[]>(nullable: false),
|
||||
AttestationCert = table.Column<byte[]>(nullable: false),
|
||||
Counter = table.Column<int>(nullable: false),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_U2FDevices", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
column: x => x.ApplicationUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_U2FDevices_ApplicationUserId",
|
||||
table: "U2FDevices",
|
||||
column: "ApplicationUserId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "U2FDevices");
|
||||
//if it did not support dropping it, then it is still here and re-adding it would throw
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Facade",
|
||||
table: "PairedSINData",
|
||||
nullable: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20190701082105_sort_paymentrequests")]
|
||||
public partial class sort_paymentrequests : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "Created",
|
||||
table: "PaymentRequests",
|
||||
nullable: false,
|
||||
defaultValue: new DateTimeOffset(new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0)));
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Created",
|
||||
table: "PaymentRequests");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20190802142637_WalletData")]
|
||||
public partial class WalletData : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Wallets",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Wallets", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "WalletTransactions",
|
||||
columns: table => new
|
||||
{
|
||||
WalletDataId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
TransactionId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Labels = table.Column<string>(nullable: true),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_WalletTransactions", x => new { x.WalletDataId, x.TransactionId });
|
||||
table.ForeignKey(
|
||||
name: "FK_WalletTransactions_Wallets_WalletDataId",
|
||||
column: x => x.WalletDataId,
|
||||
principalTable: "Wallets",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "WalletTransactions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Wallets");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,244 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20200110064617_OpenIddictUpdate")]
|
||||
public partial class OpenIddictUpdate : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (!migrationBuilder.IsSqlite())
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictTokens",
|
||||
maxLength: 450,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictAuthorizations",
|
||||
maxLength: 450,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
AuthorizationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
CreationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
ExpirationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Payload = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
ReferenceId = table.Column<string>(maxLength: 100, nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: true),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictTokens", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId",
|
||||
column: x => x.AuthorizationId,
|
||||
principalTable: "OpenIddictAuthorizations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictTokens");
|
||||
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
Scopes = table.Column<string>(nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: true),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictAuthorizations");
|
||||
}
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Requirements",
|
||||
table: "OpenIddictApplications",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (!migrationBuilder.IsSqlite())
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Requirements",
|
||||
table: "OpenIddictApplications");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictTokens",
|
||||
maxLength: 450,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictAuthorizations",
|
||||
maxLength: 450,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450,
|
||||
oldNullable: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
AuthorizationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
CreationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
ExpirationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Payload = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
ReferenceId = table.Column<string>(maxLength: 100, nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: false),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictTokens", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId",
|
||||
column: x => x.AuthorizationId,
|
||||
principalTable: "OpenIddictAuthorizations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictTokens", "WHERE Subject IS NOT NULL");
|
||||
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
Scopes = table.Column<string>(nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: false),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictAuthorizations", "WHERE Subject IS NOT NULL");
|
||||
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ClientId = table.Column<string>(maxLength: 100, nullable: false),
|
||||
ClientSecret = table.Column<string>(nullable: true),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
ConsentType = table.Column<string>(nullable: true),
|
||||
DisplayName = table.Column<string>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Permissions = table.Column<string>(nullable: true),
|
||||
PostLogoutRedirectUris = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
RedirectUris = table.Column<string>(nullable: true),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictApplications", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictApplications_AspNetUsers_ApplicationUserId",
|
||||
column: x => x.ApplicationUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictApplications", "",
|
||||
"ClientId, ClientSecret, ConcurrencyToken, ConsentType, DisplayName, Id, Permissions, PostLogoutRedirectUris, Properties, RedirectUris, Type, ApplicationUserId");
|
||||
}
|
||||
}
|
||||
|
||||
private void ReplaceOldTable(MigrationBuilder migrationBuilder, Action<string> createTable, string tableName,
|
||||
string whereClause = "", string columns = "*")
|
||||
{
|
||||
createTable.Invoke($"New_{tableName}");
|
||||
migrationBuilder.Sql(
|
||||
$"INSERT INTO New_{tableName} {(columns == "*" ? string.Empty : $"({columns})")}SELECT {columns} FROM {tableName} {whereClause};");
|
||||
migrationBuilder.Sql("PRAGMA foreign_keys=\"0\"", true);
|
||||
migrationBuilder.Sql($"DROP TABLE {tableName}", true);
|
||||
migrationBuilder.Sql($"ALTER TABLE New_{tableName} RENAME TO {tableName}", true);
|
||||
migrationBuilder.Sql("PRAGMA foreign_keys=\"1\"", true);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20200119130108_ExtendApiKeys")]
|
||||
public partial class ExtendApiKeys : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Permissions",
|
||||
table: "ApiKeys",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Type",
|
||||
table: "ApiKeys",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "UserId",
|
||||
table: "ApiKeys",
|
||||
maxLength: 50,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ApiKeys_UserId",
|
||||
table: "ApiKeys",
|
||||
column: "UserId");
|
||||
if (this.SupportAddForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ApiKeys_AspNetUsers_UserId",
|
||||
table: "ApiKeys",
|
||||
column: "UserId",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ApiKeys_AspNetUsers_UserId",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_ApiKeys_UserId",
|
||||
table: "ApiKeys");
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Permissions",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Type",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UserId",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20200224134444_Remove_OpenIddict")]
|
||||
public partial class Remove_OpenIddict : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictScopes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictAuthorizations");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenIddictApplications");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictApplications",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxLength),
|
||||
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxLength),
|
||||
ClientId = table.Column<string>(type: "TEXT", maxLength: 100, nullable: false),
|
||||
ClientSecret = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
|
||||
ConsentType = table.Column<string>(type: "TEXT", nullable: true),
|
||||
DisplayName = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Permissions = table.Column<string>(type: "TEXT", nullable: true),
|
||||
PostLogoutRedirectUris = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Properties = table.Column<string>(type: "TEXT", nullable: true),
|
||||
RedirectUris = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Requirements = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Type = table.Column<string>(type: "TEXT", maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictApplications", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictApplications_AspNetUsers_ApplicationUserId",
|
||||
column: x => x.ApplicationUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictScopes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxLength),
|
||||
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: true),
|
||||
DisplayName = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Name = table.Column<string>(type: "TEXT", maxLength: 200, nullable: false),
|
||||
Properties = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Resources = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictScopes", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictAuthorizations",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxLength),
|
||||
ApplicationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxLength),
|
||||
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
|
||||
Properties = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Scopes = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Status = table.Column<string>(type: "TEXT", maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(type: "TEXT", maxLength: 450, nullable: true),
|
||||
Type = table.Column<string>(type: "TEXT", maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictTokens",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxLength),
|
||||
ApplicationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxLength),
|
||||
AuthorizationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxLength),
|
||||
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
|
||||
CreationDate = table.Column<DateTimeOffset>(type: "TEXT", nullable: true),
|
||||
ExpirationDate = table.Column<DateTimeOffset>(type: "TEXT", nullable: true),
|
||||
Payload = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Properties = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ReferenceId = table.Column<string>(type: "TEXT", maxLength: 100, nullable: true),
|
||||
Status = table.Column<string>(type: "TEXT", maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(type: "TEXT", maxLength: 450, nullable: true),
|
||||
Type = table.Column<string>(type: "TEXT", maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictTokens", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId",
|
||||
column: x => x.AuthorizationId,
|
||||
principalTable: "OpenIddictAuthorizations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictApplications_ApplicationUserId",
|
||||
table: "OpenIddictApplications",
|
||||
column: "ApplicationUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictApplications_ClientId",
|
||||
table: "OpenIddictApplications",
|
||||
column: "ClientId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type",
|
||||
table: "OpenIddictAuthorizations",
|
||||
columns: new[] { "ApplicationId", "Status", "Subject", "Type" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictScopes_Name",
|
||||
table: "OpenIddictScopes",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictTokens_AuthorizationId",
|
||||
table: "OpenIddictTokens",
|
||||
column: "AuthorizationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictTokens_ReferenceId",
|
||||
table: "OpenIddictTokens",
|
||||
column: "ReferenceId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type",
|
||||
table: "OpenIddictTokens",
|
||||
columns: new[] { "ApplicationId", "Status", "Subject", "Type" });
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20200225133433_AddApiKeyLabel")]
|
||||
public partial class AddApiKeyLabel : Migration
|
||||
{
|
||||
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Label",
|
||||
table: "ApiKeys",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Label",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20200402065615_AddApiKeyBlob")]
|
||||
public partial class AddApiKeyBlob : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Permissions",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
|
||||
migrationBuilder.AddColumn<byte[]>(
|
||||
name: "Blob",
|
||||
table: "ApiKeys",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Blob",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Permissions",
|
||||
table: "ApiKeys",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20200413052418_PlannedTransactions")]
|
||||
public partial class PlannedTransactions : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PlannedTransactions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(maxLength: 100, nullable: false),
|
||||
BroadcastAt = table.Column<DateTimeOffset>(nullable: false),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PlannedTransactions", x => x.Id);
|
||||
});
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PayjoinLocks",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(maxLength: 100, nullable: false),
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PayjoinLocks", x => x.Id);
|
||||
});
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OffchainTransactions",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(maxLength: 64, nullable: false),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OffchainTransactions", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PayjoinLocks");
|
||||
migrationBuilder.DropTable(
|
||||
name: "PlannedTransactions");
|
||||
migrationBuilder.DropTable(
|
||||
name: "OffchainTransactions");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,889 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "3.1.1");
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.APIKeyData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(50);
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StoreId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(50);
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(50);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("StoreId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ApiKeys");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.AddressInvoiceData", b =>
|
||||
{
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset?>("CreatedTime")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("InvoiceDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Address");
|
||||
|
||||
b.HasIndex("InvoiceDataId");
|
||||
|
||||
b.ToTable("AddressInvoices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.AppData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("AppType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Settings")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StoreDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("TagAllInvoices")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("StoreDataId");
|
||||
|
||||
b.ToTable("Apps");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("RequiresEmailConfirmation")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.HistoricalAddressInvoiceData", b =>
|
||||
{
|
||||
b.Property<string>("InvoiceDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Assigned")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CryptoCode")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset?>("UnAssigned")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("InvoiceDataId", "Address");
|
||||
|
||||
b.ToTable("HistoricalAddressInvoices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.InvoiceData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CustomerEmail")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ExceptionStatus")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ItemCode")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OrderId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StoreDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("StoreDataId");
|
||||
|
||||
b.ToTable("Invoices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.InvoiceEventData", b =>
|
||||
{
|
||||
b.Property<string>("InvoiceDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UniqueId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("InvoiceDataId", "UniqueId");
|
||||
|
||||
b.ToTable("InvoiceEvents");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.OffchainTransactionData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(64);
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("OffchainTransactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PairedSINData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("PairingTime")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SIN")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StoreDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SIN");
|
||||
|
||||
b.HasIndex("StoreDataId");
|
||||
|
||||
b.ToTable("PairedSINData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PairingCodeData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("DateCreated")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Expiration")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Facade")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SIN")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StoreDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TokenValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PairingCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PayjoinLock", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(100);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PayjoinLocks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PaymentData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Accounted")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("InvoiceDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InvoiceDataId");
|
||||
|
||||
b.ToTable("Payments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PaymentRequestData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT")
|
||||
.HasDefaultValue(new DateTimeOffset(new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0)));
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("StoreDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("StoreDataId");
|
||||
|
||||
b.ToTable("PaymentRequests");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PendingInvoiceData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PendingInvoices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PlannedTransaction", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(100);
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTimeOffset>("BroadcastAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PlannedTransactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.RefundAddressesData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("InvoiceDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("InvoiceDataId");
|
||||
|
||||
b.ToTable("RefundAddresses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.SettingData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.StoreData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DefaultCrypto")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DerivationStrategies")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DerivationStrategy")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SpeedPolicy")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("StoreBlob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<byte[]>("StoreCertificate")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("StoreName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StoreWebsite")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Stores");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.StoredFile", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ApplicationUserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FileName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StorageFileName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("Timestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ApplicationUserId");
|
||||
|
||||
b.ToTable("Files");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.U2FDevice", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ApplicationUserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte[]>("AttestationCert")
|
||||
.IsRequired()
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<int>("Counter")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("KeyHandle")
|
||||
.IsRequired()
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte[]>("PublicKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ApplicationUserId");
|
||||
|
||||
b.ToTable("U2FDevices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.UserStore", b =>
|
||||
{
|
||||
b.Property<string>("ApplicationUserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StoreDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ApplicationUserId", "StoreDataId");
|
||||
|
||||
b.HasIndex("StoreDataId");
|
||||
|
||||
b.ToTable("UserStore");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.WalletData", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Wallets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.WalletTransactionData", b =>
|
||||
{
|
||||
b.Property<string>("WalletDataId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TransactionId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("Labels")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("WalletDataId", "TransactionId");
|
||||
|
||||
b.ToTable("WalletTransactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.APIKeyData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.StoreData", "StoreData")
|
||||
.WithMany("APIKeys")
|
||||
.HasForeignKey("StoreId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("BTCPayServer.Data.ApplicationUser", "User")
|
||||
.WithMany("APIKeys")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.AddressInvoiceData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData")
|
||||
.WithMany("AddressInvoices")
|
||||
.HasForeignKey("InvoiceDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.AppData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.StoreData", "StoreData")
|
||||
.WithMany("Apps")
|
||||
.HasForeignKey("StoreDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.HistoricalAddressInvoiceData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData")
|
||||
.WithMany("HistoricalAddressInvoices")
|
||||
.HasForeignKey("InvoiceDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.InvoiceData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.StoreData", "StoreData")
|
||||
.WithMany("Invoices")
|
||||
.HasForeignKey("StoreDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.InvoiceEventData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData")
|
||||
.WithMany("Events")
|
||||
.HasForeignKey("InvoiceDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PairedSINData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.StoreData", "StoreData")
|
||||
.WithMany("PairedSINs")
|
||||
.HasForeignKey("StoreDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PaymentData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData")
|
||||
.WithMany("Payments")
|
||||
.HasForeignKey("InvoiceDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PaymentRequestData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.StoreData", "StoreData")
|
||||
.WithMany("PaymentRequests")
|
||||
.HasForeignKey("StoreDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.PendingInvoiceData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData")
|
||||
.WithMany("PendingInvoices")
|
||||
.HasForeignKey("Id")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.RefundAddressesData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData")
|
||||
.WithMany("RefundAddresses")
|
||||
.HasForeignKey("InvoiceDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.StoredFile", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.ApplicationUser", "ApplicationUser")
|
||||
.WithMany("StoredFiles")
|
||||
.HasForeignKey("ApplicationUserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.U2FDevice", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.ApplicationUser", "ApplicationUser")
|
||||
.WithMany("U2FDevices")
|
||||
.HasForeignKey("ApplicationUserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.UserStore", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.ApplicationUser", "ApplicationUser")
|
||||
.WithMany("UserStores")
|
||||
.HasForeignKey("ApplicationUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("BTCPayServer.Data.StoreData", "StoreData")
|
||||
.WithMany("UserStores")
|
||||
.HasForeignKey("StoreDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("BTCPayServer.Data.WalletTransactionData", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.WalletData", "WalletData")
|
||||
.WithMany("WalletTransactions")
|
||||
.HasForeignKey("WalletDataId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("BTCPayServer.Data.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("BTCPayServer.Data.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
public static class MigrationsExtensions
|
||||
{
|
||||
public static bool SupportDropColumn(this Microsoft.EntityFrameworkCore.Migrations.Migration migration, string activeProvider)
|
||||
{
|
||||
return activeProvider != "Microsoft.EntityFrameworkCore.Sqlite";
|
||||
}
|
||||
public static bool SupportAddForeignKey(this Microsoft.EntityFrameworkCore.Migrations.Migration migration, string activeProvider)
|
||||
{
|
||||
return activeProvider != "Microsoft.EntityFrameworkCore.Sqlite";
|
||||
}
|
||||
public static bool SupportDropForeignKey(this Microsoft.EntityFrameworkCore.Migrations.Migration migration, string activeProvider)
|
||||
{
|
||||
return activeProvider != "Microsoft.EntityFrameworkCore.Sqlite";
|
||||
}
|
||||
public static bool SupportDropForeignKey(this DatabaseFacade facade)
|
||||
{
|
||||
return facade.ProviderName != "Microsoft.EntityFrameworkCore.Sqlite";
|
||||
}
|
||||
public static bool IsMySql(this Microsoft.EntityFrameworkCore.Migrations.Migration migration, string activeProvider)
|
||||
{
|
||||
return activeProvider == "Pomelo.EntityFrameworkCore.MySql";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
namespace BTCPayServer.Rating
|
||||
{
|
||||
public enum RateSource
|
||||
{
|
||||
Coingecko,
|
||||
Direct
|
||||
}
|
||||
public class AvailableRateProvider
|
||||
{
|
||||
public string Name { get; }
|
||||
public string Url { get; }
|
||||
public string Id { get; }
|
||||
public string SourceId { get; }
|
||||
public RateSource Source { get; }
|
||||
|
||||
public AvailableRateProvider(string id, string name, string url) : this(id, id, name, url, RateSource.Direct)
|
||||
{
|
||||
|
||||
}
|
||||
public AvailableRateProvider(string id, string sourceId, string name, string url, RateSource source)
|
||||
{
|
||||
Id = id;
|
||||
SourceId = sourceId;
|
||||
Name = name;
|
||||
Url = url;
|
||||
Source = source;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../Build/Version.csproj" Condition="Exists('../Build/Version.csproj')" />
|
||||
<Import Project="../Build/Common.csproj" />
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="DigitalRuby.ExchangeSharp" Version="0.6.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BTCPayServer.Common\BTCPayServer.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,272 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace BTCPayServer.Rating
|
||||
{
|
||||
public class ExchangeRates : IEnumerable<ExchangeRate>
|
||||
{
|
||||
Dictionary<string, ExchangeRate> _AllRates = new Dictionary<string, ExchangeRate>();
|
||||
public ExchangeRates()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ExchangeRates(string exchangeName, IEnumerable<PairRate> rates)
|
||||
{
|
||||
foreach (var rate in rates)
|
||||
{
|
||||
Add(new ExchangeRate(exchangeName, rate.CurrencyPair, rate.BidAsk));
|
||||
}
|
||||
}
|
||||
public ExchangeRates(IEnumerable<ExchangeRate> rates)
|
||||
{
|
||||
foreach (var rate in rates)
|
||||
{
|
||||
Add(rate);
|
||||
}
|
||||
}
|
||||
List<ExchangeRate> _Rates = new List<ExchangeRate>();
|
||||
public MultiValueDictionary<string, ExchangeRate> ByExchange
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new MultiValueDictionary<string, ExchangeRate>();
|
||||
|
||||
public void Add(ExchangeRate rate)
|
||||
{
|
||||
// 1 DOGE is always 1 DOGE
|
||||
if (rate.CurrencyPair.Left == rate.CurrencyPair.Right)
|
||||
return;
|
||||
var key = $"({rate.Exchange}) {rate.CurrencyPair}";
|
||||
if (_AllRates.TryAdd(key, rate))
|
||||
{
|
||||
_Rates.Add(rate);
|
||||
ByExchange.Add(rate.Exchange, rate);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rate.BidAsk != null)
|
||||
{
|
||||
_AllRates[key].BidAsk = rate.BidAsk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<ExchangeRate> GetEnumerator()
|
||||
{
|
||||
return _Rates.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void SetRate(string exchangeName, CurrencyPair currencyPair, BidAsk bidAsk)
|
||||
{
|
||||
if (ByExchange.TryGetValue(exchangeName, out var rates))
|
||||
{
|
||||
var rate = rates.FirstOrDefault(r => r.CurrencyPair == currencyPair);
|
||||
if(rate != null)
|
||||
{
|
||||
rate.BidAsk = bidAsk;
|
||||
}
|
||||
var invPair = currencyPair.Inverse();
|
||||
var invRate = rates.FirstOrDefault(r => r.CurrencyPair == invPair);
|
||||
if (invRate != null)
|
||||
{
|
||||
invRate.BidAsk = bidAsk?.Inverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
public BidAsk GetRate(string exchangeName, CurrencyPair currencyPair)
|
||||
{
|
||||
if (currencyPair.Left == currencyPair.Right)
|
||||
return BidAsk.One;
|
||||
if (ByExchange.TryGetValue(exchangeName, out var rates))
|
||||
{
|
||||
var rate = rates.FirstOrDefault(r => r.CurrencyPair == currencyPair);
|
||||
if (rate != null)
|
||||
return rate.BidAsk;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public class BidAsk
|
||||
{
|
||||
|
||||
private readonly static BidAsk _One = new BidAsk(1.0m);
|
||||
public static BidAsk One
|
||||
{
|
||||
get
|
||||
{
|
||||
return _One;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly static BidAsk _Zero = new BidAsk(0.0m);
|
||||
public static BidAsk Zero
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Zero;
|
||||
}
|
||||
}
|
||||
public BidAsk(decimal bid, decimal ask)
|
||||
{
|
||||
if (bid > ask)
|
||||
throw new ArgumentException("the bid should be lower than ask", nameof(bid));
|
||||
_Ask = ask;
|
||||
_Bid = bid;
|
||||
}
|
||||
public BidAsk(decimal v) : this(v, v)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private readonly decimal _Bid;
|
||||
public decimal Bid
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Bid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private readonly decimal _Ask;
|
||||
public decimal Ask
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Ask;
|
||||
}
|
||||
}
|
||||
|
||||
public decimal Center => (Ask + Bid) / 2.0m;
|
||||
|
||||
public BidAsk Inverse()
|
||||
{
|
||||
return new BidAsk(1.0m / Ask, 1.0m / Bid);
|
||||
}
|
||||
|
||||
public static BidAsk operator +(BidAsk a, BidAsk b)
|
||||
{
|
||||
return new BidAsk(a.Bid + b.Bid, a.Ask + b.Ask);
|
||||
}
|
||||
|
||||
public static BidAsk operator +(BidAsk a)
|
||||
{
|
||||
return new BidAsk(a.Bid, a.Ask);
|
||||
}
|
||||
|
||||
public static BidAsk operator -(BidAsk a)
|
||||
{
|
||||
return new BidAsk(-a.Bid, -a.Ask);
|
||||
}
|
||||
|
||||
public static BidAsk operator *(BidAsk a, BidAsk b)
|
||||
{
|
||||
return new BidAsk(a.Bid * b.Bid, a.Ask * b.Ask);
|
||||
}
|
||||
|
||||
public static BidAsk operator /(BidAsk a, BidAsk b)
|
||||
{
|
||||
// This one is tricky.
|
||||
// BTC_EUR = (6000, 6100)
|
||||
// Implicit rule give
|
||||
// EUR_BTC = 1 / BTC_EUR
|
||||
// Or
|
||||
// EUR_BTC = (1, 1) / BTC_EUR
|
||||
// Naive calculation would give us ( 1/6000, 1/6100) = (0.000166, 0.000163)
|
||||
// However, this is an invalid BidAsk!!! because 0.000166 > 0.000163
|
||||
// So instead, we need to calculate (1/6100, 1/6000)
|
||||
return new BidAsk(a.Bid / b.Ask, a.Ask / b.Bid);
|
||||
}
|
||||
|
||||
public static BidAsk operator -(BidAsk a, BidAsk b)
|
||||
{
|
||||
return new BidAsk(a.Bid - b.Bid, a.Ask - b.Ask);
|
||||
}
|
||||
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
BidAsk item = obj as BidAsk;
|
||||
if (item == null)
|
||||
return false;
|
||||
return Bid == item.Bid && Ask == item.Ask;
|
||||
}
|
||||
public static bool operator ==(BidAsk a, BidAsk b)
|
||||
{
|
||||
if (System.Object.ReferenceEquals(a, b))
|
||||
return true;
|
||||
if (((object)a == null) || ((object)b == null))
|
||||
return false;
|
||||
return a.Bid == b.Bid && a.Ask == b.Ask;
|
||||
}
|
||||
|
||||
public static bool operator !=(BidAsk a, BidAsk b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ToString().GetHashCode(StringComparison.InvariantCulture);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Bid == Ask)
|
||||
return Bid.ToString(CultureInfo.InvariantCulture);
|
||||
return $"({Bid.ToString(CultureInfo.InvariantCulture)} , {Ask.ToString(CultureInfo.InvariantCulture)})";
|
||||
}
|
||||
}
|
||||
|
||||
public class PairRate
|
||||
{
|
||||
public PairRate(CurrencyPair currencyPair, BidAsk bidAsk)
|
||||
{
|
||||
if (currencyPair == null)
|
||||
throw new ArgumentNullException(nameof(currencyPair));
|
||||
if (bidAsk == null)
|
||||
throw new ArgumentNullException(nameof(bidAsk));
|
||||
this.CurrencyPair = currencyPair;
|
||||
this.BidAsk = bidAsk;
|
||||
}
|
||||
public CurrencyPair CurrencyPair { get; }
|
||||
public BidAsk BidAsk { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{CurrencyPair} == {BidAsk}";
|
||||
}
|
||||
}
|
||||
public class ExchangeRate
|
||||
{
|
||||
public ExchangeRate()
|
||||
{
|
||||
|
||||
}
|
||||
public ExchangeRate(string exchange, CurrencyPair currencyPair, BidAsk bidAsk)
|
||||
{
|
||||
this.Exchange = exchange;
|
||||
this.CurrencyPair = currencyPair;
|
||||
this.BidAsk = bidAsk;
|
||||
}
|
||||
public string Exchange { get; set; }
|
||||
public CurrencyPair CurrencyPair { get; set; }
|
||||
public BidAsk BidAsk { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (BidAsk == null)
|
||||
return $"{Exchange}({CurrencyPair})";
|
||||
return $"{Exchange}({CurrencyPair}) == {BidAsk.ToString()}";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,269 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using BTCPayServer.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
public class BackgroundFetcherState
|
||||
{
|
||||
public string ExchangeName { get; set; }
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||
public DateTimeOffset? LastRequested { get; set; }
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||
public DateTimeOffset? LastUpdated { get; set; }
|
||||
[JsonProperty(ItemConverterType = typeof(BackgroundFetcherRateJsonConverter))]
|
||||
public List<BackgroundFetcherRate> Rates { get; set; }
|
||||
}
|
||||
public class BackgroundFetcherRate
|
||||
{
|
||||
public CurrencyPair Pair { get; set; }
|
||||
public BidAsk BidAsk { get; set; }
|
||||
}
|
||||
//This make the json more compact
|
||||
class BackgroundFetcherRateJsonConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return typeof(BackgroundFetcherRate).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
|
||||
}
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var value = (string)reader.Value;
|
||||
var parts = value.Split('|');
|
||||
return new BackgroundFetcherRate()
|
||||
{
|
||||
Pair = CurrencyPair.Parse(parts[0]),
|
||||
BidAsk = new BidAsk(decimal.Parse(parts[1], CultureInfo.InvariantCulture), decimal.Parse(parts[2], CultureInfo.InvariantCulture))
|
||||
};
|
||||
}
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
var rate = (BackgroundFetcherRate)value;
|
||||
writer.WriteValue($"{rate.Pair}|{rate.BidAsk.Bid.ToString(CultureInfo.InvariantCulture)}|{rate.BidAsk.Ask.ToString(CultureInfo.InvariantCulture)}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class is a decorator which handle caching and pre-emptive query to the underlying rate provider
|
||||
/// </summary>
|
||||
public class BackgroundFetcherRateProvider : IRateProvider
|
||||
{
|
||||
public class LatestFetch
|
||||
{
|
||||
public PairRate[] Latest;
|
||||
public DateTimeOffset NextRefresh;
|
||||
public TimeSpan Backoff = TimeSpan.FromSeconds(5.0);
|
||||
public DateTimeOffset Updated;
|
||||
public DateTimeOffset Expiration;
|
||||
public Exception Exception;
|
||||
internal PairRate[] GetResult()
|
||||
{
|
||||
if (Expiration <= DateTimeOffset.UtcNow)
|
||||
{
|
||||
if (Exception != null)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(Exception).Throw();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"The rate has expired");
|
||||
}
|
||||
}
|
||||
return Latest;
|
||||
}
|
||||
}
|
||||
|
||||
IRateProvider _Inner;
|
||||
public IRateProvider Inner => _Inner;
|
||||
|
||||
public BackgroundFetcherRateProvider(IRateProvider inner)
|
||||
{
|
||||
if (inner == null)
|
||||
throw new ArgumentNullException(nameof(inner));
|
||||
_Inner = inner;
|
||||
}
|
||||
|
||||
public BackgroundFetcherState GetState()
|
||||
{
|
||||
var state = new BackgroundFetcherState()
|
||||
{
|
||||
LastRequested = LastRequested
|
||||
};
|
||||
if (_Latest is LatestFetch fetch && fetch.Latest is PairRate[])
|
||||
{
|
||||
state.LastUpdated = fetch.Updated;
|
||||
state.Rates = fetch.Latest
|
||||
.Select(r => new BackgroundFetcherRate()
|
||||
{
|
||||
Pair = r.CurrencyPair,
|
||||
BidAsk = r.BidAsk
|
||||
}).ToList();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
public void LoadState(BackgroundFetcherState state)
|
||||
{
|
||||
if (state.LastRequested is DateTimeOffset lastRequested)
|
||||
this.LastRequested = state.LastRequested;
|
||||
if (state.LastUpdated is DateTimeOffset updated && state.Rates is List<BackgroundFetcherRate> rates)
|
||||
{
|
||||
var fetch = new LatestFetch()
|
||||
{
|
||||
Latest = rates.Select(r => new PairRate(r.Pair, r.BidAsk)).ToArray(),
|
||||
Updated = updated,
|
||||
NextRefresh = updated + RefreshRate,
|
||||
Expiration = updated + ValidatyTime
|
||||
};
|
||||
_Latest = fetch;
|
||||
}
|
||||
}
|
||||
|
||||
TimeSpan _RefreshRate = TimeSpan.FromSeconds(30);
|
||||
/// <summary>
|
||||
/// The timespan after which <see cref="UpdateIfNecessary(CancellationToken)"/> will get the rates from the underlying rate provider
|
||||
/// </summary>
|
||||
public TimeSpan RefreshRate
|
||||
{
|
||||
get
|
||||
{
|
||||
return _RefreshRate;
|
||||
}
|
||||
set
|
||||
{
|
||||
var diff = value - _RefreshRate;
|
||||
var latest = _Latest;
|
||||
if (latest != null)
|
||||
latest.NextRefresh += diff;
|
||||
_RefreshRate = value;
|
||||
}
|
||||
}
|
||||
|
||||
TimeSpan _ValidatyTime = TimeSpan.FromMinutes(10);
|
||||
/// <summary>
|
||||
/// The timespan after which calls to <see cref="GetRatesAsync(CancellationToken)"/> will query underlying provider if the rate has not been updated
|
||||
/// </summary>
|
||||
public TimeSpan ValidatyTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ValidatyTime;
|
||||
}
|
||||
set
|
||||
{
|
||||
var diff = value - _ValidatyTime;
|
||||
var latest = _Latest;
|
||||
if (latest != null)
|
||||
latest.Expiration += diff;
|
||||
_ValidatyTime = value;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTimeOffset NextUpdate
|
||||
{
|
||||
get
|
||||
{
|
||||
var latest = _Latest;
|
||||
if (latest == null)
|
||||
return DateTimeOffset.UtcNow;
|
||||
return latest.NextRefresh;
|
||||
}
|
||||
}
|
||||
|
||||
public bool DoNotAutoFetchIfExpired { get; set; }
|
||||
readonly static TimeSpan MaxBackoff = TimeSpan.FromMinutes(5.0);
|
||||
|
||||
public async Task<LatestFetch> UpdateIfNecessary(CancellationToken cancellationToken)
|
||||
{
|
||||
if (NextUpdate <= DateTimeOffset.UtcNow)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Fetch(cancellationToken);
|
||||
}
|
||||
catch { } // Exception is inside _Latest
|
||||
return _Latest;
|
||||
}
|
||||
return _Latest;
|
||||
}
|
||||
|
||||
LatestFetch _Latest;
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
LastRequested = DateTimeOffset.UtcNow;
|
||||
var latest = _Latest;
|
||||
if (!DoNotAutoFetchIfExpired && latest != null && latest.Expiration <= DateTimeOffset.UtcNow + TimeSpan.FromSeconds(1.0))
|
||||
{
|
||||
latest = null;
|
||||
}
|
||||
return (latest ?? (await Fetch(cancellationToken))).GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The last time this rate provider has been used
|
||||
/// </summary>
|
||||
public DateTimeOffset? LastRequested { get; set; }
|
||||
|
||||
public DateTimeOffset? Expiration
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Latest is LatestFetch f)
|
||||
{
|
||||
return f.Expiration;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<LatestFetch> Fetch(CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var previous = _Latest;
|
||||
var fetch = new LatestFetch();
|
||||
try
|
||||
{
|
||||
var rates = await _Inner.GetRatesAsync(cancellationToken);
|
||||
fetch.Latest = rates;
|
||||
fetch.Updated = DateTimeOffset.UtcNow;
|
||||
fetch.Expiration = fetch.Updated + ValidatyTime;
|
||||
fetch.NextRefresh = fetch.Updated + RefreshRate;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (previous != null)
|
||||
{
|
||||
fetch.Latest = previous.Latest;
|
||||
fetch.Expiration = previous.Expiration;
|
||||
fetch.Backoff = previous.Backoff * 2;
|
||||
if (fetch.Backoff > MaxBackoff)
|
||||
fetch.Backoff = MaxBackoff;
|
||||
}
|
||||
else
|
||||
{
|
||||
fetch.Expiration = DateTimeOffset.UtcNow;
|
||||
}
|
||||
fetch.NextRefresh = DateTimeOffset.UtcNow + fetch.Backoff;
|
||||
fetch.Exception = ex;
|
||||
}
|
||||
_Latest = fetch;
|
||||
fetch.GetResult(); // Will throw if not valid
|
||||
return fetch;
|
||||
}
|
||||
|
||||
public void InvalidateCache()
|
||||
{
|
||||
_Latest = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
public class BitbankRateProvider : IRateProvider
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
public BitbankRateProvider(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _httpClient.GetAsync("https://public.bitbank.cc/prices", cancellationToken);
|
||||
var jobj = await response.Content.ReadAsAsync<JObject>(cancellationToken);
|
||||
return ((jobj["data"] as JObject) ?? new JObject())
|
||||
.Properties()
|
||||
.Select(p => new PairRate(CurrencyPair.Parse(p.Name), CreateBidAsk(p)))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static BidAsk CreateBidAsk(JProperty p)
|
||||
{
|
||||
var buy = p.Value["buy"].Value<decimal>();
|
||||
var sell = p.Value["sell"].Value<decimal>();
|
||||
// Bug from their API (https://github.com/btcpayserver/btcpayserver/issues/741)
|
||||
return buy < sell ? new BidAsk(buy, sell) : new BidAsk(sell, buy);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
public class BitflyerRateProvider : IRateProvider
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
public BitflyerRateProvider(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _httpClient.GetAsync("https://api.bitflyer.jp/v1/ticker", cancellationToken);
|
||||
var jobj = await response.Content.ReadAsAsync<JObject>(cancellationToken);
|
||||
if (jobj.Property("error_message")?.Value?.Value<string>() is string err)
|
||||
{
|
||||
throw new Exception($"Error from bitflyer: {err}");
|
||||
}
|
||||
var bid = jobj.Property("best_bid").Value.Value<decimal>();
|
||||
var ask = jobj.Property("best_ask").Value.Value<decimal>();
|
||||
var rates = new PairRate[1];
|
||||
rates[0] = new PairRate(CurrencyPair.Parse(jobj.Property("product_code").Value.Value<string>()), new BidAsk(bid, ask));
|
||||
return rates;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using System.Threading;
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
public class BitpayRateProvider : IRateProvider
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
public BitpayRateProvider(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _httpClient.GetAsync("https://bitpay.com/rates", cancellationToken);
|
||||
var jarray = (JArray)(await response.Content.ReadAsAsync<JObject>(cancellationToken))["data"];
|
||||
return jarray
|
||||
.Children<JObject>()
|
||||
.Select(jobj => new PairRate(new CurrencyPair("BTC", jobj["code"].Value<string>()), new BidAsk(jobj["rate"].Value<decimal>())))
|
||||
.Where(o => o.CurrencyPair.Right != "BTC")
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
public class ByllsRateProvider : IRateProvider
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
public ByllsRateProvider(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient ?? new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _httpClient.GetAsync("https://bylls.com/api/price?from_currency=BTC&to_currency=CAD", cancellationToken);
|
||||
var jobj = await response.Content.ReadAsAsync<JObject>(cancellationToken);
|
||||
var value = jobj["public_price"]["to_price"].Value<decimal>();
|
||||
return new[] { new PairRate(new CurrencyPair("BTC", "CAD"), new BidAsk(value)) };
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1,75 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using ExchangeSharp;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
public class ExchangeSharpRateProvider<T> : IRateProvider where T : ExchangeAPI, new()
|
||||
{
|
||||
HttpClient _httpClient;
|
||||
public ExchangeSharpRateProvider(HttpClient httpClient, bool reverseCurrencyPair = false)
|
||||
{
|
||||
if (httpClient == null)
|
||||
throw new ArgumentNullException(nameof(httpClient));
|
||||
ReverseCurrencyPair = reverseCurrencyPair;
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public bool ReverseCurrencyPair
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await new SynchronizationContextRemover();
|
||||
|
||||
var exchangeAPI = new T();
|
||||
exchangeAPI.RequestMaker = new HttpClientRequestMaker(exchangeAPI, _httpClient, cancellationToken);
|
||||
var rates = await exchangeAPI.GetTickersAsync();
|
||||
|
||||
var exchangeRateTasks = rates
|
||||
.Where(t => t.Value.Ask != 0m && t.Value.Bid != 0m)
|
||||
.Select(t => CreateExchangeRate(exchangeAPI, t));
|
||||
|
||||
var exchangeRates = await Task.WhenAll(exchangeRateTasks);
|
||||
|
||||
return exchangeRates
|
||||
.Where(t => t != null)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
// ExchangeSymbolToGlobalSymbol throws exception which would kill perf
|
||||
ConcurrentDictionary<string, string> notFoundSymbols = new ConcurrentDictionary<string, string>();
|
||||
private async Task<PairRate> CreateExchangeRate(T exchangeAPI, KeyValuePair<string, ExchangeTicker> ticker)
|
||||
{
|
||||
if (notFoundSymbols.TryGetValue(ticker.Key, out _))
|
||||
return null;
|
||||
try
|
||||
{
|
||||
var tickerName = await exchangeAPI.ExchangeMarketSymbolToGlobalMarketSymbolAsync(ticker.Key);
|
||||
if (!CurrencyPair.TryParse(tickerName, out var pair))
|
||||
{
|
||||
notFoundSymbols.TryAdd(ticker.Key, ticker.Key);
|
||||
return null;
|
||||
}
|
||||
if (ReverseCurrencyPair)
|
||||
pair = new CurrencyPair(pair.Right, pair.Left);
|
||||
return new PairRate(pair, new BidAsk(ticker.Value.Bid, ticker.Value.Ask));
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
notFoundSymbols.TryAdd(ticker.Key, ticker.Key);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,210 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ExchangeSharp;
|
||||
using System.Threading;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
internal class HttpClientRequestMaker : IAPIRequestMaker
|
||||
{
|
||||
class InternalHttpWebRequest : IHttpWebRequest
|
||||
{
|
||||
internal readonly HttpWebRequest Request;
|
||||
|
||||
public Uri RequestUri => Request.RequestUri;
|
||||
|
||||
public string Method
|
||||
{
|
||||
get
|
||||
{
|
||||
return Request.Method;
|
||||
}
|
||||
set
|
||||
{
|
||||
Request.Method = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Timeout
|
||||
{
|
||||
get
|
||||
{
|
||||
return Request.Timeout;
|
||||
}
|
||||
set
|
||||
{
|
||||
Request.Timeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int ReadWriteTimeout
|
||||
{
|
||||
get
|
||||
{
|
||||
return Request.ReadWriteTimeout;
|
||||
}
|
||||
set
|
||||
{
|
||||
Request.ReadWriteTimeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
public InternalHttpWebRequest(Uri fullUri)
|
||||
{
|
||||
Request = ((WebRequest.Create(fullUri) as HttpWebRequest) ?? throw new NullReferenceException("Failed to create HttpWebRequest"));
|
||||
Request.KeepAlive = false;
|
||||
}
|
||||
|
||||
public void AddHeader(string header, string value)
|
||||
{
|
||||
switch (header.ToStringLowerInvariant())
|
||||
{
|
||||
case "content-type":
|
||||
Request.ContentType = value;
|
||||
break;
|
||||
case "content-length":
|
||||
Request.ContentLength = value.ConvertInvariant<long>(0L);
|
||||
break;
|
||||
case "user-agent":
|
||||
Request.UserAgent = value;
|
||||
break;
|
||||
case "accept":
|
||||
Request.Accept = value;
|
||||
break;
|
||||
case "connection":
|
||||
Request.Connection = value;
|
||||
break;
|
||||
default:
|
||||
Request.Headers[header] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Task WriteAllAsync(byte[] data, int index, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public HttpRequestMessage ToHttpRequestMessage()
|
||||
{
|
||||
var httpRequest = new HttpRequestMessage(HttpMethod.Get, Request.RequestUri);
|
||||
CopyHeadersFrom(httpRequest, Request);
|
||||
return httpRequest;
|
||||
}
|
||||
|
||||
internal void CopyHeadersFrom(HttpRequestMessage message, HttpWebRequest request)
|
||||
{
|
||||
foreach (string headerName in request.Headers)
|
||||
{
|
||||
string[] headerValues = request.Headers.GetValues(headerName);
|
||||
if (!message.Headers.TryAddWithoutValidation(headerName, headerValues))
|
||||
{
|
||||
if (message.Content != null)
|
||||
message.Content.Headers.TryAddWithoutValidation(headerName, headerValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class InternalHttpWebResponse : IHttpWebResponse
|
||||
{
|
||||
public InternalHttpWebResponse(HttpResponseMessage httpResponseMessage)
|
||||
{
|
||||
var headers = new Dictionary<string, List<string>>();
|
||||
foreach (var h in httpResponseMessage.Headers)
|
||||
{
|
||||
if (!headers.TryGetValue(h.Key, out var list))
|
||||
{
|
||||
list = new List<string>();
|
||||
headers.Add(h.Key, list);
|
||||
}
|
||||
list.AddRange(h.Value);
|
||||
}
|
||||
Headers = new Dictionary<string, IReadOnlyList<string>>(headers.Count);
|
||||
foreach (var item in headers)
|
||||
{
|
||||
Headers.Add(item.Key, item.Value.AsReadOnly());
|
||||
}
|
||||
}
|
||||
public Dictionary<string, IReadOnlyList<string>> Headers { get; }
|
||||
static IReadOnlyList<string> Empty = new List<string>().AsReadOnly();
|
||||
public IReadOnlyList<string> GetHeader(string name)
|
||||
{
|
||||
Headers.TryGetValue(name, out var list);
|
||||
return list ?? Empty;
|
||||
}
|
||||
}
|
||||
private readonly IAPIRequestHandler api;
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly CancellationToken _cancellationToken;
|
||||
|
||||
public HttpClientRequestMaker(IAPIRequestHandler api, HttpClient httpClient, CancellationToken cancellationToken)
|
||||
{
|
||||
if (api == null)
|
||||
throw new ArgumentNullException(nameof(api));
|
||||
if (httpClient == null)
|
||||
throw new ArgumentNullException(nameof(httpClient));
|
||||
this.api = api;
|
||||
_httpClient = httpClient;
|
||||
_cancellationToken = cancellationToken;
|
||||
}
|
||||
public Action<IAPIRequestMaker, RequestMakerState, object> RequestStateChanged
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public async Task<string> MakeRequestAsync(string url, string baseUrl = null, Dictionary<string, object> payload = null, string method = null)
|
||||
{
|
||||
await default(SynchronizationContextRemover);
|
||||
await api.RateLimit.WaitToProceedAsync();
|
||||
if (url[0] != '/')
|
||||
{
|
||||
url = "/" + url;
|
||||
}
|
||||
string uri2 = (baseUrl ?? api.BaseUrl) + url;
|
||||
if (method == null)
|
||||
{
|
||||
method = api.RequestMethod;
|
||||
}
|
||||
Uri uri = api.ProcessRequestUrl(new UriBuilder(uri2), payload, method);
|
||||
InternalHttpWebRequest request = new InternalHttpWebRequest(uri)
|
||||
{
|
||||
Method = method
|
||||
};
|
||||
request.AddHeader("content-type", api.RequestContentType);
|
||||
request.AddHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36");
|
||||
int num3 = request.Timeout = (request.ReadWriteTimeout = (int)api.RequestTimeout.TotalMilliseconds);
|
||||
await api.ProcessRequestAsync(request, payload);
|
||||
try
|
||||
{
|
||||
RequestStateChanged?.Invoke(this, RequestMakerState.Begin, uri.AbsoluteUri);
|
||||
using var webHttpRequest = request.ToHttpRequestMessage();
|
||||
using var webHttpResponse = await _httpClient.SendAsync(webHttpRequest, _cancellationToken);
|
||||
string text = await webHttpResponse.Content.ReadAsStringAsync();
|
||||
if (!webHttpResponse.IsSuccessStatusCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
throw new APIException($"{webHttpResponse.StatusCode.ConvertInvariant<int>(0)} - {webHttpResponse.StatusCode}");
|
||||
}
|
||||
throw new APIException(text);
|
||||
}
|
||||
api.ProcessResponse(new InternalHttpWebResponse(webHttpResponse));
|
||||
|
||||
RequestStateChanged?.Invoke(this, RequestMakerState.Finished, text);
|
||||
return text;
|
||||
}
|
||||
catch (Exception arg)
|
||||
{
|
||||
RequestStateChanged?.Invoke(this, RequestMakerState.Error, arg);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,194 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
using ExchangeSharp;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
// Make sure that only one request is sent to kraken in general
|
||||
public class KrakenExchangeRateProvider : IRateProvider
|
||||
{
|
||||
public KrakenExchangeRateProvider()
|
||||
{
|
||||
_Helper = new ExchangeKrakenAPI();
|
||||
}
|
||||
ExchangeKrakenAPI _Helper;
|
||||
public HttpClient HttpClient
|
||||
{
|
||||
get
|
||||
{
|
||||
return _LocalClient ?? _Client;
|
||||
}
|
||||
set
|
||||
{
|
||||
_LocalClient = value;
|
||||
}
|
||||
}
|
||||
|
||||
HttpClient _LocalClient;
|
||||
static HttpClient _Client = new HttpClient();
|
||||
|
||||
// ExchangeSymbolToGlobalSymbol throws exception which would kill perf
|
||||
ConcurrentDictionary<string, string> notFoundSymbols = new ConcurrentDictionary<string, string>(new Dictionary<string, string>()
|
||||
{
|
||||
{"ADAXBT","ADAXBT"},
|
||||
{ "BSVUSD","BSVUSD"},
|
||||
{ "QTUMEUR","QTUMEUR"},
|
||||
{ "QTUMXBT","QTUMXBT"},
|
||||
{ "EOSUSD","EOSUSD"},
|
||||
{ "XTZUSD","XTZUSD"},
|
||||
{ "XREPZUSD","XREPZUSD"},
|
||||
{ "ADAEUR","ADAEUR"},
|
||||
{ "ADAUSD","ADAUSD"},
|
||||
{ "GNOEUR","GNOEUR"},
|
||||
{ "XTZETH","XTZETH"},
|
||||
{ "XXRPZJPY","XXRPZJPY"},
|
||||
{ "XXRPZCAD","XXRPZCAD"},
|
||||
{ "XTZEUR","XTZEUR"},
|
||||
{ "QTUMETH","QTUMETH"},
|
||||
{ "XXLMZUSD","XXLMZUSD"},
|
||||
{ "QTUMCAD","QTUMCAD"},
|
||||
{ "QTUMUSD","QTUMUSD"},
|
||||
{ "XTZXBT","XTZXBT"},
|
||||
{ "GNOUSD","GNOUSD"},
|
||||
{ "ADAETH","ADAETH"},
|
||||
{ "ADACAD","ADACAD"},
|
||||
{ "XTZCAD","XTZCAD"},
|
||||
{ "BSVEUR","BSVEUR"},
|
||||
{ "XZECZJPY","XZECZJPY"},
|
||||
{ "XXLMZEUR","XXLMZEUR"},
|
||||
{"EOSEUR","EOSEUR"},
|
||||
{"BSVXBT","BSVXBT"}
|
||||
});
|
||||
string[] _Symbols = Array.Empty<string>();
|
||||
DateTimeOffset? _LastSymbolUpdate = null;
|
||||
|
||||
|
||||
Dictionary<string, string> _TickerMapping = new Dictionary<string, string>()
|
||||
{
|
||||
{ "XXDG", "DOGE" },
|
||||
{ "XXBT", "BTC" },
|
||||
{ "XBT", "BTC" },
|
||||
{ "DASH", "DASH" },
|
||||
{ "ZUSD", "USD" },
|
||||
{ "ZEUR", "EUR" },
|
||||
{ "ZJPY", "JPY" },
|
||||
{ "ZCAD", "CAD" },
|
||||
{ "ZGBP", "GBP" }
|
||||
};
|
||||
|
||||
public async Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var result = new List<PairRate>();
|
||||
var symbols = await GetSymbolsAsync(cancellationToken);
|
||||
var normalizedPairsList = symbols.Where(s => !notFoundSymbols.ContainsKey(s)).Select(s => _Helper.NormalizeMarketSymbol(s)).ToList();
|
||||
var csvPairsList = string.Join(",", normalizedPairsList);
|
||||
JToken apiTickers = await MakeJsonRequestAsync<JToken>("/0/public/Ticker", null, new Dictionary<string, object> { { "pair", csvPairsList } }, cancellationToken: cancellationToken);
|
||||
var tickers = new List<KeyValuePair<string, ExchangeTicker>>();
|
||||
foreach (string symbol in symbols)
|
||||
{
|
||||
var ticker = ConvertToExchangeTicker(symbol, apiTickers[symbol]);
|
||||
if (ticker != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
string global = null;
|
||||
var mapped1 = _TickerMapping.Where(t => symbol.StartsWith(t.Key, StringComparison.OrdinalIgnoreCase))
|
||||
.Select(t => new { KrakenTicker = t.Key, PayTicker = t.Value }).SingleOrDefault();
|
||||
if (mapped1 != null)
|
||||
{
|
||||
var p2 = symbol.Substring(mapped1.KrakenTicker.Length);
|
||||
if (_TickerMapping.TryGetValue(p2, out var mapped2))
|
||||
p2 = mapped2;
|
||||
global = $"{p2}_{mapped1.PayTicker}";
|
||||
}
|
||||
else
|
||||
{
|
||||
global = await _Helper.ExchangeMarketSymbolToGlobalMarketSymbolAsync(symbol);
|
||||
}
|
||||
if (CurrencyPair.TryParse(global, out var pair))
|
||||
result.Add(new PairRate(pair.Inverse(), new BidAsk(ticker.Bid, ticker.Ask)));
|
||||
else
|
||||
notFoundSymbols.TryAdd(symbol, symbol);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
notFoundSymbols.TryAdd(symbol, symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
private static ExchangeTicker ConvertToExchangeTicker(string symbol, JToken ticker)
|
||||
{
|
||||
if (ticker == null)
|
||||
return null;
|
||||
decimal last = ticker["c"][0].ConvertInvariant<decimal>();
|
||||
return new ExchangeTicker
|
||||
{
|
||||
Ask = ticker["a"][0].ConvertInvariant<decimal>(),
|
||||
Bid = ticker["b"][0].ConvertInvariant<decimal>(),
|
||||
Last = last,
|
||||
Volume = new ExchangeVolume
|
||||
{
|
||||
BaseCurrencyVolume = ticker["v"][1].ConvertInvariant<decimal>(),
|
||||
BaseCurrency = symbol,
|
||||
QuoteCurrencyVolume = ticker["v"][1].ConvertInvariant<decimal>() * last,
|
||||
QuoteCurrency = symbol,
|
||||
Timestamp = DateTime.UtcNow
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<string[]> GetSymbolsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_LastSymbolUpdate != null && DateTimeOffset.UtcNow - _LastSymbolUpdate.Value < TimeSpan.FromDays(0.5))
|
||||
{
|
||||
return _Symbols;
|
||||
}
|
||||
else
|
||||
{
|
||||
JToken json = await MakeJsonRequestAsync<JToken>("/0/public/AssetPairs", cancellationToken: cancellationToken);
|
||||
var symbols = (from prop in json.Children<JProperty>() where !prop.Name.Contains(".d", StringComparison.OrdinalIgnoreCase) select prop.Name).ToArray();
|
||||
_Symbols = symbols;
|
||||
_LastSymbolUpdate = DateTimeOffset.UtcNow;
|
||||
return symbols;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<T> MakeJsonRequestAsync<T>(string url, string baseUrl = null, Dictionary<string, object> payload = null, string requestMethod = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("https://api.kraken.com");
|
||||
;
|
||||
sb.Append(url);
|
||||
if (payload != null)
|
||||
{
|
||||
sb.Append("?");
|
||||
sb.Append(String.Join('&', payload.Select(kv => $"{kv.Key}={kv.Value}").OfType<object>().ToArray()));
|
||||
}
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, sb.ToString());
|
||||
var response = await HttpClient.SendAsync(request, cancellationToken);
|
||||
string stringResult = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<T>(stringResult);
|
||||
if (result is JToken json)
|
||||
{
|
||||
if (!(json is JArray) && json["error"] is JArray error && error.Count != 0)
|
||||
{
|
||||
throw new APIException(error[0].ToStringInvariant());
|
||||
}
|
||||
result = (T)(object)(json["result"] ?? json);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Rating;
|
||||
|
||||
namespace BTCPayServer.Services.Rates
|
||||
{
|
||||
public class NullRateProvider : IRateProvider
|
||||
{
|
||||
private NullRateProvider()
|
||||
{
|
||||
|
||||
}
|
||||
private static readonly NullRateProvider _Instance = new NullRateProvider();
|
||||
public static NullRateProvider Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Instance;
|
||||
}
|
||||
}
|
||||
public Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(Array.Empty<PairRate>());
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user