From 57b9ea720e9d6534617a0bca2d0270faad7fe5e3 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Fri, 16 Dec 2022 17:26:07 -0500
Subject: [PATCH 01/25] Create dependabot.yml
---
.github/dependabot.yml | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 .github/dependabot.yml
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..8c23067
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ - package-ecosystem: "nuget" # See documentation for possible values
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "weekly"
From 2d6051225ba61110ef5a8d701808a701cc6ef866 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Fri, 16 Dec 2022 17:29:12 -0500
Subject: [PATCH 02/25] Create codeql.yml
---
.github/workflows/codeql.yml | 74 ++++++++++++++++++++++++++++++++++++
1 file changed, 74 insertions(+)
create mode 100644 .github/workflows/codeql.yml
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..8a004a3
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,74 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ "dev", main ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ "dev" ]
+ schedule:
+ - cron: '20 16 * * 2'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'csharp' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+ # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+
+ # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v2
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+
+ # If the Autobuild fails above, remove it and uncomment the following three lines.
+ # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
+
+ # - run: |
+ # echo "Run, Build Application using script"
+ # ./location_of_script_within_repo/buildscript.sh
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
+ with:
+ category: "/language:${{matrix.language}}"
From 5071d2ae32d153aaeb1ff16cb763690467cb64b6 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Fri, 16 Dec 2022 17:29:46 -0500
Subject: [PATCH 03/25] Create dev_test_dotnet.yml
---
.github/workflows/dev_test_dotnet.yml | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 .github/workflows/dev_test_dotnet.yml
diff --git a/.github/workflows/dev_test_dotnet.yml b/.github/workflows/dev_test_dotnet.yml
new file mode 100644
index 0000000..3f45dc4
--- /dev/null
+++ b/.github/workflows/dev_test_dotnet.yml
@@ -0,0 +1,25 @@
+name: Build And Test
+
+on:
+ push:
+ branches: [ "dev" ]
+ pull_request:
+ branches: [ "dev" ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: 7.0.x
+ - name: Restore dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build --no-restore
+ - name: Test
+ run: dotnet test --no-build --verbosity normal
From 00506e55d8cc4d76b9c3eca7c837d46cce4c9202 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Fri, 16 Dec 2022 17:30:25 -0500
Subject: [PATCH 04/25] Create main_test_dotnet.yml
---
.github/workflows/main_test_dotnet.yml | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 .github/workflows/main_test_dotnet.yml
diff --git a/.github/workflows/main_test_dotnet.yml b/.github/workflows/main_test_dotnet.yml
new file mode 100644
index 0000000..2b801eb
--- /dev/null
+++ b/.github/workflows/main_test_dotnet.yml
@@ -0,0 +1,25 @@
+name: Build And Test main branch
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: 7.0.x
+ - name: Restore dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build --no-restore
+ - name: Test
+ run: dotnet test --no-build --verbosity normal
From 887fb7319ed05e32b7ebb88bea18b8e660de9b15 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Fri, 16 Dec 2022 17:30:56 -0500
Subject: [PATCH 05/25] Create publish_dotnet.yml
---
.github/workflows/publish_dotnet.yml | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 .github/workflows/publish_dotnet.yml
diff --git a/.github/workflows/publish_dotnet.yml b/.github/workflows/publish_dotnet.yml
new file mode 100644
index 0000000..8e08106
--- /dev/null
+++ b/.github/workflows/publish_dotnet.yml
@@ -0,0 +1,20 @@
+name: Build and Publish
+on:
+ release:
+ types: [published]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: 7.0.x
+ - name: Restore dependencies
+ run: dotnet restore
+ - name: Build
+ run: |
+ dotnet build --no-restore --configuration Release
+ - name: Publish
+ run: nuget push **\*.nupkg -Source 'https://api.nuget.org/v3/index.json' -ApiKey ${{secrets.NUGET_PUB_KEY}}
From d33091cdfbb86cdd35da56499f40dba64aaeaeb3 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Fri, 16 Dec 2022 17:32:12 -0500
Subject: [PATCH 06/25] Create bug_report.md
---
.github/ISSUE_TEMPLATE/bug_report.md | 38 ++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..dd84ea7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,38 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**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.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. iOS]
+ - Browser [e.g. chrome, safari]
+ - Version [e.g. 22]
+
+**Smartphone (please complete the following information):**
+ - Device: [e.g. iPhone6]
+ - OS: [e.g. iOS8.1]
+ - Browser [e.g. stock browser, safari]
+ - Version [e.g. 22]
+
+**Additional context**
+Add any other context about the problem here.
From 72f52d9f3d5ad50206882e8d5bed675e7501b214 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Fri, 16 Dec 2022 17:32:40 -0500
Subject: [PATCH 07/25] Create feature_request.md
---
.github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..bbcbbe7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**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.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
From 954670c6f2ff541c3bef3174d8b7ca4fad7dfcab Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Fri, 16 Dec 2022 17:35:14 -0500
Subject: [PATCH 08/25] Create FUNDING.yml
---
.github/FUNDING.yml | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 .github/FUNDING.yml
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..c44d292
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+# These are supported funding model platforms
+
+github: [ByronAP]
From bf1ca2f690169f9d1bb7a2f95c7c57321986c3aa Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Sat, 24 Dec 2022 16:08:17 -0500
Subject: [PATCH 09/25] initial commit
---
CoinpaprikaApi.sln | 40 +++
CoinpaprikaApi/CoinPaprikaClient.cs | 249 ++++++++++++++++++
CoinpaprikaApi/CoinpaprikaApi.csproj | 69 +++++
CoinpaprikaApi/Constants.cs | 43 +++
CoinpaprikaApi/Exceptions/UnknownException.cs | 16 ++
CoinpaprikaApi/Extensions.cs | 69 +++++
CoinpaprikaApi/Imp/CoinsImp.cs | 231 ++++++++++++++++
CoinpaprikaApi/Imp/ContractsImp.cs | 137 ++++++++++
CoinpaprikaApi/Imp/ExchangesImp.cs | 98 +++++++
CoinpaprikaApi/Imp/GlobalImp.cs | 55 ++++
CoinpaprikaApi/Imp/KeyImp.cs | 60 +++++
CoinpaprikaApi/Imp/PersonsImp.cs | 56 ++++
CoinpaprikaApi/Imp/TagsImp.cs | 98 +++++++
CoinpaprikaApi/Imp/TickersImp.cs | 123 +++++++++
CoinpaprikaApi/Imp/ToolsImp.cs | 96 +++++++
CoinpaprikaApi/MemCache.cs | 132 ++++++++++
CoinpaprikaApi/Models/CoinEventItem.cs | 32 +++
CoinpaprikaApi/Models/CoinExchangeItem.cs | 19 ++
CoinpaprikaApi/Models/CoinItem.cs | 28 ++
CoinpaprikaApi/Models/CoinLinks.cs | 28 ++
.../Models/CoinLinksExtendedItem.cs | 16 ++
.../Models/CoinLinksExtendedItemStats.cs | 19 ++
CoinpaprikaApi/Models/CoinMarketItem.cs | 54 ++++
CoinpaprikaApi/Models/CoinResponse.cs | 80 ++++++
CoinpaprikaApi/Models/CoinTagItem.cs | 19 ++
CoinpaprikaApi/Models/CoinTeamItem.cs | 16 ++
CoinpaprikaApi/Models/CoinTweetItem.cs | 41 +++
CoinpaprikaApi/Models/CoinWhitepaper.cs | 13 +
CoinpaprikaApi/Models/ContractData.cs | 19 ++
CoinpaprikaApi/Models/ExchangeFiat.cs | 13 +
CoinpaprikaApi/Models/ExchangeItem.cs | 63 +++++
CoinpaprikaApi/Models/ExchangeMarketItem.cs | 48 ++++
CoinpaprikaApi/Models/GlobalResponse.cs | 47 ++++
CoinpaprikaApi/Models/KeyInfoResponse.cs | 23 ++
CoinpaprikaApi/Models/KeyUsage.cs | 13 +
CoinpaprikaApi/Models/KeyUsageCurrMonth.cs | 13 +
CoinpaprikaApi/Models/MarketQuote.cs | 13 +
CoinpaprikaApi/Models/NameSymbolPair.cs | 13 +
CoinpaprikaApi/Models/OhlcvItem.cs | 32 +++
CoinpaprikaApi/Models/PersonLink.cs | 13 +
CoinpaprikaApi/Models/PersonLinks.cs | 19 ++
CoinpaprikaApi/Models/PersonPosition.cs | 19 ++
CoinpaprikaApi/Models/PersonResponse.cs | 28 ++
.../Models/PriceConverterResponse.cs | 32 +++
CoinpaprikaApi/Models/PriceVolume24hPair.cs | 13 +
CoinpaprikaApi/Models/QuoteData.cs | 25 ++
CoinpaprikaApi/Models/SearchCurrency.cs | 31 +++
CoinpaprikaApi/Models/SearchExchange.cs | 19 ++
CoinpaprikaApi/Models/SearchIco.cs | 22 ++
CoinpaprikaApi/Models/SearchPerson.cs | 16 ++
CoinpaprikaApi/Models/SearchResponse.cs | 22 ++
CoinpaprikaApi/Models/SearchTag.cs | 19 ++
CoinpaprikaApi/Models/TagItem.cs | 31 +++
CoinpaprikaApi/Models/TickItem.cs | 20 ++
CoinpaprikaApi/Models/TickerItem.cs | 42 +++
CoinpaprikaApi/Models/TickerQuote.cs | 59 +++++
.../Properties/Resources.Designer.cs | 73 +++++
CoinpaprikaApi/Properties/Resources.resx | 124 +++++++++
CoinpaprikaApi/Types/SearchCategory.cs | 15 ++
CoinpaprikaApi/Types/TickerInterval.cs | 23 ++
README.md | 32 ++-
Tests/CoinsTests.cs | 91 +++++++
Tests/ContractsTests.cs | 41 +++
Tests/ExchangesTests.cs | 32 +++
Tests/GlobalTests.cs | 14 +
Tests/Helpers.cs | 34 +++
Tests/KeyTests.cs | 43 +++
Tests/PersonsTests.cs | 14 +
Tests/TagsTests.cs | 23 ++
Tests/Tests.csproj | 24 ++
Tests/TickersTests.cs | 32 +++
Tests/ToolsTests.cs | 23 ++
Tests/Usings.cs | 3 +
coinpaprika-logo-banner-256x64.png | Bin 0 -> 6811 bytes
coinpaprika-logo-banner.png | Bin 0 -> 13960 bytes
coinpaprika-logo.png | Bin 0 -> 5999 bytes
76 files changed, 3304 insertions(+), 1 deletion(-)
create mode 100644 CoinpaprikaApi.sln
create mode 100644 CoinpaprikaApi/CoinPaprikaClient.cs
create mode 100644 CoinpaprikaApi/CoinpaprikaApi.csproj
create mode 100644 CoinpaprikaApi/Constants.cs
create mode 100644 CoinpaprikaApi/Exceptions/UnknownException.cs
create mode 100644 CoinpaprikaApi/Extensions.cs
create mode 100644 CoinpaprikaApi/Imp/CoinsImp.cs
create mode 100644 CoinpaprikaApi/Imp/ContractsImp.cs
create mode 100644 CoinpaprikaApi/Imp/ExchangesImp.cs
create mode 100644 CoinpaprikaApi/Imp/GlobalImp.cs
create mode 100644 CoinpaprikaApi/Imp/KeyImp.cs
create mode 100644 CoinpaprikaApi/Imp/PersonsImp.cs
create mode 100644 CoinpaprikaApi/Imp/TagsImp.cs
create mode 100644 CoinpaprikaApi/Imp/TickersImp.cs
create mode 100644 CoinpaprikaApi/Imp/ToolsImp.cs
create mode 100644 CoinpaprikaApi/MemCache.cs
create mode 100644 CoinpaprikaApi/Models/CoinEventItem.cs
create mode 100644 CoinpaprikaApi/Models/CoinExchangeItem.cs
create mode 100644 CoinpaprikaApi/Models/CoinItem.cs
create mode 100644 CoinpaprikaApi/Models/CoinLinks.cs
create mode 100644 CoinpaprikaApi/Models/CoinLinksExtendedItem.cs
create mode 100644 CoinpaprikaApi/Models/CoinLinksExtendedItemStats.cs
create mode 100644 CoinpaprikaApi/Models/CoinMarketItem.cs
create mode 100644 CoinpaprikaApi/Models/CoinResponse.cs
create mode 100644 CoinpaprikaApi/Models/CoinTagItem.cs
create mode 100644 CoinpaprikaApi/Models/CoinTeamItem.cs
create mode 100644 CoinpaprikaApi/Models/CoinTweetItem.cs
create mode 100644 CoinpaprikaApi/Models/CoinWhitepaper.cs
create mode 100644 CoinpaprikaApi/Models/ContractData.cs
create mode 100644 CoinpaprikaApi/Models/ExchangeFiat.cs
create mode 100644 CoinpaprikaApi/Models/ExchangeItem.cs
create mode 100644 CoinpaprikaApi/Models/ExchangeMarketItem.cs
create mode 100644 CoinpaprikaApi/Models/GlobalResponse.cs
create mode 100644 CoinpaprikaApi/Models/KeyInfoResponse.cs
create mode 100644 CoinpaprikaApi/Models/KeyUsage.cs
create mode 100644 CoinpaprikaApi/Models/KeyUsageCurrMonth.cs
create mode 100644 CoinpaprikaApi/Models/MarketQuote.cs
create mode 100644 CoinpaprikaApi/Models/NameSymbolPair.cs
create mode 100644 CoinpaprikaApi/Models/OhlcvItem.cs
create mode 100644 CoinpaprikaApi/Models/PersonLink.cs
create mode 100644 CoinpaprikaApi/Models/PersonLinks.cs
create mode 100644 CoinpaprikaApi/Models/PersonPosition.cs
create mode 100644 CoinpaprikaApi/Models/PersonResponse.cs
create mode 100644 CoinpaprikaApi/Models/PriceConverterResponse.cs
create mode 100644 CoinpaprikaApi/Models/PriceVolume24hPair.cs
create mode 100644 CoinpaprikaApi/Models/QuoteData.cs
create mode 100644 CoinpaprikaApi/Models/SearchCurrency.cs
create mode 100644 CoinpaprikaApi/Models/SearchExchange.cs
create mode 100644 CoinpaprikaApi/Models/SearchIco.cs
create mode 100644 CoinpaprikaApi/Models/SearchPerson.cs
create mode 100644 CoinpaprikaApi/Models/SearchResponse.cs
create mode 100644 CoinpaprikaApi/Models/SearchTag.cs
create mode 100644 CoinpaprikaApi/Models/TagItem.cs
create mode 100644 CoinpaprikaApi/Models/TickItem.cs
create mode 100644 CoinpaprikaApi/Models/TickerItem.cs
create mode 100644 CoinpaprikaApi/Models/TickerQuote.cs
create mode 100644 CoinpaprikaApi/Properties/Resources.Designer.cs
create mode 100644 CoinpaprikaApi/Properties/Resources.resx
create mode 100644 CoinpaprikaApi/Types/SearchCategory.cs
create mode 100644 CoinpaprikaApi/Types/TickerInterval.cs
create mode 100644 Tests/CoinsTests.cs
create mode 100644 Tests/ContractsTests.cs
create mode 100644 Tests/ExchangesTests.cs
create mode 100644 Tests/GlobalTests.cs
create mode 100644 Tests/Helpers.cs
create mode 100644 Tests/KeyTests.cs
create mode 100644 Tests/PersonsTests.cs
create mode 100644 Tests/TagsTests.cs
create mode 100644 Tests/Tests.csproj
create mode 100644 Tests/TickersTests.cs
create mode 100644 Tests/ToolsTests.cs
create mode 100644 Tests/Usings.cs
create mode 100644 coinpaprika-logo-banner-256x64.png
create mode 100644 coinpaprika-logo-banner.png
create mode 100644 coinpaprika-logo.png
diff --git a/CoinpaprikaApi.sln b/CoinpaprikaApi.sln
new file mode 100644
index 0000000..ea4ca15
--- /dev/null
+++ b/CoinpaprikaApi.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33209.295
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoinpaprikaApi", "CoinpaprikaApi\CoinpaprikaApi.csproj", "{35E78AC4-6ADB-432C-B8A7-E22A21E02334}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BEBA3D10-2B31-4FCC-9CC1-E417B22E1A0A}"
+ ProjectSection(SolutionItems) = preProject
+ coinpaprika-logo-banner-256x64.png = coinpaprika-logo-banner-256x64.png
+ coinpaprika-logo-banner.png = coinpaprika-logo-banner.png
+ coinpaprika-logo.png = coinpaprika-logo.png
+ LICENSE = LICENSE
+ README.md = README.md
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{5B3BA65B-AC32-4D72-BF5A-8BAD513889DF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {35E78AC4-6ADB-432C-B8A7-E22A21E02334}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {35E78AC4-6ADB-432C-B8A7-E22A21E02334}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {35E78AC4-6ADB-432C-B8A7-E22A21E02334}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {35E78AC4-6ADB-432C-B8A7-E22A21E02334}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5B3BA65B-AC32-4D72-BF5A-8BAD513889DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5B3BA65B-AC32-4D72-BF5A-8BAD513889DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5B3BA65B-AC32-4D72-BF5A-8BAD513889DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5B3BA65B-AC32-4D72-BF5A-8BAD513889DF}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B014F756-BF0E-48BB-9434-CFCF89261804}
+ EndGlobalSection
+EndGlobal
diff --git a/CoinpaprikaApi/CoinPaprikaClient.cs b/CoinpaprikaApi/CoinPaprikaClient.cs
new file mode 100644
index 0000000..c04b804
--- /dev/null
+++ b/CoinpaprikaApi/CoinPaprikaClient.cs
@@ -0,0 +1,249 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-17-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-24-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+using CoinpaprikaApi.Exceptions;
+using CoinpaprikaApi.Imp;
+using Microsoft.Extensions.Logging;
+using RestSharp;
+using System;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi
+{
+ ///
+ /// Create an instance of this class to access the API methods.
+ ///
+ /// Methods and parameters are named as specified in the official
+ /// Coinpaprika API documentation (Ex: API call '/coins'
+ /// translates to 'CoinpaprikaClient.Coins.GetCoinsAsync()').
+ ///
+ /// By default response caching is enabled. To disable it set to false.
+ ///
+ public class CoinpaprikaClient : IDisposable
+ {
+ ///
+ /// The RestSharp client instance used to make the API calls.
+ /// This is exposed in case you wish to change options such as use a proxy.
+ ///
+ /// The RestSharp client instance.
+ public RestClient CPRestClient { get; }
+
+ ///
+ /// Gets or sets whether this instance is using response caching.
+ /// Caching is enabled by default.
+ ///
+ /// true if this instances cache is enabled; otherwise, false.
+ public bool IsCacheEnabled { get { return _cache.Enabled; } set { _cache.Enabled = value; } }
+
+ ///
+ /// Provides access to the Key API calls.
+ /// An instance of .
+ ///
+ /// Key API calls.
+ public KeyImp Key { get; }
+
+ ///
+ /// Provides access to the Global API calls.
+ /// An instance of .
+ ///
+ /// Global API calls.
+ public GlobalImp Global { get; }
+
+ ///
+ /// Provides access to the Coins API calls.
+ /// An instance of .
+ ///
+ /// Coins API calls.
+ public CoinsImp Coins { get; }
+
+ ///
+ /// Provides access to the Persons API calls.
+ /// An instance of .
+ ///
+ /// Persons API calls.
+ public PersonsImp Persons { get; }
+
+ ///
+ /// Provides access to the Tags API calls.
+ /// An instance of .
+ ///
+ /// Tags API calls.
+ public TagsImp Tags { get; }
+
+ ///
+ /// Provides access to the Exchanges API calls.
+ /// An instance of .
+ ///
+ /// Exchanges API calls.
+ public ExchangesImp Exchanges { get; }
+
+ ///
+ /// Provides access to the Tickers API calls.
+ /// An instance of .
+ ///
+ /// Tickers API calls.
+ public TickersImp Tickers { get; }
+
+ ///
+ /// Provides access to the Tools API calls.
+ /// An instance of .
+ ///
+ /// Tools API calls.
+ public ToolsImp Tools { get; }
+
+ ///
+ /// Provides access to the Contracts API calls.
+ /// An instance of .
+ ///
+ /// Contracts API calls.
+ public ContractsImp Contracts { get; }
+
+ private readonly MemCache _cache;
+ private bool _disposedValue;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Using an API key is optional but highly recommended since the free tier is very limited.
+ /// Using a logger is optional but recommended. This can be supplied via dependency injection.
+ ///
+ /// Your API key.
+ /// Your logger.
+ public CoinpaprikaClient(string apiKey = null, ILogger logger = null)
+ {
+ _cache = new MemCache(logger);
+
+
+ if (!string.IsNullOrEmpty(apiKey) && !String.IsNullOrWhiteSpace(apiKey))
+ {
+ CPRestClient = new RestClient(Constants.API_PRO_BASE_URL);
+ CPRestClient.AddDefaultHeader("Authorization", apiKey);
+ }
+ else
+ {
+ CPRestClient = new RestClient(Constants.API_BASE_URL);
+ }
+
+ CPRestClient.AddDefaultHeader("Accept-Encoding", "gzip, deflate, br");
+ CPRestClient.AddDefaultHeader("Accept", "application/json");
+ CPRestClient.AddDefaultHeader("Connection", "keep-alive");
+ CPRestClient.AddDefaultHeader("User-Agent", $"CoinpaprikaApi .NET Client/{Assembly.GetExecutingAssembly().GetName().Version}");
+
+ Key = new KeyImp(CPRestClient, _cache, logger);
+ Global = new GlobalImp(CPRestClient, _cache, logger);
+ Coins = new CoinsImp(CPRestClient, _cache, logger);
+ Persons = new PersonsImp(CPRestClient, _cache, logger);
+ Tags = new TagsImp(CPRestClient, _cache, logger);
+ Exchanges = new ExchangesImp(CPRestClient, _cache, logger);
+ Tickers = new TickersImp(CPRestClient, _cache, logger);
+ Tools = new ToolsImp(CPRestClient, _cache, logger);
+ Contracts = new ContractsImp(CPRestClient, _cache, logger);
+ }
+
+ internal static async Task GetStringResponseAsync(RestClient client, RestRequest request, MemCache cache, ILogger logger, int cacheTime)
+ {
+ var fullUrl = client.BuildUri(request).ToString();
+
+ try
+ {
+ if (cache.TryGet(fullUrl, out var cacheResponse))
+ {
+ return (string)cacheResponse;
+ }
+ }
+ catch (Exception ex)
+ {
+ logger?.LogError(ex, "");
+ }
+
+ try
+ {
+ var response = await client.GetAsync(request);
+
+ if (response.IsSuccessStatusCode)
+ {
+ cache.CacheRequest(fullUrl, response, cacheTime);
+
+ return response.Content;
+ }
+
+ if (response.ErrorException != null)
+ {
+ logger?.LogError(response.ErrorException, "GetStringResponseAsync failed.");
+ throw response.ErrorException;
+ }
+
+ throw new UnknownException($"Unknown exception, http response code is not success, {response.StatusCode}.");
+ }
+ catch (Exception ex)
+ {
+ logger?.LogError(ex, "GetStringResponseAsync request failure.");
+ throw;
+ }
+ }
+
+ internal static string BuildUrl(params string[] parts)
+ {
+ if (parts.Length > 2)
+ {
+ var sb = new StringBuilder();
+ sb.Append("/v").Append(Constants.API_VERSION);
+ foreach (var part in parts)
+ {
+ sb.Append('/');
+ sb.Append(part);
+ }
+ return sb.ToString();
+ }
+ else
+ {
+ var result = $"/v{Constants.API_VERSION}";
+ foreach (var part in parts)
+ {
+ result += $"/{part}";
+ }
+ return result;
+ }
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ if (_cache != null)
+ {
+ try
+ {
+ _cache.Dispose();
+ }
+ catch
+ {
+ // ignore
+ }
+ }
+ }
+
+ _disposedValue = true;
+ }
+ }
+
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/CoinpaprikaApi.csproj b/CoinpaprikaApi/CoinpaprikaApi.csproj
new file mode 100644
index 0000000..c212fe7
--- /dev/null
+++ b/CoinpaprikaApi/CoinpaprikaApi.csproj
@@ -0,0 +1,69 @@
+
+
+
+ netstandard2.0
+ False
+ True
+ 1.7.5.0
+ ByronAP
+ 1.7.5.0
+ 1.7.5.0
+ MIT
+ True
+ latest-recommended
+ https://github.com/ByronAP/CoinpaprikaApi
+ https://github.com/ByronAP/CoinpaprikaApi
+ False
+ README.md
+ coinpaprika-logo.png
+ git
+ Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+ See: https://github.com/ByronAP/CoinpaprikaApi/releases
+ coinpaprika,coinpaprika-api,api,bitcoin,eth,etherium,atom,cosmos,btc,usdt,tether,bnb,usdc,doge,dogecoin,xrp,ripple,ltc,litecoin,crypto,market,price,market-cap,cryptocurrencies,marketcap,netstandard
+ Coinpaprika API Client Library
+ Coinpaprika API Client Library
+
+
+
+ 4
+
+
+
+ 4
+
+
+
+
+ True
+ \
+
+
+ True
+ \
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ PublicResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
diff --git a/CoinpaprikaApi/Constants.cs b/CoinpaprikaApi/Constants.cs
new file mode 100644
index 0000000..0e2d059
--- /dev/null
+++ b/CoinpaprikaApi/Constants.cs
@@ -0,0 +1,43 @@
+using CoinpaprikaApi.Properties;
+
+namespace CoinpaprikaApi
+{
+ public static class Constants
+ {
+ ///
+ /// The display name of the API provider.
+ ///
+ public static readonly string API_NAME = "Coinpaprika";
+
+ ///
+ /// The base API URL.
+ ///
+ public static readonly string API_BASE_URL = "https://api.coinpaprika.com";
+
+ ///
+ /// The base URL for PRO feature calls.
+ ///
+ public static readonly string API_PRO_BASE_URL = "https://api-pro.coinpaprika.com/v1/";
+
+ ///
+ /// The major API version.
+ ///
+ public static readonly uint API_VERSION = 1;
+
+ ///
+ /// The full API version.
+ ///
+ public static readonly string API_VERSION_FULL = "1.7.5";
+
+ ///
+ /// The API logo at 128 X 128 in PNG format.
+ /// This is an embedded resource.
+ ///
+ public static readonly byte[] API_LOGO_128X128_PNG = Resources.coinpaprika_logo;
+
+ ///
+ /// The API minimum cache time in milliseconds.
+ ///
+ public static readonly uint API_MIN_CACHE_TIME_MS = 30000;
+ }
+}
diff --git a/CoinpaprikaApi/Exceptions/UnknownException.cs b/CoinpaprikaApi/Exceptions/UnknownException.cs
new file mode 100644
index 0000000..45170a0
--- /dev/null
+++ b/CoinpaprikaApi/Exceptions/UnknownException.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace CoinpaprikaApi.Exceptions
+{
+ ///
+ /// An exception because I am dumb and don't know WFT it is.
+ /// Implements the
+ ///
+ ///
+ public class UnknownException : Exception
+ {
+ public UnknownException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Extensions.cs b/CoinpaprikaApi/Extensions.cs
new file mode 100644
index 0000000..c0ba7bf
--- /dev/null
+++ b/CoinpaprikaApi/Extensions.cs
@@ -0,0 +1,69 @@
+using CoinpaprikaApi.Types;
+using System;
+using System.Collections.Generic;
+
+namespace CoinpaprikaApi
+{
+ internal static class Extensions
+ {
+ internal static string ToAPIString(this TickerInterval value)
+ {
+ switch (value)
+ {
+ case TickerInterval.m5:
+ return "5m";
+ case TickerInterval.m10:
+ return "10m";
+ case TickerInterval.m15:
+ return "15m";
+ case TickerInterval.m30:
+ return "30m";
+ case TickerInterval.m45:
+ return "45m";
+ case TickerInterval.h1:
+ return "1h";
+ case TickerInterval.h2:
+ return "2h";
+ case TickerInterval.h3:
+ return "3h";
+ case TickerInterval.h6:
+ return "6h";
+ case TickerInterval.h12:
+ return "12h";
+ case TickerInterval.h24:
+ return "24h";
+ case TickerInterval.d1:
+ return "1d";
+ case TickerInterval.d7:
+ return "7d";
+ case TickerInterval.d14:
+ return "14d";
+ case TickerInterval.d30:
+ return "30d";
+ case TickerInterval.d90:
+ return "90d";
+ case TickerInterval.d365:
+ return "365d";
+ default:
+ throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown TickerInterval.");
+ }
+ }
+
+ internal static string[] ToArray(this SearchCategory value)
+ {
+ if (value.HasFlag(SearchCategory.All))
+ {
+ return new string[] { SearchCategory.icos.ToString(), SearchCategory.exchanges.ToString(), SearchCategory.tags.ToString(), SearchCategory.people.ToString(), SearchCategory.currencies.ToString() };
+ }
+
+ var results = new List();
+ if (value.HasFlag(SearchCategory.currencies)) { results.Add(SearchCategory.currencies.ToString()); }
+ if (value.HasFlag(SearchCategory.tags)) { results.Add(SearchCategory.tags.ToString()); }
+ if (value.HasFlag(SearchCategory.people)) { results.Add(SearchCategory.people.ToString()); }
+ if (value.HasFlag(SearchCategory.exchanges)) { results.Add(SearchCategory.exchanges.ToString()); }
+ if (value.HasFlag(SearchCategory.icos)) { results.Add(SearchCategory.icos.ToString()); }
+
+ return results.ToArray();
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/CoinsImp.cs b/CoinpaprikaApi/Imp/CoinsImp.cs
new file mode 100644
index 0000000..3fc8353
--- /dev/null
+++ b/CoinpaprikaApi/Imp/CoinsImp.cs
@@ -0,0 +1,231 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-18-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-24-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+using CoinpaprikaApi.Models;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the '/coins' API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class CoinsImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal CoinsImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get basic information about cryptocurrencies as an asynchronous operation.
+ ///
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ public async Task> GetCoinsAsync()
+ {
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins"));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+ ///
+ /// Get detailed descriptive information about a single coin as an asynchronous operation, without price or volume data. For price data, check the /tickers and /tickers/{coin_id} endpoints.
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ ///
+ /// A Task<> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ public async Task GetCoinAsync(string coin_id)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins", coin_id));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+
+
+ ///
+ /// Get the last 50 timeline tweets from the official Twitter profile for a given coin..
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ public async Task> GetCoinTweetsAsync(string coin_id)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins", coin_id, "twitter"));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+ ///
+ /// Get coin events as an asynchronous operation.
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ public async Task> GetCoinEventsAsync(string coin_id)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins", coin_id, "events"));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+
+ ///
+ /// Get exchanges where a given coin is traded.
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ public async Task> GetCoinExchangesAsync(string coin_id)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins", coin_id, "exchanges"));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+ ///
+ /// Get all available markets for a given coin.
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ /// A list of quotes to return (ex: BTC,USD). Default: USD
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ public async Task> GetCoinMarketsAsync(string coin_id, IEnumerable quotes = null)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ if (quotes == null || !quotes.Any()) { quotes = new[] { "USD" }; }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins", coin_id, "markets"));
+ request.AddQueryParameter("quotes", string.Join(",", quotes));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+
+ ///
+ /// Get Open/High/Low/Close values with volume and market capitalization for the last full day.
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ /// If set to true the quote currency is BTC, otherwise quote currency is USD.
+ ///
+ /// A Task<IEnumerable>> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ public async Task> GetCoinOhlcLatestAsync(string coin_id, bool btc_quote = false)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins", coin_id, "ohlcv", "latest"));
+ if (btc_quote) { request.AddQueryParameter("quote", "btc"); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 1800);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+
+ ///
+ /// Get Open/High/Low/Close values with volume and market capitalization for any date range. If the end date is the current day, data can change with every request until actual close of the day.
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ /// The start start point for historical data.
+ /// The end point for for historical data (max 1 year). If not provided calculated by the limit parameter.
+ /// The limit of result rows (max 366). Default: 1
+ /// If set to true the quote currency is BTC, otherwise quote currency is USD.
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ /// start
+ /// start - Invalid value, start must be a reasonable value.
+ /// end - Invalid value, end must be a maximum of 1 year from start.
+ /// end - Invalid value, end must be greater than start.
+ public async Task> GetCoinOhlcHistoricAsync(string coin_id, DateTimeOffset start, DateTimeOffset? end = null, uint limit = 1, bool btc_quote = false)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ if (start == null) { throw new ArgumentNullException(nameof(start)); }
+ if (start == DateTimeOffset.MinValue || start == DateTimeOffset.MaxValue) { throw new ArgumentOutOfRangeException(nameof(start), "Invalid value, start must be a reasonable value."); }
+ if (end != null && start.AddYears(1) < end) { throw new ArgumentOutOfRangeException(nameof(end), "Invalid value, end must be a maximum of 1 year from start."); }
+ if (end != null && end < start) { throw new ArgumentOutOfRangeException(nameof(end), "Invalid value, end must be greater than start."); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins", coin_id, "ohlcv", "historical"));
+ request.AddQueryParameter("start", start.ToUnixTimeSeconds());
+ if (end != null) { request.AddQueryParameter("end", end.Value.ToUnixTimeSeconds()); }
+ if (btc_quote) { request.AddQueryParameter("quote", "btc"); }
+ if (limit > 1) { request.AddQueryParameter("limit", limit); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+
+ ///
+ /// Get Open/High/Low/Close values with volume and market capitalization for the current day. Data can change every each request until actual close of the day.
+ ///
+ /// The coin identifier (ex: btc-bitcoin)..
+ /// >If set to true the quote currency is BTC, otherwise quote currency is USD.
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ public async Task> GetCoinOhlcTodayAsync(string coin_id, bool btc_quote = false)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("coins", coin_id, "ohlcv", "today"));
+ if (btc_quote) { request.AddQueryParameter("quote", "btc"); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/ContractsImp.cs b/CoinpaprikaApi/Imp/ContractsImp.cs
new file mode 100644
index 0000000..d90fd0e
--- /dev/null
+++ b/CoinpaprikaApi/Imp/ContractsImp.cs
@@ -0,0 +1,137 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-24-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-24-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+using CoinpaprikaApi.Models;
+using CoinpaprikaApi.Types;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the '/contracts' API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class ContractsImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal ContractsImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get all available contract platforms.
+ ///
+ ///
+ /// A Task<IEnumerable<string>> representing the asynchronous operation.
+ public async Task> GetPlatformsAsync()
+ {
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("contracts"));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+
+ ///
+ /// Get all available contracts for a given platform.
+ ///
+ /// The platform identifier.
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ ///
+ /// platform_id - Invalid value, platform_id must be a valid platform identified (ex: eth-ethereum)
+ public async Task> GetContractsAsync(string platform_id)
+ {
+ if (string.IsNullOrEmpty(platform_id) || string.IsNullOrWhiteSpace(platform_id)) { throw new ArgumentNullException(nameof(platform_id), "Invalid value, platform_id must be a valid platform identified (ex: eth-ethereum)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("contracts", platform_id));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+
+ ///
+ /// Get ticker data for a contract with a given address..
+ ///
+ /// The platform identifier.
+ /// The contract address (ex: 0xd26114cd6ee289accf82350c8d8487fedb8a0c07).
+ /// A Task<> representing the asynchronous operation.
+ ///
+ /// platform_id - Invalid value, platform_id must be a valid platform identified (ex: eth-ethereum)
+ /// contract_address - Invalid value, contract_address must be a valid smart contract identified (ex: 0xd26114cd6ee289accf82350c8d8487fedb8a0c07)
+ public async Task GetTickerByContractAddressAsync(string platform_id, string contract_address)
+ {
+ if (string.IsNullOrEmpty(platform_id) || string.IsNullOrWhiteSpace(platform_id)) { throw new ArgumentNullException(nameof(platform_id), "Invalid value, platform_id must be a valid platform identified (ex: eth-ethereum)"); }
+ if (string.IsNullOrEmpty(contract_address) || string.IsNullOrWhiteSpace(contract_address)) { throw new ArgumentNullException(nameof(contract_address), "Invalid value, contract_address must be a valid smart contract identified (ex: 0xd26114cd6ee289accf82350c8d8487fedb8a0c07)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("contracts", platform_id, contract_address));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+
+
+ ///
+ /// Get historical ticks for a contract with a given address.
+ ///
+ /// The platform identifier.
+ /// The contract address (ex: 0xd26114cd6ee289accf82350c8d8487fedb8a0c07).
+ /// The start start point for historical data.
+ /// The end point for for historical data.
+ /// The limit of result rows (max 5000). Default: 1000
+ /// Set to true to use BTC as quote currency, else quote is USD.
+ /// The bucket interval.
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ ///
+ /// platform_id - Invalid value, platform_id must be a valid platform identified (ex: eth-ethereum)
+ /// contract_address - Invalid value, contract_address must be a valid smart contract identified (ex: 0xd26114cd6ee289accf82350c8d8487fedb8a0c07)
+ /// end - Invalid value, end must be a valid date after start.
+ public async Task> GetHistoricalTicksByContractAddressAsync(string platform_id, string contract_address, DateTimeOffset start, DateTimeOffset? end = null, uint limit = 1000, bool quote_btc = false, TickerInterval interval = TickerInterval.m5)
+ {
+ if (string.IsNullOrEmpty(platform_id) || string.IsNullOrWhiteSpace(platform_id)) { throw new ArgumentNullException(nameof(platform_id), "Invalid value, platform_id must be a valid platform identified (ex: eth-ethereum)"); }
+ if (string.IsNullOrEmpty(contract_address) || string.IsNullOrWhiteSpace(contract_address)) { throw new ArgumentNullException(nameof(contract_address), "Invalid value, contract_address must be a valid smart contract identified (ex: 0xd26114cd6ee289accf82350c8d8487fedb8a0c07)"); }
+
+ if (end != null && end <= start) { throw new ArgumentOutOfRangeException(nameof(end), "Invalid value, end must be a valid date after start."); }
+
+ if (end != null && end > DateTimeOffset.UtcNow) { end = null; }
+
+ if (limit > 5000) { limit = 5000; }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("contracts", platform_id, contract_address, "historical"));
+ request.AddParameter("start", start.ToUnixTimeSeconds());
+ if (end != null) { request.AddParameter("end", end.Value.ToUnixTimeSeconds()); }
+ if (limit != 1000 && limit != 0) { request.AddParameter("limit", limit); }
+ if (quote_btc) { request.AddParameter("quote", "btc"); }
+ request.AddParameter("interval", interval.ToAPIString());
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/ExchangesImp.cs b/CoinpaprikaApi/Imp/ExchangesImp.cs
new file mode 100644
index 0000000..3852273
--- /dev/null
+++ b/CoinpaprikaApi/Imp/ExchangesImp.cs
@@ -0,0 +1,98 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-24-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-24-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+using CoinpaprikaApi.Models;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the '/exchanges' API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class ExchangesImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal ExchangesImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get basic information about exchanges.
+ ///
+ /// A list of quotes to return. Currently allowed values: BTC, ETH, USD, EUR, PLN, KRW, GBP, CAD, JPY, RUB, TRY, NZD, AUD, CHF, UAH, HKD, SGD, NGN, PHP, MXN, BRL, THB, CLP, CNY, CZK, DKK, HUF, IDR, ILS, INR, MYR, NOK, PKR, SEK, TWD, ZAR, VND, BOB, COP, PEN, ARS, ISK. Default: USD
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ public async Task> GetExchangesAsync(IEnumerable quotes = null)
+ {
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("exchanges"));
+ if (quotes != null) { request.AddParameter("quotes", string.Join(",", quotes)); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+ ///
+ /// Get basic information about a given exchange.
+ ///
+ /// The exchange identifier (ex: binance).
+ /// A list of quotes to return. Currently allowed values: BTC, ETH, USD, EUR, PLN, KRW, GBP, CAD, JPY, RUB, TRY, NZD, AUD, CHF, UAH, HKD, SGD, NGN, PHP, MXN, BRL, THB, CLP, CNY, CZK, DKK, HUF, IDR, ILS, INR, MYR, NOK, PKR, SEK, TWD, ZAR, VND, BOB, COP, PEN, ARS, ISK. Default: USD
+ /// A Task<> representing the asynchronous operation.
+ /// exchange_id - Invalid value, exchange_id must be a valid exchange identified (ex: binance)
+ ///
+ public async Task GetExchangeAsync(string exchange_id, IEnumerable quotes = null)
+ {
+ if (string.IsNullOrEmpty(exchange_id) || string.IsNullOrWhiteSpace(exchange_id)) { throw new ArgumentNullException(nameof(exchange_id), "Invalid value, exchange_id must be a valid exchange identified (ex: binance)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("exchanges", exchange_id));
+ if (quotes != null) { request.AddParameter("quotes", string.Join(",", quotes)); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+
+ ///
+ /// Get a list of all available markets on a given exchange.
+ ///
+ /// The exchange identifier (ex: binance).
+ /// A list of quotes to return. Currently allowed values: BTC, ETH, USD, EUR, PLN, KRW, GBP, CAD, JPY, RUB, TRY, NZD, AUD, CHF, UAH, HKD, SGD, NGN, PHP, MXN, BRL, THB, CLP, CNY, CZK, DKK, HUF, IDR, ILS, INR, MYR, NOK, PKR, SEK, TWD, ZAR, VND, BOB, COP, PEN, ARS, ISK. Default: USD
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ /// exchange_id - Invalid value, exchange_id must be a valid exchange identified (ex: binance)
+ ///
+ public async Task> GetExchangeMarketsAsync(string exchange_id, IEnumerable quotes = null)
+ {
+ if (string.IsNullOrEmpty(exchange_id) || string.IsNullOrWhiteSpace(exchange_id)) { throw new ArgumentNullException(nameof(exchange_id), "Invalid value, exchange_id must be a valid exchange identified (ex: binance)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("exchanges", exchange_id, "markets"));
+ if (quotes != null) { request.AddParameter("quotes", string.Join(",", quotes)); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/GlobalImp.cs b/CoinpaprikaApi/Imp/GlobalImp.cs
new file mode 100644
index 0000000..5113282
--- /dev/null
+++ b/CoinpaprikaApi/Imp/GlobalImp.cs
@@ -0,0 +1,55 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-18-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-18-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+
+using CoinpaprikaApi.Models;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the '/global' API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class GlobalImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal GlobalImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get market overview data as an asynchronous operation.
+ ///
+ ///
+ /// A Task<> representing the asynchronous operation.
+ public async Task GetGlobalAsync()
+ {
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("global"));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 240);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/KeyImp.cs b/CoinpaprikaApi/Imp/KeyImp.cs
new file mode 100644
index 0000000..eb80584
--- /dev/null
+++ b/CoinpaprikaApi/Imp/KeyImp.cs
@@ -0,0 +1,60 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-18-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-18-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+using CoinpaprikaApi.Models;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the '/key' API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class KeyImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal KeyImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get API key information.
+ ///
+ /// A Task<> representing the asynchronous operation.
+ /// 403 forbidden error code: 1020
+ ///
+ public async Task GetKeyInfoAsync()
+ {
+ if (!_restClient.Options.BaseUrl.Equals(Constants.API_PRO_BASE_URL))
+ {
+ throw new HttpRequestException("403 forbidden error code: 1020");
+ }
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("key", "info"));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 30);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/PersonsImp.cs b/CoinpaprikaApi/Imp/PersonsImp.cs
new file mode 100644
index 0000000..25d25c9
--- /dev/null
+++ b/CoinpaprikaApi/Imp/PersonsImp.cs
@@ -0,0 +1,56 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-23-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-23-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+using CoinpaprikaApi.Models;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the '/persons' API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class PersonsImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal PersonsImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get information about a person with the specified ID, related to the cryptocurrency market. Using this endpoint you can get a description of the person, social media links, number of teams she or he is involved in and the positions in those teams.
+ /// Always check that the error field of the response is not null or empty. If the person was not found the error field will have data.
+ ///
+ /// The person identifier (name) (ex: vitalik-buterin).
+ ///
+ /// A Task<> representing the asynchronous operation.
+ public async Task GetPersonAsync(string person_id)
+ {
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("people", person_id));
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 1800);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/TagsImp.cs b/CoinpaprikaApi/Imp/TagsImp.cs
new file mode 100644
index 0000000..0b9d305
--- /dev/null
+++ b/CoinpaprikaApi/Imp/TagsImp.cs
@@ -0,0 +1,98 @@
+using CoinpaprikaApi.Models;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the '/tags' API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class TagsImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal TagsImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get basic information about cryptocurrencies tags (categories).
+ ///
+ /// If set to true coin list will be included.
+ /// If set to true icos list will be included.
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ public async Task> GetTagsAsync(bool include_coins = false, bool include_icos = false)
+ {
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("tags"));
+ if (include_coins && include_icos)
+ {
+ request.AddQueryParameter("additional_fields", "coins,icos");
+ }
+ else
+ {
+ if (include_coins)
+ {
+ request.AddQueryParameter("additional_fields", "coins");
+ }
+
+ if (include_icos)
+ {
+ request.AddQueryParameter("additional_fields", "icos");
+ }
+ }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 1800);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+ ///
+ /// Get information about a given cryptocurrency tag.
+ ///
+ /// The tag identifier (ex: blockchain-service).
+ /// If set to true coin list will be included.
+ /// If set to true icos list will be included.
+ ///
+ /// A Task<> representing the asynchronous operation.
+ /// tag_id - Invalid value, tag_id must be a valid tag identified (ex: blockchain-service)
+ public async Task GetTagAsync(string tag_id, bool include_coins = false, bool include_icos = false)
+ {
+ if (string.IsNullOrEmpty(tag_id) || string.IsNullOrWhiteSpace(tag_id)) { throw new ArgumentNullException(nameof(tag_id), "Invalid value, tag_id must be a valid tag identified (ex: blockchain-service)"); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("tags", tag_id));
+ if (include_coins && include_icos)
+ {
+ request.AddQueryParameter("additional_fields", "coins,icos");
+ }
+ else
+ {
+ if (include_coins)
+ {
+ request.AddQueryParameter("additional_fields", "coins");
+ }
+
+ if (include_icos)
+ {
+ request.AddQueryParameter("additional_fields", "icos");
+ }
+ }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 1800);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/TickersImp.cs b/CoinpaprikaApi/Imp/TickersImp.cs
new file mode 100644
index 0000000..3777f1d
--- /dev/null
+++ b/CoinpaprikaApi/Imp/TickersImp.cs
@@ -0,0 +1,123 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-23-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-23-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+
+using CoinpaprikaApi.Models;
+using CoinpaprikaApi.Types;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the '/tickers' API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class TickersImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal TickersImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get price data of all active cryptocurrencies. Free plan is limited to 2500 results.
+ ///
+ /// A list of quotes to return. Up to 3 quotes at once. Currently allowed values: BTC, ETH, USD, EUR, PLN, KRW, GBP, CAD, JPY, RUB, TRY, NZD, AUD, CHF, UAH, HKD, SGD, NGN, PHP, MXN, BRL, THB, CLP, CNY, CZK, DKK, HUF, IDR, ILS, INR, MYR, NOK, PKR, SEK, TWD, ZAR, VND, BOB, COP, PEN, ARS, ISK. Default: USD
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ public async Task> GetTickersAsync(IEnumerable quotes = null)
+ {
+ if (quotes != null && quotes.Count() > 3) { quotes = quotes.Take(3); };
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("tickers"));
+
+ if (quotes != null) { request.AddParameter("quotes", string.Join(",", quotes)); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+
+ ///
+ /// Get price data of a single cryptocurrency.
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ /// A list of quotes to return. Up to 3 quotes at once. Currently allowed values: BTC, ETH, USD, EUR, PLN, KRW, GBP, CAD, JPY, RUB, TRY, NZD, AUD, CHF, UAH, HKD, SGD, NGN, PHP, MXN, BRL, THB, CLP, CNY, CZK, DKK, HUF, IDR, ILS, INR, MYR, NOK, PKR, SEK, TWD, ZAR, VND, BOB, COP, PEN, ARS, ISK. Default: USD
+ ///
+ /// A Task<> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ public async Task GetTickerAsync(string coin_id, IEnumerable quotes = null)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ if (quotes != null && quotes.Count() > 3) { quotes = quotes.Take(3); };
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("tickers", coin_id));
+
+ if (quotes != null) { request.AddParameter("quotes", string.Join(",", quotes)); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+
+ ///
+ /// Get historical values of price, volume_24h, market_cap for a given cryptocurrency.
+ ///
+ /// The coin identifier (ex: btc-bitcoin).
+ /// The start start point for historical data.
+ /// The end point for for historical data.
+ /// The limit of result rows (max 5000). Default: 1000
+ /// Set to true to use BTC as quote currency, else quote is USD.
+ /// The bucket interval.
+ ///
+ /// A Task<IEnumerable<>> representing the asynchronous operation.
+ /// coin_id - Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)
+ /// end - Invalid value, end must be a valid date after start.
+ public async Task> GetHistoricalTicksAsync(string coin_id, DateTimeOffset start, DateTimeOffset? end = null, uint limit = 1000, bool quote_btc = false, TickerInterval interval = TickerInterval.m5)
+ {
+ if (string.IsNullOrEmpty(coin_id) || string.IsNullOrWhiteSpace(coin_id)) { throw new ArgumentNullException(nameof(coin_id), "Invalid value, coin_id must be a valid coin identified (ex: btc-bitcoin)"); }
+
+ if (end != null && end <= start) { throw new ArgumentOutOfRangeException(nameof(end), "Invalid value, end must be a valid date after start."); }
+
+ if (end != null && end > DateTimeOffset.UtcNow) { end = null; }
+
+ if (limit > 5000) { limit = 5000; }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("tickers", coin_id, "historical"));
+
+ request.AddParameter("start", start.ToUnixTimeSeconds());
+ if (end != null) { request.AddParameter("end", end.Value.ToUnixTimeSeconds()); }
+ if (limit != 1000 && limit != 0) { request.AddParameter("limit", limit); }
+ if (quote_btc) { request.AddParameter("quote", "btc"); }
+ request.AddParameter("interval", interval.ToAPIString());
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 150);
+
+ return JsonConvert.DeserializeObject>(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Imp/ToolsImp.cs b/CoinpaprikaApi/Imp/ToolsImp.cs
new file mode 100644
index 0000000..2094f9d
--- /dev/null
+++ b/CoinpaprikaApi/Imp/ToolsImp.cs
@@ -0,0 +1,96 @@
+// ***********************************************************************
+// Assembly : CoinpaprikaApi
+// Author : ByronAP
+// Created : 12-24-2022
+//
+// Last Modified By : ByronAP
+// Last Modified On : 12-24-2022
+// ***********************************************************************
+//
+// Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
+//
+// ***********************************************************************
+using CoinpaprikaApi.Models;
+using CoinpaprikaApi.Types;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using RestSharp;
+using System;
+using System.Threading.Tasks;
+
+namespace CoinpaprikaApi.Imp
+{
+ ///
+ /// Implementation of the Tools API calls.
+ /// Implementation classes do not have a public constructor
+ /// and must be accessed through an instance of .
+ ///
+ ///
+ public class ToolsImp
+ {
+ private readonly RestClient _restClient;
+ private readonly ILogger _logger;
+ private readonly MemCache _cache;
+
+ internal ToolsImp(RestClient restClient, MemCache cache, ILogger logger)
+ {
+ _logger = logger;
+ _cache = cache;
+ _restClient = restClient;
+ }
+
+ ///
+ /// Get currencies, exchanges, icos, people, tags for a given search query.
+ ///
+ /// The query term / phrase for search (ex: eth).
+ /// One or more categories to search. Default: all
+ /// If set to true search only by symbol (works for currencies only).
+ /// The limit of results per category (max 250). Default: 6
+ ///
+ /// A Task<> representing the asynchronous operation.
+ /// query - Invalid value, query must be a valid search term (phrase).
+ public async Task SearchAsync(string query, SearchCategory categories = SearchCategory.All, bool symbol_search = false, uint limit = 6)
+ {
+ if (string.IsNullOrEmpty(query) || string.IsNullOrWhiteSpace(query)) { throw new ArgumentNullException(nameof(query), "Invalid value, query must be a valid search term (phrase)."); }
+
+ if (limit <= 0) { limit = 1; }
+
+ if (limit > 250) { limit = 250; }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("search"));
+ request.AddParameter("q", query);
+ if (categories != SearchCategory.All) { request.AddParameter("c", string.Join(",", categories.ToArray())); }
+ if (symbol_search) { request.AddParameter("modifier", "symbol_search"); }
+ if (limit != 6) { request.AddParameter("limit", limit); }
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+
+ ///
+ /// Converts a set amount of base currency to quote currency.
+ ///
+ /// The base currency identifier.
+ /// The quote currency identifier.
+ /// The amount.
+ ///
+ /// A Task<> representing the asynchronous operation.
+ /// base_currency_id - Invalid value, base_currency_id must be a valid currency id.
+ /// quote_currency_id - Invalid value, quote_currency_id must be a valid currency id.
+ public async Task PriceConvertAsync(string base_currency_id, string quote_currency_id, decimal amount)
+ {
+ if (string.IsNullOrEmpty(base_currency_id) || string.IsNullOrWhiteSpace(base_currency_id)) { throw new ArgumentNullException(nameof(base_currency_id), "Invalid value, base_currency_id must be a valid currency id."); }
+ if (string.IsNullOrEmpty(quote_currency_id) || string.IsNullOrWhiteSpace(quote_currency_id)) { throw new ArgumentNullException(nameof(quote_currency_id), "Invalid value, quote_currency_id must be a valid currency id."); }
+
+ var request = new RestRequest(CoinpaprikaClient.BuildUrl("price-converter"));
+ request.AddParameter("base_currency_id", base_currency_id);
+ request.AddParameter("quote_currency_id", quote_currency_id);
+ request.AddParameter("amount", amount);
+
+ var jsonStr = await CoinpaprikaClient.GetStringResponseAsync(_restClient, request, _cache, _logger, 90);
+
+ return JsonConvert.DeserializeObject(jsonStr);
+ }
+ }
+}
diff --git a/CoinpaprikaApi/MemCache.cs b/CoinpaprikaApi/MemCache.cs
new file mode 100644
index 0000000..367aa27
--- /dev/null
+++ b/CoinpaprikaApi/MemCache.cs
@@ -0,0 +1,132 @@
+using Microsoft.Extensions.Logging;
+using RestSharp;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Caching;
+
+namespace CoinpaprikaApi
+{
+ internal class MemCache : IDisposable
+ {
+ internal bool Enabled { get; set; } = true;
+
+ private readonly ILogger _logger;
+ private readonly List _keys;
+ private readonly MemoryCache _cache;
+ private readonly object _lockObject;
+
+ internal MemCache(ILogger logger)
+ {
+ _logger = logger;
+ _cache = new MemoryCache("response-cache");
+ _keys = new List();
+ _lockObject = new object();
+ }
+
+ private void CacheRemovedCallback(CacheEntryRemovedArguments arguments)
+ {
+ lock (_lockObject)
+ {
+ _keys.Remove(arguments.CacheItem.Key);
+ }
+ }
+
+ internal bool Contains(string key) => _cache.Contains(key);
+
+ internal bool TryGet(string key, out object value)
+ {
+ if (!Enabled)
+ {
+ _logger?.LogDebug("Cache Disabled for URL: {Key}", key);
+
+ value = null;
+ return false;
+ }
+
+ if (_cache.Contains(key))
+ {
+ _logger?.LogDebug("Cache Hit for URL: {Key}", key);
+
+ value = _cache.Get(key);
+ return true;
+ }
+ else
+ {
+ _logger?.LogDebug("Cache Miss for URL: {Key}", key);
+ value = null;
+ return false;
+ }
+ }
+
+ internal void CacheRequest(string key, RestResponse response, int cacheSeconds)
+ {
+ if (!Enabled) { return; }
+
+ var data = response.Content;
+
+ if (!string.IsNullOrEmpty(data) && !string.IsNullOrWhiteSpace(data))
+ {
+ if (cacheSeconds <= Constants.API_MIN_CACHE_TIME_MS / 1000) { cacheSeconds = Convert.ToInt16(Constants.API_MIN_CACHE_TIME_MS / 1000); }
+
+ var expiry = DateTimeOffset.UtcNow.AddSeconds(cacheSeconds);
+
+ if (expiry < DateTimeOffset.UtcNow.AddMinutes(4))
+ {
+ Set(key, data, expiry);
+ _logger?.LogDebug("Cache Set Expires in: {Expiry} seconds for URL: {Key}", cacheSeconds, key);
+ }
+ else
+ {
+ _logger?.LogWarning("The expires is far in the future. Expiry: {Expiry}, URL: {FullUrl}", expiry, key);
+ }
+ }
+ }
+
+ private void Set(string key, object value, DateTimeOffset exp)
+ {
+ lock (_lockObject)
+ {
+ var cacheItem = new CacheItem(key, value);
+ var policy = new CacheItemPolicy
+ {
+ AbsoluteExpiration = exp
+ };
+ policy.RemovedCallback += CacheRemovedCallback;
+
+ _cache.Set(cacheItem, policy);
+
+ if (!_keys.Contains(key)) { _keys.Add(key); }
+ }
+ }
+
+ internal void Clear()
+ {
+ lock (_lockObject)
+ {
+ var keys = _keys.ToArray();
+ foreach (var key in keys)
+ {
+ try
+ {
+ _cache.Remove(key);
+ }
+ catch
+ {
+ // ignore
+ }
+ }
+
+ try
+ {
+ _keys.Clear();
+ }
+ catch
+ {
+ // ignore
+ }
+ }
+ }
+
+ public void Dispose() => _cache.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/CoinpaprikaApi/Models/CoinEventItem.cs b/CoinpaprikaApi/Models/CoinEventItem.cs
new file mode 100644
index 0000000..84886e6
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinEventItem.cs
@@ -0,0 +1,32 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinEventItem
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("date")]
+ public DateTimeOffset? Date { get; set; }
+
+ [JsonProperty("date_to")]
+ public DateTimeOffset? DateTo { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("is_conference")]
+ public bool IsConference { get; set; }
+
+ [JsonProperty("link")]
+ public string Link { get; set; }
+
+ [JsonProperty("proof_image_link")]
+ public string ProofImageLink { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinExchangeItem.cs b/CoinpaprikaApi/Models/CoinExchangeItem.cs
new file mode 100644
index 0000000..a5391be
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinExchangeItem.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinExchangeItem
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("adjusted_volume_24h_share")]
+ public double AdjustedVolume24HShare { get; set; }
+
+ [JsonProperty("fiats")]
+ public NameSymbolPair[] Fiats { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinItem.cs b/CoinpaprikaApi/Models/CoinItem.cs
new file mode 100644
index 0000000..7eaac3f
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinItem.cs
@@ -0,0 +1,28 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinItem
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("symbol")]
+ public string Symbol { get; set; }
+
+ [JsonProperty("rank")]
+ public int Rank { get; set; }
+
+ [JsonProperty("is_new")]
+ public bool IsNew { get; set; }
+
+ [JsonProperty("is_active")]
+ public bool IsActive { get; set; }
+
+ [JsonProperty("type")]
+ public string Type { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinLinks.cs b/CoinpaprikaApi/Models/CoinLinks.cs
new file mode 100644
index 0000000..700ffc6
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinLinks.cs
@@ -0,0 +1,28 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinLinks
+ {
+ [JsonProperty("explorer")]
+ public string[] Explorer { get; set; }
+
+ [JsonProperty("facebook")]
+ public string[] Facebook { get; set; }
+
+ [JsonProperty("reddit")]
+ public string[] Reddit { get; set; }
+
+ [JsonProperty("source_code")]
+ public string[] SourceCode { get; set; }
+
+ [JsonProperty("website")]
+ public string[] Website { get; set; }
+
+ [JsonProperty("youtube")]
+ public string[] Youtube { get; set; }
+
+ [JsonProperty("medium")]
+ public string[] Medium { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinLinksExtendedItem.cs b/CoinpaprikaApi/Models/CoinLinksExtendedItem.cs
new file mode 100644
index 0000000..27e924c
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinLinksExtendedItem.cs
@@ -0,0 +1,16 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinLinksExtendedItem
+ {
+ [JsonProperty("url")]
+ public string Url { get; set; }
+
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("stats", NullValueHandling = NullValueHandling.Ignore)]
+ public CoinLinksExtendedItemStats Stats { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinLinksExtendedItemStats.cs b/CoinpaprikaApi/Models/CoinLinksExtendedItemStats.cs
new file mode 100644
index 0000000..13f7a4f
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinLinksExtendedItemStats.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinLinksExtendedItemStats
+ {
+ [JsonProperty("subscribers", NullValueHandling = NullValueHandling.Ignore)]
+ public long? Subscribers { get; set; }
+
+ [JsonProperty("contributors", NullValueHandling = NullValueHandling.Ignore)]
+ public long? Contributors { get; set; }
+
+ [JsonProperty("stars", NullValueHandling = NullValueHandling.Ignore)]
+ public long? Stars { get; set; }
+
+ [JsonProperty("followers", NullValueHandling = NullValueHandling.Ignore)]
+ public long? Followers { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinMarketItem.cs b/CoinpaprikaApi/Models/CoinMarketItem.cs
new file mode 100644
index 0000000..46dc04d
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinMarketItem.cs
@@ -0,0 +1,54 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinMarketItem
+ {
+ [JsonProperty("exchange_id")]
+ public string ExchangeId { get; set; }
+
+ [JsonProperty("exchange_name")]
+ public string ExchangeName { get; set; }
+
+ [JsonProperty("pair")]
+ public string Pair { get; set; }
+
+ [JsonProperty("base_currency_id")]
+ public string BaseCurrencyId { get; set; }
+
+ [JsonProperty("base_currency_name")]
+ public string BaseCurrencyName { get; set; }
+
+ [JsonProperty("quote_currency_id")]
+ public string QuoteCurrencyId { get; set; }
+
+ [JsonProperty("quote_currency_name")]
+ public string QuoteCurrencyName { get; set; }
+
+ [JsonProperty("market_url")]
+ public string MarketUrl { get; set; }
+
+ [JsonProperty("category")]
+ public string Category { get; set; }
+
+ [JsonProperty("fee_type")]
+ public string FeeType { get; set; }
+
+ [JsonProperty("outlier")]
+ public bool Outlier { get; set; }
+
+ [JsonProperty("adjusted_volume_24h_share")]
+ public double AdjustedVolume24HShare { get; set; }
+
+ [JsonProperty("quotes")]
+ public Dictionary Quotes { get; set; }
+
+ [JsonProperty("trust_score")]
+ public string TrustScore { get; set; }
+
+ [JsonProperty("last_updated")]
+ public DateTimeOffset LastUpdated { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinResponse.cs b/CoinpaprikaApi/Models/CoinResponse.cs
new file mode 100644
index 0000000..c968a0c
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinResponse.cs
@@ -0,0 +1,80 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinResponse
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("symbol")]
+ public string Symbol { get; set; }
+
+ [JsonProperty("rank")]
+ public int Rank { get; set; }
+
+ [JsonProperty("is_new")]
+ public bool IsNew { get; set; }
+
+ [JsonProperty("is_active")]
+ public bool IsActive { get; set; }
+
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("logo")]
+ public string Logo { get; set; }
+
+ [JsonProperty("tags")]
+ public CoinTagItem[] Tags { get; set; }
+
+ [JsonProperty("team")]
+ public CoinTeamItem[] Team { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("message")]
+ public string Message { get; set; }
+
+ [JsonProperty("open_source")]
+ public bool OpenSource { get; set; }
+
+ [JsonProperty("started_at")]
+ public DateTimeOffset? StartedAt { get; set; }
+
+ [JsonProperty("development_status")]
+ public string DevelopmentStatus { get; set; }
+
+ [JsonProperty("hardware_wallet")]
+ public bool HardwareWallet { get; set; }
+
+ [JsonProperty("proof_type")]
+ public string ProofType { get; set; }
+
+ [JsonProperty("org_structure")]
+ public string OrgStructure { get; set; }
+
+ [JsonProperty("hash_algorithm")]
+ public string HashAlgorithm { get; set; }
+
+ [JsonProperty("links")]
+ public CoinLinks Links { get; set; }
+
+ [JsonProperty("links_extended")]
+ public CoinLinksExtendedItem[] LinksExtended { get; set; }
+
+ [JsonProperty("whitepaper")]
+ public CoinWhitepaper Whitepaper { get; set; }
+
+ [JsonProperty("first_data_at")]
+ public DateTimeOffset? FirstDataAt { get; set; }
+
+ [JsonProperty("last_data_at")]
+ public DateTimeOffset? LastDataAt { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinTagItem.cs b/CoinpaprikaApi/Models/CoinTagItem.cs
new file mode 100644
index 0000000..a79aa29
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinTagItem.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinTagItem
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("coin_counter")]
+ public int? CoinCounter { get; set; }
+
+ [JsonProperty("ico_counter")]
+ public int? IcoCounter { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinTeamItem.cs b/CoinpaprikaApi/Models/CoinTeamItem.cs
new file mode 100644
index 0000000..fa633dc
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinTeamItem.cs
@@ -0,0 +1,16 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinTeamItem
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("position")]
+ public string Position { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinTweetItem.cs b/CoinpaprikaApi/Models/CoinTweetItem.cs
new file mode 100644
index 0000000..ffb0b68
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinTweetItem.cs
@@ -0,0 +1,41 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinTweetItem
+ {
+ [JsonProperty("date")]
+ public DateTimeOffset Date { get; set; }
+
+ [JsonProperty("user_name")]
+ public string UserName { get; set; }
+
+ [JsonProperty("user_image_link")]
+ public string UserImageLink { get; set; }
+
+ [JsonProperty("status")]
+ public string Status { get; set; }
+
+ [JsonProperty("is_retweet")]
+ public bool IsRetweet { get; set; }
+
+ [JsonProperty("retweet_count")]
+ public int? RetweetCount { get; set; }
+
+ [JsonProperty("like_count")]
+ public int? LikeCount { get; set; }
+
+ [JsonProperty("status_link")]
+ public string StatusLink { get; set; }
+
+ [JsonProperty("status_id")]
+ public string StatusId { get; set; }
+
+ [JsonProperty("media_link", NullValueHandling = NullValueHandling.Ignore)]
+ public string MediaLink { get; set; }
+
+ [JsonProperty("youtube_link", NullValueHandling = NullValueHandling.Ignore)]
+ public string YoutubeLink { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/CoinWhitepaper.cs b/CoinpaprikaApi/Models/CoinWhitepaper.cs
new file mode 100644
index 0000000..7bfd7be
--- /dev/null
+++ b/CoinpaprikaApi/Models/CoinWhitepaper.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class CoinWhitepaper
+ {
+ [JsonProperty("link")]
+ public string Link { get; set; }
+
+ [JsonProperty("thumbnail")]
+ public string Thumbnail { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/ContractData.cs b/CoinpaprikaApi/Models/ContractData.cs
new file mode 100644
index 0000000..af51364
--- /dev/null
+++ b/CoinpaprikaApi/Models/ContractData.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class ContractItem
+ {
+ [JsonProperty("address")]
+ public string Address { get; set; }
+
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("active")]
+ public bool Active { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/ExchangeFiat.cs b/CoinpaprikaApi/Models/ExchangeFiat.cs
new file mode 100644
index 0000000..4d432af
--- /dev/null
+++ b/CoinpaprikaApi/Models/ExchangeFiat.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class ExchangeFiat
+ {
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("symbol")]
+ public string Symbol { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/ExchangeItem.cs b/CoinpaprikaApi/Models/ExchangeItem.cs
new file mode 100644
index 0000000..4eb235d
--- /dev/null
+++ b/CoinpaprikaApi/Models/ExchangeItem.cs
@@ -0,0 +1,63 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+
+namespace CoinpaprikaApi.Models
+{
+ public class ExchangeItem
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("active")]
+ public bool Active { get; set; }
+
+ [JsonProperty("website_status")]
+ public bool WebsiteStatus { get; set; }
+
+ [JsonProperty("api_status")]
+ public bool ApiStatus { get; set; }
+
+ [JsonProperty("message")]
+ public string Message { get; set; }
+
+ [JsonProperty("links")]
+ public Dictionary Links { get; set; }
+
+ [JsonProperty("markets_data_fetched")]
+ public bool MarketsDataFetched { get; set; }
+
+ [JsonProperty("adjusted_rank", NullValueHandling = NullValueHandling.Ignore)]
+ public int? AdjustedRank { get; set; }
+
+ [JsonProperty("reported_rank", NullValueHandling = NullValueHandling.Ignore)]
+ public int? ReportedRank { get; set; }
+
+ [JsonProperty("currencies")]
+ public int Currencies { get; set; }
+
+ [JsonProperty("markets")]
+ public int Markets { get; set; }
+
+ [JsonProperty("fiats")]
+ public ExchangeFiat[] Fiats { get; set; }
+
+ [JsonProperty("quotes")]
+ public Dictionary Quotes { get; set; }
+
+ [JsonProperty("last_updated")]
+ public DateTimeOffset LastUpdated { get; set; }
+
+ [JsonProperty("confidence_score")]
+ public double ConfidenceScore { get; set; }
+
+ [JsonProperty("sessions_per_month", NullValueHandling = NullValueHandling.Ignore)]
+ public long? SessionsPerMonth { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/ExchangeMarketItem.cs b/CoinpaprikaApi/Models/ExchangeMarketItem.cs
new file mode 100644
index 0000000..d44f593
--- /dev/null
+++ b/CoinpaprikaApi/Models/ExchangeMarketItem.cs
@@ -0,0 +1,48 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+
+namespace CoinpaprikaApi.Models
+{
+ public class ExchangeMarketItem
+ {
+ [JsonProperty("pair")]
+ public string Pair { get; set; }
+
+ [JsonProperty("base_currency_id")]
+ public string BaseCurrencyId { get; set; }
+
+ [JsonProperty("base_currency_name")]
+ public string BaseCurrencyName { get; set; }
+
+ [JsonProperty("quote_currency_id")]
+ public string QuoteCurrencyId { get; set; }
+
+ [JsonProperty("quote_currency_name")]
+ public string QuoteCurrencyName { get; set; }
+
+ [JsonProperty("market_url")]
+ public string MarketUrl { get; set; }
+
+ [JsonProperty("category")]
+ public string Category { get; set; }
+
+ [JsonProperty("fee_type")]
+ public string FeeType { get; set; }
+
+ [JsonProperty("outlier")]
+ public bool Outlier { get; set; }
+
+ [JsonProperty("reported_volume_24h_share")]
+ public double ReportedVolume24HShare { get; set; }
+
+ [JsonProperty("quotes")]
+ public Dictionary Quotes { get; set; }
+
+ [JsonProperty("trust_score")]
+ public string TrustScore { get; set; }
+
+ [JsonProperty("last_updated")]
+ public DateTimeOffset LastUpdated { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/GlobalResponse.cs b/CoinpaprikaApi/Models/GlobalResponse.cs
new file mode 100644
index 0000000..ac0c7e7
--- /dev/null
+++ b/CoinpaprikaApi/Models/GlobalResponse.cs
@@ -0,0 +1,47 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class GlobalResponse
+ {
+ [JsonProperty("market_cap_usd")]
+ public long MarketCapUsd { get; set; }
+
+ [JsonProperty("volume_24h_usd")]
+ public long Volume24HUsd { get; set; }
+
+ [JsonProperty("bitcoin_dominance_percentage")]
+ public decimal BitcoinDominancePercentage { get; set; }
+
+ [JsonProperty("cryptocurrencies_number")]
+ public int CryptocurrenciesNumber { get; set; }
+
+ [JsonProperty("market_cap_ath_value")]
+ public long MarketCapAthValue { get; set; }
+
+ [JsonProperty("market_cap_ath_date")]
+ public DateTimeOffset? MarketCapAthDate { get; set; }
+
+ [JsonProperty("volume_24h_ath_value")]
+ public long Volume24HAthValue { get; set; }
+
+ [JsonProperty("volume_24h_ath_date")]
+ public DateTimeOffset? Volume24HAthDate { get; set; }
+
+ [JsonProperty("volume_24h_percent_from_ath")]
+ public decimal Volume24HPercentFromAth { get; set; }
+
+ [JsonProperty("volume_24h_percent_to_ath")]
+ public decimal Volume24HPercentToAth { get; set; }
+
+ [JsonProperty("market_cap_change_24h")]
+ public decimal MarketCapChange24H { get; set; }
+
+ [JsonProperty("volume_24h_change_24h")]
+ public decimal Volume24HChange24H { get; set; }
+
+ [JsonProperty("last_updated")]
+ public long LastUpdated { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/KeyInfoResponse.cs b/CoinpaprikaApi/Models/KeyInfoResponse.cs
new file mode 100644
index 0000000..a01ef93
--- /dev/null
+++ b/CoinpaprikaApi/Models/KeyInfoResponse.cs
@@ -0,0 +1,23 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class KeyInfoResponse
+ {
+ [JsonProperty("plan")]
+ public string Plan { get; set; }
+
+ [JsonProperty("plan_started_at")]
+ public DateTimeOffset? PlanStartedAt { get; set; }
+
+ [JsonProperty("plan_status")]
+ public string PlanStatus { get; set; }
+
+ [JsonProperty("portal_url")]
+ public string PortalUrl { get; set; }
+
+ [JsonProperty("usage")]
+ public KeyUsage Usage { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/KeyUsage.cs b/CoinpaprikaApi/Models/KeyUsage.cs
new file mode 100644
index 0000000..bba2ec6
--- /dev/null
+++ b/CoinpaprikaApi/Models/KeyUsage.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class KeyUsage
+ {
+ [JsonProperty("message")]
+ public string Message { get; set; }
+
+ [JsonProperty("current_month")]
+ public KeyUsageCurrMonth CurrentMonth { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/KeyUsageCurrMonth.cs b/CoinpaprikaApi/Models/KeyUsageCurrMonth.cs
new file mode 100644
index 0000000..c5b2d1a
--- /dev/null
+++ b/CoinpaprikaApi/Models/KeyUsageCurrMonth.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class KeyUsageCurrMonth
+ {
+ [JsonProperty("requests_made")]
+ public int? RequestsMade { get; set; }
+
+ [JsonProperty("requests_left")]
+ public int? RequestsLeft { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/MarketQuote.cs b/CoinpaprikaApi/Models/MarketQuote.cs
new file mode 100644
index 0000000..4f29024
--- /dev/null
+++ b/CoinpaprikaApi/Models/MarketQuote.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class MarketQuote
+ {
+ [JsonProperty("price")]
+ public decimal Price { get; set; }
+
+ [JsonProperty("volume_24h")]
+ public double Volume24H { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/NameSymbolPair.cs b/CoinpaprikaApi/Models/NameSymbolPair.cs
new file mode 100644
index 0000000..72b0c48
--- /dev/null
+++ b/CoinpaprikaApi/Models/NameSymbolPair.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class NameSymbolPair
+ {
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("symbol")]
+ public string Symbol { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/OhlcvItem.cs b/CoinpaprikaApi/Models/OhlcvItem.cs
new file mode 100644
index 0000000..3384799
--- /dev/null
+++ b/CoinpaprikaApi/Models/OhlcvItem.cs
@@ -0,0 +1,32 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class OhlcvItem
+ {
+ [JsonProperty("time_open")]
+ public DateTimeOffset? TimeOpen { get; set; }
+
+ [JsonProperty("time_close")]
+ public DateTimeOffset? TimeClose { get; set; }
+
+ [JsonProperty("open")]
+ public decimal? Open { get; set; }
+
+ [JsonProperty("high")]
+ public decimal? High { get; set; }
+
+ [JsonProperty("low")]
+ public decimal? Low { get; set; }
+
+ [JsonProperty("close")]
+ public decimal? Close { get; set; }
+
+ [JsonProperty("volume")]
+ public long Volume { get; set; }
+
+ [JsonProperty("market_cap")]
+ public long MarketCap { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/PersonLink.cs b/CoinpaprikaApi/Models/PersonLink.cs
new file mode 100644
index 0000000..c9510cd
--- /dev/null
+++ b/CoinpaprikaApi/Models/PersonLink.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class PersonLink
+ {
+ [JsonProperty("url")]
+ public string Url { get; set; }
+
+ [JsonProperty("followers")]
+ public int? Followers { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/PersonLinks.cs b/CoinpaprikaApi/Models/PersonLinks.cs
new file mode 100644
index 0000000..df245cd
--- /dev/null
+++ b/CoinpaprikaApi/Models/PersonLinks.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class PersonLinks
+ {
+ [JsonProperty("github")]
+ public PersonLink[] Github { get; set; }
+
+ [JsonProperty("linkedin")]
+ public PersonLink[] Linkedin { get; set; }
+
+ [JsonProperty("medium")]
+ public PersonLink[] Medium { get; set; }
+
+ [JsonProperty("twitter")]
+ public PersonLink[] Twitter { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/PersonPosition.cs b/CoinpaprikaApi/Models/PersonPosition.cs
new file mode 100644
index 0000000..ca3a850
--- /dev/null
+++ b/CoinpaprikaApi/Models/PersonPosition.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class PersonPosition
+ {
+ [JsonProperty("coin_id")]
+ public string CoinId { get; set; }
+
+ [JsonProperty("coin_name")]
+ public string CoinName { get; set; }
+
+ [JsonProperty("coin_symbol")]
+ public string CoinSymbol { get; set; }
+
+ [JsonProperty("position")]
+ public string PositionPosition { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/PersonResponse.cs b/CoinpaprikaApi/Models/PersonResponse.cs
new file mode 100644
index 0000000..9b6e111
--- /dev/null
+++ b/CoinpaprikaApi/Models/PersonResponse.cs
@@ -0,0 +1,28 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class PersonResponse
+ {
+ [JsonProperty("error")]
+ public string Error { get; set; }
+
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("teams_count")]
+ public int TeamsCount { get; set; }
+
+ [JsonProperty("links")]
+ public PersonLinks Links { get; set; }
+
+ [JsonProperty("positions")]
+ public PersonPosition[] Positions { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/PriceConverterResponse.cs b/CoinpaprikaApi/Models/PriceConverterResponse.cs
new file mode 100644
index 0000000..e3190a2
--- /dev/null
+++ b/CoinpaprikaApi/Models/PriceConverterResponse.cs
@@ -0,0 +1,32 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class PriceConverterResponse
+ {
+ [JsonProperty("base_currency_id")]
+ public string BaseCurrencyId { get; set; }
+
+ [JsonProperty("base_currency_name")]
+ public string BaseCurrencyName { get; set; }
+
+ [JsonProperty("base_price_last_updated")]
+ public DateTimeOffset BasePriceLastUpdated { get; set; }
+
+ [JsonProperty("quote_currency_id")]
+ public string QuoteCurrencyId { get; set; }
+
+ [JsonProperty("quote_currency_name")]
+ public string QuoteCurrencyName { get; set; }
+
+ [JsonProperty("quote_price_last_updated")]
+ public DateTimeOffset QuotePriceLastUpdated { get; set; }
+
+ [JsonProperty("amount")]
+ public decimal Amount { get; set; }
+
+ [JsonProperty("price")]
+ public decimal Price { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/PriceVolume24hPair.cs b/CoinpaprikaApi/Models/PriceVolume24hPair.cs
new file mode 100644
index 0000000..0b115e7
--- /dev/null
+++ b/CoinpaprikaApi/Models/PriceVolume24hPair.cs
@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class PriceVolume24hPair
+ {
+ [JsonProperty("price")]
+ public double Price { get; set; }
+
+ [JsonProperty("volume_24h")]
+ public double Volume24H { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/QuoteData.cs b/CoinpaprikaApi/Models/QuoteData.cs
new file mode 100644
index 0000000..f4bf54b
--- /dev/null
+++ b/CoinpaprikaApi/Models/QuoteData.cs
@@ -0,0 +1,25 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class QuoteData
+ {
+ [JsonProperty("reported_volume_24h")]
+ public double ReportedVolume24H { get; set; }
+
+ [JsonProperty("adjusted_volume_24h")]
+ public double AdjustedVolume24H { get; set; }
+
+ [JsonProperty("reported_volume_7d")]
+ public double ReportedVolume7D { get; set; }
+
+ [JsonProperty("adjusted_volume_7d")]
+ public double AdjustedVolume7D { get; set; }
+
+ [JsonProperty("reported_volume_30d")]
+ public double ReportedVolume30D { get; set; }
+
+ [JsonProperty("adjusted_volume_30d")]
+ public double AdjustedVolume30D { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/SearchCurrency.cs b/CoinpaprikaApi/Models/SearchCurrency.cs
new file mode 100644
index 0000000..965c523
--- /dev/null
+++ b/CoinpaprikaApi/Models/SearchCurrency.cs
@@ -0,0 +1,31 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class SearchCurrency
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("symbol")]
+ public string Symbol { get; set; }
+
+ [JsonProperty("rank")]
+ public int Rank { get; set; }
+
+ [JsonProperty("is_new")]
+ public bool IsNew { get; set; }
+
+ [JsonProperty("is_active")]
+ public bool IsActive { get; set; }
+
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("rev")]
+ public long Rev { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/SearchExchange.cs b/CoinpaprikaApi/Models/SearchExchange.cs
new file mode 100644
index 0000000..fff0a7a
--- /dev/null
+++ b/CoinpaprikaApi/Models/SearchExchange.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class SearchExchange
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("rank")]
+ public int Rank { get; set; }
+
+ [JsonProperty("rev")]
+ public long Rev { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/SearchIco.cs b/CoinpaprikaApi/Models/SearchIco.cs
new file mode 100644
index 0000000..934df6c
--- /dev/null
+++ b/CoinpaprikaApi/Models/SearchIco.cs
@@ -0,0 +1,22 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class SearchIco
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("symbol")]
+ public string Symbol { get; set; }
+
+ [JsonProperty("is_new")]
+ public bool IsNew { get; set; }
+
+ [JsonProperty("rev")]
+ public long Rev { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/SearchPerson.cs b/CoinpaprikaApi/Models/SearchPerson.cs
new file mode 100644
index 0000000..8e921de
--- /dev/null
+++ b/CoinpaprikaApi/Models/SearchPerson.cs
@@ -0,0 +1,16 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class SearchPerson
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("teams_count")]
+ public int TeamsCount { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/SearchResponse.cs b/CoinpaprikaApi/Models/SearchResponse.cs
new file mode 100644
index 0000000..e336a49
--- /dev/null
+++ b/CoinpaprikaApi/Models/SearchResponse.cs
@@ -0,0 +1,22 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class SearchResponse
+ {
+ [JsonProperty("currencies")]
+ public SearchCurrency[] Currencies { get; set; }
+
+ [JsonProperty("exchanges")]
+ public SearchExchange[] Exchanges { get; set; }
+
+ [JsonProperty("icos")]
+ public SearchIco[] Icos { get; set; }
+
+ [JsonProperty("people")]
+ public SearchPerson[] People { get; set; }
+
+ [JsonProperty("tags")]
+ public SearchTag[] Tags { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/SearchTag.cs b/CoinpaprikaApi/Models/SearchTag.cs
new file mode 100644
index 0000000..c0cd252
--- /dev/null
+++ b/CoinpaprikaApi/Models/SearchTag.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class SearchTag
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("coin_counter")]
+ public int CoinCounter { get; set; }
+
+ [JsonProperty("ico_counter")]
+ public int IcoCounter { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/TagItem.cs b/CoinpaprikaApi/Models/TagItem.cs
new file mode 100644
index 0000000..b1a0ce6
--- /dev/null
+++ b/CoinpaprikaApi/Models/TagItem.cs
@@ -0,0 +1,31 @@
+using Newtonsoft.Json;
+
+namespace CoinpaprikaApi.Models
+{
+ public class TagItem
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("description")]
+ public string Description { get; set; }
+
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("coin_counter", NullValueHandling = NullValueHandling.Ignore)]
+ public int CoinCounter { get; set; }
+
+ [JsonProperty("ico_counter", NullValueHandling = NullValueHandling.Ignore)]
+ public int IcoCounter { get; set; }
+
+ [JsonProperty("coins", NullValueHandling = NullValueHandling.Ignore)]
+ public string[] Coins { get; set; }
+
+ [JsonProperty("icos", NullValueHandling = NullValueHandling.Ignore)]
+ public string[] Icos { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/TickItem.cs b/CoinpaprikaApi/Models/TickItem.cs
new file mode 100644
index 0000000..fd404b9
--- /dev/null
+++ b/CoinpaprikaApi/Models/TickItem.cs
@@ -0,0 +1,20 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class TickItem
+ {
+ [JsonProperty("timestamp")]
+ public DateTimeOffset Timestamp { get; set; }
+
+ [JsonProperty("price")]
+ public decimal Price { get; set; }
+
+ [JsonProperty("volume_24h")]
+ public long Volume24H { get; set; }
+
+ [JsonProperty("market_cap")]
+ public long MarketCap { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/TickerItem.cs b/CoinpaprikaApi/Models/TickerItem.cs
new file mode 100644
index 0000000..9ceb09d
--- /dev/null
+++ b/CoinpaprikaApi/Models/TickerItem.cs
@@ -0,0 +1,42 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+
+namespace CoinpaprikaApi.Models
+{
+ public class TickerItem
+ {
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("symbol")]
+ public string Symbol { get; set; }
+
+ [JsonProperty("rank")]
+ public int Rank { get; set; }
+
+ [JsonProperty("circulating_supply")]
+ public double CirculatingSupply { get; set; }
+
+ [JsonProperty("total_supply")]
+ public double TotalSupply { get; set; }
+
+ [JsonProperty("max_supply")]
+ public double MaxSupply { get; set; }
+
+ [JsonProperty("beta_value")]
+ public double BetaValue { get; set; }
+
+ [JsonProperty("first_data_at")]
+ public DateTimeOffset FirstDataAt { get; set; }
+
+ [JsonProperty("last_updated")]
+ public DateTimeOffset LastUpdated { get; set; }
+
+ [JsonProperty("quotes")]
+ public Dictionary Quotes { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Models/TickerQuote.cs b/CoinpaprikaApi/Models/TickerQuote.cs
new file mode 100644
index 0000000..fe61536
--- /dev/null
+++ b/CoinpaprikaApi/Models/TickerQuote.cs
@@ -0,0 +1,59 @@
+using Newtonsoft.Json;
+using System;
+
+namespace CoinpaprikaApi.Models
+{
+ public class TickerQuote
+ {
+ [JsonProperty("price")]
+ public decimal Price { get; set; }
+
+ [JsonProperty("volume_24h")]
+ public double Volume24H { get; set; }
+
+ [JsonProperty("volume_24h_change_24h")]
+ public double Volume24HChange24H { get; set; }
+
+ [JsonProperty("market_cap")]
+ public long MarketCap { get; set; }
+
+ [JsonProperty("market_cap_change_24h")]
+ public double MarketCapChange24H { get; set; }
+
+ [JsonProperty("percent_change_15m")]
+ public double PercentChange15M { get; set; }
+
+ [JsonProperty("percent_change_30m")]
+ public double PercentChange30M { get; set; }
+
+ [JsonProperty("percent_change_1h")]
+ public double PercentChange1H { get; set; }
+
+ [JsonProperty("percent_change_6h")]
+ public double PercentChange6H { get; set; }
+
+ [JsonProperty("percent_change_12h")]
+ public double PercentChange12H { get; set; }
+
+ [JsonProperty("percent_change_24h")]
+ public double PercentChange24H { get; set; }
+
+ [JsonProperty("percent_change_7d")]
+ public double PercentChange7D { get; set; }
+
+ [JsonProperty("percent_change_30d")]
+ public double PercentChange30D { get; set; }
+
+ [JsonProperty("percent_change_1y")]
+ public double PercentChange1Y { get; set; }
+
+ [JsonProperty("ath_price")]
+ public decimal AthPrice { get; set; }
+
+ [JsonProperty("ath_date")]
+ public DateTimeOffset AthDate { get; set; }
+
+ [JsonProperty("percent_from_price_ath")]
+ public double PercentFromPriceAth { get; set; }
+ }
+}
diff --git a/CoinpaprikaApi/Properties/Resources.Designer.cs b/CoinpaprikaApi/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..8cd961e
--- /dev/null
+++ b/CoinpaprikaApi/Properties/Resources.Designer.cs
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace CoinpaprikaApi.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ public class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CoinpaprikaApi.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ public static byte[] coinpaprika_logo {
+ get {
+ object obj = ResourceManager.GetObject("coinpaprika-logo", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+ }
+}
diff --git a/CoinpaprikaApi/Properties/Resources.resx b/CoinpaprikaApi/Properties/Resources.resx
new file mode 100644
index 0000000..b11ca06
--- /dev/null
+++ b/CoinpaprikaApi/Properties/Resources.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\..\coinpaprika-logo.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/CoinpaprikaApi/Types/SearchCategory.cs b/CoinpaprikaApi/Types/SearchCategory.cs
new file mode 100644
index 0000000..fd85932
--- /dev/null
+++ b/CoinpaprikaApi/Types/SearchCategory.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace CoinpaprikaApi.Types
+{
+ [Flags]
+ public enum SearchCategory
+ {
+ All = 0,
+ currencies = 1,
+ exchanges = 2,
+ icos = 4,
+ people = 8,
+ tags = 16
+ }
+}
diff --git a/CoinpaprikaApi/Types/TickerInterval.cs b/CoinpaprikaApi/Types/TickerInterval.cs
new file mode 100644
index 0000000..f830862
--- /dev/null
+++ b/CoinpaprikaApi/Types/TickerInterval.cs
@@ -0,0 +1,23 @@
+namespace CoinpaprikaApi.Types
+{
+ public enum TickerInterval
+ {
+ m5,
+ m10,
+ m15,
+ m30,
+ m45,
+ h1,
+ h2,
+ h3,
+ h6,
+ h12,
+ h24,
+ d1,
+ d7,
+ d14,
+ d30,
+ d90,
+ d365
+ }
+}
diff --git a/README.md b/README.md
index d512161..89fa44c 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,31 @@
-# CoinpaprikaApi
\ No newline at end of file
+# CoinpaprikaApi
+![Coinpaprika Logo](https://raw.githubusercontent.com/ByronAP/CoinpaprikaApi/dev/coinpaprika-logo-banner-256x64.png)
+## Coinpaprika API Library for .NET
+
+[![Nuget](https://img.shields.io/nuget/v/CoinpaprikaAPI)](https://www.nuget.org/packages/CoinpaprikaAPI)
+[![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/ByronAP)
+
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4597bd69581d4039ae591a161fa43f83)](https://www.codacy.com/gh/ByronAP/CoinpaprikaApi/dashboard?utm_source=github.com&utm_medium=referral&utm_content=ByronAP/CoinpaprikaApi&utm_campaign=Badge_Grade)
+[![CodeQL](https://github.com/ByronAP/CoinpaprikaApi/actions/workflows/codeql.yml/badge.svg)](https://github.com/ByronAP/CoinpaprikaApi/actions/workflows/codeql.yml)
+[![Tests](https://github.com/ByronAP/CoinpaprikaApi/actions/workflows/dev_test_dotnet.yml/badge.svg)](https://github.com/ByronAP/CoinpaprikaApi/actions/workflows/dev_test_dotnet.yml)
+
+[Coinpaprika API Documentation](https://api.coinpaprika.com/)
+
+[Library Documentation](https://byronap.github.io/CoinpaprikaApi_docs)
+
+### Features
+
++ Supports all API calls (except changelog)
++ Method names and locations match API
++ Concrete classes
++ Fully asynchronous
++ Compatible with dependency injection and logging
++ Integrated response caching
++ Easier to use then other libraries
++ Changelog endpoint is not implemented (no way for me to test)
+
+
+Warning: If you don't have an API key Coinpaprika has a ridiculously low rate limit.
+
+
+Just create an instance of 'CoinpaprikaClient' and start making calls.
diff --git a/Tests/CoinsTests.cs b/Tests/CoinsTests.cs
new file mode 100644
index 0000000..a98d6f1
--- /dev/null
+++ b/Tests/CoinsTests.cs
@@ -0,0 +1,91 @@
+namespace Tests
+{
+ public class Tests
+ {
+ [Test]
+ public async Task GetCoinsTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinsAsync();
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+
+ var eosItem = callResult.FirstOrDefault(x => x.Id.Equals("eos-eos", StringComparison.InvariantCultureIgnoreCase));
+
+ Assert.That(eosItem, Is.Not.Null);
+ Assert.That(eosItem.Name, Is.EqualTo("EOS"));
+ }
+
+ [Test]
+ public async Task GetCoinTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinAsync("eos-eos");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Name, Is.EqualTo("EOS"));
+ }
+
+ [Test]
+ public async Task GetCoinTweetsTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinTweetsAsync("btc-bitcoin");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetCoinEventsTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinEventsAsync("btc-bitcoin");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetCoinExchangesTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinExchangesAsync("btc-bitcoin");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetCoinMarketsTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinMarketsAsync("btc-bitcoin");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetCoinOhlcLatestTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcLatestAsync("btc-bitcoin");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetCoinOhlcHistoricTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcHistoricAsync("btc-bitcoin", DateTimeOffset.UtcNow.AddDays(-1));
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetCoinOhlcTodayTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcTodayAsync("btc-bitcoin");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Tests/ContractsTests.cs b/Tests/ContractsTests.cs
new file mode 100644
index 0000000..b70ea88
--- /dev/null
+++ b/Tests/ContractsTests.cs
@@ -0,0 +1,41 @@
+namespace Tests
+{
+ internal class ContractsTests
+ {
+ [Test]
+ public async Task GetPlatformsTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Contracts.GetPlatformsAsync();
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetContractsTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Contracts.GetContractsAsync("eth-ethereum");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetTickerByContractAddressTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Contracts.GetTickerByContractAddressAsync("eth-ethereum", "0xd26114cd6ee289accf82350c8d8487fedb8a0c07");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Quotes, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetHistoricalTicksByContractAddressTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Contracts.GetHistoricalTicksByContractAddressAsync("eth-ethereum", "0xd26114cd6ee289accf82350c8d8487fedb8a0c07", DateTimeOffset.UtcNow.AddDays(-5), interval: CoinpaprikaApi.Types.TickerInterval.d1);
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ }
+}
diff --git a/Tests/ExchangesTests.cs b/Tests/ExchangesTests.cs
new file mode 100644
index 0000000..661b191
--- /dev/null
+++ b/Tests/ExchangesTests.cs
@@ -0,0 +1,32 @@
+namespace Tests
+{
+ internal class ExchangesTests
+ {
+ [Test]
+ public async Task GetExchangesTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangesAsync();
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetExchangeTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangeAsync("binance");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Quotes, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetExchangeMarketsTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangeMarketsAsync("binance");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ }
+}
diff --git a/Tests/GlobalTests.cs b/Tests/GlobalTests.cs
new file mode 100644
index 0000000..5c27aef
--- /dev/null
+++ b/Tests/GlobalTests.cs
@@ -0,0 +1,14 @@
+namespace Tests
+{
+ internal class GlobalTests
+ {
+ [Test]
+ public async Task GetGlobalTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Global.GetGlobalAsync();
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.MarketCapUsd, Is.GreaterThan(1));
+ }
+ }
+}
diff --git a/Tests/Helpers.cs b/Tests/Helpers.cs
new file mode 100644
index 0000000..23e8e3b
--- /dev/null
+++ b/Tests/Helpers.cs
@@ -0,0 +1,34 @@
+namespace Tests
+{
+ internal static class Helpers
+ {
+ private const uint API_CALL_INTERVAL_SECONDS = 10;
+
+ private static CoinpaprikaClient? _apiClient = null;
+ private static DateTimeOffset _lastCallTime = DateTimeOffset.MinValue;
+
+ internal static async Task GetApiClient()
+ {
+ if (_apiClient == null)
+ {
+ var factory = LoggerFactory.Create(x =>
+ {
+ x.AddConsole();
+ x.SetMinimumLevel(LogLevel.Debug);
+ });
+ var logger = factory.CreateLogger();
+
+ _apiClient = new CoinpaprikaClient(logger: logger);
+ }
+
+ if (_lastCallTime.AddSeconds(API_CALL_INTERVAL_SECONDS) >= DateTimeOffset.UtcNow)
+ {
+ await Task.Delay(_lastCallTime.AddSeconds(API_CALL_INTERVAL_SECONDS) - DateTimeOffset.UtcNow); ;
+ }
+
+ _lastCallTime = DateTimeOffset.UtcNow;
+
+ return _apiClient;
+ }
+ }
+}
diff --git a/Tests/KeyTests.cs b/Tests/KeyTests.cs
new file mode 100644
index 0000000..ca3786a
--- /dev/null
+++ b/Tests/KeyTests.cs
@@ -0,0 +1,43 @@
+namespace Tests
+{
+ internal class KeyTests
+ {
+ [Test]
+ public async Task GetKeyInfoTest()
+ {
+ // I don't have an API key so I can only test failure
+
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Key.GetKeyInfoAsync();
+ }
+ catch (HttpRequestException ex)
+ {
+ if (!ex.Message.Contains("forbidden", StringComparison.InvariantCultureIgnoreCase))
+ {
+ Assert.Fail();
+ }
+ }
+
+ await Task.Delay(10000);
+
+ using CoinpaprikaClient tmpClient = new("AFakeApiKey");
+
+ try
+ {
+ var callResult = await tmpClient.Key.GetKeyInfoAsync();
+ }
+ catch (HttpRequestException ex)
+ {
+ if (!ex.Message.Contains("forbidden", StringComparison.InvariantCultureIgnoreCase))
+ {
+ Assert.Fail();
+ }
+ }
+
+ await Task.Delay(10000);
+
+ Assert.Pass();
+ }
+ }
+}
diff --git a/Tests/PersonsTests.cs b/Tests/PersonsTests.cs
new file mode 100644
index 0000000..1a8d918
--- /dev/null
+++ b/Tests/PersonsTests.cs
@@ -0,0 +1,14 @@
+namespace Tests
+{
+ internal class PersonsTests
+ {
+ [Test]
+ public async Task GetPersonTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Persons.GetPersonAsync("vitalik-buterin");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Id, Is.EqualTo("vitalik-buterin"));
+ }
+ }
+}
diff --git a/Tests/TagsTests.cs b/Tests/TagsTests.cs
new file mode 100644
index 0000000..7070e97
--- /dev/null
+++ b/Tests/TagsTests.cs
@@ -0,0 +1,23 @@
+namespace Tests
+{
+ internal class TagsTests
+ {
+ [Test]
+ public async Task GetTagsTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tags.GetTagsAsync();
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetTagTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tags.GetTagAsync("blockchain-service", true, true);
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Coins, Is.Not.Empty);
+ }
+ }
+}
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
new file mode 100644
index 0000000..261ae3c
--- /dev/null
+++ b/Tests/Tests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/TickersTests.cs b/Tests/TickersTests.cs
new file mode 100644
index 0000000..184c9bf
--- /dev/null
+++ b/Tests/TickersTests.cs
@@ -0,0 +1,32 @@
+namespace Tests
+{
+ internal class TickersTests
+ {
+ [Test]
+ public async Task GetTickersTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tickers.GetTickersAsync();
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetTickerTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tickers.GetTickerAsync("btc-bitcoin");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Quotes, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task GetHistoricalTicksTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tickers.GetHistoricalTicksAsync("btc-bitcoin", DateTimeOffset.UtcNow.AddDays(-5), interval: CoinpaprikaApi.Types.TickerInterval.d1);
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ }
+}
diff --git a/Tests/ToolsTests.cs b/Tests/ToolsTests.cs
new file mode 100644
index 0000000..25f6927
--- /dev/null
+++ b/Tests/ToolsTests.cs
@@ -0,0 +1,23 @@
+namespace Tests
+{
+ internal class ToolsTests
+ {
+ [Test]
+ public async Task SearchTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tools.SearchAsync("btc");
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Currencies, Is.Not.Empty);
+ }
+
+ [Test]
+ public async Task PriceConvertTest()
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tools.PriceConvertAsync("eth-ethereum", "btc-bitcoin", 100);
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Price, Is.GreaterThan(1));
+ }
+ }
+}
diff --git a/Tests/Usings.cs b/Tests/Usings.cs
new file mode 100644
index 0000000..f20ee4e
--- /dev/null
+++ b/Tests/Usings.cs
@@ -0,0 +1,3 @@
+global using CoinpaprikaApi;
+global using Microsoft.Extensions.Logging;
+global using NUnit.Framework;
\ No newline at end of file
diff --git a/coinpaprika-logo-banner-256x64.png b/coinpaprika-logo-banner-256x64.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a065e08c76cbb0154c91a64284783691d86b17f
GIT binary patch
literal 6811
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
#O~IIas}^m7L~yc}J
z8N+YrxzrDMtL8lT+<_8!%@g;$4Gz~t$7~b*lnUzD&`vwHZ2eaGa;iCxslKj@xq0V3*p64|BXxD*ZM#xAGo@&xBp|C5eqvz-`o#^c@Y
zG~oMKZT-MZrs3L-r77{3t?a?{d3UdQvV8;28*}(@FFSRcHmBUAH3*=
z>4A33_1=!@@Ez}T?8dY@>|_A^vl6D&(?K?IeW^qu@I>h4^yGGc^`h2UkxA
z>FntsyL&pw8kl3`iPUSJ+~8aXJChM`*W%p9;XF~tuYr^4&elHv?tGmZ-HFnES8Ybj
z^M^qg2oWFzf&dXvIC%n~6t$oJBSUc<`;SAatwV6l4KUJa80krbH{OE!&p(dQ
z=ejqa|Ng(eDb?1_DSfyq2m-VV7Z7c2{qeG|{^_64Y!=Kg(ELP)XA%EW(4_+_EIDf!
z*2nCam(zgNwP>Xb3j~Z(Wcv1@aB4uw9o+v62?YWBD?JMcX2$*z`^ZQCUQeZ9Ois>v
ze}UIT`M4}FCEAz#HCZSus0e110Yre5tOdZs`KpPoB?2bEk
zMQ_`5Mv!I5b#;(yYZta%A3m-iEDQsf^7scJ1cT5nod0tE`0;m`VSHGOM8K%AAk9ue
z5MWGCqN&bTN<0J*0t#4BZOOd-
z=D%oTW1k_i0;0%^ll7-*fMKBKfwo7OAn1jYC*Yoxgm&8&!0N|q@GHJ#b|UGmN*za6~h|
z4?rQrqF}lvQ?+nM@$|rFjmgQ!^@)iFh!Vtj+_d)>gZK%7J~oE*NwfgprP)Fk|ccJ^^FCMTgZH^0>I*b|TCjvWKd7fiFmhYugF@MHkYFoI$z
zWaiNe0!S!is?n5!7Sxq$dT^zXs0AoRzW=28;ZRY87`4)S7m@G*z{sQ_Mj|hV*5CAT
zW*DHk9Ed1Xd_RE?A6FwhsY8rL_R@U5)OKbJAOu7bA%w$#t^<@pj7C9Z*(A2b^s*B(
z$AISZ2)3;GMR48vKcuRvv7%bl?LDZACe{!E!#KydY{Zw0Qo?i;L7
zFvEYox8H}4is4Dwp>-QZBe&mimlz3OFeWF>A1^m;aVkHN#e>mXKXkX;(C|H`>sF}m
zGWXAik1GtG3_u$mg1lnok=jpv`gWzR?gg69gK3v3o=ynBD5zQlAp~-==6ivrrdF}0
z<~62iR%W43{XTqDi!!=B0WIV~6y;24!}?DIS6%ygB1tFgwAw{u1h%bjP>A8c-oVP0
z_bSVme~THqPF20sJ&F8_41(Lj0
z)*#ajFiisiI}~2K?u(I)H$T91{S~U~W$qmG;loFznBBWa00#3Lengh@q3dt>yFhc}
zdZoVZyFwr^L<@OPwRq`~0867_h5?(o2tnnb6b*e%PS)Hk*3|sOe6CM@_S=UKAD4#8
z?*kwN%+O)vav-uYDAz}ylni4x)wHcfI`g=Z$=pZP0$@;(KmbIvuKQwaI*Pyx?Wsf|
zVltR)7DONrqcKB>MxK`&oBop!bZZySgHZ}rEL!Z!m-;?@%opZ%Aqb_QstU%~gwn9=
zM`NQE~9hI*8I1rs)r8qob{0>>6g6D!iDefj&L~V{8;cEDpK84m6zxM9Dm92sRLE
zS^c&U3cVx*0>31L43Izo`otudp@WEiIMtH9Ei;jvABWM?!1Y
z8bpv#96SR`DF_jKJKu+o1%~IHfIfWq`2EKcOY!sJ!^dLc{{c4TLr7{GNRj{m002ov
JPDHLkV1fw|%02)9
literal 0
HcmV?d00001
diff --git a/coinpaprika-logo-banner.png b/coinpaprika-logo-banner.png
new file mode 100644
index 0000000000000000000000000000000000000000..5ff12cdfacd183594cd659da0805b5fd50b3b35d
GIT binary patch
literal 13960
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
aBD5d&{z?eacmr)V0@4!l;^m?c-~R(Fyorkd
literal 0
HcmV?d00001
diff --git a/coinpaprika-logo.png b/coinpaprika-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..f8f769af7e6a4de7f3c9c19dfc33f0efdf4339c4
GIT binary patch
literal 5999
zcmV-#7m(;FGjq?a%ZK<7DN?jVQIz#|EY)#f
zCu(d3j$;Q=8aXZ8rtS-9QzU4M27UaI0tw(Yagj8zBUq^$+kg`XkY(AeW6PFgS&1WC
zg7^@*qR8bwxV!iLIIo%hadt^+y}R7Kdzak1dq2Phx#ylcGxyH-%>3pzznKxm(L;2Z
z81Mk_5O5ec0_+9`fOxkv+oH6AS>PgY5;z6C0K5da-ONaINdPI}ao`Eyy+E=XiT3#k
zn!tB}r-8o!8tYAPy#m+`{9E7?KzhA}>9Z#4z~_MfM$}StgzWHh1>g^Wv%o*6U->tK
zG|_K=mZ&ZYog~tU0DcWP4SWi4I?1$8S8<5y;xzE&T0guN0c3$M0)Gk&t~H}R8_pn6
zm+(cRx>^;h6~GbT72u<5FIS%%%twjp>d0ztUX1`AAR2;neZ1Ib!#G4#XAfNO#_I{-
ze&8E)XkhfYsT6?ci0W`zRuaHL;IHUg_`OVqs16S?c)p@m)o&0pQDv-&o2M_zB>%-ORnuRZc02ngfv2v$uvh>?L=z8vqi+Ma>%I{l{sqCnNE{so7{F4IFHHymNVEyi+C!Uw
zSD#Dr%oopfvj~@oCg@5F7Z!H`zY9Fl%^dqgJo4cJA9x}|ECo{9NMTc*4XMn9SdKxc
z5FrFgD3o*%Kz?tDti6}BCuh4=j1-Yk|IEULYg>R_z&ZNv-LCWgUmWJd2Q)D&izQ=}
zDl>fVD*-=xv4Yly!I2b?{QY6}o@ijJ1eS0>KoGiAt2MszX~TuF()BZ19X?SjFb3~z
z0sa&4aJO>l6LI(b`*`%@A+}7Qq(fj_e(-gd?|p5KFfiy4>J^XIeo!K8WZ8R%K?s3F
zqNIZsO=2p;$-k>~t4NAy^!GKmIt)w#zuv7J`dlS<%Oz};L8%zp1Q_je;j~`z-k1LG
z1mFFlL(3~;Fc>tpin0HgVPL4M?wBW;kJ(rdz=v7G1VW$H6V`_Df;s?x*rI+p#pK(q
zW$%Cf>tmdHF@_g3Fc@r=Kqjl~J6JM3
zGSqAB6+iQ%=RMq}!RQc#z)}vwyJOuh+OI++00(%q+o|`7XtzAR{708K{gT6}?`HYd
zGuI#1ji0a3F6Z&WCIGgTB$ipe)##8%frJIzM>IU>vq99#9$)?3>YX~u64=THBm#lN
zLOA7a7b^igAnCh&Hyzo091dYj}ZsCDE9$&n9BufgL#M20}={00G9^
zkVg7&UjUnsTaQ^7BM=CT(Rg8#R%v4dU=eu$`)m?!*+0OZV+|ZTjlm#=BGf+P=ey1U&Y!TiJQELeegxO@I&*
zFK7_9Vzg>%BeG0OqP2W|ZZeO3>@Y`vx=bQgK*-2HClFu+m&cpT&Qv!d+qkt6srFet
zQVJe>Vi)gvZv`dOSTcq&ApqKh#OyTHTA46ddj4R&^aXGex%JK>AN+WZ)KCpaWs$h^(b~i3St1o~qQgAFD%EY-hZgHCk$TzB}@+A_n0%oShjQbrfd~_$b
zJ${5Rba7e|p<)=bT=Omnw2uz#4J&hB0A1if+~#KsDIT#jsrnqECU9C3+qcj%q;yy^
z@#H=x9z9O0pm0hq3D-g^fR*}o6TKgHx`_Mw^aZd+b~+Xh>>1@Y?U5Qk4^nWb=#Z_=
zpaP3{m_&FX?E#C)+v7|N}E=bVg`gs{+h}jw5zA(OF-={BtRkFhp
zd^BzGKBck8PoWZV?0gZ`3=o$*q=@0=6tnwnE}tkeeNT$UE(;^UYCvK-Kp57v9$N^B
zrDK$mU-Yo6AFoA#Nx}TB^z1pDoT8rkeg`ZUf
zIYp2Z7y+uTNlp5sE_tZ7#w}R*DTN5>ObEWl8%knE3jFfh=lIyI-JQMfcLB?Aw=#sT
zi&H3Kf*`tRz|SgT(*bw={sfgHaY8$KhLme?sy^|_5UZ&X7=n~!_O2A?K2o4HY!ROh
zqGcJYMMf=-n-}=IQ>14+er;xqx#1zcG2NYoB7FfY!LD3}cU5Ol=?o@Z?4E@nCrL~P
zWX{(>MpnKCgcM+bmQlwaD~AlcHcR1+HZT9qPQ0Q;Y%ahoCxS&bgAtLiT7wq#Aw|JX
z(6$5q;e|IizvD2c%e8fX*M1kU1osZ*iOtO-6A93ZJazNVxgaHJ4=CD2i}rwpSF~{R
z3OB3p(-J=|@d}FSK8L|q>fHV((*!9&=!htdYhFeOj1(Aa{$H-%BSQlM=I%(Kg^y*$
zNaYIrtE?d5tlvf47r+wS=hhLiI0zBFmP0K1|AN7{@X}x`L3_kv*SBg6{HTSOw-5$`
zgv2cB+c0xylGdPuRrj%n2H5k~IiA?H{?$VL
zE?^Od3Rw=#O(HW{FzXM+7J(#2`rRo)%OO$n$((gbUGPa<4zODxGB5;=
zz)wgTyJO7Wm83mnV^>2OJ8foh1AU*#|MSq8JNoLGt1am`6}_
z(6uHqndBSQmDd`sMBfIuhT8{n+)|mv%4FxQ|Mge?wFm*q3uzB1nxhVWT4Lr$3|H)i
zd9)*_9dK}JAxHmcn&ga+o40uTXY=?OiE4z%c${Gjx8yrt*xeVvHM~3N;I!MwnA4U1
z{~efUSQjKDMhHY;BG>T>_e&p|qc-_dE%tn~Ol#C)=B@;8R-x(vGMk~;YH)yn(O73A
zg1!wfj}(Fv;rt3*rC^Ei{|(20wgg^IvHRI7^_>nwKWq}KhWI%J2t;+3TMyhxv*9vv
zVPef$^aU`_U4sP<)Gi~E$?iY>>p+Cy78FiRbI*U7z*yiFEVKj>XryJcJDsFt*}QyV
z?dkUgFwcE4foyolRQe~KKQ|enA&d)*QWz`hN)~1wh2xNJHpqCLwOD-t0J(UK6SWzn
z9i#K9yA5Q%NZJwa_!|LOHpzC2wBMO%`$iye&yE3h`!3iU7k%3m7L61@AcP?9wurf%
z4F&rG03H?r+7FS=23Y?$0N=9kRcDR)wim!?I>nJ@1(i(P?4qn4V=!SrBax&L@2vdW
zUI53EHu-vG>6yP?Kx?$J2|H{7w!IN}p9m1jirjQP*8Ce|&~2BQRE8PR*@2?lS^x(J
z3!E_Z$oT86x(7g57D7qRj=ja%c4x!DZQTVtnvG+XOUT$J9sXU9ASB4Dv7Byutlgd(&o$Vm9Z3S?AN0EJVQ&`zNEW0{)^CE;q
zyDqNnPz^OLKjmIBDeW87JuK{|0vk6Hc;
z7_G5}hG|Sr((=5H)7h2+cxYsh;qojpo$9%v-xah*plKJ@7Z|!N1#pjFk2YcK(0Q^M
zFc^Z_Sl?*vD*@awSm5B?6e^Y3
z95H|EK}p^c4(0m#_7L7y0=PHrpj)kI*;fxY|3WFkdYvv0p#Kicb2D-$sYFn&11Ai2*LMS-7#Xfg#aELE;3Y}
zjePGmZQQmHz#}mMPOK-xz80gKO}?MsLDlVi0_a+{yZ{aq^BkQx
zkIMA;(a7`DzhN@Nx2DToOLof(;Gs+$D+r>3!?pvIuKcCek^+d%4`zq_?yHJ|tR%%~mw_
z?`1-bsg(IFWd-ob+jjHrMmgH;tCu~0mPJr0b7^1)&vw!HTVP8H;C+Kx
z9>4e|GL=E7-u{Xv2r$hCe>t$5N^AX|zs28D>s
zuMO|wYhxR8Y)lVFMZA-klKjh@#ouesVlo+oZT0q?zYu7*jW6K;=orRyx9?wIOSAw-
zGYS4+G|3~a3P=kXkN5PG4}g$_xIr$H<}QS^SK~NqrCn(
z|CQ)D0qlr7{Nw#2+&^{_nhr9PiJtggcJwSTKUrm(b)GKl=7$^D^e?b(0SMq=KEr;m
ziB+1Tx_d8YTOO13W>*(n=at~Gti$8FN%HM8$ZTQW(Cchb*)I0Oo
zN=S*W*Qi)A{)0*JW*4V=S3^ev_`R&)_Lz!7tipg5MvK1USt3d!lqN_CmA^FcT$9Kx>Ti&%EIugL=-x%ZR3zw0W
zwdA>aeO5q7bh}L@mE^ZYh8Id3>*%>29SLB((c;^eE1Xg>bh~}kI`6YQ^Tu<8rFY
z{AR=A^|>2s@GXS|IvR7hVaSwomdb4dcH)|<-zy4>J@?>vaqAwju({WEvBDpF#M!8DtMCgjV+_&0Mt
zrzCWQK4dxY596jU!b3m$_DIZSQd~zto?WJjqv{1=p^u`uz4RqT@gaI!qhtK;l#@4ZK
z?+vB}45&nAAOs!)ZtG_1vw`NhN}EfT!~Q~^RJ|H`L6t>M?#+KKLPY)#-)Ah5qTwP8vq{@jCaHZ=ZbEAQ&50V6Nozfck6i|nx#G1o=6
zng}7I7{ATHe8rvy>F?go{0R9K?&u&7YIFycap93eP;Sd3q))?1~x(Fc=5>VFFm;up2(1?&k
zktpWM(A4PY6lUG1Bc#MQHm8Nd50W{)KU3jsbJLII*UBGqO&u>5zz~sRsBnV|bp-+J
zPuSd@j&oNs#=)RPzFt8kGlY#g2!YDy32U`zRN*+VaA1;Iv_3$}C}1Uw0!~8LMaB{c
z47%Nnwv6{&YSLybnc+1o{${qq>84B2v)%iOTqb(@OA8kk3jp8~z-Mn@p;lzrR@{-c}A{)du5%>Gi?sYIqWO>e>rS2>{?Lz~dWVp0$&(6iLq|J5XfbK!L%TDT;H`
zRJGyw?T7iPqlXFWb%@9Lix*yIZhQh=C~&zj#JH1Sa$=H3sHtzBDcKvvp93FXd~rFm
z`xC$&z`>0yQ75#5ke0NVEmavSRdIwMEs|6$#hXpTjw8pQG|OZNf7X1Ndc1(~6wS%G
z?eK&z#~I+0OTDpN3jk5&zd&Rc^yytL6M1^yTR}#2W0jPQrMfB8naOL!c+ZUbZ+M
z@EIZx-=D7a!=1))mx%nyw-U`CY}%;DEli#0x4#wm6j4;ynpw#Yuolw5hk+-6M}R~(
z67BO7w195|PXm8R7aqKB3E)~{L~#WV5j9IkfZf0V5bt(oTa-313tS{J=1vhg
Date: Sat, 24 Dec 2022 16:21:26 -0500
Subject: [PATCH 10/25] fix test name
---
Tests/CoinsTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Tests/CoinsTests.cs b/Tests/CoinsTests.cs
index a98d6f1..57213c6 100644
--- a/Tests/CoinsTests.cs
+++ b/Tests/CoinsTests.cs
@@ -1,6 +1,6 @@
namespace Tests
{
- public class Tests
+ public class CoinsTests
{
[Test]
public async Task GetCoinsTest()
From 545a3ef27961bc6118db23360a079f1136dded82 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Sat, 24 Dec 2022 16:21:54 -0500
Subject: [PATCH 11/25] warn on GetCoinOhlcHistoricTest http exception
---
Tests/CoinsTests.cs | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/Tests/CoinsTests.cs b/Tests/CoinsTests.cs
index 57213c6..ca4d71b 100644
--- a/Tests/CoinsTests.cs
+++ b/Tests/CoinsTests.cs
@@ -73,10 +73,17 @@ public async Task GetCoinOhlcLatestTest()
[Test]
public async Task GetCoinOhlcHistoricTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcHistoricAsync("btc-bitcoin", DateTimeOffset.UtcNow.AddDays(-1));
-
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcHistoricAsync("btc-bitcoin", DateTimeOffset.UtcNow.AddDays(-1));
+
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
From 3ace386cbfacafe4624378970fbdd918e398ec6a Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Sat, 24 Dec 2022 17:13:06 -0500
Subject: [PATCH 12/25] change package id since existing id is in use
---
CoinpaprikaApi/CoinpaprikaApi.csproj | 1 +
1 file changed, 1 insertion(+)
diff --git a/CoinpaprikaApi/CoinpaprikaApi.csproj b/CoinpaprikaApi/CoinpaprikaApi.csproj
index c212fe7..dab86dd 100644
--- a/CoinpaprikaApi/CoinpaprikaApi.csproj
+++ b/CoinpaprikaApi/CoinpaprikaApi.csproj
@@ -22,6 +22,7 @@
coinpaprika,coinpaprika-api,api,bitcoin,eth,etherium,atom,cosmos,btc,usdt,tether,bnb,usdc,doge,dogecoin,xrp,ripple,ltc,litecoin,crypto,market,price,market-cap,cryptocurrencies,marketcap,netstandard
Coinpaprika API Client Library
Coinpaprika API Client Library
+ Coinpaprika_Api
From 4fbc27eab5dd47e7e95eedcc7d5b78686e7b6394 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Sat, 24 Dec 2022 17:25:49 -0500
Subject: [PATCH 13/25] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 89fa44c..f05b3cc 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
![Coinpaprika Logo](https://raw.githubusercontent.com/ByronAP/CoinpaprikaApi/dev/coinpaprika-logo-banner-256x64.png)
## Coinpaprika API Library for .NET
-[![Nuget](https://img.shields.io/nuget/v/CoinpaprikaAPI)](https://www.nuget.org/packages/CoinpaprikaAPI)
+[![Nuget](https://img.shields.io/nuget/v/Coinpaprika_Api)](https://www.nuget.org/packages/Coinpaprika_Api)
[![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/ByronAP)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4597bd69581d4039ae591a161fa43f83)](https://www.codacy.com/gh/ByronAP/CoinpaprikaApi/dashboard?utm_source=github.com&utm_medium=referral&utm_content=ByronAP/CoinpaprikaApi&utm_campaign=Badge_Grade)
From 41e3b8457f20c6d863ef05c93dfa605b5f67097e Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Tue, 27 Dec 2022 20:26:31 -0500
Subject: [PATCH 14/25] Update README.md
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index f05b3cc..f90dc4e 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
![Coinpaprika Logo](https://raw.githubusercontent.com/ByronAP/CoinpaprikaApi/dev/coinpaprika-logo-banner-256x64.png)
## Coinpaprika API Library for .NET
+[![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/ByronAP)
[![Nuget](https://img.shields.io/nuget/v/Coinpaprika_Api)](https://www.nuget.org/packages/Coinpaprika_Api)
-[![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/ByronAP)
-
+[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FByronAP%2FCoinpaprikaApi.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FByronAP%2FCoinpaprikaApi?ref=badge_shield)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4597bd69581d4039ae591a161fa43f83)](https://www.codacy.com/gh/ByronAP/CoinpaprikaApi/dashboard?utm_source=github.com&utm_medium=referral&utm_content=ByronAP/CoinpaprikaApi&utm_campaign=Badge_Grade)
[![CodeQL](https://github.com/ByronAP/CoinpaprikaApi/actions/workflows/codeql.yml/badge.svg)](https://github.com/ByronAP/CoinpaprikaApi/actions/workflows/codeql.yml)
[![Tests](https://github.com/ByronAP/CoinpaprikaApi/actions/workflows/dev_test_dotnet.yml/badge.svg)](https://github.com/ByronAP/CoinpaprikaApi/actions/workflows/dev_test_dotnet.yml)
From c9830b9b5174d8b4a053f8db52f378017a1b14dc Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 28 Dec 2022 22:42:12 -0500
Subject: [PATCH 15/25] Bump NUnit.Analyzers from 3.3.0 to 3.5.0 (#4)
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 3.3.0 to 3.5.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.txt)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/3.3.0...3.5.0)
---
updated-dependencies:
- dependency-name: NUnit.Analyzers
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Tests/Tests.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 261ae3c..3e9714d 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -13,7 +13,7 @@
-
+
From 6e37f51f11b39ef63de018bbc1e82999acbc8cc6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 28 Dec 2022 22:42:21 -0500
Subject: [PATCH 16/25] Bump Microsoft.NET.Test.Sdk from 17.3.2 to 17.4.1 (#5)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.3.2 to 17.4.1.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.3.2...v17.4.1)
---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Tests/Tests.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 3e9714d..8d5093a 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -10,7 +10,7 @@
-
+
From 5784f18be7dfe18a54b7b50b22435158297c8ed9 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 28 Dec 2022 22:49:50 -0500
Subject: [PATCH 17/25] Bump NUnit3TestAdapter from 4.2.1 to 4.3.1 (#6)
Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 4.2.1 to 4.3.1.
- [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases)
- [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V4.2.1...V4.3.1)
---
updated-dependencies:
- dependency-name: NUnit3TestAdapter
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Tests/Tests.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 8d5093a..63d7228 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -12,7 +12,7 @@
-
+
From 1b7442992dc541a911d1ab30fd1bf9a422cf7cc8 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 28 Dec 2022 22:50:11 -0500
Subject: [PATCH 18/25] Bump coverlet.collector from 3.1.2 to 3.2.0 (#7)
Bumps [coverlet.collector](https://github.com/coverlet-coverage/coverlet) from 3.1.2 to 3.2.0.
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/commits/v3.2.0)
---
updated-dependencies:
- dependency-name: coverlet.collector
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Tests/Tests.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 63d7228..7f395d6 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -14,7 +14,7 @@
-
+
From 63f80d9d9531a1f1cd774a46dc500c8550887617 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Wed, 28 Dec 2022 22:52:11 -0500
Subject: [PATCH 19/25] update test deps
---
Tests/Tests.csproj | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 7f395d6..87dcfc3 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -13,8 +13,14 @@
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
From 6009ee5c2475f2676ea6bd367f9a63fd19b2e599 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Thu, 29 Dec 2022 01:44:52 -0500
Subject: [PATCH 20/25] 8 add service collection extension (#9)
* add
* add di tests
* make AthPrice nullable
---
.../CoinPaprikaServiceCollectionExtensions.cs | 20 +++++++++
CoinpaprikaApi/CoinpaprikaApi.csproj | 1 +
CoinpaprikaApi/Models/TickerQuote.cs | 2 +-
Tests/DITests.cs | 41 +++++++++++++++++++
Tests/Tests.csproj | 1 +
Tests/Usings.cs | 1 +
6 files changed, 65 insertions(+), 1 deletion(-)
create mode 100644 CoinpaprikaApi/CoinPaprikaServiceCollectionExtensions.cs
create mode 100644 Tests/DITests.cs
diff --git a/CoinpaprikaApi/CoinPaprikaServiceCollectionExtensions.cs b/CoinpaprikaApi/CoinPaprikaServiceCollectionExtensions.cs
new file mode 100644
index 0000000..03b2de1
--- /dev/null
+++ b/CoinpaprikaApi/CoinPaprikaServiceCollectionExtensions.cs
@@ -0,0 +1,20 @@
+using CoinpaprikaApi;
+using Microsoft.Extensions.Logging;
+
+namespace Microsoft.Extensions.DependencyInjection
+{
+ public static class CoinpaprikaServiceCollectionExtensions
+ {
+ public static IServiceCollection AddCoinpaprikaApi(this IServiceCollection services)
+ => services.AddSingleton();
+
+ public static IServiceCollection AddCoinpaprikaApi(this IServiceCollection services, string apiKey)
+ => services.AddSingleton(new CoinpaprikaClient(apiKey: apiKey));
+
+ public static IServiceCollection AddCoinpaprikaApi(this IServiceCollection services, ILogger logger)
+ => services.AddSingleton(new CoinpaprikaClient(logger: logger));
+
+ public static IServiceCollection AddCoinpaprikaApi(this IServiceCollection services, string apiKey, ILogger logger)
+ => services.AddSingleton(new CoinpaprikaClient(apiKey: apiKey, logger: logger));
+ }
+}
diff --git a/CoinpaprikaApi/CoinpaprikaApi.csproj b/CoinpaprikaApi/CoinpaprikaApi.csproj
index dab86dd..3cad281 100644
--- a/CoinpaprikaApi/CoinpaprikaApi.csproj
+++ b/CoinpaprikaApi/CoinpaprikaApi.csproj
@@ -46,6 +46,7 @@
+
diff --git a/CoinpaprikaApi/Models/TickerQuote.cs b/CoinpaprikaApi/Models/TickerQuote.cs
index fe61536..b5c1fa1 100644
--- a/CoinpaprikaApi/Models/TickerQuote.cs
+++ b/CoinpaprikaApi/Models/TickerQuote.cs
@@ -48,7 +48,7 @@ public class TickerQuote
public double PercentChange1Y { get; set; }
[JsonProperty("ath_price")]
- public decimal AthPrice { get; set; }
+ public decimal? AthPrice { get; set; }
[JsonProperty("ath_date")]
public DateTimeOffset AthDate { get; set; }
diff --git a/Tests/DITests.cs b/Tests/DITests.cs
new file mode 100644
index 0000000..b84024b
--- /dev/null
+++ b/Tests/DITests.cs
@@ -0,0 +1,41 @@
+namespace Tests
+{
+ internal class DITests
+ {
+ [Test]
+ public void CreateViaDITest()
+ {
+ var services = new ServiceCollection();
+
+ services.AddLogging();
+ services.AddCoinpaprikaApi();
+
+ using var provider = services.BuildServiceProvider();
+
+ var api = provider.GetService();
+
+ Assert.That(api, Is.Not.Null);
+
+ Assert.That(api.CPRestClient.Options.BaseUrl, Is.Not.Null);
+ Assert.That(api.CPRestClient.Options.BaseUrl.ToString(), Is.EqualTo(Constants.API_BASE_URL + "/"));
+ }
+
+ [Test]
+ public void CreateViaDIWithApiKeyTest()
+ {
+ var services = new ServiceCollection();
+
+ services.AddLogging();
+ services.AddCoinpaprikaApi("FakeApiKey");
+
+ using var provider = services.BuildServiceProvider();
+
+ var api = provider.GetService();
+
+ Assert.That(api, Is.Not.Null);
+
+ Assert.That(api.CPRestClient.Options.BaseUrl, Is.Not.Null);
+ Assert.That(api.CPRestClient.Options.BaseUrl.ToString(), Is.EqualTo(Constants.API_PRO_BASE_URL));
+ }
+ }
+}
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 87dcfc3..34b640e 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -9,6 +9,7 @@
+
diff --git a/Tests/Usings.cs b/Tests/Usings.cs
index f20ee4e..329a618 100644
--- a/Tests/Usings.cs
+++ b/Tests/Usings.cs
@@ -1,3 +1,4 @@
global using CoinpaprikaApi;
+global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Logging;
global using NUnit.Framework;
\ No newline at end of file
From c13f3ae6837cd25a09dfe09786efb57817e390bb Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Thu, 29 Dec 2022 01:53:09 -0500
Subject: [PATCH 21/25] make AthDate nullable
---
CoinpaprikaApi/Models/TickerQuote.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CoinpaprikaApi/Models/TickerQuote.cs b/CoinpaprikaApi/Models/TickerQuote.cs
index b5c1fa1..b898009 100644
--- a/CoinpaprikaApi/Models/TickerQuote.cs
+++ b/CoinpaprikaApi/Models/TickerQuote.cs
@@ -1,4 +1,4 @@
-using Newtonsoft.Json;
+using Newtonsoft.Json;
using System;
namespace CoinpaprikaApi.Models
@@ -51,7 +51,7 @@ public class TickerQuote
public decimal? AthPrice { get; set; }
[JsonProperty("ath_date")]
- public DateTimeOffset AthDate { get; set; }
+ public DateTimeOffset? AthDate { get; set; }
[JsonProperty("percent_from_price_ath")]
public double PercentFromPriceAth { get; set; }
From fa9bc36979eb2cad454070319109dda8ff3eb2db Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Thu, 29 Dec 2022 01:53:28 -0500
Subject: [PATCH 22/25] make PercentFromPriceAth nullable
---
CoinpaprikaApi/Models/TickerQuote.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CoinpaprikaApi/Models/TickerQuote.cs b/CoinpaprikaApi/Models/TickerQuote.cs
index b898009..e824727 100644
--- a/CoinpaprikaApi/Models/TickerQuote.cs
+++ b/CoinpaprikaApi/Models/TickerQuote.cs
@@ -1,4 +1,4 @@
-using Newtonsoft.Json;
+using Newtonsoft.Json;
using System;
namespace CoinpaprikaApi.Models
@@ -54,6 +54,6 @@ public class TickerQuote
public DateTimeOffset? AthDate { get; set; }
[JsonProperty("percent_from_price_ath")]
- public double PercentFromPriceAth { get; set; }
+ public double? PercentFromPriceAth { get; set; }
}
}
From 3234df9b2ed76fe15771bfa0d2633738213ff3c6 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Thu, 29 Dec 2022 09:52:55 -0500
Subject: [PATCH 23/25] warn not fail on payment required response
---
Tests/CoinsTests.cs | 112 ++++++++++++++++++++++++++++++----------
Tests/ContractsTests.cs | 52 ++++++++++++++-----
Tests/ExchangesTests.cs | 39 ++++++++++----
Tests/GlobalTests.cs | 13 +++--
Tests/KeyTests.cs | 12 ++++-
Tests/PersonsTests.cs | 13 +++--
Tests/TagsTests.cs | 26 +++++++---
Tests/TickersTests.cs | 39 ++++++++++----
Tests/ToolsTests.cs | 26 +++++++---
9 files changed, 254 insertions(+), 78 deletions(-)
diff --git a/Tests/CoinsTests.cs b/Tests/CoinsTests.cs
index ca4d71b..575e93c 100644
--- a/Tests/CoinsTests.cs
+++ b/Tests/CoinsTests.cs
@@ -5,69 +5,118 @@ public class CoinsTests
[Test]
public async Task GetCoinsTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinsAsync();
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinsAsync();
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
- var eosItem = callResult.FirstOrDefault(x => x.Id.Equals("eos-eos", StringComparison.InvariantCultureIgnoreCase));
+ var eosItem = callResult.FirstOrDefault(x => x.Id.Equals("eos-eos", StringComparison.InvariantCultureIgnoreCase));
- Assert.That(eosItem, Is.Not.Null);
- Assert.That(eosItem.Name, Is.EqualTo("EOS"));
+ Assert.That(eosItem, Is.Not.Null);
+ Assert.That(eosItem.Name, Is.EqualTo("EOS"));
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetCoinTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinAsync("eos-eos");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinAsync("eos-eos");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.Name, Is.EqualTo("EOS"));
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Name, Is.EqualTo("EOS"));
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetCoinTweetsTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinTweetsAsync("btc-bitcoin");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinTweetsAsync("btc-bitcoin");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetCoinEventsTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinEventsAsync("btc-bitcoin");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinEventsAsync("btc-bitcoin");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetCoinExchangesTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinExchangesAsync("btc-bitcoin");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinExchangesAsync("btc-bitcoin");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetCoinMarketsTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinMarketsAsync("btc-bitcoin");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinMarketsAsync("btc-bitcoin");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetCoinOhlcLatestTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcLatestAsync("btc-bitcoin");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcLatestAsync("btc-bitcoin");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
@@ -80,7 +129,7 @@ public async Task GetCoinOhlcHistoricTest()
Assert.That(callResult, Is.Not.Null);
Assert.That(callResult, Is.Not.Empty);
}
- catch (HttpRequestException ex)
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
{
Assert.Warn(ex.Message);
}
@@ -89,10 +138,17 @@ public async Task GetCoinOhlcHistoricTest()
[Test]
public async Task GetCoinOhlcTodayTest()
{
- var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcTodayAsync("btc-bitcoin");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Coins.GetCoinOhlcTodayAsync("btc-bitcoin");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
}
}
\ No newline at end of file
diff --git a/Tests/ContractsTests.cs b/Tests/ContractsTests.cs
index b70ea88..65551c1 100644
--- a/Tests/ContractsTests.cs
+++ b/Tests/ContractsTests.cs
@@ -5,37 +5,65 @@ internal class ContractsTests
[Test]
public async Task GetPlatformsTest()
{
- var callResult = await (await Helpers.GetApiClient()).Contracts.GetPlatformsAsync();
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Contracts.GetPlatformsAsync();
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetContractsTest()
{
- var callResult = await (await Helpers.GetApiClient()).Contracts.GetContractsAsync("eth-ethereum");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Contracts.GetContractsAsync("eth-ethereum");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetTickerByContractAddressTest()
{
- var callResult = await (await Helpers.GetApiClient()).Contracts.GetTickerByContractAddressAsync("eth-ethereum", "0xd26114cd6ee289accf82350c8d8487fedb8a0c07");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Contracts.GetTickerByContractAddressAsync("eth-ethereum", "0xd26114cd6ee289accf82350c8d8487fedb8a0c07");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.Quotes, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Quotes, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetHistoricalTicksByContractAddressTest()
{
- var callResult = await (await Helpers.GetApiClient()).Contracts.GetHistoricalTicksByContractAddressAsync("eth-ethereum", "0xd26114cd6ee289accf82350c8d8487fedb8a0c07", DateTimeOffset.UtcNow.AddDays(-5), interval: CoinpaprikaApi.Types.TickerInterval.d1);
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Contracts.GetHistoricalTicksByContractAddressAsync("eth-ethereum", "0xd26114cd6ee289accf82350c8d8487fedb8a0c07", DateTimeOffset.UtcNow.AddDays(-5), interval: CoinpaprikaApi.Types.TickerInterval.d1);
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
}
}
diff --git a/Tests/ExchangesTests.cs b/Tests/ExchangesTests.cs
index 661b191..aefbb20 100644
--- a/Tests/ExchangesTests.cs
+++ b/Tests/ExchangesTests.cs
@@ -5,28 +5,49 @@ internal class ExchangesTests
[Test]
public async Task GetExchangesTest()
{
- var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangesAsync();
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangesAsync();
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetExchangeTest()
{
- var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangeAsync("binance");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangeAsync("binance");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.Quotes, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Quotes, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetExchangeMarketsTest()
{
- var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangeMarketsAsync("binance");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Exchanges.GetExchangeMarketsAsync("binance");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
}
}
diff --git a/Tests/GlobalTests.cs b/Tests/GlobalTests.cs
index 5c27aef..983613a 100644
--- a/Tests/GlobalTests.cs
+++ b/Tests/GlobalTests.cs
@@ -5,10 +5,17 @@ internal class GlobalTests
[Test]
public async Task GetGlobalTest()
{
- var callResult = await (await Helpers.GetApiClient()).Global.GetGlobalAsync();
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Global.GetGlobalAsync();
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.MarketCapUsd, Is.GreaterThan(1));
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.MarketCapUsd, Is.GreaterThan(1));
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
}
}
diff --git a/Tests/KeyTests.cs b/Tests/KeyTests.cs
index ca3786a..781b58f 100644
--- a/Tests/KeyTests.cs
+++ b/Tests/KeyTests.cs
@@ -13,7 +13,11 @@ public async Task GetKeyInfoTest()
}
catch (HttpRequestException ex)
{
- if (!ex.Message.Contains("forbidden", StringComparison.InvariantCultureIgnoreCase))
+ if (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
+ else if (!ex.Message.Contains("forbidden", StringComparison.InvariantCultureIgnoreCase))
{
Assert.Fail();
}
@@ -29,7 +33,11 @@ public async Task GetKeyInfoTest()
}
catch (HttpRequestException ex)
{
- if (!ex.Message.Contains("forbidden", StringComparison.InvariantCultureIgnoreCase))
+ if (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
+ else if (!ex.Message.Contains("forbidden", StringComparison.InvariantCultureIgnoreCase))
{
Assert.Fail();
}
diff --git a/Tests/PersonsTests.cs b/Tests/PersonsTests.cs
index 1a8d918..8456ab2 100644
--- a/Tests/PersonsTests.cs
+++ b/Tests/PersonsTests.cs
@@ -5,10 +5,17 @@ internal class PersonsTests
[Test]
public async Task GetPersonTest()
{
- var callResult = await (await Helpers.GetApiClient()).Persons.GetPersonAsync("vitalik-buterin");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Persons.GetPersonAsync("vitalik-buterin");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.Id, Is.EqualTo("vitalik-buterin"));
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Id, Is.EqualTo("vitalik-buterin"));
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
}
}
diff --git a/Tests/TagsTests.cs b/Tests/TagsTests.cs
index 7070e97..0891ba4 100644
--- a/Tests/TagsTests.cs
+++ b/Tests/TagsTests.cs
@@ -5,19 +5,33 @@ internal class TagsTests
[Test]
public async Task GetTagsTest()
{
- var callResult = await (await Helpers.GetApiClient()).Tags.GetTagsAsync();
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tags.GetTagsAsync();
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetTagTest()
{
- var callResult = await (await Helpers.GetApiClient()).Tags.GetTagAsync("blockchain-service", true, true);
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tags.GetTagAsync("blockchain-service", true, true);
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.Coins, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Coins, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
}
}
diff --git a/Tests/TickersTests.cs b/Tests/TickersTests.cs
index 184c9bf..3c9bcac 100644
--- a/Tests/TickersTests.cs
+++ b/Tests/TickersTests.cs
@@ -5,28 +5,49 @@ internal class TickersTests
[Test]
public async Task GetTickersTest()
{
- var callResult = await (await Helpers.GetApiClient()).Tickers.GetTickersAsync();
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tickers.GetTickersAsync();
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetTickerTest()
{
- var callResult = await (await Helpers.GetApiClient()).Tickers.GetTickerAsync("btc-bitcoin");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tickers.GetTickerAsync("btc-bitcoin");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.Quotes, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Quotes, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task GetHistoricalTicksTest()
{
- var callResult = await (await Helpers.GetApiClient()).Tickers.GetHistoricalTicksAsync("btc-bitcoin", DateTimeOffset.UtcNow.AddDays(-5), interval: CoinpaprikaApi.Types.TickerInterval.d1);
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tickers.GetHistoricalTicksAsync("btc-bitcoin", DateTimeOffset.UtcNow.AddDays(-5), interval: CoinpaprikaApi.Types.TickerInterval.d1);
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
}
}
diff --git a/Tests/ToolsTests.cs b/Tests/ToolsTests.cs
index 25f6927..037d248 100644
--- a/Tests/ToolsTests.cs
+++ b/Tests/ToolsTests.cs
@@ -5,19 +5,33 @@ internal class ToolsTests
[Test]
public async Task SearchTest()
{
- var callResult = await (await Helpers.GetApiClient()).Tools.SearchAsync("btc");
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tools.SearchAsync("btc");
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.Currencies, Is.Not.Empty);
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Currencies, Is.Not.Empty);
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
[Test]
public async Task PriceConvertTest()
{
- var callResult = await (await Helpers.GetApiClient()).Tools.PriceConvertAsync("eth-ethereum", "btc-bitcoin", 100);
+ try
+ {
+ var callResult = await (await Helpers.GetApiClient()).Tools.PriceConvertAsync("eth-ethereum", "btc-bitcoin", 100);
- Assert.That(callResult, Is.Not.Null);
- Assert.That(callResult.Price, Is.GreaterThan(1));
+ Assert.That(callResult, Is.Not.Null);
+ Assert.That(callResult.Price, Is.GreaterThan(1));
+ }
+ catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.PaymentRequired)
+ {
+ Assert.Warn(ex.Message);
+ }
}
}
}
From a8d7052a8b95102b5387157ff3dda43a11153ae3 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Thu, 29 Dec 2022 10:04:33 -0500
Subject: [PATCH 24/25] update package keywords
---
CoinpaprikaApi/CoinpaprikaApi.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CoinpaprikaApi/CoinpaprikaApi.csproj b/CoinpaprikaApi/CoinpaprikaApi.csproj
index 3cad281..e5f51ba 100644
--- a/CoinpaprikaApi/CoinpaprikaApi.csproj
+++ b/CoinpaprikaApi/CoinpaprikaApi.csproj
@@ -19,7 +19,7 @@
git
Copyright © 2022 ByronAP, Coinpaprika. All rights reserved.
See: https://github.com/ByronAP/CoinpaprikaApi/releases
- coinpaprika,coinpaprika-api,api,bitcoin,eth,etherium,atom,cosmos,btc,usdt,tether,bnb,usdc,doge,dogecoin,xrp,ripple,ltc,litecoin,crypto,market,price,market-cap,cryptocurrencies,marketcap,netstandard
+ coinpaprika,coinpaprika-api,api,bitcoin,eth,etherium,atom,cosmos,btc,usdt,tether,bnb,usdc,doge,dogecoin,xrp,ripple,ltc,litecoin,crypto,market,price,market-cap,cryptocurrencies,marketcap,netstandard,library,wrapper
Coinpaprika API Client Library
Coinpaprika API Client Library
Coinpaprika_Api
From 6d3a2bc47362ecba9be24aeb452cccb810c25b37 Mon Sep 17 00:00:00 2001
From: Allen Byron Penner <7310089+ByronAP@users.noreply.github.com>
Date: Thu, 29 Dec 2022 10:05:02 -0500
Subject: [PATCH 25/25] bump version 1.7.5.1
---
CoinpaprikaApi/CoinpaprikaApi.csproj | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/CoinpaprikaApi/CoinpaprikaApi.csproj b/CoinpaprikaApi/CoinpaprikaApi.csproj
index e5f51ba..6e2008c 100644
--- a/CoinpaprikaApi/CoinpaprikaApi.csproj
+++ b/CoinpaprikaApi/CoinpaprikaApi.csproj
@@ -4,10 +4,10 @@
netstandard2.0
False
True
- 1.7.5.0
+ 1.7.5.1
ByronAP
- 1.7.5.0
- 1.7.5.0
+ 1.7.5.1
+ 1.7.5.1
MIT
True
latest-recommended