diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..8fddb89 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: JKorf \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..f8c254c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,20 @@ +--- +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** +What endpoints and subscriptions are called. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Debug logging** +Add debug logging related to the issue. Enable Debug logging in the client options by settings LogLevel to Debug. diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 0000000..31607fa --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,25 @@ +name: .NET + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal diff --git a/Examples/Examples.sln b/Examples/Examples.sln new file mode 100644 index 0000000..d015159 --- /dev/null +++ b/Examples/Examples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32002.185 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TODO.Examples.Api", "TODO.Api\TODO.Examples.Api.csproj", "{8D7694ED-912A-4F92-B924-CFD107EB20CA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TODO.Examples.Console", "TODO.Console\TODO.Examples.Console.csproj", "{5B869493-8271-45C5-93AE-5357B45FE005}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8D7694ED-912A-4F92-B924-CFD107EB20CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D7694ED-912A-4F92-B924-CFD107EB20CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D7694ED-912A-4F92-B924-CFD107EB20CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D7694ED-912A-4F92-B924-CFD107EB20CA}.Release|Any CPU.Build.0 = Release|Any CPU + {5B869493-8271-45C5-93AE-5357B45FE005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B869493-8271-45C5-93AE-5357B45FE005}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B869493-8271-45C5-93AE-5357B45FE005}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B869493-8271-45C5-93AE-5357B45FE005}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0FC03929-769B-4314-AF91-AF01E06278DD} + EndGlobalSection +EndGlobal diff --git a/Examples/README.md b/Examples/README.md new file mode 100644 index 0000000..441b292 --- /dev/null +++ b/Examples/README.md @@ -0,0 +1,7 @@ +# Examples + +### TODO.Examples.Api +A minimal API showing how to integrate TODO.Net in a web API project + +### TODO.Examples.Console +A simple console client demonstrating basic usage \ No newline at end of file diff --git a/Examples/TODO.Api/Program.cs b/Examples/TODO.Api/Program.cs new file mode 100644 index 0000000..3ea7a94 --- /dev/null +++ b/Examples/TODO.Api/Program.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Mvc; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +// Add the TODO services +builder.Services.AddTODO(); + +// OR to provide API credentials for accessing private endpoints, or setting other options: +/* +builder.Services.AddTODO(restOptions => +{ + restOptions.ApiCredentials = new ApiCredentials("", ""); + restOptions.RequestTimeout = TimeSpan.FromSeconds(5); +}, socketOptions => +{ + socketOptions.ApiCredentials = new ApiCredentials("", ""); +}); +*/ + +var app = builder.Build(); +app.UseSwagger(); +app.UseSwaggerUI(); +app.UseHttpsRedirection(); + +// Map the endpoint and inject the rest client +app.MapGet("/{Symbol}", async ([FromServices] ITODORestClient client, string symbol) => +{ + var result = await client.SpotApi.ExchangeData.GetSpotTickersAsync(symbol); + return result.Data.List.First().LastPrice; +}) +.WithOpenApi(); + + +app.MapGet("/Balances", async ([FromServices] ITODORestClient client) => +{ + var result = await client.SpotApi.Account.GetBalancesAsync(); + return (object)(result.Success ? result.Data : result.Error!); +}) +.WithOpenApi(); + +app.Run(); \ No newline at end of file diff --git a/Examples/TODO.Api/Properties/launchSettings.json b/Examples/TODO.Api/Properties/launchSettings.json new file mode 100644 index 0000000..066e9d1 --- /dev/null +++ b/Examples/TODO.Api/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:23442", + "sslPort": 44376 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5114", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7266;http://localhost:5114", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Examples/TODO.Api/TODO.Examples.Api.csproj b/Examples/TODO.Api/TODO.Examples.Api.csproj new file mode 100644 index 0000000..17fa1ac --- /dev/null +++ b/Examples/TODO.Api/TODO.Examples.Api.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + diff --git a/Examples/TODO.Api/appsettings.Development.json b/Examples/TODO.Api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Examples/TODO.Api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Examples/TODO.Api/appsettings.json b/Examples/TODO.Api/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Examples/TODO.Api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Examples/TODO.Console/Program.cs b/Examples/TODO.Console/Program.cs new file mode 100644 index 0000000..51a06a8 --- /dev/null +++ b/Examples/TODO.Console/Program.cs @@ -0,0 +1,20 @@ + +using TODO.Net.Clients; + +// REST +var restClient = new TODORestClient(); +var ticker = await restClient.V5Api.ExchangeData.GetSpotTickersAsync("ETHUSDT"); +Console.WriteLine($"Rest client ticker price for ETHUSDT: {ticker.Data.List.First().LastPrice}"); + +Console.WriteLine(); +Console.WriteLine("Press enter to start websocket subscription"); +Console.ReadLine(); + +// Websocket +var socketClient = new TODOSocketClient(); +var subscription = await socketClient.V5SpotApi.SubscribeToTickerUpdatesAsync("ETHUSDT", update => +{ + Console.WriteLine($"Websocket client ticker price for ETHUSDT: {update.Data.LastPrice}"); +}); + +Console.ReadLine(); diff --git a/Examples/TODO.Console/TODO.Examples.Console.csproj b/Examples/TODO.Console/TODO.Examples.Console.csproj new file mode 100644 index 0000000..cd0be2e --- /dev/null +++ b/Examples/TODO.Console/TODO.Examples.Console.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetAccount.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetAccount.txt new file mode 100644 index 0000000..b3ff040 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetAccount.txt @@ -0,0 +1,28 @@ +GET +/api/v4/futures/usdt/accounts +true +{ + "user": 1666, + "currency": "USDT", + "total": "9707.803567115145", + "unrealised_pnl": "3371.248828", + "position_margin": "38.712189181", + "order_margin": "0", + "available": "9669.091377934145", + "point": "0", + "bonus": "0", + "in_dual_mode": false, + "enable_evolved_classic": false, + "history": { + "dnw": "10000", + "pnl": "68.3685", + "fee": "-1.645812875", + "refr": "0", + "fund": "-358.919120009855", + "point_dnw": "0", + "point_fee": "0", + "point_refr": "0", + "bonus_dnw": "0", + "bonus_offset": "0" + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetLedger.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetLedger.txt new file mode 100644 index 0000000..207ae4f --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetLedger.txt @@ -0,0 +1,14 @@ +GET +/api/v4/futures/usdt/account_book +true +[ + { + "time": 1682294400.123456, + "change": "0.000010152188", + "balance": "4.59316525194", + "text": "ETH_USD:6086261", + "type": "fee", + "contract": "ETH_USD", + "trade_id": "1" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetTradingFee.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetTradingFee.txt new file mode 100644 index 0000000..d386d0a --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/GetTradingFee.txt @@ -0,0 +1,13 @@ +GET +/api/v4/futures/usdt/fee +true +{ + "1INCH_USDT": { + "taker_fee": "0.00025", + "maker_fee": "-0.00010" + }, + "AAVE_USDT": { + "taker_fee": "0.00025", + "maker_fee": "-0.00010" + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/UpdatePositionMode.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/UpdatePositionMode.txt new file mode 100644 index 0000000..f9fb2b6 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Account/UpdatePositionMode.txt @@ -0,0 +1,28 @@ +POST +/api/v4/futures/usdt/dual_mode +true +{ + "user": 1666, + "currency": "USDT", + "total": "9707.803567115145", + "unrealised_pnl": "3371.248828", + "position_margin": "38.712189181", + "order_margin": "0", + "available": "9669.091377934145", + "point": "0", + "bonus": "0", + "in_dual_mode": false, + "enable_evolved_classic": false, + "history": { + "dnw": "10000", + "pnl": "68.3685", + "fee": "-1.645812875", + "refr": "0", + "fund": "-358.919120009855", + "point_dnw": "0", + "point_fee": "0", + "point_refr": "0", + "bonus_dnw": "0", + "bonus_offset": "0" + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContract.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContract.txt new file mode 100644 index 0000000..9491506 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContract.txt @@ -0,0 +1,47 @@ +GET +/api/v4/futures/usdt/contracts/ETH_USDT +false +{ + "name": "BTC_USDT", + "type": "direct", + "quanto_multiplier": "0.0001", + "ref_discount_rate": "0", + "order_price_deviate": "0.5", + "maintenance_rate": "0.005", + "mark_type": "index", + "last_price": "38026", + "mark_price": "37985.6", + "index_price": "37954.92", + "funding_rate_indicative": "0.000219", + "mark_price_round": "0.01", + "funding_offset": 0, + "in_delisting": false, + "risk_limit_base": "1000000", + "interest_rate": "0.0003", + "order_price_round": "0.1", + "order_size_min": 1, + "ref_rebate_rate": "0.2", + "funding_interval": 28800, + "risk_limit_step": "1000000", + "leverage_min": "1", + "leverage_max": "100", + "risk_limit_max": "8000000", + "maker_fee_rate": "-0.00025", + "taker_fee_rate": "0.00075", + "funding_rate": "0.002053", + "order_size_max": 1000000, + "funding_next_apply": 1610035200, + "short_users": 977, + "config_change_time": 1609899548, + "trade_size": 28530850594, + "position_size": 5223816, + "long_users": 455, + "funding_impact_value": "60000", + "orders_limit": 50, + "trade_id": 10851092, + "orderbook_id": 2129638396, + "enable_bonus": true, + "enable_credit": true, + "create_time": 1669688556, + "funding_cap_ratio": "0.75" +} diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContractStats.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContractStats.txt new file mode 100644 index 0000000..57db323 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContractStats.txt @@ -0,0 +1,21 @@ +GET +/api/v4/futures/usdt/contract_stats +false +[ + { + "time": 1603865400, + "lsr_taker": 100, + "lsr_account": 0.5, + "long_liq_size": 0, + "short_liq_size": 0, + "open_interest": 124724, + "short_liq_usd": 0, + "mark_price": "8865", + "top_lsr_size": 1.02, + "short_liq_amount": 0, + "long_liq_amount": 0, + "open_interest_usd": 1511, + "top_lsr_account": 1.5, + "long_liq_usd": 0 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContracts.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContracts.txt new file mode 100644 index 0000000..80fafc6 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetContracts.txt @@ -0,0 +1,49 @@ +GET +/api/v4/futures/usdt/contracts +false +[ + { + "name": "BTC_USDT", + "type": "direct", + "quanto_multiplier": "0.0001", + "ref_discount_rate": "0", + "order_price_deviate": "0.5", + "maintenance_rate": "0.005", + "mark_type": "index", + "last_price": "38026", + "mark_price": "37985.6", + "index_price": "37954.92", + "funding_rate_indicative": "0.000219", + "mark_price_round": "0.01", + "funding_offset": 0, + "in_delisting": false, + "risk_limit_base": "1000000", + "interest_rate": "0.0003", + "order_price_round": "0.1", + "order_size_min": 1, + "ref_rebate_rate": "0.2", + "funding_interval": 28800, + "risk_limit_step": "1000000", + "leverage_min": "1", + "leverage_max": "100", + "risk_limit_max": "8000000", + "maker_fee_rate": "-0.00025", + "taker_fee_rate": "0.00075", + "funding_rate": "0.002053", + "order_size_max": 1000000, + "funding_next_apply": 1610035200, + "short_users": 977, + "config_change_time": 1609899548, + "trade_size": 28530850594, + "position_size": 5223816, + "long_users": 455, + "funding_impact_value": "60000", + "orders_limit": 50, + "trade_id": 10851092, + "orderbook_id": 2129638396, + "enable_bonus": true, + "enable_credit": true, + "create_time": 1669688556, + "funding_cap_ratio": "0.75" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetFundingRateHistory.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetFundingRateHistory.txt new file mode 100644 index 0000000..9e02d1b --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetFundingRateHistory.txt @@ -0,0 +1,9 @@ +GET +/api/v4/futures/usdt/funding_rate +false +[ + { + "t": 1543968000, + "r": "0.000157" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetIndexConstituents.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetIndexConstituents.txt new file mode 100644 index 0000000..a5fcba9 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetIndexConstituents.txt @@ -0,0 +1,26 @@ +GET +/api/v4/futures/usdt/index_constituents/ETH_USDT +false +{ + "index": "BTC_USDT", + "constituents": [ + { + "exchange": "Binance", + "symbols": [ + "BTC_USDT" + ] + }, + { + "exchange": "Gate.io", + "symbols": [ + "BTC_USDT" + ] + }, + { + "exchange": "Huobi", + "symbols": [ + "BTC_USDT" + ] + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetIndexKlines.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetIndexKlines.txt new file mode 100644 index 0000000..24749ff --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetIndexKlines.txt @@ -0,0 +1,12 @@ +GET +/api/v4/futures/usdt/premium_index +false +[ + { + "t": 1539852480, + "c": "0", + "h": "0.00023", + "l": "0", + "o": "0" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetInsuranceBalanceHistory.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetInsuranceBalanceHistory.txt new file mode 100644 index 0000000..0091b37 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetInsuranceBalanceHistory.txt @@ -0,0 +1,9 @@ +GET +/api/v4/futures/usdt/insurance +false +[ + { + "t": 1543968000, + "b": "83.0031" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetKlines.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetKlines.txt new file mode 100644 index 0000000..a1461b9 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetKlines.txt @@ -0,0 +1,14 @@ +GET +/api/v4/futures/usdt/candlesticks +false +[ + { + "t": 1539852480, + "v": 97151, + "c": "1.032", + "h": "1.032", + "l": "1.032", + "o": "1.032", + "sum": "3580" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetLiquidations.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetLiquidations.txt new file mode 100644 index 0000000..cd12d10 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetLiquidations.txt @@ -0,0 +1,13 @@ +GET +/api/v4/futures/usdt/liq_orders +false +[ + { + "time": 1548654951, + "contract": "BTC_USDT", + "size": 600, + "order_price": "3405", + "fill_price": "3424", + "left": 0 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetOrderBook.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetOrderBook.txt new file mode 100644 index 0000000..74bb7ab --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetOrderBook.txt @@ -0,0 +1,28 @@ +GET +/api/v4/futures/usdt/order_book +false +{ + "id": 123456, + "current": 1623898993.123, + "update": 1623898993.121, + "asks": [ + { + "p": "1.52", + "s": 100 + }, + { + "p": "1.53", + "s": 40 + } + ], + "bids": [ + { + "p": "1.17", + "s": 150 + }, + { + "p": "1.16", + "s": 203 + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetRiskLimitTiers.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetRiskLimitTiers.txt new file mode 100644 index 0000000..556b910 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetRiskLimitTiers.txt @@ -0,0 +1,26 @@ +GET +/api/v4/futures/usdt/risk_limit_tiers +false +[ + { + "maintenance_rate": "0.01", + "tier": 1, + "initial_rate": "0.02", + "leverage_max": "50", + "risk_limit": "500000" + }, + { + "initial_rate": "0.03", + "maintenance_rate": "0.02", + "tier": 2, + "risk_limit": "1000000", + "leverage_max": "33.33" + }, + { + "maintenance_rate": "0.01", + "tier": 1, + "initial_rate": "0.02", + "leverage_max": "50", + "risk_limit": "500000" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetTickers.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetTickers.txt new file mode 100644 index 0000000..eaa8ba6 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetTickers.txt @@ -0,0 +1,25 @@ +GET +/api/v4/futures/usdt/tickers +false +[ + { + "contract": "BTC_USDT", + "last": "6432", + "low_24h": "6278", + "high_24h": "6790", + "change_percentage": "4.43", + "total_size": "32323904", + "volume_24h": "184040233284", + "volume_24h_btc": "28613220", + "volume_24h_usd": "184040233284", + "volume_24h_base": "28613220", + "volume_24h_quote": "184040233284", + "volume_24h_settle": "28613220", + "mark_price": "6534", + "funding_rate": "0.0001", + "funding_rate_indicative": "0.0001", + "index_price": "6531", + "highest_bid": "34089.7", + "lowest_ask": "34217.9" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetTrades.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetTrades.txt new file mode 100644 index 0000000..82cb98d --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/ExchangeData/GetTrades.txt @@ -0,0 +1,12 @@ +GET +/api/v4/futures/usdt/trades +false +[ + { + "id": 121234231, + "create_time": 1514764800, + "contract": "BTC_USDT", + "size": -100, + "price": "100.123" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelAllOrders.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelAllOrders.txt new file mode 100644 index 0000000..c60418d --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelAllOrders.txt @@ -0,0 +1,30 @@ +DELETE +/api/v4/futures/usdt/orders +true +[ + { + "id": 15675394, + "user": 100000, + "contract": "BTC_USDT", + "create_time": 1546569968, + "size": 6024, + "iceberg": 0, + "left": 6024, + "price": "3765", + "fill_price": "0", + "mkfr": "-0.00025", + "tkfr": "0.00075", + "tif": "gtc", + "refu": 0, + "is_reduce_only": false, + "is_close": false, + "is_liq": false, + "text": "t-my-custom-id", + "status": "finished", + "finish_time": 1514764900, + "finish_as": "cancelled", + "stp_id": 0, + "stp_act": "-", + "amend_text": "-" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrder.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrder.txt new file mode 100644 index 0000000..fad5760 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrder.txt @@ -0,0 +1,29 @@ +DELETE +/api/v4/futures/usdt/orders/123 +true + + { + "id": 15675394, + "user": 100000, + "contract": "BTC_USDT", + "create_time": 1546569968, + "size": 6024, + "iceberg": 0, + "left": 6024, + "price": "3765", + "fill_price": "0", + "mkfr": "-0.00025", + "tkfr": "0.00075", + "tif": "gtc", + "refu": 0, + "is_reduce_only": false, + "is_close": false, + "is_liq": false, + "text": "t-my-custom-id", + "status": "finished", + "finish_time": 1514764900, + "finish_as": "cancelled", + "stp_id": 0, + "stp_act": "-", + "amend_text": "-" + } diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrders.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrders.txt new file mode 100644 index 0000000..66b7887 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrders.txt @@ -0,0 +1,11 @@ +POST +/api/v4/futures/usdt/batch_cancel_orders +true +[ + { + "user_id": 111, + "id": "123456", + "succeeded": true, + "message": "" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrdersAfter.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrdersAfter.txt new file mode 100644 index 0000000..207fed3 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelOrdersAfter.txt @@ -0,0 +1,6 @@ +POST +/api/v4/futures/usdt/countdown_cancel_all +true +{ + "triggerTime": "1660039145000" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelTriggerOrder.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelTriggerOrder.txt new file mode 100644 index 0000000..f27c941 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelTriggerOrder.txt @@ -0,0 +1,26 @@ +DELETE +/api/v4/futures/usdt/price_orders/123 +true + { + "initial": { + "contract": "BTC_USDT", + "size": 100, + "price": "5.03" + }, + "trigger": { + "strategy_type": 0, + "price_type": 0, + "price": "3000", + "rule": 1, + "expiration": 86400 + }, + "id": 1283293, + "user": 1234, + "create_time": 1514764800, + "finish_time": 1514764900, + "trade_id": 13566, + "status": "finished", + "finish_as": "cancelled", + "reason": "", + "order_type": "close-long-order" + } \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelTriggerOrders.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelTriggerOrders.txt new file mode 100644 index 0000000..6434d5f --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/CancelTriggerOrders.txt @@ -0,0 +1,28 @@ +DELETE +/api/v4/futures/usdt/price_orders +true +[ + { + "initial": { + "contract": "BTC_USDT", + "size": 100, + "price": "5.03" + }, + "trigger": { + "strategy_type": 0, + "price_type": 0, + "price": "3000", + "rule": 1, + "expiration": 86400 + }, + "id": 1283293, + "user": 1234, + "create_time": 1514764800, + "finish_time": 1514764900, + "trade_id": 13566, + "status": "finished", + "finish_as": "cancelled", + "reason": "", + "order_type": "close-long-order" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/EditOrder.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/EditOrder.txt new file mode 100644 index 0000000..00239ec --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/EditOrder.txt @@ -0,0 +1,29 @@ +PUT +/api/v4/futures/usdt/orders/123 +true + + { + "id": 15675394, + "user": 100000, + "contract": "BTC_USDT", + "create_time": 1546569968, + "size": 6024, + "iceberg": 0, + "left": 6024, + "price": "3765", + "fill_price": "0", + "mkfr": "-0.00025", + "tkfr": "0.00075", + "tif": "gtc", + "refu": 0, + "is_reduce_only": false, + "is_close": false, + "is_liq": false, + "text": "t-my-custom-id", + "status": "finished", + "finish_time": 1514764900, + "finish_as": "cancelled", + "stp_id": 0, + "stp_act": "-", + "amend_text": "-" + } diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetAutoDeleveragingHistory.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetAutoDeleveragingHistory.txt new file mode 100644 index 0000000..c93e6bf --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetAutoDeleveragingHistory.txt @@ -0,0 +1,17 @@ +GET +/api/v4/futures/usdt/auto_deleverages +true +[ + { + "time": 1675841679, + "contract": "ACH_USDT", + "order_id": 73873128, + "user": 1666, + "cross_leverage_limit": "0", + "leverage": "0", + "entry_price": "2649.648633636364", + "fill_price": "2790.8082", + "position_size": 1, + "trade_size": -10 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetDualModePositions.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetDualModePositions.txt new file mode 100644 index 0000000..9af375c --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetDualModePositions.txt @@ -0,0 +1,38 @@ +GET +/api/v4/futures/usdt/dual_comp/positions/ETH_USDT +true +[ + { + "user": 10000, + "contract": "BTC_USDT", + "size": -9440, + "leverage": "0", + "risk_limit": "100", + "leverage_max": "100", + "maintenance_rate": "0.005", + "value": "3568.62", + "margin": "4.431548146258", + "entry_price": "3779.55", + "liq_price": "99999999", + "mark_price": "3780.32", + "unrealised_pnl": "-0.000507486844", + "realised_pnl": "0.045543982432", + "pnl_pnl": "0.045543982432", + "pnl_fund": "0", + "pnl_fee": "0", + "history_pnl": "0", + "last_close_pnl": "0", + "realised_point": "0", + "history_point": "0", + "adl_ranking": 5, + "pending_orders": 16, + "close_order": { + "id": 232323, + "price": "3779", + "is_liq": false + }, + "mode": "single", + "update_time": 1684994406, + "cross_leverage_limit": "0" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetLiquidationHistory.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetLiquidationHistory.txt new file mode 100644 index 0000000..f01adf3 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetLiquidationHistory.txt @@ -0,0 +1,19 @@ +GET +/api/v4/futures/usdt/liquidates +true +[ + { + "time": 1548654951, + "contract": "BTC_USDT", + "size": 600, + "leverage": "25", + "margin": "0.006705256878", + "entry_price": "3536.123", + "liq_price": "3421.54", + "mark_price": "3420.27", + "order_id": 317393847, + "order_price": "3405", + "fill_price": "3424", + "left": 0 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrder.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrder.txt new file mode 100644 index 0000000..385df63 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrder.txt @@ -0,0 +1,29 @@ +GET +/api/v4/futures/usdt/orders/123 +true + + { + "id": 15675394, + "user": 100000, + "contract": "BTC_USDT", + "create_time": 1546569968, + "size": 6024, + "iceberg": 0, + "left": 6024, + "price": "3765", + "fill_price": "0", + "mkfr": "-0.00025", + "tkfr": "0.00075", + "tif": "gtc", + "refu": 0, + "is_reduce_only": false, + "is_close": false, + "is_liq": false, + "text": "t-my-custom-id", + "status": "finished", + "finish_time": 1514764900, + "finish_as": "cancelled", + "stp_id": 0, + "stp_act": "-", + "amend_text": "-" + } diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrders.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrders.txt new file mode 100644 index 0000000..7777f09 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrders.txt @@ -0,0 +1,30 @@ +GET +/api/v4/futures/usdt/orders +true +[ + { + "id": 15675394, + "user": 100000, + "contract": "BTC_USDT", + "create_time": 1546569968, + "size": 6024, + "iceberg": 0, + "left": 6024, + "price": "3765", + "fill_price": "0", + "mkfr": "-0.00025", + "tkfr": "0.00075", + "tif": "gtc", + "refu": 0, + "is_reduce_only": false, + "is_close": false, + "is_liq": false, + "text": "t-my-custom-id", + "status": "finished", + "finish_time": 1514764900, + "finish_as": "cancelled", + "stp_id": 0, + "stp_act": "-", + "amend_text": "-" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrdersByTime.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrdersByTime.txt new file mode 100644 index 0000000..c4d5691 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetOrdersByTime.txt @@ -0,0 +1,30 @@ +GET +/api/v4/futures/usdt/orders_timerange +true +[ + { + "id": 15675394, + "user": 100000, + "contract": "BTC_USDT", + "create_time": 1546569968, + "size": 6024, + "iceberg": 0, + "left": 6024, + "price": "3765", + "fill_price": "0", + "mkfr": "-0.00025", + "tkfr": "0.00075", + "tif": "gtc", + "refu": 0, + "is_reduce_only": false, + "is_close": false, + "is_liq": false, + "text": "t-my-custom-id", + "status": "finished", + "finish_time": 1514764900, + "finish_as": "cancelled", + "stp_id": 0, + "stp_act": "-", + "amend_text": "-" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetPositionCloseHistory.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetPositionCloseHistory.txt new file mode 100644 index 0000000..0164e00 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetPositionCloseHistory.txt @@ -0,0 +1,19 @@ +GET +/api/v4/futures/usdt/position_close +true +[ + { + "time": 1546487347, + "pnl": "0.00013", + "pnl_pnl": "0.00011", + "pnl_fund": "0.00001", + "pnl_fee": "0.00001", + "side": "long", + "contract": "BTC_USDT", + "text": "web", + "max_size": "100", + "first_open_time": 1546487347, + "long_price": "2026.87", + "short_price": "2544.4" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetPositions.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetPositions.txt new file mode 100644 index 0000000..00d3928 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetPositions.txt @@ -0,0 +1,38 @@ +GET +/api/v4/futures/usdt/positions +true +[ + { + "user": 10000, + "contract": "BTC_USDT", + "size": -9440, + "leverage": "0", + "risk_limit": "100", + "leverage_max": "100", + "maintenance_rate": "0.005", + "value": "3568.62", + "margin": "4.431548146258", + "entry_price": "3779.55", + "liq_price": "99999999", + "mark_price": "3780.32", + "unrealised_pnl": "-0.000507486844", + "realised_pnl": "0.045543982432", + "pnl_pnl": "0.045543982432", + "pnl_fund": "0", + "pnl_fee": "0", + "history_pnl": "0", + "last_close_pnl": "0", + "realised_point": "0", + "history_point": "0", + "adl_ranking": 5, + "pending_orders": 16, + "close_order": { + "id": 232323, + "price": "3779", + "is_liq": false + }, + "mode": "single", + "update_time": 1684994406, + "cross_leverage_limit": "0" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetTriggerOrder.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetTriggerOrder.txt new file mode 100644 index 0000000..9926899 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetTriggerOrder.txt @@ -0,0 +1,26 @@ +GET +/api/v4/futures/usdt/price_orders/123 +true + { + "initial": { + "contract": "BTC_USDT", + "size": 100, + "price": "5.03" + }, + "trigger": { + "strategy_type": 0, + "price_type": 0, + "price": "3000", + "rule": 1, + "expiration": 86400 + }, + "id": 1283293, + "user": 1234, + "create_time": 1514764800, + "finish_time": 1514764900, + "trade_id": 13566, + "status": "finished", + "finish_as": "cancelled", + "reason": "", + "order_type": "close-long-order" + } \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetTriggerOrders.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetTriggerOrders.txt new file mode 100644 index 0000000..1c5771a --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetTriggerOrders.txt @@ -0,0 +1,28 @@ +GET +/api/v4/futures/usdt/price_orders +true +[ + { + "initial": { + "contract": "BTC_USDT", + "size": 100, + "price": "5.03" + }, + "trigger": { + "strategy_type": 0, + "price_type": 0, + "price": "3000", + "rule": 1, + "expiration": 86400 + }, + "id": 1283293, + "user": 1234, + "create_time": 1514764800, + "finish_time": 1514764900, + "trade_id": 13566, + "status": "finished", + "finish_as": "cancelled", + "reason": "", + "order_type": "close-long-order" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetUserTrades.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetUserTrades.txt new file mode 100644 index 0000000..c464ff3 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetUserTrades.txt @@ -0,0 +1,17 @@ +GET +/api/v4/futures/usdt/my_trades +true +[ + { + "id": 121234231, + "create_time": 1514764800.123, + "contract": "BTC_USDT", + "order_id": "21893289839", + "size": 100, + "price": "100.123", + "text": "t-123456", + "fee": "0.01", + "point_fee": "0", + "role": "taker" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetUserTradesByTimestamp.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetUserTradesByTimestamp.txt new file mode 100644 index 0000000..e471a7c --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/GetUserTradesByTimestamp.txt @@ -0,0 +1,17 @@ +GET +/api/v4/futures/usdt/my_trades_timerange +true +[ + { + "id": 121234231, + "create_time": 1514764800.123, + "contract": "BTC_USDT", + "order_id": "21893289839", + "size": 100, + "price": "100.123", + "text": "t-123456", + "fee": "0.01", + "point_fee": "0", + "role": "taker" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceMultipleOrder.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceMultipleOrder.txt new file mode 100644 index 0000000..5c3069d --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceMultipleOrder.txt @@ -0,0 +1,30 @@ +POST +/api/v4/futures/usdt/batch_orders +true +[ + { + "id": 15675394, + "user": 100000, + "contract": "BTC_USDT", + "create_time": 1546569968, + "size": 6024, + "iceberg": 0, + "left": 6024, + "price": "3765", + "fill_price": "0", + "mkfr": "-0.00025", + "tkfr": "0.00075", + "tif": "gtc", + "refu": 0, + "is_reduce_only": false, + "is_close": false, + "is_liq": false, + "text": "t-my-custom-id", + "status": "finished", + "finish_time": 1514764900, + "finish_as": "cancelled", + "stp_id": 0, + "stp_act": "-", + "amend_text": "-" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceOrder.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceOrder.txt new file mode 100644 index 0000000..ccfb5a1 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceOrder.txt @@ -0,0 +1,28 @@ +POST +/api/v4/futures/usdt/orders +true +{ + "id": 15675394, + "user": 100000, + "contract": "BTC_USDT", + "create_time": 1546569968, + "size": 6024, + "iceberg": 0, + "left": 6024, + "price": "3765", + "fill_price": "0", + "mkfr": "-0.00025", + "tkfr": "0.00075", + "tif": "gtc", + "refu": 0, + "is_reduce_only": false, + "is_close": false, + "is_liq": false, + "text": "t-my-custom-id", + "status": "finished", + "finish_time": 1514764900, + "finish_as": "cancelled", + "stp_id": 0, + "stp_act": "-", + "amend_text": "-" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceTriggerOrder.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceTriggerOrder.txt new file mode 100644 index 0000000..34a734d --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/PlaceTriggerOrder.txt @@ -0,0 +1,6 @@ +POST +/api/v4/futures/usdt/price_orders +true +{ + "id": 1432329 +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionLeverage.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionLeverage.txt new file mode 100644 index 0000000..062b3f5 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionLeverage.txt @@ -0,0 +1,38 @@ +POST +/api/v4/futures/usdt/dual_comp/positions/ETH_USDT/leverage +true +[ + { + "user": 10000, + "contract": "BTC_USDT", + "size": -9440, + "leverage": "0", + "risk_limit": "100", + "leverage_max": "100", + "maintenance_rate": "0.005", + "value": "3568.62", + "margin": "4.431548146258", + "entry_price": "3779.55", + "liq_price": "99999999", + "mark_price": "3780.32", + "unrealised_pnl": "-0.000507486844", + "realised_pnl": "0.045543982432", + "pnl_pnl": "0.045543982432", + "pnl_fund": "0", + "pnl_fee": "0", + "history_pnl": "0", + "last_close_pnl": "0", + "realised_point": "0", + "history_point": "0", + "adl_ranking": 5, + "pending_orders": 16, + "close_order": { + "id": 232323, + "price": "3779", + "is_liq": false + }, + "mode": "single", + "update_time": 1684994406, + "cross_leverage_limit": "0" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionMargin.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionMargin.txt new file mode 100644 index 0000000..17a7ffa --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionMargin.txt @@ -0,0 +1,38 @@ +POST +/api/v4/futures/usdt/dual_comp/positions/ETH_USDT/margin +true +[ + { + "user": 10000, + "contract": "BTC_USDT", + "size": -9440, + "leverage": "0", + "risk_limit": "100", + "leverage_max": "100", + "maintenance_rate": "0.005", + "value": "3568.62", + "margin": "4.431548146258", + "entry_price": "3779.55", + "liq_price": "99999999", + "mark_price": "3780.32", + "unrealised_pnl": "-0.000507486844", + "realised_pnl": "0.045543982432", + "pnl_pnl": "0.045543982432", + "pnl_fund": "0", + "pnl_fee": "0", + "history_pnl": "0", + "last_close_pnl": "0", + "realised_point": "0", + "history_point": "0", + "adl_ranking": 5, + "pending_orders": 16, + "close_order": { + "id": 232323, + "price": "3779", + "is_liq": false + }, + "mode": "single", + "update_time": 1684994406, + "cross_leverage_limit": "0" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionRiskLimit.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionRiskLimit.txt new file mode 100644 index 0000000..55a0d6a --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdateDualModePositionRiskLimit.txt @@ -0,0 +1,38 @@ +POST +/api/v4/futures/usdt/dual_comp/positions/ETH_USDT/risk_limit +true +[ + { + "user": 10000, + "contract": "BTC_USDT", + "size": -9440, + "leverage": "0", + "risk_limit": "100", + "leverage_max": "100", + "maintenance_rate": "0.005", + "value": "3568.62", + "margin": "4.431548146258", + "entry_price": "3779.55", + "liq_price": "99999999", + "mark_price": "3780.32", + "unrealised_pnl": "-0.000507486844", + "realised_pnl": "0.045543982432", + "pnl_pnl": "0.045543982432", + "pnl_fund": "0", + "pnl_fee": "0", + "history_pnl": "0", + "last_close_pnl": "0", + "realised_point": "0", + "history_point": "0", + "adl_ranking": 5, + "pending_orders": 16, + "close_order": { + "id": 232323, + "price": "3779", + "is_liq": false + }, + "mode": "single", + "update_time": 1684994406, + "cross_leverage_limit": "0" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionLeverage.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionLeverage.txt new file mode 100644 index 0000000..8611e99 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionLeverage.txt @@ -0,0 +1,36 @@ +POST +/api/v4/futures/usdt/positions/ETH_USDT/leverage +true +{ + "user": 10000, + "contract": "BTC_USDT", + "size": -9440, + "leverage": "0", + "risk_limit": "100", + "leverage_max": "100", + "maintenance_rate": "0.005", + "value": "3568.62", + "margin": "4.431548146258", + "entry_price": "3779.55", + "liq_price": "99999999", + "mark_price": "3780.32", + "unrealised_pnl": "-0.000507486844", + "realised_pnl": "0.045543982432", + "pnl_pnl": "0.045543982432", + "pnl_fund": "0", + "pnl_fee": "0", + "history_pnl": "0", + "last_close_pnl": "0", + "realised_point": "0", + "history_point": "0", + "adl_ranking": 5, + "pending_orders": 16, + "close_order": { + "id": 232323, + "price": "3779", + "is_liq": false + }, + "mode": "single", + "update_time": 1684994406, + "cross_leverage_limit": "0" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionMargin.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionMargin.txt new file mode 100644 index 0000000..a896a58 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionMargin.txt @@ -0,0 +1,36 @@ +POST +/api/v4/futures/usdt/positions/ETH_USDT/margin +true +{ + "user": 10000, + "contract": "BTC_USDT", + "size": -9440, + "leverage": "0", + "risk_limit": "100", + "leverage_max": "100", + "maintenance_rate": "0.005", + "value": "3568.62", + "margin": "4.431548146258", + "entry_price": "3779.55", + "liq_price": "99999999", + "mark_price": "3780.32", + "unrealised_pnl": "-0.000507486844", + "realised_pnl": "0.045543982432", + "pnl_pnl": "0.045543982432", + "pnl_fund": "0", + "pnl_fee": "0", + "history_pnl": "0", + "last_close_pnl": "0", + "realised_point": "0", + "history_point": "0", + "adl_ranking": 5, + "pending_orders": 16, + "close_order": { + "id": 232323, + "price": "3779", + "is_liq": false + }, + "mode": "single", + "update_time": 1684994406, + "cross_leverage_limit": "0" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionRiskLimit.txt b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionRiskLimit.txt new file mode 100644 index 0000000..d99c0ba --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/PerpetualFutures/Trading/UpdatePositionRiskLimit.txt @@ -0,0 +1,36 @@ +POST +/api/v4/futures/usdt/positions/ETH_USDT/risk_limit +true +{ + "user": 10000, + "contract": "BTC_USDT", + "size": -9440, + "leverage": "0", + "risk_limit": "100", + "leverage_max": "100", + "maintenance_rate": "0.005", + "value": "3568.62", + "margin": "4.431548146258", + "entry_price": "3779.55", + "liq_price": "99999999", + "mark_price": "3780.32", + "unrealised_pnl": "-0.000507486844", + "realised_pnl": "0.045543982432", + "pnl_pnl": "0.045543982432", + "pnl_fund": "0", + "pnl_fee": "0", + "history_pnl": "0", + "last_close_pnl": "0", + "realised_point": "0", + "history_point": "0", + "adl_ranking": 5, + "pending_orders": 16, + "close_order": { + "id": 232323, + "price": "3779", + "is_liq": false + }, + "mode": "single", + "update_time": 1684994406, + "cross_leverage_limit": "0" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/BorrowOrRepay.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/BorrowOrRepay.txt new file mode 100644 index 0000000..30aeb3a --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/BorrowOrRepay.txt @@ -0,0 +1,4 @@ +POST +/api/v4/unified/loans +true + diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/CancelWithdrawal.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/CancelWithdrawal.txt new file mode 100644 index 0000000..8548a77 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/CancelWithdrawal.txt @@ -0,0 +1,15 @@ +DELETE +/api/v4/withdrawals/123 +true +{ + "id": "210496", + "timestamp": "1542000000", + "withdraw_order_id": "order_123456", + "currency": "USDT", + "address": "1HkxtBAMrA3tP5ENnYY2CZortjZvFDH5Cs", + "txid": "128988928203223323290", + "amount": "222.61", + "memo": "", + "status": "DONE", + "chain": "TRX" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/ConvertSmallBalances.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/ConvertSmallBalances.txt new file mode 100644 index 0000000..0087c2e --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/ConvertSmallBalances.txt @@ -0,0 +1,4 @@ +POST +/api/v4/wallet/small_balance +true + diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/CreateCrossMarginLoan.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/CreateCrossMarginLoan.txt new file mode 100644 index 0000000..905694c --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/CreateCrossMarginLoan.txt @@ -0,0 +1,15 @@ +POST +/api/v4/margin/cross/loans +true +{ + "id": "17", + "create_time": 1620381696159, + "update_time": 1620381696159, + "currency": "EOS", + "amount": "110.553635", + "text": "web", + "status": 2, + "repaid": "110.506649705159", + "repaid_interest": "0.046985294841", + "unpaid_interest": "0.0000074393366667" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/CrossMarginRepay.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/CrossMarginRepay.txt new file mode 100644 index 0000000..2b6465c --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/CrossMarginRepay.txt @@ -0,0 +1,17 @@ +POST +/api/v4/margin/cross/repayments +true +[ + { + "id": "17", + "create_time": 1620381696159, + "update_time": 1620381696159, + "currency": "EOS", + "amount": "110.553635", + "text": "web", + "status": 2, + "repaid": "110.506649705159", + "repaid_interest": "0.046985294841", + "unpaid_interest": "0.0000074393366667" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GenerateDepositAddress.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GenerateDepositAddress.txt new file mode 100644 index 0000000..7ffb8c8 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GenerateDepositAddress.txt @@ -0,0 +1,16 @@ +GET +/api/v4/wallet/deposit_address +true +{ + "currency": "USDT", + "address": "LPXtk1kWHioP62SzfqwKbYE3Z7Wt2ujYEc", + "multichain_addresses": [ + { + "chain": "TRX", + "address": "LPXtk1kWHioP62SzfqwKbYE3Z7Wt2ujYEc", + "payment_id": "", + "payment_name": "", + "obtain_failed": 0 + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetAccountBalances.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetAccountBalances.txt new file mode 100644 index 0000000..e6c14ae --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetAccountBalances.txt @@ -0,0 +1,52 @@ +GET +/api/v4/wallet/total_balance +true +{ + "details": { + "cross_margin": { + "amount": "0", + "currency": "USDT" + }, + "spot": { + "currency": "USDT", + "amount": "42264489969935775.5160259954878034182418" + }, + "finance": { + "amount": "662714381.70310327810191647181", + "currency": "USDT" + }, + "margin": { + "amount": "1259175.664137668554329559", + "currency": "USDT", + "borrowed": "0.00" + }, + "quant": { + "amount": "591702859674467879.6488202650892478553852", + "currency": "USDT" + }, + "futures": { + "amount": "2384175.5606114082065", + "currency": "USDT", + "unrealised_pnl": "0.00" + }, + "delivery": { + "currency": "USDT", + "amount": "1519804.9756702", + "unrealised_pnl": "0.00" + }, + "warrant": { + "amount": "0", + "currency": "USDT" + }, + "cbbc": { + "currency": "USDT", + "amount": "0" + } + }, + "total": { + "currency": "USDT", + "amount": "633967350312281193.068368815439797304437", + "unrealised_pnl": "0.00", + "borrowed": "0.00" + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetAccountInfo.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetAccountInfo.txt new file mode 100644 index 0000000..d2a21e2 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetAccountInfo.txt @@ -0,0 +1,16 @@ +GET +/api/v4/account/detail +true +{ + "user_id": 1667201533, + "ip_whitelist": [ + "127.0.0.1" + ], + "currency_pairs": [ + "USDT_BTC" + ], + "key": { + "mode": 1 + }, + "tier": 2 +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetBalances.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetBalances.txt new file mode 100644 index 0000000..74923c6 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetBalances.txt @@ -0,0 +1,11 @@ +GET +/api/v4/spot/accounts +true +[ + { + "currency": "ETH", + "available": "968.8", + "locked": "0", + "update_id": 98 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginAccounts.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginAccounts.txt new file mode 100644 index 0000000..d064f47 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginAccounts.txt @@ -0,0 +1,55 @@ +GET +/api/v4/margin/cross/accounts +true +{ + "user_id": 10001, + "locked": false, + "balances": { + "ETH": { + "available": "0", + "freeze": "0", + "borrowed": "0.075393666654", + "interest": "0.0000106807603333", + "negative_liab": "0", + "futures_pos_liab": "0", + "equity": "1016.1", + "total_freeze": "0", + "total_liab": "0" + }, + "POINT": { + "available": "9999999999.017023138734", + "freeze": "0", + "borrowed": "0", + "interest": "0", + "negative_liab": "0", + "futures_pos_liab": "0", + "equity": "12016.1", + "total_freeze": "0", + "total_liab": "0" + }, + "USDT": { + "available": "0.00000062023", + "freeze": "0", + "borrowed": "0", + "interest": "0", + "negative_liab": "0", + "futures_pos_liab": "0", + "equity": "16.1", + "total_freeze": "0", + "total_liab": "0" + } + }, + "total": "230.94621713", + "borrowed": "161.66395521", + "interest": "0.02290237", + "risk": "1.4284", + "total_initial_margin": "1025.0524665088", + "total_margin_balance": "3382495.944473949183", + "total_maintenance_margin": "205.01049330176", + "total_initial_margin_rate": "3299.827135672679", + "total_maintenance_margin_rate": "16499.135678363399", + "total_available_margin": "3381470.892007440383", + "portfolio_margin_total": "3381470.892007440383", + "portfolio_margin_total_liab": "0", + "portfolio_margin_total_equity": "100016.1" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginBalanceHistory.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginBalanceHistory.txt new file mode 100644 index 0000000..20cf7b6 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginBalanceHistory.txt @@ -0,0 +1,13 @@ +GET +/api/v4/margin/cross/account_book +true +[ + { + "id": "123456", + "time": 1547633726123, + "currency": "BTC", + "change": "1.03", + "balance": "4.59316525194", + "type": "in" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginEstimatedInterestRates.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginEstimatedInterestRates.txt new file mode 100644 index 0000000..a20cb81 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginEstimatedInterestRates.txt @@ -0,0 +1,7 @@ +GET +/api/v4/margin/cross/estimate_rate +true +{ + "BTC": "0.000002", + "GT": "0.000001" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginInterestHistory.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginInterestHistory.txt new file mode 100644 index 0000000..d672dbd --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginInterestHistory.txt @@ -0,0 +1,14 @@ +GET +/api/v4/margin/cross/interest_records +true +[ + { + "status": 1, + "currency_pair": "BTC_USDT", + "currency": "USDT", + "actual_rate": "0.00000236", + "interest": "0.00006136", + "type": "platform", + "create_time": 1673247054000 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginLoan.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginLoan.txt new file mode 100644 index 0000000..6021a82 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginLoan.txt @@ -0,0 +1,15 @@ +GET +/api/v4/margin/cross/loans/123 +true +{ + "id": "17", + "create_time": 1620381696159, + "update_time": 1620381696159, + "currency": "EOS", + "amount": "110.553635", + "text": "web", + "status": 2, + "repaid": "110.506649705159", + "repaid_interest": "0.046985294841", + "unpaid_interest": "0.0000074393366667" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginLoans.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginLoans.txt new file mode 100644 index 0000000..98948fc --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginLoans.txt @@ -0,0 +1,17 @@ +GET +/api/v4/margin/cross/loans +true +[ + { + "id": "17", + "create_time": 1620381696159, + "update_time": 1620381696159, + "currency": "EOS", + "amount": "110.553635", + "text": "web", + "status": 2, + "repaid": "110.506649705159", + "repaid_interest": "0.046985294841", + "unpaid_interest": "0.0000074393366667" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginMaxBorrowable.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginMaxBorrowable.txt new file mode 100644 index 0000000..73dc80c --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginMaxBorrowable.txt @@ -0,0 +1,7 @@ +GET +/api/v4/margin/cross/borrowable +true +{ + "currency": "ETH", + "amount": "10000" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginMaxTransferable.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginMaxTransferable.txt new file mode 100644 index 0000000..e8d81f9 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginMaxTransferable.txt @@ -0,0 +1,7 @@ +GET +/api/v4/margin/cross/transferable +true +{ + "currency": "ETH", + "amount": "10000" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginRepayments.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginRepayments.txt new file mode 100644 index 0000000..0e8f18e --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetCrossMarginRepayments.txt @@ -0,0 +1,14 @@ +GET +/api/v4/margin/cross/repayments +true +[ + { + "id": "51", + "create_time": 1620696347990, + "loan_id": "30", + "currency": "BTC", + "principal": "5.385542", + "interest": "0.000044879516", + "repayment_type": "auto_repay" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetDeposits.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetDeposits.txt new file mode 100644 index 0000000..893ad72 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetDeposits.txt @@ -0,0 +1,17 @@ +GET +/api/v4/wallet/deposits +true +[ + { + "id": "210496", + "timestamp": "1542000000", + "withdraw_order_id": "order_123456", + "currency": "USDT", + "address": "1HkxtBAMrA3tP5ENnYY2CZortjZvFDH5Cs", + "txid": "128988928203223323290", + "amount": "222.61", + "memo": "", + "status": "DONE", + "chain": "TRX" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetEstimatedLendingRates.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetEstimatedLendingRates.txt new file mode 100644 index 0000000..c3c0d10 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetEstimatedLendingRates.txt @@ -0,0 +1,8 @@ +GET +/api/v4/unified/estimate_rate +true +{ + "BTC": "0.000002", + "GT": "0.000001", + "ETH": "" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetInterestHistory.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetInterestHistory.txt new file mode 100644 index 0000000..45e6693 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetInterestHistory.txt @@ -0,0 +1,14 @@ +GET +/api/v4/unified/interest_records +true +[ + { + "status": 1, + "currency_pair": "BTC_USDT", + "currency": "USDT", + "actual_rate": "0.00000236", + "interest": "0.00006136", + "type": "platform", + "create_time": 1673247054000 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLedger.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLedger.txt new file mode 100644 index 0000000..31d0ddb --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLedger.txt @@ -0,0 +1,14 @@ +GET +/api/v4/spot/account_book +true +[ + { + "id": "123456", + "time": 1547633726123, + "currency": "BTC", + "change": "1.03", + "balance": "4.59316525194", + "type": "margin_in", + "text": "3815099" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLoanHistory.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLoanHistory.txt new file mode 100644 index 0000000..d85c8ca --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLoanHistory.txt @@ -0,0 +1,15 @@ +GET +/api/v4/unified/loan_records +true +[ + { + "id": 16442, + "type": "borrow", + "margin_mode": "cross", + "currency_pair": "AE_USDT", + "currency": "USDT", + "amount": "1000", + "create_time": 1673247054000, + "repayment_type": "auto_repay" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLoans.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLoans.txt new file mode 100644 index 0000000..deaf323 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetLoans.txt @@ -0,0 +1,13 @@ +GET +/api/v4/unified/loans +true +[ + { + "currency": "USDT", + "currency_pair": "GT_USDT", + "amount": "1", + "type": "margin", + "change_time": 1673247054000, + "create_time": 1673247054000 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginAccounts.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginAccounts.txt new file mode 100644 index 0000000..1ce0a42 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginAccounts.txt @@ -0,0 +1,24 @@ +GET +/api/v4/margin/accounts +true +[ + { + "currency_pair": "ETH_BTC", + "locked": false, + "risk": "1.1", + "base": { + "currency": "ETH", + "available": "30.1", + "locked": "0", + "borrowed": "10.1", + "interest": "0" + }, + "quote": { + "currency": "BTC", + "available": "10", + "locked": "0", + "borrowed": "1.5", + "interest": "0" + } + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginAutoRepay.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginAutoRepay.txt new file mode 100644 index 0000000..f905daf --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginAutoRepay.txt @@ -0,0 +1,6 @@ +GET +/api/v4/margin/auto_repay +true +{ + "status": "on" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginBalanceHistory.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginBalanceHistory.txt new file mode 100644 index 0000000..2c573ec --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginBalanceHistory.txt @@ -0,0 +1,14 @@ +GET +/api/v4/margin/account_book +true +[ + { + "id": "123456", + "time": "1547633726", + "time_ms": 1547633726123, + "currency": "BTC", + "currency_pair": "BTC_USDT", + "change": "1.03", + "balance": "4.59316525194" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginFundingAccounts.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginFundingAccounts.txt new file mode 100644 index 0000000..902dd29 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginFundingAccounts.txt @@ -0,0 +1,12 @@ +GET +/api/v4/margin/funding_accounts +true +[ + { + "currency": "BTC", + "available": "1.238", + "locked": "0", + "lent": "3.32", + "total_lent": "3.32" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginInterestHistory.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginInterestHistory.txt new file mode 100644 index 0000000..83ae6b8 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginInterestHistory.txt @@ -0,0 +1,14 @@ +GET +/api/v4/margin/uni/interest_records +true +[ + { + "status": 1, + "currency_pair": "BTC_USDT", + "currency": "USDT", + "actual_rate": "0.00000236", + "interest": "0.00006136", + "type": "platform", + "create_time": 1673247054000 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginLoanHistory.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginLoanHistory.txt new file mode 100644 index 0000000..6fbbb3d --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginLoanHistory.txt @@ -0,0 +1,12 @@ +GET +/api/v4/margin/uni/loan_records +true +[ + { + "type": "borrow", + "currency_pair": "AE_USDT", + "currency": "USDT", + "amount": "1000", + "create_time": 1673247054000 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginLoans.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginLoans.txt new file mode 100644 index 0000000..080bf5b --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginLoans.txt @@ -0,0 +1,13 @@ +GET +/api/v4/margin/uni/loans +true +[ + { + "currency": "USDT", + "currency_pair": "GT_USDT", + "amount": "1", + "type": "margin", + "change_time": 1673247054000, + "create_time": 1673247054000 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginMaxBorrowable.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginMaxBorrowable.txt new file mode 100644 index 0000000..71de29a --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginMaxBorrowable.txt @@ -0,0 +1,8 @@ +GET +/api/v4/margin/uni/borrowable +true +{ + "currency": "AE", + "borrowable": "1123.344", + "currency_pair": "AE_USDT" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginMaxTransferable.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginMaxTransferable.txt new file mode 100644 index 0000000..06f4ea9 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetMarginMaxTransferable.txt @@ -0,0 +1,8 @@ +GET +/api/v4/margin/transferable +true +{ + "currency": "ETH", + "currency_pair": "ETH_USDT", + "amount": "10000" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetRiskUnits.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetRiskUnits.txt new file mode 100644 index 0000000..2548c5d --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetRiskUnits.txt @@ -0,0 +1,19 @@ +GET +/api/v4/unified/risk_units +true +{ + "user_id": 0, + "spot_hedge": true, + "risk_units": [ + { + "symbol": "BTC", + "spot_in_use": "-13500.000001223", + "maintain_margin": "2334.002", + "initial_margin": "2334.002", + "delta": "0.22", + "gamma": "0.42", + "theta": "0.29", + "vega": "0.22" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSavedAddress.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSavedAddress.txt new file mode 100644 index 0000000..99694e2 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSavedAddress.txt @@ -0,0 +1,13 @@ +GET +/api/v4/wallet/saved_address +true +[ + { + "currency": "usdt", + "chain": "TRX", + "address": "TWYirLzw2RARB2jfeFcfRPmeuU3rC7rakT", + "name": "gate", + "tag": "", + "verified": "1" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSmallBalanceConversions.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSmallBalanceConversions.txt new file mode 100644 index 0000000..73119dd --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSmallBalanceConversions.txt @@ -0,0 +1,12 @@ +GET +/api/v4/wallet/small_balance_history +true +[ + { + "id": "28583810", + "create_time": 1706670777, + "currency": "FLOKI", + "amount": "182.29400000", + "gt_amount": "0.001079" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSmallBalances.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSmallBalances.txt new file mode 100644 index 0000000..62fbb2f --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetSmallBalances.txt @@ -0,0 +1,17 @@ +GET +/api/v4/wallet/small_balance +true +[ + { + "currency": "FLOKI", + "available_balance": "182.29400000", + "estimated_as_btc": "0.00000012", + "convertible_to_gt": "0.001080" + }, + { + "currency": "MBLK", + "available_balance": "0.91723337", + "estimated_as_btc": "0.00000102", + "convertible_to_gt": "0.009188" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetTradingFee.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetTradingFee.txt new file mode 100644 index 0000000..68793ac --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetTradingFee.txt @@ -0,0 +1,18 @@ +GET +/api/v4/wallet/fee +true +{ + "user_id": 10001, + "taker_fee": "0.002", + "maker_fee": "0.002", + "futures_taker_fee": "-0.00025", + "futures_maker_fee": "0.00075", + "gt_discount": false, + "gt_taker_fee": "0", + "gt_maker_fee": "0", + "loan_fee": "0.18", + "point_type": "1", + "delivery_taker_fee": "0.00016", + "delivery_maker_fee": "-0.00015", + "debit_fee": 3 +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountBorrowable.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountBorrowable.txt new file mode 100644 index 0000000..3eedbda --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountBorrowable.txt @@ -0,0 +1,7 @@ +GET +/api/v4/unified/borrowable +true +{ + "currency": "ETH", + "amount": "10000" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountInfo.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountInfo.txt new file mode 100644 index 0000000..deb3123 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountInfo.txt @@ -0,0 +1,56 @@ +GET +/api/v4/unified/accounts +true +{ + "user_id": 10001, + "locked": false, + "balances": { + "ETH": { + "available": "0", + "freeze": "0", + "borrowed": "0.075393666654", + "negative_liab": "0", + "futures_pos_liab": "0", + "equity": "1016.1", + "total_freeze": "0", + "total_liab": "0", + "spot_in_use": "1.111" + }, + "POINT": { + "available": "9999999999.017023138734", + "freeze": "0", + "borrowed": "0", + "negative_liab": "0", + "futures_pos_liab": "0", + "equity": "12016.1", + "total_freeze": "0", + "total_liab": "0", + "spot_in_use": "12" + }, + "USDT": { + "available": "0.00000062023", + "freeze": "0", + "borrowed": "0", + "negative_liab": "0", + "futures_pos_liab": "0", + "equity": "16.1", + "total_freeze": "0", + "total_liab": "0", + "spot_in_use": "12" + } + }, + "total": "230.94621713", + "borrowed": "161.66395521", + "total_initial_margin": "1025.0524665088", + "total_margin_balance": "3382495.944473949183", + "total_maintenance_margin": "205.01049330176", + "total_initial_margin_rate": "3299.827135672679", + "total_maintenance_margin_rate": "16499.135678363399", + "total_available_margin": "3381470.892007440383", + "unified_account_total": "3381470.892007440383", + "unified_account_total_liab": "0", + "unified_account_total_equity": "100016.1", + "leverage": "2", + "spot_order_loss": "12", + "spot_hedge": false +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountMode.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountMode.txt new file mode 100644 index 0000000..10eab2c --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountMode.txt @@ -0,0 +1,9 @@ +GET +/api/v4/unified/unified_mode +true +{ + "mode": "portfolio", + "settings": { + "spot_hedge": true + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountTransferable.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountTransferable.txt new file mode 100644 index 0000000..c3df7cb --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetUnifiedAccountTransferable.txt @@ -0,0 +1,7 @@ +GET +/api/v4/unified/transferable +true +{ + "currency": "ETH", + "amount": "10000" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetWithdrawStatus.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetWithdrawStatus.txt new file mode 100644 index 0000000..2778177 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetWithdrawStatus.txt @@ -0,0 +1,27 @@ +GET +/api/v4/wallet/withdraw_status +true +[ + { + "currency": "GT", + "name": "GateToken", + "name_cn": "GateToken", + "deposit": "0", + "withdraw_percent": "0%", + "withdraw_fix": "0.01", + "withdraw_day_limit": "20000", + "withdraw_day_limit_remain": "20000", + "withdraw_amount_mini": "0.11", + "withdraw_eachtime_limit": "20000", + "withdraw_fix_on_chains": { + "BTC": "20", + "ETH": "15", + "TRX": "0", + "EOS": "2.5" + }, + "withdraw_percent_on_chains": { + "ETH": "0%", + "GTEVM": "0%" + } + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetWithdrawals.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetWithdrawals.txt new file mode 100644 index 0000000..2691cbc --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/GetWithdrawals.txt @@ -0,0 +1,18 @@ +GET +/api/v4/wallet/withdrawals +true +[ + { + "id": "210496", + "timestamp": "1542000000", + "withdraw_order_id": "order_123456", + "currency": "USDT", + "address": "1HkxtBAMrA3tP5ENnYY2CZortjZvFDH5Cs", + "txid": "128988928203223323290", + "amount": "222.61", + "fee": "0.01", + "memo": "", + "status": "DONE", + "chain": "TRX" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/MarginBorrowOrRepay.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/MarginBorrowOrRepay.txt new file mode 100644 index 0000000..ff0a8bd --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/MarginBorrowOrRepay.txt @@ -0,0 +1,4 @@ +POST +/api/v4/margin/uni/loans +true + diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/SetMarginAutoRepay.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/SetMarginAutoRepay.txt new file mode 100644 index 0000000..9820eff --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/SetMarginAutoRepay.txt @@ -0,0 +1,6 @@ +POST +/api/v4/margin/auto_repay +true +{ + "status": "on" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/SetUnifiedAccountMode.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/SetUnifiedAccountMode.txt new file mode 100644 index 0000000..315312b --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/SetUnifiedAccountMode.txt @@ -0,0 +1,3 @@ +PUT +/api/v4/unified/unified_mode +true diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/Transfer.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/Transfer.txt new file mode 100644 index 0000000..b16ffbd --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/Transfer.txt @@ -0,0 +1,6 @@ +POST +/api/v4/wallet/transfers +true +{ + "tx_id": 59636381286 +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Account/Withdraw.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Account/Withdraw.txt new file mode 100644 index 0000000..b67fb3f --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Account/Withdraw.txt @@ -0,0 +1,15 @@ +POST +/api/v4/withdrawals +true +{ + "id": "210496", + "timestamp": "1542000000", + "withdraw_order_id": "order_123456", + "currency": "USDT", + "address": "1HkxtBAMrA3tP5ENnYY2CZortjZvFDH5Cs", + "txid": "128988928203223323290", + "amount": "222.61", + "memo": "", + "status": "DONE", + "chain": "TRX" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetAsset.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetAsset.txt new file mode 100644 index 0000000..3ad0253 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetAsset.txt @@ -0,0 +1,12 @@ +GET +/api/v4/spot/currencies/BTC +false +{ +"currency": "GT", +"delisted": false, +"withdraw_disabled": false, +"withdraw_delayed": false, +"deposit_disabled": false, +"trade_disabled": false, +"chain": "GT" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetAssets.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetAssets.txt new file mode 100644 index 0000000..d03c555 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetAssets.txt @@ -0,0 +1,14 @@ +GET +/api/v4/spot/currencies +false +[ + { + "currency": "GT", + "delisted": false, + "withdraw_disabled": false, + "withdraw_delayed": false, + "deposit_disabled": false, + "trade_disabled": false, + "chain": "GT" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetCrossMarginAsset.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetCrossMarginAsset.txt new file mode 100644 index 0000000..ae19bd0 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetCrossMarginAsset.txt @@ -0,0 +1,15 @@ +GET +/api/v4/margin/cross/currencies/ETH +false +{ + "name": "BTC", + "rate": "0.0002", + "prec": "0.000001", + "discount": "1", + "min_borrow_amount": "0.01", + "user_max_borrow_amount": "1000000", + "total_max_borrow_amount": "10000000", + "price": "63015.5214", + "loanable": true, + "status": 1 +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetCrossMarginAssets.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetCrossMarginAssets.txt new file mode 100644 index 0000000..13b5ea4 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetCrossMarginAssets.txt @@ -0,0 +1,17 @@ +GET +/api/v4/margin/cross/currencies +false +[ + { + "name": "BTC", + "rate": "0.0002", + "prec": "0.000001", + "discount": "1", + "min_borrow_amount": "0.01", + "user_max_borrow_amount": "1000000", + "total_max_borrow_amount": "10000000", + "price": "63015.5214", + "loanable": true, + "status": 1 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetDiscountTiers.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetDiscountTiers.txt new file mode 100644 index 0000000..505651c --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetDiscountTiers.txt @@ -0,0 +1,4 @@ +GET +/api/v4/unified/currency_discount_tiers +false +[{"currency":"USDT","discount_tiers":[{"tier":"1","discount":"1","lower_limit":"0","upper_limit":"+"}]},{"currency":"USDC","discount_tiers":[{"tier":"1","discount":"1","lower_limit":"0","upper_limit":"10000000"},{"tier":"2","discount":"0.98","lower_limit":"10000000","upper_limit":"15000000"},{"tier":"3","discount":"0.95","lower_limit":"15000000","upper_limit":"20000000"},{"tier":"4","discount":"0.925","lower_limit":"20000000","upper_limit":"50000000"},{"tier":"5","discount":"0.9","lower_limit":"50000000","upper_limit":"100000000"},{"tier":"6","discount":"0","lower_limit":"100000000","upper_limit":"+"}]},{"currency":"BTC","discount_tiers":[{"tier":"1","discount":"1","lower_limit":"0","upper_limit":"5000000"},{"tier":"2","discount":"0.97","lower_limit":"5000000","upper_limit":"10000000"},{"tier":"3","discount":"0.95","lower_limit":"10000000","upper_limit":"20000000"},{"tier":"4","discount":"0.9","lower_limit":"20000000","upper_limit":"50000000"},{"tier":"5","discount":"0.8","lower_limit":"50000000","upper_limit":"100000000"},{"tier":"6","discount":"0","lower_limit":"100000000","upper_limit":"+"}]},{"currency":"ETH","discount_tiers":[{"tier":"1","discount":"1","lower_limit":"0","upper_limit":"2000000"},{"tier":"2","discount":"0.98","lower_limit":"2000000","upper_limit":"5000000"},{"tier":"3","discount":"0.97","lower_limit":"5000000","upper_limit":"10000000"},{"tier":"4","discount":"0.95","lower_limit":"10000000","upper_limit":"20000000"},{"tier":"5","discount":"0.9","lower_limit":"20000000","upper_limit":"40000000"},{"tier":"6","discount":"0.7","lower_limit":"40000000","upper_limit":"100000000"},{"tier":"7","discount":"0","lower_limit":"100000000","upper_limit":"+"}]},{"currency":"GT","discount_tiers":[{"tier":"1","discount":"0.95","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0.8","lower_limit":"50000","upper_limit":"100000"},{"tier":"3","discount":"0.5","lower_limit":"100000","upper_limit":"200000"},{"tier":"4","discount":"0.2","lower_limit":"200000","upper_limit":"1000000"},{"tier":"5","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"DOGE","discount_tiers":[{"tier":"1","discount":"0.95","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.9","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.85","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0.7","lower_limit":"2000000","upper_limit":"4000000"},{"tier":"5","discount":"0.5","lower_limit":"4000000","upper_limit":"5000000"},{"tier":"6","discount":"0","lower_limit":"5000000","upper_limit":"+"}]},{"currency":"LTC","discount_tiers":[{"tier":"1","discount":"0.95","lower_limit":"0","upper_limit":"1000000"},{"tier":"2","discount":"0.9","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"3","discount":"0.8","lower_limit":"2000000","upper_limit":"3000000"},{"tier":"4","discount":"0.3","lower_limit":"3000000","upper_limit":"5000000"},{"tier":"5","discount":"0","lower_limit":"5000000","upper_limit":"+"}]},{"currency":"SHIB","discount_tiers":[{"tier":"1","discount":"0.95","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.9","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.85","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.8","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0.4","lower_limit":"2000000","upper_limit":"3000000"},{"tier":"6","discount":"0.1","lower_limit":"3000000","upper_limit":"4000000"},{"tier":"7","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"XRP","discount_tiers":[{"tier":"1","discount":"0.95","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.9","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.85","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.8","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0.5","lower_limit":"2000000","upper_limit":"4000000"},{"tier":"6","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"ADA","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.8","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.7","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0.4","lower_limit":"2000000","upper_limit":"4000000"},{"tier":"5","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"ARB","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.8","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.7","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.6","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0.5","lower_limit":"2000000","upper_limit":"2500000"},{"tier":"6","discount":"0","lower_limit":"2500000","upper_limit":"+"}]},{"currency":"BCH","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.8","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.7","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0.4","lower_limit":"2000000","upper_limit":"3000000"},{"tier":"5","discount":"0.1","lower_limit":"3000000","upper_limit":"4000000"},{"tier":"6","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"BNB","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.8","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.7","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.6","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0.5","lower_limit":"2000000","upper_limit":"3000000"},{"tier":"6","discount":"0","lower_limit":"3000000","upper_limit":"+"}]},{"currency":"DOT","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.85","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.8","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.5","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0.1","lower_limit":"2000000","upper_limit":"4000000"},{"tier":"6","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"FIL","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.8","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.7","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0.5","lower_limit":"2000000","upper_limit":"3000000"},{"tier":"5","discount":"0","lower_limit":"3000000","upper_limit":"+"}]},{"currency":"FLOW","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.8","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.5","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"LINK","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.8","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.7","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.3","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0.1","lower_limit":"2000000","upper_limit":"4000000"},{"tier":"6","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"MATIC","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.8","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.5","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.3","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0.1","lower_limit":"2000000","upper_limit":"4000000"},{"tier":"6","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"SOL","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.8","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.7","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0.5","lower_limit":"2000000","upper_limit":"4000000"},{"tier":"5","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"SUSHI","discount_tiers":[{"tier":"1","discount":"0.9","lower_limit":"0","upper_limit":"250000"},{"tier":"2","discount":"0.6","lower_limit":"250000","upper_limit":"500000"},{"tier":"3","discount":"0.2","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"AAVE","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.6","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.3","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0","lower_limit":"2000000","upper_limit":"+"}]},{"currency":"AGIX","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.7","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.5","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0.2","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"5","discount":"0","lower_limit":"2000000","upper_limit":"+"}]},{"currency":"ALGO","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.7","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.6","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"APE","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.7","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.6","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"ASTR","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"100000"},{"tier":"2","discount":"0.7","lower_limit":"100000","upper_limit":"200000"},{"tier":"3","discount":"0.4","lower_limit":"200000","upper_limit":"500000"},{"tier":"4","discount":"0","lower_limit":"500000","upper_limit":"+"}]},{"currency":"ATOM","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.4","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.1","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0","lower_limit":"2000000","upper_limit":"+"}]},{"currency":"AVAX","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"1000000"},{"tier":"2","discount":"0.7","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"3","discount":"0.1","lower_limit":"2000000","upper_limit":"4000000"},{"tier":"4","discount":"0","lower_limit":"4000000","upper_limit":"+"}]},{"currency":"BLUR","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.6","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.5","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0.2","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"5","discount":"0","lower_limit":"1500000","upper_limit":"+"}]},{"currency":"BSV","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.7","lower_limit":"200000","upper_limit":"400000"},{"tier":"3","discount":"0.5","lower_limit":"400000","upper_limit":"600000"},{"tier":"4","discount":"0.1","lower_limit":"600000","upper_limit":"1000000"},{"tier":"5","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"CFX","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.7","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.4","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0","lower_limit":"1500000","upper_limit":"+"}]},{"currency":"EOS","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.7","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.4","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.2","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0","lower_limit":"2000000","upper_limit":"+"}]},{"currency":"ETC","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.7","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.6","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.5","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0.4","lower_limit":"2000000","upper_limit":"3000000"},{"tier":"6","discount":"0","lower_limit":"3000000","upper_limit":"+"}]},{"currency":"FLOKI","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.5","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0","lower_limit":"500000","upper_limit":"+"}]},{"currency":"GALA","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.7","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.4","lower_limit":"1000000","upper_limit":"1500000"},{"tier":"4","discount":"0.2","lower_limit":"1500000","upper_limit":"2000000"},{"tier":"5","discount":"0","lower_limit":"2000000","upper_limit":"+"}]},{"currency":"GMT","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.7","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.3","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"HBAR","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.7","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.5","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"INJ","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.7","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.4","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"MASK","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.7","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.5","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"NEAR","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.7","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.6","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0.4","lower_limit":"2000000","upper_limit":"3000000"},{"tier":"5","discount":"0","lower_limit":"3000000","upper_limit":"+"}]},{"currency":"SUI","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.7","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.6","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0.3","lower_limit":"2000000","upper_limit":"3000000"},{"tier":"5","discount":"0","lower_limit":"3000000","upper_limit":"+"}]},{"currency":"TRX","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"500000"},{"tier":"2","discount":"0.7","lower_limit":"500000","upper_limit":"1000000"},{"tier":"3","discount":"0.1","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"4","discount":"0","lower_limit":"2000000","upper_limit":"+"}]},{"currency":"UNI","discount_tiers":[{"tier":"1","discount":"0.8","lower_limit":"0","upper_limit":"250000"},{"tier":"2","discount":"0.7","lower_limit":"250000","upper_limit":"500000"},{"tier":"3","discount":"0.4","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0.2","lower_limit":"1000000","upper_limit":"2000000"},{"tier":"5","discount":"0","lower_limit":"2000000","upper_limit":"+"}]},{"currency":"DYDX","discount_tiers":[{"tier":"1","discount":"0.7","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.5","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.4","lower_limit":"500000","upper_limit":"1000000"},{"tier":"4","discount":"0","lower_limit":"1000000","upper_limit":"+"}]},{"currency":"AXS","discount_tiers":[{"tier":"1","discount":"0.6","lower_limit":"0","upper_limit":"100000"},{"tier":"2","discount":"0.5","lower_limit":"100000","upper_limit":"200000"},{"tier":"3","discount":"0.4","lower_limit":"200000","upper_limit":"400000"},{"tier":"4","discount":"0","lower_limit":"400000","upper_limit":"+"}]},{"currency":"LUNC","discount_tiers":[{"tier":"1","discount":"0.6","lower_limit":"0","upper_limit":"100000"},{"tier":"2","discount":"0.5","lower_limit":"100000","upper_limit":"200000"},{"tier":"3","discount":"0.2","lower_limit":"200000","upper_limit":"500000"},{"tier":"4","discount":"0","lower_limit":"500000","upper_limit":"+"}]},{"currency":"MAGIC","discount_tiers":[{"tier":"1","discount":"0.6","lower_limit":"0","upper_limit":"100000"},{"tier":"2","discount":"0.5","lower_limit":"100000","upper_limit":"200000"},{"tier":"3","discount":"0.1","lower_limit":"200000","upper_limit":"500000"},{"tier":"4","discount":"0","lower_limit":"500000","upper_limit":"+"}]},{"currency":"RUNE","discount_tiers":[{"tier":"1","discount":"0.6","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.5","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0.4","lower_limit":"500000","upper_limit":"800000"},{"tier":"4","discount":"0","lower_limit":"800000","upper_limit":"+"}]},{"currency":"WAVES","discount_tiers":[{"tier":"1","discount":"0.6","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.5","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0","lower_limit":"500000","upper_limit":"+"}]},{"currency":"ZIL","discount_tiers":[{"tier":"1","discount":"0.6","lower_limit":"0","upper_limit":"100000"},{"tier":"2","discount":"0.4","lower_limit":"100000","upper_limit":"200000"},{"tier":"3","discount":"0.2","lower_limit":"200000","upper_limit":"400000"},{"tier":"4","discount":"0","lower_limit":"400000","upper_limit":"+"}]},{"currency":"CRO","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0","lower_limit":"50000","upper_limit":"+"}]},{"currency":"ETHW","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0","lower_limit":"50000","upper_limit":"+"}]},{"currency":"FLUX","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0","lower_limit":"50000","upper_limit":"+"}]},{"currency":"ID","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0","lower_limit":"50000","upper_limit":"+"}]},{"currency":"JASMY","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"200000"},{"tier":"2","discount":"0.2","lower_limit":"200000","upper_limit":"500000"},{"tier":"3","discount":"0","lower_limit":"500000","upper_limit":"+"}]},{"currency":"KDA","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0","lower_limit":"50000","upper_limit":"+"}]},{"currency":"LOOKS","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0","lower_limit":"50000","upper_limit":"+"}]},{"currency":"LQTY","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0","lower_limit":"50000","upper_limit":"+"}]},{"currency":"SLP","discount_tiers":[{"tier":"1","discount":"0.5","lower_limit":"0","upper_limit":"50000"},{"tier":"2","discount":"0","lower_limit":"50000","upper_limit":"+"}]}] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetKlines.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetKlines.txt new file mode 100644 index 0000000..5ed93eb --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetKlines.txt @@ -0,0 +1,4 @@ +GET +/api/v4/spot/candlesticks +false +[["1717246800","1157762.86821200","67772.5","67839.9","67715","67715.1","17.07790000","true"]] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLendingSymbol.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLendingSymbol.txt new file mode 100644 index 0000000..953a361 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLendingSymbol.txt @@ -0,0 +1,9 @@ +GET +/api/v4/margin/uni/currency_pairs/ETH +false +{ + "currency_pair": "AE_USDT", + "base_min_borrow_amount": "100", + "quote_min_borrow_amount": "100", + "leverage": "3" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLendingSymbols.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLendingSymbols.txt new file mode 100644 index 0000000..4118fcf --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLendingSymbols.txt @@ -0,0 +1,11 @@ +GET +/api/v4/margin/uni/currency_pairs +false +[ + { + "currency_pair": "AE_USDT", + "base_min_borrow_amount": "100", + "quote_min_borrow_amount": "100", + "leverage": "3" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLoanMarginTiers.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLoanMarginTiers.txt new file mode 100644 index 0000000..c69a47b --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetLoanMarginTiers.txt @@ -0,0 +1,16 @@ +GET +/api/v4/unified/loan_margin_tiers +false +[ + { + "currency": "USDT", + "margin_tiers": [ + { + "tier": "1", + "margin_rate": "0.02", + "lower_limit": "200000", + "upper_limit": "400000" + } + ] + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetNetworks.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetNetworks.txt new file mode 100644 index 0000000..97da776 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetNetworks.txt @@ -0,0 +1,13 @@ +GET +/api/v4/wallet/currency_chains +false +[ + { + "chain": "ETH", + "name_cn": "ERC20", + "name_en": "ETH/ERC20", + "is_disabled": 0, + "is_deposit_disabled": 0, + "is_withdraw_disabled": 0 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetOrderBook.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetOrderBook.txt new file mode 100644 index 0000000..f1e1a0d --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetOrderBook.txt @@ -0,0 +1,28 @@ +GET +/api/v4/spot/order_book +false +{ + "id": 123456, + "current": 1623898993123, + "update": 1623898993121, + "asks": [ + [ + "1.52", + "1.151" + ], + [ + "1.53", + "1.218" + ] + ], + "bids": [ + [ + "1.17", + "201.863" + ], + [ + "1.16", + "725.464" + ] + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetSymbol.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetSymbol.txt new file mode 100644 index 0000000..7d8a2a5 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetSymbol.txt @@ -0,0 +1,18 @@ +GET +/api/v4/spot/currency_pairs/BTC_USDT +false +{ + "id": "ETH_USDT", + "base": "ETH", + "quote": "USDT", + "fee": "0.2", + "min_base_amount": "0.001", + "min_quote_amount": "1.0", + "max_base_amount": "10000", + "max_quote_amount": "10000000", + "amount_precision": 3, + "precision": 6, + "trade_status": "tradable", + "sell_start": 1516378650, + "buy_start": 1516378650 +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetSymbols.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetSymbols.txt new file mode 100644 index 0000000..b4fcbb7 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetSymbols.txt @@ -0,0 +1,20 @@ +GET +/api/v4/spot/currency_pairs +false +[ + { + "id": "ETH_USDT", + "base": "ETH", + "quote": "USDT", + "fee": "0.2", + "min_base_amount": "0.001", + "min_quote_amount": "1.0", + "max_base_amount": "10000", + "max_quote_amount": "10000000", + "amount_precision": 3, + "precision": 6, + "trade_status": "tradable", + "sell_start": 1516378650, + "buy_start": 1516378650 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetTickers.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetTickers.txt new file mode 100644 index 0000000..cdb925d --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetTickers.txt @@ -0,0 +1,22 @@ +GET +/api/v4/spot/tickers +false +[ + { + "currency_pair": "BTC3L_USDT", + "last": "2.46140352", + "lowest_ask": "2.477", + "highest_bid": "2.4606821", + "change_percentage": "-8.91", + "change_utc0": "-8.91", + "change_utc8": "-8.91", + "base_volume": "656614.0845820589", + "quote_volume": "1602221.66468375534639404191", + "high_24h": "2.7431", + "low_24h": "1.9863", + "etf_net_value": "2.46316141", + "etf_pre_net_value": "2.43201848", + "etf_pre_timestamp": 1611244800, + "etf_leverage": "2.2803019447281203" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetTrades.txt b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetTrades.txt new file mode 100644 index 0000000..7828d47 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/ExchangeData/GetTrades.txt @@ -0,0 +1,14 @@ +GET +/api/v4/spot/trades +false +[ + { + "id": "1232893232", + "create_time": "1548000000", + "create_time_ms": "1548000000123.456", + "side": "buy", + "amount": "0.15", + "price": "0.03", + "sequence_id": "588018" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelAllOders.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelAllOders.txt new file mode 100644 index 0000000..df3a7e0 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelAllOders.txt @@ -0,0 +1,39 @@ +DELETE +/api/v4/spot/orders +true +[ + { + "id": "1852454420", + "text": "t-abc123", + "amend_text": "-", + "succeeded": true, + "create_time": "1710488334", + "update_time": "1710488334", + "create_time_ms": 1710488334073, + "update_time_ms": 1710488334074, + "status": "closed", + "currency_pair": "BTC_USDT", + "type": "limit", + "account": "unified", + "side": "buy", + "amount": "0.001", + "price": "65000", + "time_in_force": "gtc", + "iceberg": "0", + "left": "0", + "filled_amount": "0.001", + "fill_price": "63.4693", + "filled_total": "63.4693", + "avg_deal_price": "63469.3", + "fee": "0.00000022", + "fee_currency": "BTC", + "point_fee": "0", + "gt_fee": "0", + "gt_maker_fee": "0", + "gt_taker_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "USDT", + "finish_as": "filled" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelAllTriggerOrders.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelAllTriggerOrders.txt new file mode 100644 index 0000000..24d97eb --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelAllTriggerOrders.txt @@ -0,0 +1,29 @@ +DELETE +/api/v4/spot/price_orders +true +[ + { + "trigger": { + "price": "100", + "rule": ">=", + "expiration": 3600 + }, + "put": { + "type": "limit", + "side": "buy", + "price": "2.15", + "amount": "2.00000000", + "account": "normal", + "time_in_force": "gtc", + "text": "api" + }, + "id": 1283293, + "user": 1234, + "market": "GT_USDT", + "ctime": 1616397800, + "ftime": 1616397801, + "fired_order_id": 0, + "status": "", + "reason": "" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrder.txt new file mode 100644 index 0000000..214e635 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrder.txt @@ -0,0 +1,36 @@ +DELETE +/api/v4/spot/orders/123 +true +{ + "id": "1852454420", + "text": "t-abc123", + "amend_text": "-", + "create_time": "1710488334", + "update_time": "1710488334", + "create_time_ms": 1710488334073, + "update_time_ms": 1710488334074, + "status": "closed", + "currency_pair": "BTC_USDT", + "type": "limit", + "account": "unified", + "side": "buy", + "amount": "0.001", + "price": "65000", + "time_in_force": "gtc", + "iceberg": "0", + "left": "0", + "filled_amount": "0.001", + "fill_price": "63.4693", + "filled_total": "63.4693", + "avg_deal_price": "63469.3", + "fee": "0.00000022", + "fee_currency": "BTC", + "point_fee": "0", + "gt_fee": "0", + "gt_maker_fee": "0", + "gt_taker_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "USDT", + "finish_as": "filled" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrders.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrders.txt new file mode 100644 index 0000000..0af6dd7 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrders.txt @@ -0,0 +1,13 @@ +POST +/api/v4/spot/cancel_batch_orders +true +[ + { + "currency_pair": "BTC_USDT", + "id": "123456", + "text": "123456", + "succeeded": true, + "label": null, + "message": null + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrdersAfter.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrdersAfter.txt new file mode 100644 index 0000000..884f700 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelOrdersAfter.txt @@ -0,0 +1,6 @@ +POST +/api/v4/spot/countdown_cancel_all +true +{ + "triggerTime": "1660039145000" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelTriggerOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelTriggerOrder.txt new file mode 100644 index 0000000..0b41db7 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/CancelTriggerOrder.txt @@ -0,0 +1,27 @@ +DELETE +/api/v4/spot/price_orders/123 +true +{ + "trigger": { + "price": "100", + "rule": ">=", + "expiration": 3600 + }, + "put": { + "type": "limit", + "side": "buy", + "price": "2.15", + "amount": "2.00000000", + "account": "normal", + "time_in_force": "gtc", + "text": "api" + }, + "id": 1283293, + "user": 1234, + "market": "GT_USDT", + "ctime": 1616397800, + "ftime": 1616397801, + "fired_order_id": 0, + "status": "", + "reason": "" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/EditMultipleOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/EditMultipleOrder.txt new file mode 100644 index 0000000..4259532 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/EditMultipleOrder.txt @@ -0,0 +1,41 @@ +POST +/api/v4/spot/amend_batch_orders +true +[ + { + "order_id": "12332324", + "amend_text": "t-123456", + "text": "t-123456", + "succeeded": true, + "label": "", + "message": "", + "id": "12332324", + "create_time": "1548000000", + "update_time": "1548000100", + "create_time_ms": 1548000000123, + "update_time_ms": 1548000100123, + "currency_pair": "ETC_BTC", + "status": "cancelled", + "type": "limit", + "account": "spot", + "side": "buy", + "amount": "1", + "price": "5.00032", + "time_in_force": "gtc", + "iceberg": "0", + "left": "0.5", + "filled_amount": "1.242", + "filled_total": "2.50016", + "avg_deal_price": "5.00032", + "fee": "0.005", + "fee_currency": "ETH", + "point_fee": "0", + "gt_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "BTC", + "stp_act": "cn", + "finish_as": "stp", + "stp_id": 10240 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/EditOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/EditOrder.txt new file mode 100644 index 0000000..7e1698e --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/EditOrder.txt @@ -0,0 +1,36 @@ +PATCH +/api/v4/spot/orders/123 +true +{ + "id": "1852454420", + "text": "t-abc123", + "amend_text": "-", + "create_time": "1710488334", + "update_time": "1710488334", + "create_time_ms": 1710488334073, + "update_time_ms": 1710488334074, + "status": "closed", + "currency_pair": "BTC_USDT", + "type": "limit", + "account": "unified", + "side": "buy", + "amount": "0.001", + "price": "65000", + "time_in_force": "gtc", + "iceberg": "0", + "left": "0", + "filled_amount": "0.001", + "fill_price": "63.4693", + "filled_total": "63.4693", + "avg_deal_price": "63469.3", + "fee": "0.00000022", + "fee_currency": "BTC", + "point_fee": "0", + "gt_fee": "0", + "gt_maker_fee": "0", + "gt_taker_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "USDT", + "finish_as": "filled" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOpenOrders.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOpenOrders.txt new file mode 100644 index 0000000..d03ccf9 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOpenOrders.txt @@ -0,0 +1,34 @@ +GET +/api/v4/spot/open_orders +true +[ + { + "currency_pair": "ETH_BTC", + "total": 1, + "orders": [ + { + "id": "12332324", + "text": "t-123456", + "create_time": "1548000000", + "update_time": "1548000100", + "currency_pair": "ETH_BTC", + "status": "open", + "type": "limit", + "account": "spot", + "side": "buy", + "amount": "1", + "price": "5.00032", + "time_in_force": "gtc", + "left": "0.5", + "filled_total": "2.50016", + "fee": "0.005", + "fee_currency": "ETH", + "point_fee": "0", + "gt_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "BTC" + } + ] + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOrder.txt new file mode 100644 index 0000000..9e227d0 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOrder.txt @@ -0,0 +1,36 @@ +GET +/api/v4/spot/orders/123 +true +{ + "id": "1852454420", + "text": "t-abc123", + "amend_text": "-", + "create_time": "1710488334", + "update_time": "1710488334", + "create_time_ms": 1710488334073, + "update_time_ms": 1710488334074, + "status": "closed", + "currency_pair": "BTC_USDT", + "type": "limit", + "account": "unified", + "side": "buy", + "amount": "0.001", + "price": "65000", + "time_in_force": "gtc", + "iceberg": "0", + "left": "0", + "filled_amount": "0.001", + "fill_price": "63.4693", + "filled_total": "63.4693", + "avg_deal_price": "63469.3", + "fee": "0.00000022", + "fee_currency": "BTC", + "point_fee": "0", + "gt_fee": "0", + "gt_maker_fee": "0", + "gt_taker_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "USDT", + "finish_as": "filled" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOrders.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOrders.txt new file mode 100644 index 0000000..6a20bc3 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetOrders.txt @@ -0,0 +1,38 @@ +GET +/api/v4/spot/orders +true +[ + { + "id": "1852454420", + "text": "t-abc123", + "amend_text": "-", + "create_time": "1710488334", + "update_time": "1710488334", + "create_time_ms": 1710488334073, + "update_time_ms": 1710488334074, + "status": "closed", + "currency_pair": "BTC_USDT", + "type": "limit", + "account": "unified", + "side": "buy", + "amount": "0.001", + "price": "65000", + "time_in_force": "gtc", + "iceberg": "0", + "left": "0", + "filled_amount": "0.001", + "fill_price": "63.4693", + "filled_total": "63.4693", + "avg_deal_price": "63469.3", + "fee": "0.00000022", + "fee_currency": "BTC", + "point_fee": "0", + "gt_fee": "0", + "gt_maker_fee": "0", + "gt_taker_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "USDT", + "finish_as": "filled" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetTriggerOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetTriggerOrder.txt new file mode 100644 index 0000000..f262d7e --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetTriggerOrder.txt @@ -0,0 +1,27 @@ +GET +/api/v4/spot/price_orders/123 +true +{ + "trigger": { + "price": "100", + "rule": ">=", + "expiration": 3600 + }, + "put": { + "type": "limit", + "side": "buy", + "price": "2.15", + "amount": "2.00000000", + "account": "normal", + "time_in_force": "gtc", + "text": "api" + }, + "id": 1283293, + "user": 1234, + "market": "GT_USDT", + "ctime": 1616397800, + "ftime": 1616397801, + "fired_order_id": 0, + "status": "", + "reason": "" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetTriggerOrders.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetTriggerOrders.txt new file mode 100644 index 0000000..51d33b2 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetTriggerOrders.txt @@ -0,0 +1,29 @@ +GET +/api/v4/spot/price_orders +true +[ + { + "trigger": { + "price": "100", + "rule": ">=", + "expiration": 3600 + }, + "put": { + "type": "limit", + "side": "buy", + "price": "2.15", + "amount": "2.00000000", + "account": "normal", + "time_in_force": "gtc", + "text": "api" + }, + "id": 1283293, + "user": 1234, + "market": "GT_USDT", + "ctime": 1616397800, + "ftime": 1616397801, + "fired_order_id": 0, + "status": "", + "reason": "" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetUserTrades.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetUserTrades.txt new file mode 100644 index 0000000..0673683 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/GetUserTrades.txt @@ -0,0 +1,21 @@ +GET +/api/v4/spot/my_trades +true +[ + { + "id": "1232893232", + "create_time": "1548000000", + "create_time_ms": "1548000000123.456", + "order_id": "4128442423", + "side": "buy", + "role": "maker", + "amount": "0.15", + "price": "0.03", + "fee": "0.0005", + "fee_currency": "ETH", + "point_fee": "0", + "gt_fee": "0", + "sequence_id": "588018", + "text": "t-test" + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceMultipleOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceMultipleOrder.txt new file mode 100644 index 0000000..41a88a9 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceMultipleOrder.txt @@ -0,0 +1,41 @@ +POST +/api/v4/spot/batch_orders +true +[ + { + "order_id": "12332324", + "amend_text": "t-123456", + "text": "t-123456", + "succeeded": true, + "label": "", + "message": "", + "id": "12332324", + "create_time": "1548000000", + "update_time": "1548000100", + "create_time_ms": 1548000000123, + "update_time_ms": 1548000100123, + "currency_pair": "ETC_BTC", + "status": "cancelled", + "type": "limit", + "account": "spot", + "side": "buy", + "amount": "1", + "price": "5.00032", + "time_in_force": "gtc", + "iceberg": "0", + "left": "0.5", + "filled_amount": "1.242", + "filled_total": "2.50016", + "avg_deal_price": "5.00032", + "fee": "0.005", + "fee_currency": "ETH", + "point_fee": "0", + "gt_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "BTC", + "stp_act": "cn", + "finish_as": "stp", + "stp_id": 10240 + } +] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceOrder.txt new file mode 100644 index 0000000..1789cfd --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceOrder.txt @@ -0,0 +1,36 @@ +POST +/api/v4/spot/orders +true +{ + "id": "1852454420", + "text": "t-abc123", + "amend_text": "-", + "create_time": "1710488334", + "update_time": "1710488334", + "create_time_ms": 1710488334073, + "update_time_ms": 1710488334074, + "status": "closed", + "currency_pair": "BTC_USDT", + "type": "limit", + "account": "unified", + "side": "buy", + "amount": "0.001", + "price": "65000", + "time_in_force": "gtc", + "iceberg": "0", + "left": "0", + "filled_amount": "0.001", + "fill_price": "63.4693", + "filled_total": "63.4693", + "avg_deal_price": "63469.3", + "fee": "0.00000022", + "fee_currency": "BTC", + "point_fee": "0", + "gt_fee": "0", + "gt_maker_fee": "0", + "gt_taker_fee": "0", + "gt_discount": false, + "rebated_fee": "0", + "rebated_fee_currency": "USDT", + "finish_as": "filled" +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceTriggerOrder.txt b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceTriggerOrder.txt new file mode 100644 index 0000000..2205009 --- /dev/null +++ b/GateIo.Net.UnitTests/Endpoints/Spot/Trading/PlaceTriggerOrder.txt @@ -0,0 +1,6 @@ +POST +/api/v4/spot/price_orders +true +{ + "id": 1432329 +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/GateIo.Net.UnitTests.csproj b/GateIo.Net.UnitTests/GateIo.Net.UnitTests.csproj new file mode 100644 index 0000000..3cd3644 --- /dev/null +++ b/GateIo.Net.UnitTests/GateIo.Net.UnitTests.csproj @@ -0,0 +1,20 @@ + + + + net6.0 + + false + + + + + + + + + + + + + + diff --git a/GateIo.Net.UnitTests/GateIoRestClientTests.cs b/GateIo.Net.UnitTests/GateIoRestClientTests.cs new file mode 100644 index 0000000..e578c0e --- /dev/null +++ b/GateIo.Net.UnitTests/GateIoRestClientTests.cs @@ -0,0 +1,47 @@ +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Clients; +using CryptoExchange.Net.Converters.JsonNet; +using NUnit.Framework; +using System.Collections.Generic; +using System.Net.Http; +using GateIo.Net.Clients; +using GateIo.Net; + +namespace Gate.io.Net.UnitTests +{ + [TestFixture()] + public class GateIoRestClientTests + { + //[Test] + public void CheckSignatureExample1() + { + var authProvider = new GateIoAuthenticationProvider(new ApiCredentials("vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A", "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j")); + var client = (RestApiClient)new GateIoRestClient().SpotApi; + + CryptoExchange.Net.Testing.TestHelpers.CheckSignature( + client, + authProvider, + HttpMethod.Post, + "/api/v3/order", + (uriParams, bodyParams, headers) => + { + return bodyParams["signature"].ToString(); + }, + "c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71", + new Dictionary + { + { "symbol", "LTCBTC" }, + }, + DateTimeConverter.ParseFromLong(1499827319559), + true, + false); + } + + [Test] + public void CheckInterfaces() + { + CryptoExchange.Net.Testing.TestHelpers.CheckForMissingRestInterfaces(); + CryptoExchange.Net.Testing.TestHelpers.CheckForMissingSocketInterfaces(); + } + } +} diff --git a/GateIo.Net.UnitTests/Properties/AssemblyInfo.cs b/GateIo.Net.UnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..77f5a5a --- /dev/null +++ b/GateIo.Net.UnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,9 @@ +using System.Runtime.InteropServices; + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("aed4b7eb-e3f6-407a-9852-01a2458216b0")] \ No newline at end of file diff --git a/GateIo.Net.UnitTests/RestRequestTests.cs b/GateIo.Net.UnitTests/RestRequestTests.cs new file mode 100644 index 0000000..38fb5de --- /dev/null +++ b/GateIo.Net.UnitTests/RestRequestTests.cs @@ -0,0 +1,217 @@ +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Testing; +using GateIo.Net.Clients; +using GateIo.Net.Enums; +using GateIo.Net.Objects.Models; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Gate.io.Net.UnitTests +{ + [TestFixture] + public class RestRequestTests + { + [Test] + public async Task ValidateSpotAccountCalls() + { + var client = new GateIoRestClient(opts => + { + opts.AutoTimestamp = false; + opts.ApiCredentials = new CryptoExchange.Net.Authentication.ApiCredentials("123", "456"); + }); + var tester = new RestRequestValidator(client, "Endpoints/Spot/Account", "https://api.gateio.ws", IsAuthenticated, stjCompare: true); + await tester.ValidateAsync(client => client.SpotApi.Account.GetBalancesAsync(), "GetBalances"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetLedgerAsync(), "GetLedger"); + await tester.ValidateAsync(client => client.SpotApi.Account.WithdrawAsync("ETH", 1, "123", "ETH"), "Withdraw"); + await tester.ValidateAsync(client => client.SpotApi.Account.CancelWithdrawalAsync("123"), "CancelWithdrawal"); + await tester.ValidateAsync(client => client.SpotApi.Account.GenerateDepositAddressAsync("ETH"), "GenerateDepositAddress"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetWithdrawalsAsync(), "GetWithdrawals"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetDepositsAsync(), "GetDeposits"); + await tester.ValidateAsync(client => client.SpotApi.Account.TransferAsync("ETH", AccountType.Spot, AccountType.PerpertualFutures, 1), "Transfer"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetWithdrawStatusAsync(), "GetWithdrawStatus"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetSavedAddressAsync("ETH"), "GetSavedAddress", ignoreProperties: new List { "verified" }); + await tester.ValidateAsync(client => client.SpotApi.Account.GetTradingFeeAsync(), "GetTradingFee", ignoreProperties: new List { "point_type" }); + await tester.ValidateAsync(client => client.SpotApi.Account.GetAccountBalancesAsync(), "GetAccountBalances"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetSmallBalancesAsync(), "GetSmallBalances"); + await tester.ValidateAsync(client => client.SpotApi.Account.ConvertSmallBalancesAsync(), "ConvertSmallBalances"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetSmallBalanceConversionsAsync(), "GetSmallBalanceConversions"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountInfoAsync(), "GetUnifiedAccountInfo"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountBorrowableAsync("ETH"), "GetUnifiedAccountBorrowable"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountTransferableAsync("ETH"), "GetUnifiedAccountTransferable"); + await tester.ValidateAsync(client => client.SpotApi.Account.UnifiedAccountBorrowOrRepayAsync("ETH", BorrowDirection.Borrow, 10), "BorrowOrRepay"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountLoansAsync("ETH"), "GetLoans"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountLoanHistoryAsync(), "GetLoanHistory"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountInterestHistoryAsync(), "GetInterestHistory"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountRiskUnitsAsync(), "GetRiskUnits"); + await tester.ValidateAsync(client => client.SpotApi.Account.SetUnifiedAccountModeAsync(UnifiedAccountMode.Classic), "SetUnifiedAccountMode"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountModeAsync(), "GetUnifiedAccountMode"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetUnifiedAccountEstimatedLendingRatesAsync(new[] { "ETH" }), "GetEstimatedLendingRates"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetAccountInfoAsync(), "GetAccountInfo"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginAccountsAsync(), "GetMarginAccounts"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginBalanceHistoryAsync(), "GetMarginBalanceHistory", ignoreProperties: new List { "time" }); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginFundingAccountsAsync(), "GetMarginFundingAccounts"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginFundingAccountsAsync(), "GetMarginFundingAccounts"); + await tester.ValidateAsync(client => client.SpotApi.Account.SetMarginAutoRepayAsync(true), "SetMarginAutoRepay"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginMaxTransferableAsync("ETH"), "GetMarginMaxTransferable"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginAccountsAsync(), "GetCrossMarginAccounts"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginBalanceHistoryAsync(), "GetCrossMarginBalanceHistory"); + await tester.ValidateAsync(client => client.SpotApi.Account.CreateCrossMarginLoanAsync("ETH", 1), "CreateCrossMarginLoan"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginLoansAsync("ETH"), "GetCrossMarginLoans"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginLoanAsync("123"), "GetCrossMarginLoan"); + await tester.ValidateAsync(client => client.SpotApi.Account.CrossMarginRepayAsync("ETH", 123), "CrossMarginRepay"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginRepaymentsAsync("ETH"), "GetCrossMarginRepayments"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginInterestHistoryAsync("ETH"), "GetCrossMarginInterestHistory"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginMaxTransferableAsync("ETH"), "GetCrossMarginMaxTransferable"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginEstimatedInterestRatesAsync(new[] { "ETH" }), "GetCrossMarginEstimatedInterestRates"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetCrossMarginMaxBorrowableAsync("ETH"), "GetCrossMarginMaxBorrowable"); + await tester.ValidateAsync(client => client.SpotApi.Account.BorrowOrRepayAsync("ETH", "ETH_USDT", BorrowDirection.Borrow, 1), "MarginBorrowOrRepay"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginLoansAsync(), "GetMarginLoans"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginLoanHistoryAsync(), "GetMarginLoanHistory"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginInterestHistoryAsync(), "GetMarginInterestHistory"); + await tester.ValidateAsync(client => client.SpotApi.Account.GetMarginMaxBorrowableAsync("ETH", "ETH_USDT"), "GetMarginMaxBorrowable"); + } + + [Test] + public async Task ValidateSpotExchangeDataCalls() + { + var client = new GateIoRestClient(opts => + { + opts.AutoTimestamp = false; + opts.ApiCredentials = new CryptoExchange.Net.Authentication.ApiCredentials("123", "456"); + }); + var tester = new RestRequestValidator(client, "Endpoints/Spot/ExchangeData", "https://api.gateio.ws", IsAuthenticated, stjCompare: true); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetAssetsAsync(), "GetAssets"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetAssetAsync("BTC"), "GetAsset"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetSymbolAsync("BTC_USDT"), "GetSymbol"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetSymbolsAsync(), "GetSymbols"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetTickersAsync(), "GetTickers"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetOrderBookAsync("BTC_USDT"), "GetOrderBook"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetTradesAsync("BTC_USDT"), "GetTrades", ignoreProperties: new List { "create_time" }); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetKlinesAsync("BTC_USDT", KlineInterval.OneDay), "GetKlines"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetNetworksAsync("BTC"), "GetNetworks"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetDiscountTiersAsync(), "GetDiscountTiers"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetLoanMarginTiersAsync(), "GetLoanMarginTiers"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetCrossMarginAssetAsync("ETH"), "GetCrossMarginAsset"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetCrossMarginAssetsAsync(), "GetCrossMarginAssets"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetLendingSymbolsAsync(), "GetLendingSymbols"); + await tester.ValidateAsync(client => client.SpotApi.ExchangeData.GetLendingSymbolAsync("ETH"), "GetLendingSymbol"); + + } + + [Test] + public async Task ValidateSpotTradingCalls() + { + var client = new GateIoRestClient(opts => + { + opts.AutoTimestamp = false; + opts.ApiCredentials = new CryptoExchange.Net.Authentication.ApiCredentials("123", "456"); + }); + var tester = new RestRequestValidator(client, "Endpoints/Spot/Trading", "https://api.gateio.ws", IsAuthenticated, stjCompare: true); + await tester.ValidateAsync(client => client.SpotApi.Trading.PlaceOrderAsync("ETH_USDT", OrderSide.Buy, NewOrderType.Limit, 40), "PlaceOrder", ignoreProperties: new List { "create_time", "update_time", "fill_price", "" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.GetOpenOrdersAsync(), "GetOpenOrders", ignoreProperties: new List { "create_time", "update_time", "fill_price" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.GetOrdersAsync(true, "ETH_USDT"), "GetOrders", ignoreProperties: new List { "create_time", "update_time", "fill_price" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.GetOrderAsync("ETH_USDT", 123), "GetOrder", ignoreProperties: new List { "create_time", "update_time", "fill_price" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.CancelAllOrdersAsync("ETH_USDT"), "CancelAllOders", ignoreProperties: new List { "create_time", "update_time", "fill_price" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.CancelOrdersAsync(new[] { new GateIoBatchCancelRequest { Id = "123", Symbol = "ETH_USDT" } }), "CancelOrders"); + await tester.ValidateAsync(client => client.SpotApi.Trading.EditOrderAsync("ETH_USDT", 123, 123), "EditOrder", ignoreProperties: new List { "create_time", "update_time", "fill_price" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.CancelOrderAsync("ETH_USDT", 123), "CancelOrder", ignoreProperties: new List { "create_time", "update_time", "fill_price" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.GetUserTradesAsync(), "GetUserTrades", ignoreProperties: new List { "create_time" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.CancelOrdersAfterAsync(TimeSpan.Zero), "CancelOrdersAfter"); + await tester.ValidateAsync(client => client.SpotApi.Trading.PlaceTriggerOrderAsync("ETH_USDT", OrderSide.Sell, NewOrderType.Market, TriggerType.EqualOrHigher, 2000, TimeSpan.FromMinutes(10), 10, TriggerAccountType.Normal, TimeInForce.GoodTillCancel), "PlaceTriggerOrder"); + await tester.ValidateAsync(client => client.SpotApi.Trading.GetTriggerOrdersAsync(false), "GetTriggerOrders"); + await tester.ValidateAsync(client => client.SpotApi.Trading.CancelAllTriggerOrdersAsync(), "CancelAllTriggerOrders"); + await tester.ValidateAsync(client => client.SpotApi.Trading.GetTriggerOrderAsync(123), "GetTriggerOrder"); + await tester.ValidateAsync(client => client.SpotApi.Trading.CancelTriggerOrderAsync(123), "CancelTriggerOrder"); + await tester.ValidateAsync(client => client.SpotApi.Trading.PlaceMultipleOrderAsync(new[] { new GateIoBatchPlaceRequest() }), "PlaceMultipleOrder", ignoreProperties: new List { "order_id", "create_time", "update_time", "fill_price" }); + await tester.ValidateAsync(client => client.SpotApi.Trading.EditMultipleOrderAsync(new[] { new GateIoBatchEditRequest() }), "EditMultipleOrder", ignoreProperties: new List { "order_id", "create_time", "update_time", "fill_price" }); + + } + + [Test] + public async Task ValidatePerpFuturesAccountDataCalls() + { + var client = new GateIoRestClient(opts => + { + opts.AutoTimestamp = false; + opts.ApiCredentials = new CryptoExchange.Net.Authentication.ApiCredentials("123", "456"); + }); + var tester = new RestRequestValidator(client, "Endpoints/PerpetualFutures/Account", "https://api.gateio.ws", IsAuthenticated, stjCompare: true); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Account.GetAccountAsync("usdt"), "GetAccount"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Account.GetLedgerAsync("usdt"), "GetLedger"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Account.UpdatePositionModeAsync("usdt", true), "UpdatePositionMode"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Account.GetTradingFeeAsync("usdt"), "GetTradingFee"); + } + + [Test] + public async Task ValidatePerpFuturesExchangeDataCalls() + { + var client = new GateIoRestClient(opts => + { + opts.AutoTimestamp = false; + opts.ApiCredentials = new CryptoExchange.Net.Authentication.ApiCredentials("123", "456"); + }); + var tester = new RestRequestValidator(client, "Endpoints/PerpetualFutures/ExchangeData", "https://api.gateio.ws", IsAuthenticated, stjCompare: true); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetContractsAsync("usdt"), "GetContracts", ignoreProperties: new List { "risk_limit_base", "risk_limit_step", "risk_limit_max" }); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetContractAsync("usdt", "ETH_USDT"), "GetContract", ignoreProperties: new List { "risk_limit_base", "risk_limit_step", "risk_limit_max" }); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetOrderBookAsync("usdt", "ETH_USDT"), "GetOrderBook"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetTradesAsync("usdt", "ETH_USDT"), "GetTrades"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetKlinesAsync("usdt", "ETH_USDT", KlineInterval.EightHours), "GetKlines"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetIndexKlinesAsync("usdt", "ETH_USDT", KlineInterval.EightHours), "GetIndexKlines"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetTickersAsync("usdt", "ETH_USDT"), "GetTickers"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetFundingRateHistoryAsync("usdt", "ETH_USDT"), "GetFundingRateHistory"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetInsuranceBalanceHistoryAsync("usdt"), "GetInsuranceBalanceHistory"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetContractStatsAsync("usdt", "ETH_USDT"), "GetContractStats"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetIndexConstituentsAsync("usdt", "ETH_USDT"), "GetIndexConstituents"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetLiquidationsAsync("usdt", "ETH_USDT"), "GetLiquidations"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.ExchangeData.GetRiskLimitTiersAsync("usdt", "ETH_USDT"), "GetRiskLimitTiers"); + + } + + [Test] + public async Task ValidatePerpFuturesTradingDataCalls() + { + var client = new GateIoRestClient(opts => + { + opts.AutoTimestamp = false; + opts.ApiCredentials = new CryptoExchange.Net.Authentication.ApiCredentials("123", "456"); + }); + var tester = new RestRequestValidator(client, "Endpoints/PerpetualFutures/Trading", "https://api.gateio.ws", IsAuthenticated, stjCompare: true); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetPositionsAsync("usdt"), "GetPositions"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.UpdatePositionMarginAsync("usdt", "ETH_USDT", 1), "UpdatePositionMargin"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.UpdatePositionLeverageAsync("usdt", "ETH_USDT", 1), "UpdatePositionLeverage"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.UpdatePositionRiskLimitAsync("usdt", "ETH_USDT", 1), "UpdatePositionRiskLimit"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetDualModePositionsAsync("usdt", "ETH_USDT"), "GetDualModePositions"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.UpdateDualModePositionMarginAsync("usdt", "ETH_USDT", 1, PositionMode.Single), "UpdateDualModePositionMargin"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.UpdateDualModePositionLeverageAsync("usdt", "ETH_USDT", 10), "UpdateDualModePositionLeverage"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.UpdateDualModePositionRiskLimitAsync("usdt", "ETH_USDT", 10), "UpdateDualModePositionRiskLimit"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.PlaceOrderAsync("usdt", "ETH_USDT", OrderSide.Buy, 1), "PlaceOrder"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.PlaceMultipleOrderAsync("usdt", new[] { new GateIoPerpBatchPlaceRequest() }), "PlaceMultipleOrder"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetOrdersAsync("usdt", "ETH_USDT"), "GetOrders"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetOrdersByTimestampAsync("usdt", "ETH_USDT"), "GetOrdersByTime"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.CancelAllOrdersAsync("usdt", "ETH_USDT"), "CancelAllOrders"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetOrderAsync("usdt", 123), "GetOrder"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.CancelOrderAsync("usdt", 123), "CancelOrder"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.EditOrderAsync("usdt", 123), "EditOrder"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetUserTradesAsync("usdt"), "GetUserTrades"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetUserTradesByTimestampAsync("usdt"), "GetUserTradesByTimestamp"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetPositionCloseHistoryAsync("usdt"), "GetPositionCloseHistory"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetLiquidationHistoryAsync("usdt"), "GetLiquidationHistory"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetAutoDeleveragingHistoryAsync("usdt"), "GetAutoDeleveragingHistory"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.CancelOrdersAfterAsync("usdt", TimeSpan.Zero), "CancelOrdersAfter"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.CancelOrdersAsync("usdt", new[] { 1L }), "CancelOrders"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.PlaceTriggerOrderAsync("usdt", "ETH_USDT", OrderSide.Sell, 1, TriggerType.EqualOrLower, 100), "PlaceTriggerOrder"); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetTriggerOrdersAsync("usdt", true), "GetTriggerOrders", ignoreProperties: new List { "strategy_type" }); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.CancelTriggerOrdersAsync("usdt", "ETH_USDT"), "CancelTriggerOrders", ignoreProperties: new List { "strategy_type" }); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.GetTriggerOrderAsync("usdt", 123), "GetTriggerOrder", ignoreProperties: new List { "strategy_type" }); + await tester.ValidateAsync(client => client.PerpetualFuturesApi.Trading.CancelTriggerOrderAsync("usdt", 123), "CancelTriggerOrder", ignoreProperties: new List { "strategy_type" }); + } + + private bool IsAuthenticated(WebCallResult result) + { + return result.RequestHeaders.Any(r => r.Key == "SIGN"); + } + } +} diff --git a/GateIo.Net.UnitTests/SocketSubscriptionTests.cs b/GateIo.Net.UnitTests/SocketSubscriptionTests.cs new file mode 100644 index 0000000..58b331b --- /dev/null +++ b/GateIo.Net.UnitTests/SocketSubscriptionTests.cs @@ -0,0 +1,60 @@ +using CryptoExchange.Net.Testing; +using NUnit.Framework; +using System.Threading.Tasks; +using GateIo.Net.Clients; +using GateIo.Net.Objects.Models; +using System.Collections.Generic; + +namespace Gate.io.Net.UnitTests +{ + [TestFixture] + public class SocketSubscriptionTests + { + [Test] + public async Task ValidateSpotSubscriptions() + { + var client = new GateIoSocketClient(opts => + { + opts.ApiCredentials = new CryptoExchange.Net.Authentication.ApiCredentials("123", "456"); + }); + var tester = new SocketSubscriptionValidator(client, "Subscriptions/Spot", "wss://api.gateio.ws", "result", stjCompare: true); + await tester.ValidateAsync((client, handler) => client.SpotApi.SubscribeToTickerUpdatesAsync("ETH_USDT", handler), "SubscribeToTickerUpdates", ignoreProperties: new List { "time" }); + await tester.ValidateAsync((client, handler) => client.SpotApi.SubscribeToTradeUpdatesAsync("ETH_USDT", handler), "SubscribeToTradeUpdates", ignoreProperties: new List { "time", "create_time" }); + await tester.ValidateAsync((client, handler) => client.SpotApi.SubscribeToKlineUpdatesAsync("ETH_USDT", GateIo.Net.Enums.KlineInterval.OneMinute, handler), "SubscribeToKlineUpdates", ignoreProperties: new List { "time" }); + await tester.ValidateAsync((client, handler) => client.SpotApi.SubscribeToBookTickerUpdatesAsync("ETH_USDT", handler), "SubscribeToBookTickerUpdates", ignoreProperties: new List { "time" }); + await tester.ValidateAsync((client, handler) => client.SpotApi.SubscribeToOrderBookUpdatesAsync("ETH_USDT", 1000, handler), "SubscribeToOrderBookUpdates", ignoreProperties: new List { "time", "E" }); + await tester.ValidateAsync((client, handler) => client.SpotApi.SubscribeToPartialOrderBookUpdatesAsync("ETH_USDT", 5, 1000, handler), "SubscribeToPartialOrderBookUpdates", ignoreProperties: new List { "time", "E" }); + await tester.ValidateAsync>((client, handler) => client.SpotApi.SubscribeToOrderUpdatesAsync(handler), "SubscribeToOrderUpdates", ignoreProperties: new List { "time", "create_time", "update_time", "biz_info" }); + await tester.ValidateAsync>((client, handler) => client.SpotApi.SubscribeToUserTradeUpdatesAsync(handler), "SubscribeToUserTradeUpdates", ignoreProperties: new List { "time", "create_time" }); + await tester.ValidateAsync>((client, handler) => client.SpotApi.SubscribeToBalanceUpdatesAsync(handler), "SubscribeToBalanceUpdates", ignoreProperties: new List { "time", "timestamp" }); + await tester.ValidateAsync>((client, handler) => client.SpotApi.SubscribeToMarginBalanceUpdatesAsync(handler), "SubscribeToMarginBalanceUpdates", ignoreProperties: new List { "time", "timestamp" }); + await tester.ValidateAsync>((client, handler) => client.SpotApi.SubscribeToFundingBalanceUpdatesAsync(handler), "SubscribeToFundingBalanceUpdates", ignoreProperties: new List { "time", "timestamp" }); + await tester.ValidateAsync>((client, handler) => client.SpotApi.SubscribeToCrossMarginBalanceUpdatesAsync(handler), "SubscribeToCrossMarginBalanceUpdates", ignoreProperties: new List { "time", "timestamp" }); + await tester.ValidateAsync((client, handler) => client.SpotApi.SubscribeToTriggerOrderUpdatesAsync(handler), "SubscribeToTriggerOrderUpdates", ignoreProperties: new List { "time", "timestamp" }); + } + + [Test] + public async Task ValidatePerpFuturesSubscriptions() + { + var client = new GateIoSocketClient(opts => + { + opts.ApiCredentials = new CryptoExchange.Net.Authentication.ApiCredentials("123", "456"); + }); + var tester = new SocketSubscriptionValidator(client, "Subscriptions/Futures", "wss://fx-ws.gateio.ws", "result", stjCompare: true); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToTickerUpdatesAsync("usdt", "ETH_USDT", handler), "SubscribeToTickerUpdates", ignoreProperties: new List { "time" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToTradeUpdatesAsync("usdt", "ETH_USDT", handler), "SubscribeToTradeUpdates", ignoreProperties: new List { "time", "create_time" }); + await tester.ValidateAsync((client, handler) => client.PerpetualFuturesApi.SubscribeToBookTickerUpdatesAsync("usdt", "ETH_USDT", handler), "SubscribeToBookTickerUpdates", ignoreProperties: new List { "time" }); + await tester.ValidateAsync((client, handler) => client.PerpetualFuturesApi.SubscribeToOrderBookUpdatesAsync("usdt", "ETH_USDT", 100, 5, handler), "SubscribeToBookUpdates", ignoreProperties: new List { "time" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToKlineUpdatesAsync("usdt", "ETH_USDT", GateIo.Net.Enums.KlineInterval.FiveMinutes, handler), "SubscribeToKlineUpdates", ignoreProperties: new List { "time" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToOrderUpdatesAsync(123, "usdt", handler), "SubscribeToOrderUpdates", ignoreProperties: new List { "time", "create_time_ms", "finish_time_ms", "refr" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToUserTradeUpdatesAsync(123, "usdt", handler), "SubscribeToUserTradeUpdates", ignoreProperties: new List { "time", "create_time_ms" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToUserLiquidationUpdatesAsync(123, "usdt", handler), "SubscribeToUserLiquidationUpdates", ignoreProperties: new List { "time", "time_ms", "create_time_ms" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToUserAutoDeleverageUpdatesAsync(123, "usdt", handler), "SubscribeToUserAutoDeleverageUpdates", ignoreProperties: new List { "time", "time_ms", "create_time_ms" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToPositionCloseUpdatesAsync(123, "usdt", handler), "SubscribeToPositionCloseUpdates", ignoreProperties: new List { "time", "time_ms", "create_time_ms" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToBalanceUpdatesAsync(123, "usdt", handler), "SubscribeToBalanceUpdates", ignoreProperties: new List { "time", "time_ms", "create_time_ms" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToReduceRiskLimitUpdatesAsync(123, "usdt", handler), "SubscribeToReduceRiskLimitUpdates", ignoreProperties: new List { "time", "time_ms", "create_time_ms" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToPositionUpdatesAsync(123, "usdt", handler), "SubscribeToPositionUpdates", ignoreProperties: new List { "time", "time_ms", "create_time_ms" }); + await tester.ValidateAsync>((client, handler) => client.PerpetualFuturesApi.SubscribeToTriggerOrderUpdatesAsync(123, "usdt", handler), "SubscribeToTriggerOrderUpdates", ignoreProperties: new List { "time", "time_ms", "create_time_ms", "strategy_type", "iceberg", "stop_trigger" }); + } + } +} diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBalanceUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBalanceUpdates.txt new file mode 100644 index 0000000..840bc6b --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBalanceUpdates.txt @@ -0,0 +1,21 @@ +> {"time":"1","id":-999,"channel":"futures.balances","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.balances","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "channel": "futures.balances", + "event": "update", + "time": 1541505434, + "time_ms": 1541505434123, + "result": [ + { + "balance": 9.998739899488, + "change": -0.000002074115, + "text": "BTC_USD:3914424", + "time": 1547199246, + "time_ms": 1547199246123, + "type": "fee", + "user": "211", + "currency": "btc" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBookTickerUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBookTickerUpdates.txt new file mode 100644 index 0000000..681079d --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBookTickerUpdates.txt @@ -0,0 +1,18 @@ +> {"time":"1","id":-999,"channel":"futures.book_ticker","event":"subscribe","payload":["ETH_USDT"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.book_ticker","event":"subscribe","payload":["ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1615366379, + "time_ms": 1615366379123, + "channel": "futures.book_ticker", + "event": "update", + "result": { + "t": 1615366379123, + "u": 2517661076, + "s": "ETH_USDT", + "b": "54696.6", + "B": 37000, + "a": "54696.7", + "A": 47061 + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBookUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBookUpdates.txt new file mode 100644 index 0000000..594b1ff --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToBookUpdates.txt @@ -0,0 +1,35 @@ +> {"time":"1","id":-999,"channel":"futures.order_book_update","event":"subscribe","payload":["ETH_USDT", "100ms", "5"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.order_book_update","event":"subscribe","payload":["ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1615366381, + "time_ms": 1615366381123, + "channel": "futures.order_book_update", + "event": "update", + "result": { + "t": 1615366381417, + "s": "ETH_USDT", + "U": 2517661101, + "u": 2517661113, + "b": [ + { + "p": "54672.1", + "s": 0 + }, + { + "p": "54664.5", + "s": 58794 + } + ], + "a": [ + { + "p": "54743.6", + "s": 0 + }, + { + "p": "54742", + "s": 95 + } + ] + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToKlineUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToKlineUpdates.txt new file mode 100644 index 0000000..f6d7783 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToKlineUpdates.txt @@ -0,0 +1,29 @@ +> {"time":"1","id":-999,"channel":"futures.candlesticks","event":"subscribe","payload":["5m", "ETH_USDT"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.order_book_update","event":"subscribe","payload":["5m", "ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1542162490, + "time_ms": 1542162490123, + "channel": "futures.candlesticks", + "event": "update", + "result": [ + { + "t": 1545129300, + "v": 27525555, + "c": "95.4", + "h": "96.9", + "l": "89.5", + "o": "94.3", + "n": "5m_ETH_USDT" + }, + { + "t": 1545129300, + "v": 27525555, + "c": "95.4", + "h": "96.9", + "l": "89.5", + "o": "94.3", + "n": "5m_ETH_USDT" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToOrderUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToOrderUpdates.txt new file mode 100644 index 0000000..7f80020 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToOrderUpdates.txt @@ -0,0 +1,36 @@ +> {"time":"1","id":-999,"channel":"futures.orders","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.orders","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "channel": "futures.orders", + "event": "update", + "time": 1541505434, + "time_ms": 1541505434123, + "result": [ + { + "contract": "BTC_USD", + "create_time": 1628736847, + "create_time_ms": 1628736847325, + "fill_price": 40000.4, + "finish_as": "filled", + "finish_time": 1628736848, + "finish_time_ms": 1628736848321, + "iceberg": 0, + "id": 4872460, + "is_close": false, + "is_liq": false, + "is_reduce_only": false, + "left": 0, + "mkfr": -0.00025, + "price": 40000.4, + "refr": 0, + "refu": 0, + "size": 1, + "status": "finished", + "text": "-", + "tif": "gtc", + "tkfr": 0.0005, + "user": "110" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToPositionCloseUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToPositionCloseUpdates.txt new file mode 100644 index 0000000..e63f351 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToPositionCloseUpdates.txt @@ -0,0 +1,20 @@ +> {"time":"1","id":-999,"channel":"futures.position_closes","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.position_closes","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "channel": "futures.position_closes", + "event": "update", + "time": 1541505434, + "time_ms": 1541505434123, + "result": [ + { + "contract": "BTC_USD", + "pnl": -0.000624354791, + "side": "long", + "text": "web", + "time": 1547198562, + "time_ms": 1547198562123, + "user": "21" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToPositionUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToPositionUpdates.txt new file mode 100644 index 0000000..aa7257c --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToPositionUpdates.txt @@ -0,0 +1,33 @@ +> {"time":"1","id":-999,"channel":"futures.positions","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.positions","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1588212926, + "time_ms": 1588212926123, + "channel": "futures.positions", + "event": "update", + "result": [ + { + "contract": "BTC_USD", + "cross_leverage_limit": 0, + "entry_price": 40000.36666661111, + "history_pnl": -0.000108569505, + "history_point": 0, + "last_close_pnl": -0.000050123368, + "leverage": 0, + "leverage_max": 100, + "liq_price": 0.1, + "maintenance_rate": 0.005, + "margin": 49.999890611186, + "mode": "single", + "realised_pnl": -1.25e-8, + "realised_point": 0, + "risk_limit": 100, + "size": 3, + "time": 1628736848, + "time_ms": 1628736848321, + "user": "110", + "update_id": 170919 + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToReduceRiskLimitUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToReduceRiskLimitUpdates.txt new file mode 100644 index 0000000..2433a78 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToReduceRiskLimitUpdates.txt @@ -0,0 +1,22 @@ +> {"time":"1","id":-999,"channel":"futures.reduce_risk_limits","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.reduce_risk_limits","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1551858330, + "time_ms": 1551858330123, + "channel": "futures.reduce_risk_limits", + "event": "update", + "result": [ + { + "cancel_orders": 0, + "contract": "ETH_USD", + "leverage_max": 10, + "liq_price": 136.53, + "maintenance_rate": 0.09, + "risk_limit": 450, + "time": 1551858330, + "time_ms": 1551858330123, + "user": "20011" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTickerUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTickerUpdates.txt new file mode 100644 index 0000000..543314c --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTickerUpdates.txt @@ -0,0 +1,30 @@ +> {"time":"1","id":-999,"channel":"futures.tickers","event":"subscribe","payload":["ETH_USDT"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.tickers","event":"subscribe","payload":["ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1541659086, + "time_ms": 1541659086123, + "channel": "futures.tickers", + "event": "update", + "result": [ + { + "contract": "ETH_USDT", + "last": "118.4", + "change_percentage": "0.77", + "funding_rate": "-0.000114", + "funding_rate_indicative": "0.01875", + "mark_price": "118.35", + "index_price": "118.36", + "total_size": "73648", + "volume_24h": "745487577", + "volume_24h_btc": "117", + "volume_24h_usd": "419950", + "quanto_base_rate": "", + "volume_24h_quote": "1665006", + "volume_24h_settle": "178", + "volume_24h_base": "5526", + "low_24h": "99.2", + "high_24h": "132.5" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTradeUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTradeUpdates.txt new file mode 100644 index 0000000..ac3adc2 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTradeUpdates.txt @@ -0,0 +1,20 @@ +> {"time":"1","id":-999,"channel":"futures.trades","event":"subscribe","payload":["ETH_USDT"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.trades","event":"subscribe","payload":["ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "channel": "futures.trades", + "event": "update", + "time": 1541503698, + "time_ms": 1541503698123, + "result": [ + { + "size": -108, + "id": 27753479, + "create_time": 1545136464, + "create_time_ms": 1545136464123, + "price": "96.4", + "contract": "ETH_USDT", + "is_internal": true + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTriggerOrderUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTriggerOrderUpdates.txt new file mode 100644 index 0000000..5779c00 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToTriggerOrderUpdates.txt @@ -0,0 +1,46 @@ +> {"time":"1","id":-999,"channel":"futures.autoorders","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.autoorders","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1596798126, + "time_ms": 1596798126123, + "channel": "futures.autoorders", + "event": "update", + "result": [ + { + "user": 123456, + "trigger": { + "strategy_type": 0, + "price_type": 0, + "price": "10000", + "rule": 2, + "expiration": 86400 + }, + "initial": { + "contract": "BTC_USDT", + "size": 10, + "price": "10000", + "tif": "gtc", + "text": "web", + "iceberg": 0, + "is_close": false, + "is_reduce_only": false, + "auto_size": "" + }, + "id": 9256, + "trade_id": 0, + "status": "open", + "reason": "", + "create_time": 1596798126, + "name": "price_autoorders", + "is_stop_order": false, + "stop_trigger": { + "rule": 0, + "trigger_price": "", + "order_price": "" + }, + "order_type": "close-long-order", + "me_order_id": "213867453823" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserAutoDeleverageUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserAutoDeleverageUpdates.txt new file mode 100644 index 0000000..a9f9083 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserAutoDeleverageUpdates.txt @@ -0,0 +1,21 @@ +> {"time":"1","id":-999,"channel":"futures.auto_deleverages","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.auto_deleverages","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "channel": "futures.auto_deleverages", + "event": "update", + "time": 1541505434, + "time_ms": 1541505434123, + "result": [ + { + "entry_price": 209, + "fill_price": 215.1, + "position_size": 10, + "trade_size": 10, + "time": 1541486601, + "time_ms": 1541486601123, + "contract": "BTC_USD", + "user": "1040" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserLiquidationUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserLiquidationUpdates.txt new file mode 100644 index 0000000..3a9cc12 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserLiquidationUpdates.txt @@ -0,0 +1,27 @@ +> {"time":"1","id":-999,"channel":"futures.liquidates","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.liquidates","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "channel": "futures.liquidates", + "event": "update", + "time": 1541505434, + "time_ms": 1541505434123, + "result": [ + { + "entry_price": 209, + "fill_price": 215.1, + "left": 0, + "leverage": 0.0, + "liq_price": 213, + "margin": 0.007816722941, + "mark_price": 213, + "order_id": 4093362, + "order_price": 215.1, + "size": -124, + "time": 1541486601, + "time_ms": 1541486601123, + "contract": "BTC_USD", + "user": "104" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserTradeUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserTradeUpdates.txt new file mode 100644 index 0000000..74a0e92 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Futures/SubscribeToUserTradeUpdates.txt @@ -0,0 +1,24 @@ +> {"time":"1","id":-999,"channel":"futures.usertrades","event":"subscribe","payload":[123, "!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"futures.usertrades","event":"subscribe","payload":[123, "!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1543205083, + "time_ms": 1543205083123, + "channel": "futures.usertrades", + "event": "update", + "result": [ + { + "id": "3335259", + "create_time": 1628736848, + "create_time_ms": 1628736848321, + "contract": "BTC_USD", + "order_id": "4872460", + "size": 1, + "price": "40000.4", + "role": "maker", + "text": "api", + "fee": 0.0009290592, + "point_fee": 0 + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToBalanceUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToBalanceUpdates.txt new file mode 100644 index 0000000..1378878 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToBalanceUpdates.txt @@ -0,0 +1,23 @@ +> {"time":"1","id":-999,"channel":"spot.balances","event":"subscribe","payload":["!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.balances","event":"subscribe","payload":["!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1605248616, + "time_ms": 1605248616763, + "channel": "spot.balances", + "event": "update", + "result": [ + { + "timestamp": "1667556323", + "timestamp_ms": "1667556323730", + "user": "1000001", + "currency": "USDT", + "change": "0", + "total": "222244.3827652", + "available": "222244.3827", + "freeze": "5", + "freeze_change": "5.000000", + "change_type": "order-create" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToBookTickerUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToBookTickerUpdates.txt new file mode 100644 index 0000000..cae05c0 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToBookTickerUpdates.txt @@ -0,0 +1,18 @@ +> {"time":"1","id":-999,"channel":"spot.book_ticker","event":"subscribe","payload":["ETH_USDT"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.book_ticker","event":"subscribe","payload":["ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1606293275, + "time_ms": 1606293275723, + "channel": "spot.book_ticker", + "event": "update", + "result": { + "t": 1606293275123, + "u": 48733182, + "s": "ETH_USDT", + "b": "19177.79", + "B": "0.0003341504", + "a": "19179.38", + "A": "0.09" + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToCrossMarginBalanceUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToCrossMarginBalanceUpdates.txt new file mode 100644 index 0000000..9617bc1 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToCrossMarginBalanceUpdates.txt @@ -0,0 +1,23 @@ +> {"time":"1","id":-999,"channel":"spot.cross_balances","event":"subscribe","payload":["!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.cross_balances","event":"subscribe","payload":["!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1605248616, + "time_ms": 1605248616763, + "channel": "spot.cross_balances", + "event": "update", + "result": [ + { + "timestamp": "1605248616", + "timestamp_ms": "1605248616123", + "user": "1000001", + "currency": "USDT", + "change": "100", + "total": "1032951.325075926", + "available": "1022943.325075926", + "freeze": "0", + "freeze_change": "0", + "change_type": "cross-margin-transfer" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToFundingBalanceUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToFundingBalanceUpdates.txt new file mode 100644 index 0000000..9bcb988 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToFundingBalanceUpdates.txt @@ -0,0 +1,20 @@ +> {"time":"1","id":-999,"channel":"spot.funding_balances","event":"subscribe","payload":["!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.funding_balances","event":"subscribe","payload":["!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1605248616, + "time_ms": 1605248616763, + "channel": "spot.funding_balances", + "event": "update", + "result": [ + { + "timestamp": "1605248616", + "timestamp_ms": "1605248616123", + "user": "1000001", + "currency": "USDT", + "change": "100", + "freeze": "100", + "lent": "0" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToKlineUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToKlineUpdates.txt new file mode 100644 index 0000000..857a9e3 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToKlineUpdates.txt @@ -0,0 +1,20 @@ +> {"time":"1","id":-999,"channel":"spot.candlesticks","event":"subscribe","payload":["1m", "ETH_USDT"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.candlesticks","event":"subscribe","payload":["1m", "ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1606292600, + "time_ms": 1606292600376, + "channel": "spot.candlesticks", + "event": "update", + "result": { + "t": "1606292580", + "v": "2362.32035", + "c": "19128.1", + "h": "19128.1", + "l": "19128.1", + "o": "19128.1", + "n": "1m_ETH_USDT", + "a": "3.8283", + "w": true + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToMarginBalanceUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToMarginBalanceUpdates.txt new file mode 100644 index 0000000..ac6db5c --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToMarginBalanceUpdates.txt @@ -0,0 +1,23 @@ +> {"time":"1","id":-999,"channel":"spot.margin_balances","event":"subscribe","payload":["!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.margin_balances","event":"subscribe","payload":["!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1605248616, + "time_ms": 1605248616763, + "channel": "spot.margin_balances", + "event": "update", + "result": [ + { + "timestamp": "1605248812", + "timestamp_ms": "1605248812123", + "user": "1000001", + "currency_pair": "BTC_USDT", + "currency": "BTC", + "change": "-0.002", + "available": "999.999836", + "freeze": "1", + "borrowed": "0", + "interest": "0" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToOrderBookUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToOrderBookUpdates.txt new file mode 100644 index 0000000..35a8085 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToOrderBookUpdates.txt @@ -0,0 +1,22 @@ +> {"time":"1","id":-999,"channel":"spot.order_book_update","event":"subscribe","payload":["ETH_USDT", "1000ms"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.order_book_update","event":"subscribe","payload":["ETH_USDT", "1000ms"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1606294781, + "time_ms": 1606294781236, + "channel": "spot.order_book_update", + "event": "update", + "result": { + "t": 1606294781123, + "e": "depthUpdate", + "E": 1606294781, + "s": "ETH_USDT", + "U": 48776301, + "u": 48776306, + "b": [ + ["19137.74", "0.0001"], + ["19088.37", "0"] + ], + "a": [["19137.75", "0.6135"]] + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToOrderUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToOrderUpdates.txt new file mode 100644 index 0000000..0c966bf --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToOrderUpdates.txt @@ -0,0 +1,42 @@ +> {"time":"1","id":-999,"channel":"spot.orders","event":"subscribe","payload":["!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.orders","event":"subscribe","payload":["!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1694655225, + "time_ms": 1694655225315, + "channel": "spot.orders", + "event": "update", + "result": [ + { + "id": "399123456", + "text": "t-testtext", + "create_time": "1694655225", + "update_time": "1694655225", + "currency_pair": "BTC_USDT", + "type": "limit", + "account": "spot", + "side": "sell", + "amount": "0.0001", + "price": "26253.3", + "time_in_force": "gtc", + "left": "0.0001", + "filled_total": "0", + "avg_deal_price": "0", + "fee": "0", + "fee_currency": "USDT", + "point_fee": "0", + "gt_fee": "0", + "rebated_fee": "0", + "rebated_fee_currency": "USDT", + "create_time_ms": "1694655225315", + "update_time_ms": "1694655225315", + "user": 3497082, + "event": "put", + "stp_id": 0, + "stp_act": "-", + "finish_as": "open", + "biz_info": "-", + "amend_text": "-" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToPartialOrderBookUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToPartialOrderBookUpdates.txt new file mode 100644 index 0000000..88e0d1f --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToPartialOrderBookUpdates.txt @@ -0,0 +1,28 @@ +> {"time":"1","id":-999,"channel":"spot.order_book","event":"subscribe","payload":["ETH_USDT", "5", "1000ms"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.order_book","event":"subscribe","payload":["ETH_USDT", "5", "1000ms"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1606295412, + "time_ms": 1606295412213, + "channel": "spot.order_book", + "event": "update", + "result": { + "t": 1606295412123, + "lastUpdateId": 48791820, + "s": "ETH_USDT", + "bids": [ + ["19079.55", "0.0195"], + ["19079.07", "0.7341"], + ["19076.23", "0.00011808"], + ["19073.9", "0.105"], + ["19068.83", "0.1009"] + ], + "asks": [ + ["19080.24", "0.1638"], + ["19080.91", "0.1366"], + ["19080.92", "0.01"], + ["19081.29", "0.01"], + ["19083.8", "0.097"] + ] + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTickerUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTickerUpdates.txt new file mode 100644 index 0000000..01aff2e --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTickerUpdates.txt @@ -0,0 +1,4 @@ +> {"time":"1","id":-999,"channel":"spot.tickers","event":"subscribe","payload":["ETH_USDT"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.tickers","event":"subscribe","payload":["ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{"time":1717595233,"time_ms":1717595233666,"conn_id":"","channel":"spot.tickers","event":"update","result":{"currency_pair":"ETH_USDT","last":"70775.2","lowest_ask":"70773.1","highest_bid":"70773","change_percentage":"1.618","base_volume":"4643.108806389","quote_volume":"328461488.44111","high_24h":"71366","low_24h":"69336.2"}} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTradeUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTradeUpdates.txt new file mode 100644 index 0000000..dd85428 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTradeUpdates.txt @@ -0,0 +1,19 @@ +> {"time":"1","id":-999,"channel":"spot.trades","event":"subscribe","payload":["ETH_USDT"]} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.trades","event":"subscribe","payload":["ETH_USDT"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1606292218, + "time_ms": 1606292218231, + "channel": "spot.trades", + "event": "update", + "result": { + "id": 309143071, + "create_time": 1606292218, + "create_time_ms": "1606292218213.4578", + "side": "sell", + "currency_pair": "ETH_USDT", + "amount": "16.4700000000", + "price": "0.4705000000", + "range": "2390902-2390902" + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTriggerOrderUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTriggerOrderUpdates.txt new file mode 100644 index 0000000..4031995 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToTriggerOrderUpdates.txt @@ -0,0 +1,35 @@ +> {"time":"1","id":-999,"channel":"spot.priceorders","event":"subscribe","payload":["!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.priceorders","event":"subscribe","payload":["!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1691847986, + "time_ms": 1691847986454, + "channel": "spot.priceorders", + "event": "update", + "result": { + "market": "METAN_USDT", + "uid": "13679450", + "id": "247480109", + "currency_type": "METAN", + "exchange_type": "USDT", + "reason": "", + "err_msg": "", + "fired_order_id": 0, + "instant_cancel": false, + "trigger_price": "0.00302", + "trigger_rule": "<=", + "trigger_expiration": 900, + "price": "0.00300", + "amount": "26666.667", + "source": "", + "order_type": "limit", + "side": "buy", + "engine_type": "normal", + "is_stop_order": false, + "stop_trigger_price": "", + "stop_trigger_rule": "", + "stop_price": "", + "ctime": "1691517983131", + "ftime": "-62135596800000" + } +} \ No newline at end of file diff --git a/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToUserTradeUpdates.txt b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToUserTradeUpdates.txt new file mode 100644 index 0000000..3d21158 --- /dev/null +++ b/GateIo.Net.UnitTests/Subscriptions/Spot/SubscribeToUserTradeUpdates.txt @@ -0,0 +1,27 @@ +> {"time":"1","id":-999,"channel":"spot.usertrades","event":"subscribe","payload":["!all"],"auth":{"method": "api_key", "KEY": "123"}} +< {"time":"1","time_ms":1717595231793,"id":-999,"conn_id":"28838ac31473dcbb","trace_id":"789a534faf3c51651b7764b0ac63b4a8","channel":"spot.usertrades","event":"subscribe","payload":["!all"],"result":{"status":"success"},"requestId":"789a534faf3c51651b7764b0ac63b4a8"} += +{ + "time": 1605176741, + "time_ms": 1605176741763, + "channel": "spot.usertrades", + "event": "update", + "result": [ + { + "id": 5736713, + "user_id": 1000001, + "order_id": "30784428", + "currency_pair": "BTC_USDT", + "create_time": 1605176741, + "create_time_ms": "1605176741123.456", + "side": "sell", + "amount": "1.00000000", + "role": "taker", + "price": "10000.00000000", + "fee": "0.00200000000000", + "point_fee": "0", + "gt_fee": "0", + "text": "apiv4" + } + ] +} \ No newline at end of file diff --git a/GateIo.Net.sln b/GateIo.Net.sln new file mode 100644 index 0000000..673cc27 --- /dev/null +++ b/GateIo.Net.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34723.18 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GateIo.Net", "GateIo.Net\GateIo.Net.csproj", "{4E00B047-875A-4AAC-A205-F1EF0DB81FD7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GateIo.Net.UnitTests", "GateIo.Net.UnitTests\GateIo.Net.UnitTests.csproj", "{09E46E06-F6CA-4330-8ADF-106673480F95}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4E00B047-875A-4AAC-A205-F1EF0DB81FD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E00B047-875A-4AAC-A205-F1EF0DB81FD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E00B047-875A-4AAC-A205-F1EF0DB81FD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E00B047-875A-4AAC-A205-F1EF0DB81FD7}.Release|Any CPU.Build.0 = Release|Any CPU + {09E46E06-F6CA-4330-8ADF-106673480F95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09E46E06-F6CA-4330-8ADF-106673480F95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09E46E06-F6CA-4330-8ADF-106673480F95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09E46E06-F6CA-4330-8ADF-106673480F95}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C6772B97-910A-4F07-B33E-D5C6097ED1FC} + EndGlobalSection +EndGlobal diff --git a/GateIo.Net/AssemblyInfo.cs b/GateIo.Net/AssemblyInfo.cs new file mode 100644 index 0000000..800e978 --- /dev/null +++ b/GateIo.Net/AssemblyInfo.cs @@ -0,0 +1 @@ +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("GateIo.Net.UnitTests")] \ No newline at end of file diff --git a/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApi.cs b/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApi.cs new file mode 100644 index 0000000..d65d049 --- /dev/null +++ b/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApi.cs @@ -0,0 +1,149 @@ +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Objects; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using GateIo.Net.Objects.Options; +using CryptoExchange.Net.Clients; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Converters.SystemTextJson; +using CryptoExchange.Net.Converters.MessageParsing; +using System.Linq; + +namespace GateIo.Net.Clients.FuturesApi +{ + /// + public class GateIoRestClientPerpetualFuturesApi : RestApiClient, IGateIoRestClientPerpetualFuturesApi + { + #region fields + internal static TimeSyncState _timeSyncState = new TimeSyncState("Perpetual Futures Api"); + internal string _brokerId; + #endregion + + #region Api clients + /// + public IGateIoRestClientPerpetualFuturesApiAccount Account { get; } + /// + public IGateIoRestClientPerpetualFuturesApiExchangeData ExchangeData { get; } + /// + public IGateIoRestClientPerpetualFuturesApiTrading Trading { get; } + /// + public string ExchangeName => "GateIo"; + #endregion + + #region constructor/destructor + internal GateIoRestClientPerpetualFuturesApi(ILogger logger, HttpClient? httpClient, GateIoRestOptions options) + : base(logger, httpClient, options.Environment.RestClientAddress!, options, options.PerpetualFuturesOptions) + { + Account = new GateIoRestClientPerpetualFuturesApiAccount(this); + ExchangeData = new GateIoRestClientPerpetualFuturesApiExchangeData(logger, this); + Trading = new GateIoRestClientPerpetualFuturesApiTrading(logger, this); + + _brokerId = string.IsNullOrEmpty(options.BrokerId) ? "copytraderpw" : options.BrokerId!; + ParameterPositions[HttpMethod.Delete] = HttpMethodParameterPosition.InUri; + } + + #endregion + + /// + protected override IStreamMessageAccessor CreateAccessor() => new SystemTextJsonStreamMessageAccessor(); + /// + protected override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(); + + /// + protected override AuthenticationProvider CreateAuthenticationProvider(ApiCredentials credentials) + => new GateIoAuthenticationProvider(credentials); + + internal Task SendAsync(RequestDefinition definition, ParameterCollection? parameters, CancellationToken cancellationToken, int? weight = null) + => base.SendAsync(BaseAddress, definition, parameters, cancellationToken, null, weight); + + internal Task> SendAsync(RequestDefinition definition, ParameterCollection? parameters, CancellationToken cancellationToken, int? weight = null, Dictionary? requestHeaders = null) where T : class + => SendToAddressAsync(BaseAddress, definition, parameters, cancellationToken, weight, requestHeaders); + + internal async Task> SendToAddressAsync(string baseAddress, RequestDefinition definition, ParameterCollection? parameters, CancellationToken cancellationToken, int? weight = null, Dictionary? requestHeaders = null) where T : class + { + var result = await base.SendAsync(baseAddress, definition, parameters, cancellationToken, requestHeaders, weight).ConfigureAwait(false); + + // GateIo Optional response checking + + return result; + } + + internal Task> SendAsync(RequestDefinition definition, ParameterCollection? queryParameters, ParameterCollection? bodyParameters, CancellationToken cancellationToken, int? weight = null, Dictionary? requestHeaders = null) where T : class + => SendToAddressAsync(BaseAddress, definition, queryParameters, bodyParameters, cancellationToken, weight, requestHeaders); + + internal async Task> SendToAddressAsync(string baseAddress, RequestDefinition definition, ParameterCollection? queryParameters, ParameterCollection? bodyParameters, CancellationToken cancellationToken, int? weight = null, Dictionary? requestHeaders = null) where T : class + { + var result = await base.SendAsync(baseAddress, definition, queryParameters, bodyParameters, cancellationToken, requestHeaders, weight).ConfigureAwait(false); + + // GateIo Optional response checking + + return result; + } + + /// + protected override Error ParseErrorResponse(int httpStatusCode, IEnumerable>> responseHeaders, IMessageAccessor accessor) + { + if (!accessor.IsJson) + return new ServerError(accessor.GetOriginalString()); + + var lbl = accessor.GetValue(MessagePath.Get().Property("label")); + if (lbl == null) + return new ServerError(accessor.GetOriginalString()); + + var msg = accessor.GetValue(MessagePath.Get().Property("message")); + return new ServerError(lbl + ": " + msg); + } + + /// + protected override ServerRateLimitError ParseRateLimitResponse(int httpStatusCode, IEnumerable>> responseHeaders, IMessageAccessor accessor) + { + if (!accessor.IsJson) + return new ServerRateLimitError(accessor.GetOriginalString()); + + var error = GetRateLimitError(accessor); + + var resetTime = responseHeaders.SingleOrDefault(x => x.Key.Equals("X-Gate-RateLimit-Reset-Timestamp")); + if (resetTime.Value?.Any() != true) + return error; + + var value = resetTime.Value.First(); + var timestamp = DateTimeConverter.ParseFromString(value); + + error.RetryAfter = timestamp.AddSeconds(1); + return error; + } + + private ServerRateLimitError GetRateLimitError(IMessageAccessor accessor) + { + if (!accessor.IsJson) + return new ServerRateLimitError(accessor.GetOriginalString()); + + var lbl = accessor.GetValue(MessagePath.Get().Property("label")); + if (lbl == null) + return new ServerRateLimitError(accessor.GetOriginalString()); + + var msg = accessor.GetValue(MessagePath.Get().Property("message")); + return new ServerRateLimitError(lbl + ": " + msg); + } + + /// + protected override Task> GetServerTimestampAsync() + => ExchangeData.GetServerTimeAsync(); + + /// + public override TimeSyncInfo? GetTimeSyncInfo() + => new TimeSyncInfo(_logger, ApiOptions.AutoTimestamp ?? ClientOptions.AutoTimestamp, ApiOptions.TimestampRecalculationInterval ?? ClientOptions.TimestampRecalculationInterval, _timeSyncState); + + /// + public override TimeSpan? GetTimeOffset() + => _timeSyncState.TimeOffset; + + /// + public override string FormatSymbol(string baseAsset, string quoteAsset) => baseAsset.ToUpperInvariant() + "_" + quoteAsset.ToUpperInvariant(); + } +} diff --git a/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiAccount.cs b/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiAccount.cs new file mode 100644 index 0000000..195026b --- /dev/null +++ b/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiAccount.cs @@ -0,0 +1,80 @@ +using CryptoExchange.Net.Objects; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; +using GateIo.Net.Objects.Models; +using System.Collections.Generic; +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace GateIo.Net.Clients.FuturesApi +{ + /// + public class GateIoRestClientPerpetualFuturesApiAccount : IGateIoRestClientPerpetualFuturesApiAccount + { + private static readonly RequestDefinitionCache _definitions = new RequestDefinitionCache(); + private readonly GateIoRestClientPerpetualFuturesApi _baseClient; + + internal GateIoRestClientPerpetualFuturesApiAccount(GateIoRestClientPerpetualFuturesApi baseClient) + { + _baseClient = baseClient; + } + + #region Get Risk Limit Tiers + + /// + public async Task> GetAccountAsync( + string settlementAsset, + CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/accounts", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync (request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Account Ledger + + /// + public async Task>> GetLedgerAsync(string settlementAsset, string? contract = null, DateTime? startTime = null, DateTime? endTime = null, int? page = null, int? limit = null, string? type = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptional("type", type); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/account_book", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Update Position Mode + + /// + public async Task> UpdatePositionModeAsync(string settlementAsset, bool dualMode, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("dual_mode", dualMode.ToString().ToLowerInvariant()); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/dual_mode", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Trading Fees + + /// + public async Task>> GetTradingFeeAsync(string settlementAsset, string? contract = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/fee", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + } +} diff --git a/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiExchangeData.cs b/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiExchangeData.cs new file mode 100644 index 0000000..d2942f0 --- /dev/null +++ b/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiExchangeData.cs @@ -0,0 +1,280 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Objects; +using GateIo.Net.Objects.Models; +using Microsoft.Extensions.Logging; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; +using System.Collections.Generic; +using GateIo.Net.Enums; + +namespace GateIo.Net.Clients.FuturesApi +{ + /// + public class GateIoRestClientPerpetualFuturesApiExchangeData : IGateIoRestClientPerpetualFuturesApiExchangeData + { + private readonly ILogger _logger; + + private static readonly RequestDefinitionCache _definitions = new RequestDefinitionCache(); + private readonly GateIoRestClientPerpetualFuturesApi _baseClient; + + internal GateIoRestClientPerpetualFuturesApiExchangeData(ILogger logger, GateIoRestClientPerpetualFuturesApi baseClient) + { + _logger = logger; + _baseClient = baseClient; + } + + + #region Get Server Time + + /// + public async Task> GetServerTimeAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/time", GateIoExchange.RateLimiter.Public, 1); + var result = await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + return result.As(result.Data.ServerTime); + } + + #endregion + + #region Get Contracts + + /// + public async Task>> GetContractsAsync(string settlementAsset, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/contracts", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Contract + + /// + public async Task> GetContractAsync(string settlementAsset, string contract, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/contracts/" + contract, GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Order Book + + /// + public async Task> GetOrderBookAsync(string settlementAsset, string contract, int? mergeDepth = null, int? depth = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddOptional("interval", mergeDepth); + parameters.AddOptional("limit", depth); + parameters.AddOptional("with_id", true.ToString().ToLowerInvariant()); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/order_book", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Trades + + /// + public async Task>> GetTradesAsync( + string settlementAsset, + string contract, + int? limit = null, + int? offset = null, + string? lastId = null, + DateTime? startime = null, + DateTime? endTime = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + parameters.AddOptional("last_id", lastId); + parameters.AddOptionalMilliseconds("from", startime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/trades", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Klines + + /// + public async Task>> GetKlinesAsync( + string settlementAsset, + string contract, + KlineInterval interval, + int? limit = null, + DateTime? startime = null, + DateTime? endTime = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddEnum("interval", interval); + parameters.AddOptional("limit", limit); + parameters.AddOptionalMilliseconds("from", startime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/candlesticks", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Index Klines + + /// + public async Task>> GetIndexKlinesAsync( + string settlementAsset, + string contract, + KlineInterval interval, + int? limit = null, + DateTime? startime = null, + DateTime? endTime = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddEnum("interval", interval); + parameters.AddOptional("limit", limit); + parameters.AddOptionalMilliseconds("from", startime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/premium_index", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Tickers + + /// + public async Task>> GetTickersAsync( + string settlementAsset, + string? contract = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/tickers", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Funding Rate History + + /// + public async Task>> GetFundingRateHistoryAsync( + string settlementAsset, + string contract, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddOptional("limit", limit); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/funding_rate", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Insurance Balance History + + /// + public async Task>> GetInsuranceBalanceHistoryAsync( + string settlementAsset, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("limit", limit); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/insurance", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Stats + + /// + public async Task>> GetContractStatsAsync( + string settlementAsset, + string contract, + int? limit = null, + DateTime? startTime = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddOptional("limit", limit); + parameters.AddOptionalMilliseconds("from", startTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/contract_stats", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Index Constituents + + /// + public async Task> GetIndexConstituentsAsync( + string settlementAsset, + string contract, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/index_constituents/{contract}", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Liquidations + + /// + public async Task>> GetLiquidationsAsync( + string settlementAsset, + string? contract = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + parameters.AddOptional("limit", limit); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/liq_orders", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Risk Limit Tiers + + /// + public async Task>> GetRiskLimitTiersAsync( + string settlementAsset, + string contract, + int? offset = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/risk_limit_tiers", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + } +} diff --git a/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiTrading.cs b/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiTrading.cs new file mode 100644 index 0000000..51613fb --- /dev/null +++ b/GateIo.Net/Clients/FuturesApi/GateIoRestClientPerpetualFuturesApiTrading.cs @@ -0,0 +1,576 @@ +using Microsoft.Extensions.Logging; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; +using System.Collections.Generic; +using CryptoExchange.Net.Objects; +using System.Threading.Tasks; +using GateIo.Net.Objects.Models; +using System.Net.Http; +using System.Threading; +using GateIo.Net.Enums; +using System; +using System.Linq; + +namespace GateIo.Net.Clients.FuturesApi +{ + /// + public class GateIoRestClientPerpetualFuturesApiTrading : IGateIoRestClientPerpetualFuturesApiTrading + { + private static readonly RequestDefinitionCache _definitions = new RequestDefinitionCache(); + private readonly GateIoRestClientPerpetualFuturesApi _baseClient; + + internal GateIoRestClientPerpetualFuturesApiTrading(ILogger logger, GateIoRestClientPerpetualFuturesApi baseClient) + { + _baseClient = baseClient; + } + + #region Get Positions + + /// + public async Task>> GetPositionsAsync(string settlementAsset, bool? holding = null, int? page = null, int? limit = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptional("holding", holding); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/positions", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Position + + /// + public async Task> GetPositionAsync(string settlementAsset, string contract, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/positions/{contract}", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Update Position Margin + + /// + public async Task> UpdatePositionMarginAsync(string settlementAsset, string contract, decimal change, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddString("change", change); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/positions/{contract}/margin", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Update Position Leverage + + /// + public async Task> UpdatePositionLeverageAsync(string settlementAsset, string contract, decimal leverage, decimal? crossLeverageLimit = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddString("leverage", leverage); + parameters.AddOptionalString("cross_leverage_limit", crossLeverageLimit); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/positions/{contract}/leverage", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Update Position Risk Limit + + /// + public async Task> UpdatePositionRiskLimitAsync(string settlementAsset, string contract, decimal riskLimit, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddString("risk_limit", riskLimit); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/positions/{contract}/risk_limit", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Dual Mode Positions + + /// + public async Task>> GetDualModePositionsAsync(string settlementAsset, string contract, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/dual_comp/positions/{contract}", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Update Dual Mode Position Margin + + /// + public async Task>> UpdateDualModePositionMarginAsync(string settlementAsset, string contract, decimal change, PositionMode mode, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddString("change", change); + parameters.AddEnum("dual_side", mode); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/dual_comp/positions/{contract}/margin", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Update Dual Mode Position Margin + + /// + public async Task>> UpdateDualModePositionLeverageAsync(string settlementAsset, string contract, decimal leverage, decimal? crossLeverageLimit = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddString("leverage", leverage); + parameters.AddOptionalString("cross_leverage_limit", crossLeverageLimit); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/dual_comp/positions/{contract}/leverage", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Update Dual Mode Position Margin + + /// + public async Task>> UpdateDualModePositionRiskLimitAsync(string settlementAsset, string contract, int riskLimit, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddString("risk_limit", riskLimit); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/dual_comp/positions/{contract}/risk_limit", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Place Order + + /// + public async Task> PlaceOrderAsync( + string settlementAsset, + string contract, + OrderSide orderSide, + int quantity, + decimal? price = null, + bool? closePosition = null, + bool? reduceOnly = null, + TimeInForce? timeInForce = null, + int? icebergQuantity = null, + CloseSide? closeSide = null, + SelfTradePreventionMode? stpMode = null, + string? text = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddString("size", orderSide == OrderSide.Buy ? quantity: -quantity); + if (price.HasValue || ((timeInForce == TimeInForce.ImmediateOrCancel || timeInForce == TimeInForce.FillOrKill) && quantity != 0)) + parameters.AddOptionalString("price", price ?? 0); + parameters.AddOptional("close", closePosition); + parameters.AddOptional("reduce_only", reduceOnly); + parameters.AddOptionalEnum("tif", timeInForce); + parameters.AddOptionalString("iceberg", icebergQuantity); + parameters.AddOptional("text", text); + parameters.AddOptional("auto_size", closeSide); + parameters.AddOptional("stp_act", stpMode); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/orders", GateIoExchange.RateLimiter.RestFuturesOrderPlacement, 1, true); + return await _baseClient.SendAsync(request, parameters, ct, 1, new Dictionary { { "X-Gate-Channel-Id", _baseClient._brokerId } }).ConfigureAwait(false); + } + + #endregion + + #region Place Multiple Orders + + /// + public async Task>> PlaceMultipleOrderAsync( + string settlementAsset, + IEnumerable orders, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.SetBody(orders); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/batch_orders", GateIoExchange.RateLimiter.RestFuturesOrderPlacement, 1, true); + var result = await _baseClient.SendAsync>(request, parameters, ct, 1, new Dictionary { { "X-Gate-Channel-Id", _baseClient._brokerId } }).ConfigureAwait(false); + return result; + } + + #endregion + + #region Get Orders + + /// + public async Task>> GetOrdersAsync( + string settlementAsset, + string? contract = null, + OrderStatus? status = null, + int? limit = null, + int? offset = null, + string? lastId = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + parameters.AddOptionalEnum("status", status); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + parameters.AddOptional("last_id", lastId); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/orders", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel All Orders + + /// + public async Task>> CancelAllOrdersAsync(string settlementAsset, string contract, OrderSide? side = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + parameters.AddOptionalEnum("side", side); + var request = _definitions.GetOrCreate(HttpMethod.Delete, $"/api/v4/futures/{settlementAsset}/orders", GateIoExchange.RateLimiter.RestFuturesOrderCancelation, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel After + + /// + public async Task> CancelOrdersAfterAsync(string settlementAsset, TimeSpan cancelAfter, string? contract = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("timeout", (int)cancelAfter.TotalSeconds); + parameters.AddOptional("contract", contract); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/countdown_cancel_all", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel Orders + + /// + public async Task>> CancelOrdersAsync(string settlementAsset, IEnumerable orderIds, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.SetBody(orderIds.Select(x => x.ToString())); + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/batch_cancel_orders", GateIoExchange.RateLimiter.RestFuturesOrderCancelation, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Orders By Timestamp + + /// + public async Task>> GetOrdersByTimestampAsync( + string settlementAsset, + string? contract = null, + OrderStatus? status = null, + int? limit = null, + int? offset = null, + DateTime? startTime = null, + DateTime? endTime = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + parameters.AddOptionalEnum("status", status); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/orders_timerange", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Order + + /// + public async Task> GetOrderAsync( + string settlementAsset, + long orderId, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("order_id", orderId); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/orders/" + orderId, GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel Order + + /// + public async Task> CancelOrderAsync( + string settlementAsset, + long orderId, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("order_id", orderId); + var request = _definitions.GetOrCreate(HttpMethod.Delete, $"/api/v4/futures/{settlementAsset}/orders/" + orderId, GateIoExchange.RateLimiter.RestFuturesOrderCancelation, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Edit Order + + /// + public async Task> EditOrderAsync( + string settlementAsset, + long orderId, + int? quantity = null, + decimal? price = null, + string? amendText = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("order_id", orderId); + parameters.AddOptional("size", quantity); + parameters.AddOptionalString("price", price); + parameters.AddOptional("amend_text", amendText); + var request = _definitions.GetOrCreate(HttpMethod.Put, $"/api/v4/futures/{settlementAsset}/orders/" + orderId, GateIoExchange.RateLimiter.RestFuturesOrderPlacement, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get User Trades + + /// + public async Task>> GetUserTradesAsync( + string settlementAsset, + string? contract = null, + long? orderId = null, + int? limit = null, + int? offset = null, + long? lastId = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("order", orderId); + parameters.AddOptional("contract", contract); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + parameters.AddOptional("last_id", lastId); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/my_trades", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get User Trades By Timestamp + + /// + public async Task>> GetUserTradesByTimestampAsync( + string settlementAsset, + string? contract = null, + long? orderId = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + int? offset = null, + Role? role = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("order", orderId); + parameters.AddOptional("contract", contract); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + parameters.AddOptionalEnum("role", role); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/my_trades_timerange", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Position Close History + + /// + public async Task>> GetPositionCloseHistoryAsync( + string settlementAsset, + string? contract = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + int? offset = null, + Role? role = null, + PositionSide? side = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + parameters.AddOptionalEnum("role", role); + parameters.AddOptionalEnum("side", side); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/position_close", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Liquidation History + + /// + public async Task>> GetLiquidationHistoryAsync( + string settlementAsset, + string? contract = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + parameters.AddOptional("limit", limit); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/liquidates", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Auto Deleveraging History + + /// + public async Task>> GetAutoDeleveragingHistoryAsync( + string settlementAsset, + string? contract = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("contract", contract); + parameters.AddOptional("limit", limit); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/auto_deleverages", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Place Trigger Order + + /// + public async Task> PlaceTriggerOrderAsync( + string settlementAsset, + string contract, + OrderSide orderSide, + int quantity, + TriggerType triggerType, + decimal triggerPrice, + decimal? orderPrice = null, + bool? closePosition = null, + bool? reduceOnly = null, + CloseSide? closeSide = null, + PriceType? priceType = null, + TriggerOrderType? triggerOrderType = null, + TimeInForce? timeInForce = null, + string? text = null, + TimeSpan? expiration = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + var initial = new ParameterCollection(); + initial.Add("contract", contract); + initial.AddString("price", triggerPrice); + initial.AddString("size", orderSide == OrderSide.Buy ? quantity : -quantity); + initial.AddOptional("close", closePosition); + initial.AddOptional("reduce_only", reduceOnly); + initial.AddOptionalEnum("tif", timeInForce); + initial.AddOptional("text", text); + initial.AddOptionalEnum("auto_size", closeSide); + + var order = new ParameterCollection(); + order.AddOptionalString("price", orderPrice); + order.AddOptionalEnumAsInt("price_type", priceType); + order.AddOptional("rule", triggerType == TriggerType.EqualOrHigher ? 1 : 2); + order.AddOptionalString("expiration", (int?)expiration?.TotalSeconds); + + parameters.Add("initial", initial); + parameters.Add("trigger", order); + parameters.AddOptionalEnum("order_type", triggerOrderType); + + var request = _definitions.GetOrCreate(HttpMethod.Post, $"/api/v4/futures/{settlementAsset}/price_orders", GateIoExchange.RateLimiter.RestFuturesOrderPlacement, 1, true); + return await _baseClient.SendAsync(request, parameters, ct, 1, new Dictionary { { "X-Gate-Channel-Id", _baseClient._brokerId } }).ConfigureAwait(false); + } + + #endregion + + #region Get Trigger Orders + + /// + public async Task>> GetTriggerOrdersAsync( + string settlementAsset, + bool open, + string? contract = null, + int? limit = null, + int? offset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("status", open ? "open" : "finished"); + parameters.AddOptional("contract", contract); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/price_orders", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel Trigger Orders + + /// + public async Task>> CancelTriggerOrdersAsync( + string settlementAsset, + string contract, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("contract", contract); + + var request = _definitions.GetOrCreate(HttpMethod.Delete, $"/api/v4/futures/{settlementAsset}/price_orders", GateIoExchange.RateLimiter.RestFuturesOrderCancelation, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Trigger Order + + /// + public async Task> GetTriggerOrderAsync( + string settlementAsset, + long orderId, + CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/futures/{settlementAsset}/price_orders/{orderId}", GateIoExchange.RateLimiter.RestFuturesOther, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel Trigger Order + + /// + public async Task> CancelTriggerOrderAsync( + string settlementAsset, + long orderId, + CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Delete, $"/api/v4/futures/{settlementAsset}/price_orders/{orderId}", GateIoExchange.RateLimiter.RestFuturesOrderCancelation, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + } +} diff --git a/GateIo.Net/Clients/FuturesApi/GateIoSocketClientPerpetualFuturesApi.cs b/GateIo.Net/Clients/FuturesApi/GateIoSocketClientPerpetualFuturesApi.cs new file mode 100644 index 0000000..8dd58a3 --- /dev/null +++ b/GateIo.Net/Clients/FuturesApi/GateIoSocketClientPerpetualFuturesApi.cs @@ -0,0 +1,191 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Clients; +using CryptoExchange.Net.Converters.MessageParsing; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using CryptoExchange.Net.Sockets; +using GateIo.Net.Objects.Models; +using Microsoft.Extensions.Logging; +using GateIo.Net.Objects.Options; +using GateIo.Net.Objects.Sockets.Subscriptions; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; +using CryptoExchange.Net; +using CryptoExchange.Net.Converters.SystemTextJson; +using System.Collections.Generic; +using System.Linq; +using GateIo.Net.Enums; + +namespace GateIo.Net.Clients.FuturesApi +{ + /// + /// Client providing access to the GateIo futures websocket Api + /// + public class GateIoSocketClientPerpetualFuturesApi : SocketApiClient, IGateIoSocketClientPerpetualFuturesApi + { + #region fields + private static readonly MessagePath _idPath = MessagePath.Get().Property("id"); + private static readonly MessagePath _channelPath = MessagePath.Get().Property("channel"); + private static readonly MessagePath _contractPath = MessagePath.Get().Property("result").Index(0).Property("contract"); + private static readonly MessagePath _contractPath2 = MessagePath.Get().Property("result").Property("s"); + private static readonly MessagePath _klinePath = MessagePath.Get().Property("result").Index(0).Property("n"); + #endregion + + #region constructor/destructor + + /// + /// ctor + /// + internal GateIoSocketClientPerpetualFuturesApi(ILogger logger, GateIoSocketOptions options) : + base(logger, options.Environment.FuturesSocketClientAddress!, options, options.PerpetualFuturesOptions) + { + } + #endregion + + /// + protected override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(); + /// + protected override IByteMessageAccessor CreateAccessor() => new SystemTextJsonByteMessageAccessor(); + + /// + protected override AuthenticationProvider CreateAuthenticationProvider(ApiCredentials credentials) + => new GateIoAuthenticationProvider(credentials); + + /// + public async Task> SubscribeToTradeUpdatesAsync(string settlementAsset, string contract, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription>(_logger, "futures.trades", new[] { "futures.trades." + contract }, new[] { contract }, x => onMessage(x.WithSymbol(x.Data.First().Contract)), false); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToTickerUpdatesAsync(string settlementAsset, string contract, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription>(_logger, "futures.tickers", new[] { "futures.tickers." + contract }, new[] { contract }, x => onMessage(x.WithSymbol(x.Data.First().Contract)), false); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToBookTickerUpdatesAsync(string settlementAsset, string contract, Action> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription(_logger, "futures.book_ticker", new[] { "futures.book_ticker." + contract }, new[] { contract }, x => onMessage(x.WithSymbol(x.Data.Contract)), false); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToOrderBookUpdatesAsync(string settlementAsset, string contract, int updateMs, int depth, Action> onMessage, CancellationToken ct = default) + { + updateMs.ValidateIntValues(nameof(updateMs), 20, 100, 1000); + depth.ValidateIntValues(nameof(depth), 5, 10, 20, 50, 100); + + var subscription = new GateIoSubscription(_logger, "futures.order_book_update", new[] { "futures.order_book_update." + contract }, new[] { contract, updateMs + "ms", depth.ToString() }, x => onMessage(x.WithSymbol(x.Data.Contract)), false); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToKlineUpdatesAsync(string settlementAsset, string contract, KlineInterval interval, Action>> onMessage, CancellationToken ct = default) + { + var intervalStr = EnumConverter.GetString(interval); + var subscription = new GateIoSubscription>(_logger, "futures.candlesticks", new[] { "futures.candlesticks." + intervalStr + "_" + contract }, new[] { intervalStr, contract }, x => onMessage(x.WithSymbol(x.Data.First().Contract)), false); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToOrderUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.orders", new[] { "futures.orders" }, new[] { userId.ToString(), "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToUserTradeUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.usertrades", new[] { "futures.usertrades" }, new[] { userId.ToString(), "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToUserLiquidationUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.liquidates", new[] { "futures.liquidates" }, new[] { userId.ToString(), "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToUserAutoDeleverageUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.auto_deleverages", new[] { "futures.auto_deleverages" }, new[] { userId.ToString(), "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToPositionCloseUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.position_closes", new[] { "futures.position_closes" }, new[] { userId.ToString(), "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToBalanceUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.balances", new[] { "futures.balances" }, new[] { userId.ToString() }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToReduceRiskLimitUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.reduce_risk_limits", new[] { "futures.reduce_risk_limits" }, new[] { userId.ToString(), "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToPositionUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.positions", new[] { "futures.positions" }, new[] { userId.ToString(), "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToTriggerOrderUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "futures.autoorders", new[] { "futures.autoorders" }, new[] { userId.ToString(), "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("v4/ws/" + settlementAsset), subscription, ct).ConfigureAwait(false); + } + + /// + public override string? GetListenerIdentifier(IMessageAccessor message) + { + var id = message.GetValue(_idPath); + if (id != null) + return id.ToString(); + + var channel = message.GetValue(_channelPath); + + if (string.Equals(channel, "futures.trades") + || string.Equals(channel, "futures.tickers")) + { + return channel + "." + message.GetValue(_contractPath); + } + + if (string.Equals(channel, "futures.candlesticks")) + return channel + "." + message.GetValue(_klinePath); + + if (string.Equals(channel, "futures.book_ticker") + || string.Equals(channel, "futures.order_book_update") + || string.Equals(channel, "futures.order_book")) + return channel + "." + message.GetValue(_contractPath2); + + return channel; + } + + /// + protected override Query? GetAuthenticationRequest() => null; + + /// + public override string FormatSymbol(string baseAsset, string quoteAsset) => baseAsset.ToUpperInvariant() + "_" + quoteAsset.ToUpperInvariant(); + } +} diff --git a/GateIo.Net/Clients/GateIoRestClient.cs b/GateIo.Net/Clients/GateIoRestClient.cs new file mode 100644 index 0000000..cf90d1e --- /dev/null +++ b/GateIo.Net/Clients/GateIoRestClient.cs @@ -0,0 +1,74 @@ +using Microsoft.Extensions.Logging; +using System.Net.Http; +using System; +using CryptoExchange.Net.Authentication; +using GateIo.Net.Interfaces.Clients; +using GateIo.Net.Interfaces.Clients.SpotApi; +using GateIo.Net.Objects.Options; +using GateIo.Net.Clients.SpotApi; +using GateIo.Net.Clients.FuturesApi; +using CryptoExchange.Net.Clients; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; + +namespace GateIo.Net.Clients +{ + /// + public class GateIoRestClient : BaseRestClient, IGateIoRestClient + { + #region Api clients + + /// + public IGateIoRestClientSpotApi SpotApi { get; } + /// + public IGateIoRestClientPerpetualFuturesApi PerpetualFuturesApi { get; } + + #endregion + + #region constructor/destructor + + /// + /// Create a new instance of the GateIoRestClient using provided options + /// + /// Option configuration delegate + public GateIoRestClient(Action? optionsDelegate = null) : this(null, null, optionsDelegate) + { + } + + /// + /// Create a new instance of the GateIoRestClient using provided options + /// + /// Option configuration delegate + /// The logger factory + /// Http client for this client + public GateIoRestClient(HttpClient? httpClient, ILoggerFactory? loggerFactory, Action? optionsDelegate = null) : base(loggerFactory, "GateIo") + { + var options = GateIoRestOptions.Default.Copy(); + if (optionsDelegate != null) + optionsDelegate(options); + Initialize(options); + + SpotApi = AddApiClient(new GateIoRestClientSpotApi(_logger, httpClient, options)); + PerpetualFuturesApi = AddApiClient(new GateIoRestClientPerpetualFuturesApi(_logger, httpClient, options)); + } + + #endregion + + /// + /// Set the default options to be used when creating new clients + /// + /// Option configuration delegate + public static void SetDefaultOptions(Action optionsDelegate) + { + var options = GateIoRestOptions.Default.Copy(); + optionsDelegate(options); + GateIoRestOptions.Default = options; + } + + /// + public void SetApiCredentials(ApiCredentials credentials) + { + SpotApi.SetApiCredentials(credentials); + PerpetualFuturesApi.SetApiCredentials(credentials); + } + } +} diff --git a/GateIo.Net/Clients/GateIoSocketClient.cs b/GateIo.Net/Clients/GateIoSocketClient.cs new file mode 100644 index 0000000..103b50d --- /dev/null +++ b/GateIo.Net/Clients/GateIoSocketClient.cs @@ -0,0 +1,81 @@ +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Clients; +using Microsoft.Extensions.Logging; +using System; +using GateIo.Net.Clients.FuturesApi; +using GateIo.Net.Clients.SpotApi; +using GateIo.Net.Interfaces.Clients; +using GateIo.Net.Interfaces.Clients.SpotApi; +using GateIo.Net.Objects.Options; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; + +namespace GateIo.Net.Clients +{ + /// + public class GateIoSocketClient : BaseSocketClient, IGateIoSocketClient + { + #region fields + #endregion + + #region Api clients + + /// + public IGateIoSocketClientSpotApi SpotApi { get; set; } + + /// + public IGateIoSocketClientPerpetualFuturesApi PerpetualFuturesApi { get; set; } + + #endregion + + #region constructor/destructor + /// + /// Create a new instance of GateIoSocketClient + /// + /// The logger factory + public GateIoSocketClient(ILoggerFactory? loggerFactory = null) : this((x) => { }, loggerFactory) + { + } + + /// + /// Create a new instance of GateIoSocketClient + /// + /// Option configuration delegate + public GateIoSocketClient(Action optionsDelegate) : this(optionsDelegate, null) + { + } + + /// + /// Create a new instance of GateIoSocketClient + /// + /// The logger factory + /// Option configuration delegate + public GateIoSocketClient(Action? optionsDelegate, ILoggerFactory? loggerFactory = null) : base(loggerFactory, "GateIo") + { + var options = GateIoSocketOptions.Default.Copy(); + optionsDelegate?.Invoke(options); + Initialize(options); + + SpotApi = AddApiClient(new GateIoSocketClientSpotApi(_logger, options)); + PerpetualFuturesApi = AddApiClient(new GateIoSocketClientPerpetualFuturesApi(_logger, options)); + } + #endregion + + /// + /// Set the default options to be used when creating new clients + /// + /// Option configuration delegate + public static void SetDefaultOptions(Action optionsDelegate) + { + var options = GateIoSocketOptions.Default.Copy(); + optionsDelegate(options); + GateIoSocketOptions.Default = options; + } + + /// + public void SetApiCredentials(ApiCredentials credentials) + { + SpotApi.SetApiCredentials(credentials); + PerpetualFuturesApi.SetApiCredentials(credentials); + } + } +} diff --git a/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApi.cs b/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApi.cs new file mode 100644 index 0000000..a108b40 --- /dev/null +++ b/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApi.cs @@ -0,0 +1,462 @@ +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Objects; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.CommonObjects; +using CryptoExchange.Net.Interfaces.CommonClients; +using GateIo.Net.Interfaces.Clients.SpotApi; +using GateIo.Net.Objects.Options; +using CryptoExchange.Net.Clients; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Converters.MessageParsing; +using CryptoExchange.Net.Converters.SystemTextJson; +using System.Globalization; +using System.Linq; + +namespace GateIo.Net.Clients.SpotApi +{ + /// + public class GateIoRestClientSpotApi : RestApiClient, IGateIoRestClientSpotApi, ISpotClient + { + #region fields + internal static TimeSyncState _timeSyncState = new TimeSyncState("Spot Api"); + internal string _brokerId; + #endregion + + #region Api clients + /// + public IGateIoRestClientSpotApiAccount Account { get; } + /// + public IGateIoRestClientSpotApiExchangeData ExchangeData { get; } + /// + public IGateIoRestClientSpotApiTrading Trading { get; } + /// + public string ExchangeName => "GateIo"; + #endregion + + /// + /// Event triggered when an order is placed via this client. Only available for Spot orders + /// + public event Action? OnOrderPlaced; + /// + /// Event triggered when an order is canceled via this client. Note that this does not trigger when using CancelAllOrdersAsync. Only available for Spot orders + /// + public event Action? OnOrderCanceled; + + #region constructor/destructor + internal GateIoRestClientSpotApi(ILogger logger, HttpClient? httpClient, GateIoRestOptions options) + : base(logger, httpClient, options.Environment.RestClientAddress, options, options.SpotOptions) + { + Account = new GateIoRestClientSpotApiAccount(this); + ExchangeData = new GateIoRestClientSpotApiExchangeData(logger, this); + Trading = new GateIoRestClientSpotApiTrading(logger, this); + + _brokerId = string.IsNullOrEmpty(options.BrokerId) ? "copytraderpw" : options.BrokerId!; + ParameterPositions[HttpMethod.Delete] = HttpMethodParameterPosition.InUri; + } + #endregion + + /// + protected override IStreamMessageAccessor CreateAccessor() => new SystemTextJsonStreamMessageAccessor(); + /// + protected override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(); + + /// + protected override AuthenticationProvider CreateAuthenticationProvider(ApiCredentials credentials) + => new GateIoAuthenticationProvider(credentials); + + internal Task SendAsync(RequestDefinition definition, ParameterCollection? parameters, CancellationToken cancellationToken, int? weight = null) + => base.SendAsync(BaseAddress, definition, parameters, cancellationToken, null, weight); + + internal Task> SendAsync(RequestDefinition definition, ParameterCollection? parameters, CancellationToken cancellationToken, int? weight = null, Dictionary? requestHeaders = null) where T : class + => SendToAddressAsync(BaseAddress, definition, parameters, cancellationToken, weight, requestHeaders); + + internal async Task> SendToAddressAsync(string baseAddress, RequestDefinition definition, ParameterCollection? parameters, CancellationToken cancellationToken, int? weight = null, Dictionary? requestHeaders = null) where T : class + { + var result = await base.SendAsync(baseAddress, definition, parameters, cancellationToken, requestHeaders, weight).ConfigureAwait(false); + + // GateIo Optional response checking + + return result; + } + + internal Task> SendAsync(RequestDefinition definition, ParameterCollection? queryParameters, ParameterCollection? bodyParameters, CancellationToken cancellationToken, int? weight = null) where T : class + => SendToAddressAsync(BaseAddress, definition, queryParameters, bodyParameters, cancellationToken, weight); + + internal async Task> SendToAddressAsync(string baseAddress, RequestDefinition definition, ParameterCollection? queryParameters, ParameterCollection? bodyParameters, CancellationToken cancellationToken, int? weight = null) where T : class + { + var result = await base.SendAsync(baseAddress, definition, queryParameters, bodyParameters, cancellationToken, null, weight).ConfigureAwait(false); + + // GateIo Optional response checking + + return result; + } + + /// + protected override Error ParseErrorResponse(int httpStatusCode, IEnumerable>> responseHeaders, IMessageAccessor accessor) + { + if (!accessor.IsJson) + return new ServerError(accessor.GetOriginalString()); + + var lbl = accessor.GetValue(MessagePath.Get().Property("label")); + if (lbl == null) + return new ServerError(accessor.GetOriginalString()); + + var msg = accessor.GetValue(MessagePath.Get().Property("message")); + return new ServerError(lbl + ": " + msg); + } + + /// + protected override ServerRateLimitError ParseRateLimitResponse(int httpStatusCode, IEnumerable>> responseHeaders, IMessageAccessor accessor) + { + if (!accessor.IsJson) + return new ServerRateLimitError(accessor.GetOriginalString()); + + var error = GetRateLimitError(accessor); + + var resetTime = responseHeaders.SingleOrDefault(x => x.Key.Equals("X-Gate-RateLimit-Reset-Timestamp")); + if (resetTime.Value?.Any() != true) + return error; + + var value = resetTime.Value.First(); + var timestamp = DateTimeConverter.ParseFromString(value); + + error.RetryAfter = timestamp.AddSeconds(1); + return error; + } + + private ServerRateLimitError GetRateLimitError(IMessageAccessor accessor) + { + if (!accessor.IsJson) + return new ServerRateLimitError(accessor.GetOriginalString()); + + var lbl = accessor.GetValue(MessagePath.Get().Property("label")); + if (lbl == null) + return new ServerRateLimitError(accessor.GetOriginalString()); + + var msg = accessor.GetValue(MessagePath.Get().Property("message")); + return new ServerRateLimitError(lbl + ": " + msg); + } + + /// + protected override Task> GetServerTimestampAsync() + => ExchangeData.GetServerTimeAsync(); + + /// + public override TimeSyncInfo? GetTimeSyncInfo() + => new TimeSyncInfo(_logger, ApiOptions.AutoTimestamp ?? ClientOptions.AutoTimestamp, ApiOptions.TimestampRecalculationInterval ?? ClientOptions.TimestampRecalculationInterval, _timeSyncState); + + /// + public override TimeSpan? GetTimeOffset() + => _timeSyncState.TimeOffset; + + + /// + public override string FormatSymbol(string baseAsset, string quoteAsset) => baseAsset.ToUpperInvariant() + "_" + quoteAsset.ToUpperInvariant(); + + /// + public ISpotClient CommonSpotClient => this; + + /// + public string GetSymbolName(string baseAsset, string quoteAsset) => baseAsset.ToUpperInvariant() + "_" + quoteAsset.ToUpperInvariant(); + + internal void InvokeOrderPlaced(OrderId id) + { + OnOrderPlaced?.Invoke(id); + } + + internal void InvokeOrderCanceled(OrderId id) + { + OnOrderCanceled?.Invoke(id); + } + + async Task> ISpotClient.PlaceOrderAsync(string symbol, CommonOrderSide side, CommonOrderType type, decimal quantity, decimal? price, string? accountId, string? clientOrderId, CancellationToken ct) + { + if (string.IsNullOrWhiteSpace(symbol)) + throw new ArgumentException(nameof(symbol) + " required for Gate.io " + nameof(ISpotClient.PlaceOrderAsync), nameof(symbol)); + + var result = await Trading.PlaceOrderAsync(symbol, + side == CommonOrderSide.Sell ? Enums.OrderSide.Sell : Enums.OrderSide.Buy, + type == CommonOrderType.Limit ? Enums.NewOrderType.Limit : Enums.NewOrderType.Market, + quantity, + price, + timeInForce: type == CommonOrderType.Limit ? Enums.TimeInForce.GoodTillCancel : null, + text: clientOrderId).ConfigureAwait(false); + if (!result) + return result.As(null); + + return result.As(new OrderId + { + SourceObject = result.Data, + Id = result.Data.Id.ToString(CultureInfo.InvariantCulture) + }); + } + + async Task> IBaseRestClient.GetOrderAsync(string orderId, string? symbol, CancellationToken ct) + { + if (!long.TryParse(orderId, out var id)) + throw new ArgumentException("Order id invalid", nameof(orderId)); + + if (string.IsNullOrWhiteSpace(symbol)) + throw new ArgumentException(nameof(symbol) + " required for Gate.io " + nameof(ISpotClient.GetOrderAsync), nameof(symbol)); + + var order = await Trading.GetOrderAsync(symbol!, id, ct: ct).ConfigureAwait(false); + if (!order) + return order.As(null); + + return order.As(new Order + { + SourceObject = order, + Id = order.Data.Id.ToString(CultureInfo.InvariantCulture), + Symbol = order.Data.Symbol, + Price = order.Data.Price, + Quantity = order.Data.Quantity, + QuantityFilled = order.Data.QuantityFilled, + Side = order.Data.Side == Enums.OrderSide.Buy ? CommonOrderSide.Buy : CommonOrderSide.Sell, + Type = order.Data.Type == Enums.OrderType.Market ? CommonOrderType.Market : order.Data.Type == Enums.OrderType.Limit ? CommonOrderType.Limit : CommonOrderType.Other, + Status = order.Data.Status == Enums.OrderStatus.Open ? CommonOrderStatus.Active : order.Data.Status == Enums.OrderStatus.Canceled ? CommonOrderStatus.Canceled : CommonOrderStatus.Filled, + Timestamp = order.Data.CreateTime + }); + } + + async Task>> IBaseRestClient.GetOrderTradesAsync(string orderId, string? symbol, CancellationToken ct) + { + if (!long.TryParse(orderId, out var id)) + throw new ArgumentException("Order id invalid", nameof(orderId)); + + if (string.IsNullOrWhiteSpace(symbol)) + throw new ArgumentException(nameof(symbol) + " required for Gate.io " + nameof(ISpotClient.GetOrderTradesAsync), nameof(symbol)); + + var trades = await Trading.GetUserTradesAsync(symbol!, id, ct: ct).ConfigureAwait(false); + if (!trades) + return trades.As>(null); + + return trades.As(trades.Data.Select(t => + new UserTrade + { + SourceObject = t, + Id = t.Id.ToString(CultureInfo.InvariantCulture), + OrderId = t.OrderId.ToString(CultureInfo.InvariantCulture), + Symbol = t.Symbol, + Price = t.Price, + Quantity = t.Quantity, + Fee = t.Fee, + FeeAsset = t.FeeAsset, + Timestamp = t.CreateTime + })); + } + + async Task>> IBaseRestClient.GetOpenOrdersAsync(string? symbol, CancellationToken ct) + { + var orderInfo = await Trading.GetOpenOrdersAsync(ct: ct).ConfigureAwait(false); + if (!orderInfo) + return orderInfo.As>(null); + + return orderInfo.As(orderInfo.Data.SelectMany(d => d.Orders).Select(s => + new Order + { + SourceObject = s, + Id = s.Id.ToString(CultureInfo.InvariantCulture), + Symbol = s.Symbol, + Price = s.Price, + Quantity = s.Quantity, + QuantityFilled = s.QuantityFilled, + Side = s.Side == Enums.OrderSide.Buy ? CommonOrderSide.Buy : CommonOrderSide.Sell, + Type = s.Type == Enums.OrderType.Market ? CommonOrderType.Market : s.Type == Enums.OrderType.Limit ? CommonOrderType.Limit : CommonOrderType.Other, + Status = s.Status == Enums.OrderStatus.Open ? CommonOrderStatus.Active : s.Status == Enums.OrderStatus.Canceled ? CommonOrderStatus.Canceled : CommonOrderStatus.Filled, + Timestamp = s.CreateTime + })); + } + + async Task>> IBaseRestClient.GetClosedOrdersAsync(string? symbol, CancellationToken ct) + { + var orderInfo = await Trading.GetOrdersAsync(false, symbol, ct: ct).ConfigureAwait(false); + if (!orderInfo) + return orderInfo.As>(null); + + return orderInfo.As(orderInfo.Data.Select(s => + new Order + { + SourceObject = s, + Id = s.Id.ToString(CultureInfo.InvariantCulture), + Symbol = s.Symbol, + Price = s.Price, + Quantity = s.Quantity, + QuantityFilled = s.QuantityFilled, + Side = s.Side == Enums.OrderSide.Buy ? CommonOrderSide.Buy : CommonOrderSide.Sell, + Type = s.Type == Enums.OrderType.Market ? CommonOrderType.Market : s.Type == Enums.OrderType.Limit ? CommonOrderType.Limit : CommonOrderType.Other, + Status = s.Status == Enums.OrderStatus.Open ? CommonOrderStatus.Active : s.Status == Enums.OrderStatus.Canceled ? CommonOrderStatus.Canceled : CommonOrderStatus.Filled, + Timestamp = s.CreateTime + })); + } + + async Task> IBaseRestClient.CancelOrderAsync(string orderId, string? symbol, CancellationToken ct) + { + if (!long.TryParse(orderId, out var id)) + throw new ArgumentException("Order id invalid", nameof(orderId)); + + if (string.IsNullOrWhiteSpace(symbol)) + throw new ArgumentException(nameof(symbol) + " required for Gate.io " + nameof(ISpotClient.CancelOrderAsync), nameof(symbol)); + + var order = await Trading.CancelOrderAsync(symbol!, id, ct: ct).ConfigureAwait(false); + if (!order) + return order.As(null); + + return order.As(new OrderId + { + SourceObject = order.Data, + Id = order.Data.Id.ToString(CultureInfo.InvariantCulture) + }); + } + + async Task>> IBaseRestClient.GetSymbolsAsync(CancellationToken ct) + { + var exchangeInfo = await ExchangeData.GetSymbolsAsync(ct: ct).ConfigureAwait(false); + if (!exchangeInfo) + return exchangeInfo.As>(null); + + return exchangeInfo.As(exchangeInfo.Data.Select(s => + new Symbol + { + SourceObject = s, + Name = s.Name, + MinTradeQuantity = s.MinBaseQuantity, + PriceStep = s.PricePrecision, + QuantityStep = s.QuantityPrecision + })); + } + + async Task> IBaseRestClient.GetTickerAsync(string symbol, CancellationToken ct) + { + if (string.IsNullOrWhiteSpace(symbol)) + throw new ArgumentException(nameof(symbol) + " required for Gate.io " + nameof(ISpotClient.GetTickerAsync), nameof(symbol)); + + var tickers = await ExchangeData.GetTickersAsync(symbol, ct: ct).ConfigureAwait(false); + if (!tickers) + return tickers.As(null); + + var ticker = tickers.Data.Single(); + + return tickers.As(new Ticker + { + SourceObject = ticker, + Symbol = ticker.Symbol, + HighPrice = ticker.HighPrice, + LowPrice = ticker.LowPrice, + Price24H = ticker.LastPrice * (1 - ticker.ChangePercentage24h / 100), + LastPrice = ticker.LastPrice, + Volume = ticker.BaseVolume + }); + } + + async Task>> IBaseRestClient.GetTickersAsync(CancellationToken ct) + { + var tickers = await ExchangeData.GetTickersAsync(ct: ct).ConfigureAwait(false); + if (!tickers) + return tickers.As>(null); + + return tickers.As(tickers.Data.Select(t => new Ticker + { + SourceObject = t, + Symbol = t.Symbol, + HighPrice = t.HighPrice, + LowPrice = t.LowPrice, + Price24H = t.LastPrice * (1 - t.ChangePercentage24h / 100), + LastPrice = t.LastPrice, + Volume = t.BaseVolume + })); + } + + async Task>> IBaseRestClient.GetKlinesAsync(string symbol, TimeSpan timespan, DateTime? startTime, DateTime? endTime, int? limit, CancellationToken ct) + { + if (string.IsNullOrWhiteSpace(symbol)) + throw new ArgumentException(nameof(symbol) + " required for Gate.io " + nameof(ISpotClient.GetKlinesAsync), nameof(symbol)); + + var klines = await ExchangeData.GetKlinesAsync(symbol, GetKlineIntervalFromTimespan(timespan), startTime, endTime, limit, ct: ct).ConfigureAwait(false); + if (!klines) + return klines.As>(null); + + return klines.As(klines.Data.Select(t => new Kline + { + SourceObject = t, + HighPrice = t.HighPrice, + LowPrice = t.LowPrice, + OpenTime = t.OpenTime, + ClosePrice = t.ClosePrice, + OpenPrice = t.OpenPrice, + Volume = t.BaseVolume + })); + } + + async Task> IBaseRestClient.GetOrderBookAsync(string symbol, CancellationToken ct) + { + if (string.IsNullOrWhiteSpace(symbol)) + throw new ArgumentException(nameof(symbol) + " required for Gate.io " + nameof(ISpotClient.GetOrderBookAsync), nameof(symbol)); + + var orderbook = await ExchangeData.GetOrderBookAsync(symbol, ct: ct).ConfigureAwait(false); + if (!orderbook) + return orderbook.As(null); + + return orderbook.As(new OrderBook + { + SourceObject = orderbook.Data, + Asks = orderbook.Data.Asks.Select(a => new OrderBookEntry { Price = a.Price, Quantity = a.Quantity }), + Bids = orderbook.Data.Bids.Select(b => new OrderBookEntry { Price = b.Price, Quantity = b.Quantity }) + }); + } + + async Task>> IBaseRestClient.GetRecentTradesAsync(string symbol, CancellationToken ct) + { + if (string.IsNullOrWhiteSpace(symbol)) + throw new ArgumentException(nameof(symbol) + " required for Gate.io " + nameof(ISpotClient.GetRecentTradesAsync), nameof(symbol)); + + var trades = await ExchangeData.GetTradesAsync(symbol, ct: ct).ConfigureAwait(false); + if (!trades) + return trades.As>(null); + + return trades.As(trades.Data.Select(t => new Trade + { + SourceObject = t, + Symbol = symbol, + Price = t.Price, + Quantity = t.Quantity, + Timestamp = t.CreateTime + })); + } + + async Task>> IBaseRestClient.GetBalancesAsync(string? accountId, CancellationToken ct) + { + var balances = await Account.GetBalancesAsync(ct: ct).ConfigureAwait(false); + if (!balances) + return balances.As>(null); + + return balances.As(balances.Data.Select(t => new Balance + { + SourceObject = t, + Asset = t.Asset, + Available = t.Available, + Total = t.Available + t.Locked + })); + } + + private static Enums.KlineInterval GetKlineIntervalFromTimespan(TimeSpan timeSpan) + { + if (timeSpan == TimeSpan.FromMinutes(1)) return Enums.KlineInterval.OneMinute; + if (timeSpan == TimeSpan.FromMinutes(5)) return Enums.KlineInterval.FiveMinutes; + if (timeSpan == TimeSpan.FromMinutes(15)) return Enums.KlineInterval.FifteenMinutes; + if (timeSpan == TimeSpan.FromMinutes(30)) return Enums.KlineInterval.ThirtyMinutes; + if (timeSpan == TimeSpan.FromHours(1)) return Enums.KlineInterval.OneHour; + if (timeSpan == TimeSpan.FromHours(4)) return Enums.KlineInterval.FourHours; + if (timeSpan == TimeSpan.FromHours(8)) return Enums.KlineInterval.EightHours; + if (timeSpan == TimeSpan.FromDays(1)) return Enums.KlineInterval.OneDay; + if (timeSpan == TimeSpan.FromDays(7)) return Enums.KlineInterval.OneWeek; + if (timeSpan == TimeSpan.FromDays(30) || timeSpan == TimeSpan.FromDays(31)) return Enums.KlineInterval.OneMonth; + + throw new ArgumentException("Unsupported timespan for Gate.io Klines, check supported intervals using GateIo.Net.Enums.KlineInterval"); + } + } +} diff --git a/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiAccount.cs b/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiAccount.cs new file mode 100644 index 0000000..c42d355 --- /dev/null +++ b/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiAccount.cs @@ -0,0 +1,888 @@ +using CryptoExchange.Net.Objects; +using GateIo.Net.Interfaces.Clients.SpotApi; +using GateIo.Net.Objects.Models; +using GateIo.Net.Enums; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace GateIo.Net.Clients.SpotApi +{ + /// + public class GateIoRestClientSpotApiAccount : IGateIoRestClientSpotApiAccount + { + private readonly GateIoRestClientSpotApi _baseClient; + private static readonly RequestDefinitionCache _definitions = new RequestDefinitionCache(); + + internal GateIoRestClientSpotApiAccount(GateIoRestClientSpotApi baseClient) + { + _baseClient = baseClient; + } + + #region Get Balances + + /// + public async Task>> GetBalancesAsync(string? asset = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/accounts", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Account Ledger + + /// + public async Task>> GetLedgerAsync(string? asset = null, DateTime? startTime = null, DateTime? endTime = null, int? page = null, int? limit = null, string? type = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptional("type", type); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/account_book", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Withdraw + + /// + public async Task> WithdrawAsync(string asset, decimal quantity, string address, string network, string? memo = null, string? clientOrderId = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + parameters.AddString("amount", quantity); + parameters.Add("address", address); + parameters.Add("chain", network); + parameters.AddOptional("withdraw_order_id", clientOrderId); + parameters.AddOptional("memo", memo); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/withdrawals", GateIoExchange.RateLimiter.RestSpotOther, 1, true, 1, TimeSpan.FromSeconds(3)); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel Withdrawal + + /// + public async Task> CancelWithdrawalAsync(string withdrawalId, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Delete, "/api/v4/withdrawals/" + withdrawalId, GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Generate Deposit Address + + /// + public async Task> GenerateDepositAddressAsync(string asset, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/deposit_address", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Withdrawals + + /// + public async Task>> GetWithdrawalsAsync( + string? asset = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + int? offset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptional("to", endTime); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/withdrawals", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Deposits + + /// + public async Task>> GetDepositsAsync( + string? asset = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + int? offset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptional("to", endTime); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/deposits", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Transfer + + /// + public async Task> TransferAsync( + string asset, + AccountType from, + AccountType to, + decimal quantity, + string? marginSymbol = null, + string? settleAsset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddEnum("from", from); + parameters.AddEnum("to", to); + parameters.AddString("amount", quantity); + parameters.AddOptional("currency_pair", marginSymbol); + parameters.AddOptional("settle", settleAsset); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/wallet/transfers", GateIoExchange.RateLimiter.RestSpotOther, 1, true, 80, TimeSpan.FromSeconds(10)); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Withdraw Status + + /// + public async Task>> GetWithdrawStatusAsync( + string? asset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/withdraw_status", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Saved Deposit Address + + /// + public async Task>> GetSavedAddressAsync( + string asset, + string? network = null, + int? limit = null, + int? page = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + parameters.AddOptional("chain", network); + parameters.AddOptional("limit", limit); + parameters.AddOptional("page", page); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/saved_address", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Trading Fee + + /// + public async Task> GetTradingFeeAsync( + string? symbol = null, + string? settleAsset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency_pair", symbol); + parameters.AddOptional("settle", settleAsset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/fee", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Account Balances + + /// + public async Task> GetAccountBalancesAsync( + string? valuationAsset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", valuationAsset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/total_balance", GateIoExchange.RateLimiter.Public, 1, true, 80, TimeSpan.FromSeconds(10)); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Small Balances + + /// + public async Task>> GetSmallBalancesAsync( + CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/small_balance", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Convert Small Balances + + /// + public async Task ConvertSmallBalancesAsync( + IEnumerable? assets = null, + bool? all = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", assets); + parameters.AddOptional("is_all", all); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/wallet/small_balance", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Small Balances Conversions + + /// + public async Task>> GetSmallBalanceConversionsAsync( + string? asset = null, + int? page = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/wallet/small_balance_history", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Info + + /// + public async Task> GetUnifiedAccountInfoAsync( + string? asset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/accounts", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Borrowable + + /// + public async Task> GetUnifiedAccountBorrowableAsync( + string asset, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/borrowable", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Transferable + + /// + public async Task> GetUnifiedAccountTransferableAsync( + string asset, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/transferable", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Unified Account Borrow Or Repay + + /// + public async Task UnifiedAccountBorrowOrRepayAsync( + string asset, + BorrowDirection direction, + decimal quantity, + bool? repayAll = null, + string? text = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + parameters.AddEnum("type", direction); + parameters.AddString("amount", quantity); + parameters.AddOptional("repaid_all", repayAll); + parameters.AddOptional("text", text); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/unified/loans", GateIoExchange.RateLimiter.RestPrivate, 1, true, 15, TimeSpan.FromSeconds(10)); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Loans + + /// + public async Task>> GetUnifiedAccountLoansAsync( + string? asset = null, + int? page = null, + int? limit = null, + LoanType? type = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptionalEnum("type", type); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/loans", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Loan History + + /// + public async Task>> GetUnifiedAccountLoanHistoryAsync( + string? asset = null, + BorrowDirection? direction = null, + int? page = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptionalEnum("type", direction); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/loan_records", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Interest History + + /// + public async Task>> GetUnifiedAccountInterestHistoryAsync( + string? asset = null, + int? page = null, + int? limit = null, + LoanType? type = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptionalEnum("type", type); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/interest_records", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Risk Units + + /// + public async Task> GetUnifiedAccountRiskUnitsAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/risk_units", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Set Unified Account Mode + + /// + public async Task SetUnifiedAccountModeAsync(UnifiedAccountMode mode, bool? usdtFutures = null, bool? spotHedge = null, bool? useFunding = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddEnum("mode", mode); + if (usdtFutures != null || spotHedge != null || useFunding != null) + { + var inner = new ParameterCollection(); + inner.AddOptional("usdt_futures", usdtFutures); + inner.AddOptional("spot_hedge", spotHedge); + inner.AddOptional("use_funding", useFunding); + parameters.Add("settings", inner); + } + var request = _definitions.GetOrCreate(HttpMethod.Put, "/api/v4/unified/unified_mode", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Mode + + /// + public async Task> GetUnifiedAccountModeAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/unified_mode", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Unified Account Estimated Lending Rates + + /// + public async Task>> GetUnifiedAccountEstimatedLendingRatesAsync(IEnumerable assets, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currencies", string.Join(",", assets)); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/unified/estimate_rate", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Account Info + + /// + public async Task> GetAccountInfoAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/account/detail", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Accounts + + /// + public async Task>> GetMarginAccountsAsync(string? symbol = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency_pair", symbol); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/accounts", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Balance History + + /// + public async Task>> GetMarginBalanceHistoryAsync( + string? asset = null, + string? symbol = null, + string? type = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? page = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("currency_pair", symbol); + parameters.AddOptional("type", type); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/account_book", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Funding Accounts + + /// + public async Task>> GetMarginFundingAccountsAsync( + string? asset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/funding_accounts", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Set Margin Auto Repay + + /// + public async Task> SetMarginAutoRepayAsync( + bool enabled, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("status", enabled ? "on" : "off"); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/margin/auto_repay", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Auto Repay + + /// + public async Task> GetMarginAutoRepayAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/auto_repay", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Max Transferable + + /// + public async Task> GetMarginMaxTransferableAsync(string asset, string? symbol = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + parameters.AddOptional("currency_pair", symbol); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/transferable", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Accounts + + /// + public async Task> GetCrossMarginAccountsAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/accounts", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Balance History + + /// + public async Task>> GetCrossMarginBalanceHistoryAsync(string? asset = null, + string? type = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? page = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("type", type); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/account_book", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Create Cross Margin Borrow Loan + + /// + public async Task> CreateCrossMarginLoanAsync( + string asset, + decimal quantity, + string? text = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + parameters.Add("amount", quantity); + parameters.AddOptional("text", text); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/margin/cross/loans", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Loans + + /// + public async Task>> GetCrossMarginLoansAsync( + string? asset = null, + int? limit = null, + int? offset = null, + bool? reverse = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("limit", limit); + parameters.AddOptional("reverse", reverse); + parameters.AddOptional("offset", offset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/loans", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Loan + + /// + public async Task> GetCrossMarginLoanAsync(string id, + CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/loans/" + id, GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Cross Margin Repay + + /// + public async Task>> CrossMarginRepayAsync( + string asset, + decimal quantity, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + parameters.Add("amount", quantity); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/margin/cross/repayments", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Repayments + + /// + public async Task>> GetCrossMarginRepaymentsAsync( + string? asset = null, + string? loanId = null, + int? limit = null, + int? offset = null, + bool? reverse = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("limit", limit); + parameters.AddOptional("loan_id", loanId); + parameters.AddOptional("reverse", reverse); + parameters.AddOptional("offset", offset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/repayments", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Interest History + + /// + public async Task>> GetCrossMarginInterestHistoryAsync( + string? asset = null, + int? page = null, + int? limit = null, + DateTime? startTime = null, + DateTime? endTime = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("limit", limit); + parameters.AddOptional("page", page); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/interest_records", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Max Transferable + + /// + public async Task> GetCrossMarginMaxTransferableAsync(string asset, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/transferable", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Estimated Interest Rates + + /// + public async Task>> GetCrossMarginEstimatedInterestRatesAsync(IEnumerable assets, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currencies", string.Join(",", assets)); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/estimate_rate", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Max Borrowable + + /// + public async Task> GetCrossMarginMaxBorrowableAsync(string asset, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/cross/borrowable", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Estimated Interest Rates + + /// + public async Task>> GetMarginEstimatedInterestRatesAsync(IEnumerable assets, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currencies", string.Join(",", assets)); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/uni/estimate_rate", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Borrow Or Repay + + /// + public async Task BorrowOrRepayAsync( + string asset, + string symbol, + BorrowDirection direction, + decimal quantity, + bool? repayAll = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + parameters.AddEnum("type", direction); + parameters.AddString("amount", quantity); + parameters.AddOptional("repaid_all", repayAll); + parameters.AddOptional("currency_pair", symbol); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/margin/uni/loans", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Loans + + /// + public async Task>> GetMarginLoansAsync( + string? asset = null, + string? symbol = null, + int? page = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("currency_pair", symbol); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/uni/loans", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Loan History + + /// + public async Task>> GetMarginLoanHistoryAsync( + string? asset = null, + string? symbol = null, + BorrowDirection? direction = null, + int? page = null, + int? limit = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("currency_pair", symbol); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptionalEnum("type", direction); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/uni/loan_records", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Interest History + + /// + public async Task>> GetMarginInterestHistoryAsync( + string? asset = null, + string? symbol = null, + int? page = null, + int? limit = null, + DateTime? startTime = null, + DateTime? endTime = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency", asset); + parameters.AddOptional("currency_pair", symbol); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/uni/interest_records", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Margin Max Borrowable + + /// + public async Task> GetMarginMaxBorrowableAsync( + string asset, + string symbol, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + parameters.Add("currency_pair", symbol); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/margin/uni/borrowable", GateIoExchange.RateLimiter.RestPrivate, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + } +} diff --git a/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiExchangeData.cs b/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiExchangeData.cs new file mode 100644 index 0000000..eb2f6cb --- /dev/null +++ b/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiExchangeData.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Objects; +using Microsoft.Extensions.Logging; +using GateIo.Net.Interfaces.Clients.SpotApi; +using GateIo.Net.Objects.Models; +using GateIo.Net.Enums; + +namespace GateIo.Net.Clients.SpotApi +{ + /// + public class GateIoRestClientSpotApiExchangeData : IGateIoRestClientSpotApiExchangeData + { + private readonly GateIoRestClientSpotApi _baseClient; + private static readonly RequestDefinitionCache _definitions = new RequestDefinitionCache(); + + internal GateIoRestClientSpotApiExchangeData(ILogger logger, GateIoRestClientSpotApi baseClient) + { + _baseClient = baseClient; + } + + #region Get Server Time + + /// + public async Task> GetServerTimeAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/time", GateIoExchange.RateLimiter.Public, 1); + var result = await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + return result.As(result.Data.ServerTime); + } + + #endregion + + #region Get Assets + + /// + public async Task>> GetAssetsAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/currencies", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Asset + + /// + public async Task> GetAssetAsync(string asset, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/spot/currencies/{asset}", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Symbol + + /// + public async Task> GetSymbolAsync(string symbol, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/spot/currency_pairs/{symbol}", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Symbols + + /// + public async Task>> GetSymbolsAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/spot/currency_pairs", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Tickers + + /// + public async Task>> GetTickersAsync(string? symbol = null, string? timezone = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency_pair", symbol); + parameters.AddOptional("timezone", timezone); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/spot/tickers", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Order Book + + /// + public async Task> GetOrderBookAsync(string symbol, int? mergeDepth = null, int? limit = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency_pair", symbol); + parameters.AddOptional("interval", mergeDepth); + parameters.AddOptional("limit", limit); + parameters.AddOptional("with_id", true.ToString().ToLowerInvariant()); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/spot/order_book", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Trades + + /// + public async Task>> GetTradesAsync(string symbol, int? limit = null, string? lastId = null, bool? reverse = null, DateTime? startTime = null, DateTime? endTime = null, int? page = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency_pair", symbol); + parameters.AddOptional("limit", limit); + parameters.AddOptional("last_id", lastId); + parameters.AddOptional("reverse", reverse); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + parameters.AddOptional("page", page); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/spot/trades", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Klines + + /// + public async Task>> GetKlinesAsync(string symbol, KlineInterval interval, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency_pair", symbol); + parameters.AddEnum("interval", interval); + parameters.AddOptional("limit", limit); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/spot/candlesticks", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Networks + + /// + public async Task>> GetNetworksAsync(string asset, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency", asset); + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/wallet/currency_chains", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Discount Tiers + + /// + public async Task>> GetDiscountTiersAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/unified/currency_discount_tiers", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Loan Margin Tiers + + /// + public async Task>> GetLoanMarginTiersAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/unified/loan_margin_tiers", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Asset + + /// + public async Task> GetCrossMarginAssetAsync(string asset, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/margin/cross/currencies/" + asset, GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Cross Margin Assets + + /// + public async Task>> GetCrossMarginAssetsAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/margin/cross/currencies", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Lending Symbols + + /// + public async Task>> GetLendingSymbolsAsync(CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/margin/uni/currency_pairs", GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync>(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Lending Symbol + + /// + public async Task> GetLendingSymbolAsync(string symbol, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, $"/api/v4/margin/uni/currency_pairs/" + symbol, GateIoExchange.RateLimiter.Public, 1); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + } +} diff --git a/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiTrading.cs b/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiTrading.cs new file mode 100644 index 0000000..231b95e --- /dev/null +++ b/GateIo.Net/Clients/SpotApi/GateIoRestClientSpotApiTrading.cs @@ -0,0 +1,429 @@ +using Microsoft.Extensions.Logging; +using GateIo.Net.Interfaces.Clients.SpotApi; +using CryptoExchange.Net.Objects; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Threading; +using System.Net.Http; +using GateIo.Net.Enums; +using GateIo.Net.Objects.Models; +using System; +using System.Globalization; +using CryptoExchange.Net.Converters.SystemTextJson; + +namespace GateIo.Net.Clients.SpotApi +{ + /// + public class GateIoRestClientSpotApiTrading : IGateIoRestClientSpotApiTrading + { + private readonly GateIoRestClientSpotApi _baseClient; + private static readonly RequestDefinitionCache _definitions = new RequestDefinitionCache(); + + + internal GateIoRestClientSpotApiTrading(ILogger logger, GateIoRestClientSpotApi baseClient) + { + _baseClient = baseClient; + } + + #region Place Order + + /// + public async Task> PlaceOrderAsync( + string symbol, + OrderSide side, + NewOrderType type, + decimal quantity, + decimal? price = null, + TimeInForce? timeInForce = null, + decimal? icebergQuantity = null, + SpotAccountType? accountType = null, + bool? autoBorrow = null, + bool? autoRepay = null, + SelfTradePreventionMode? selfTradePreventionMode = null, + string? text = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency_pair", symbol); + parameters.AddEnum("type", type); + parameters.AddEnum("side", side); + parameters.AddString("amount", quantity); + parameters.AddOptionalString("price", price); + parameters.AddOptionalString("iceberg", icebergQuantity); + parameters.AddOptionalEnum("account", accountType); + parameters.AddOptionalEnum("time_in_force", timeInForce); + parameters.AddOptionalEnum("stp_act", selfTradePreventionMode); + parameters.AddOptional("auto_borrow", autoBorrow); + parameters.AddOptional("auto_repay", autoRepay); + parameters.AddOptional("text", text); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/spot/orders", GateIoExchange.RateLimiter.RestSpotOrderPlacement, 1, true); + var result = await _baseClient.SendAsync(request, parameters, ct, 1, new Dictionary { { "X-Gate-Channel-Id", _baseClient._brokerId } }).ConfigureAwait(false); + + if (result) + _baseClient.InvokeOrderPlaced(new CryptoExchange.Net.CommonObjects.OrderId + { + Id = result.Data.Id.ToString(), + SourceObject = result.Data + }); + + return result; + } + + #endregion + + #region Place Multiple Orders + + /// + public async Task>> PlaceMultipleOrderAsync( + IEnumerable orders, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.SetBody(orders); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/spot/batch_orders", GateIoExchange.RateLimiter.RestSpotOrderPlacement, 1, true); + var result = await _baseClient.SendAsync>(request, parameters, ct, 1, new Dictionary { { "X-Gate-Channel-Id", _baseClient._brokerId } }).ConfigureAwait(false); + foreach(var order in result.Data) + { + if (order.Succeeded) + _baseClient.InvokeOrderPlaced(new CryptoExchange.Net.CommonObjects.OrderId + { + Id = order.Id.ToString(), + SourceObject = result.Data + }); + } + + return result; + } + + #endregion + + #region Get Open Orders + + /// + public async Task>> GetOpenOrdersAsync( + int? page = null, + int? limit = null, + SpotAccountType? accountType = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptionalEnum("account", accountType); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/open_orders", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Orders + + /// + public async Task>> GetOrdersAsync( + bool open, + string? symbol = null, + int? page = null, + int? limit = null, + SpotAccountType? accountType = null, + DateTime? startTime = null, + DateTime? endTime = null, + OrderSide? side = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddEnum("status", open ? "open" : "finished"); + parameters.AddOptional("currency_pair", symbol); + parameters.AddOptional("page", page); + parameters.AddOptional("limit", limit); + parameters.AddOptionalEnum("account", accountType); + parameters.AddOptionalEnum("side", side); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/orders", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Order + + /// + public async Task> GetOrderAsync( + string symbol, + long orderId, + SpotAccountType? accountType = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency_pair", symbol); + parameters.AddOptionalEnum("account", accountType); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/orders/" + orderId, GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel All Orders + + /// + public async Task>> CancelAllOrdersAsync( + string symbol, + OrderSide? side = null, + SpotAccountType? accountType = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency_pair", symbol); + parameters.AddOptionalEnum("side", side); + parameters.AddOptionalEnum("account", accountType); + var request = _definitions.GetOrCreate(HttpMethod.Delete, "/api/v4/spot/orders", GateIoExchange.RateLimiter.RestSpotOrderCancelation, 1, true); + var result = await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + foreach (var order in result.Data) + { + if (order.Succeeded) + _baseClient.InvokeOrderCanceled(new CryptoExchange.Net.CommonObjects.OrderId + { + Id = order.Id.ToString(), + SourceObject = result.Data + }); + } + return result; + } + + #endregion + + #region Cancel Orders + + /// + public async Task>> CancelOrdersAsync( + IEnumerable orders, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.SetBody(orders); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/spot/cancel_batch_orders", GateIoExchange.RateLimiter.RestSpotOrderCancelation, 1, true); + var result = await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + foreach (var order in result.Data) + { + if (order.Succeeded) + _baseClient.InvokeOrderCanceled(new CryptoExchange.Net.CommonObjects.OrderId + { + Id = order.OrderId, + SourceObject = result.Data + }); + } + return result; + } + + #endregion + + #region Edit Order + + /// + public async Task> EditOrderAsync( + string symbol, + long orderId, + decimal? price = null, + decimal? quantity = null, + string? amendText = null, + SpotAccountType? accountType = null, + CancellationToken ct = default) + { + var queryParameters = new ParameterCollection(); + queryParameters.Add("currency_pair", symbol); + + var bodyParameters = new ParameterCollection(); + bodyParameters.AddOptionalString("price", price); + bodyParameters.AddOptionalString("amount", quantity); + bodyParameters.AddOptional("amend_text", amendText); + bodyParameters.AddOptionalEnum("account", accountType); + var request = _definitions.GetOrCreate(new HttpMethod("Patch"), "/api/v4/spot/orders/" + orderId, GateIoExchange.RateLimiter.RestSpotOrderPlacement, 1, true); + return await _baseClient.SendAsync(request, queryParameters, bodyParameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Edit Multiple Orders + + /// + public async Task>> EditMultipleOrderAsync( + IEnumerable orders, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.SetBody(orders); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/spot/amend_batch_orders", GateIoExchange.RateLimiter.RestSpotOrderPlacement, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel Order + + /// + public async Task> CancelOrderAsync( + string symbol, + long orderId, + SpotAccountType? accountType = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("currency_pair", symbol); + parameters.AddOptionalEnum("account", accountType); + var request = _definitions.GetOrCreate(HttpMethod.Delete, "/api/v4/spot/orders/" + orderId, GateIoExchange.RateLimiter.RestSpotOrderCancelation, 1, true); + var result = await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + if (result) + _baseClient.InvokeOrderCanceled(new CryptoExchange.Net.CommonObjects.OrderId + { + Id = result.Data.Id.ToString(), + SourceObject = result.Data + }); + return result; + } + + #endregion + + #region Get User Trades + + /// + public async Task>> GetUserTradesAsync( + string? symbol = null, + long? orderId = null, + int? limit = null, + int? page = null, + DateTime? startTime = null, + DateTime? endTime = null, + SpotAccountType? accountType = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("currency_pair", symbol); + parameters.AddOptional("order_id", orderId); + parameters.AddOptional("limit", limit); + parameters.AddOptional("page", page); + parameters.AddOptionalMilliseconds("from", startTime); + parameters.AddOptionalMilliseconds("to", endTime); + parameters.AddOptionalEnum("account", accountType); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/my_trades", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel Orders After + + /// + public async Task> CancelOrdersAfterAsync( + TimeSpan cancelAfter, + string? symbol = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("timeout", (int)cancelAfter.TotalSeconds); + parameters.AddOptional("currency_pair", symbol); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/spot/countdown_cancel_all", GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Place Trigger Order + + /// + public async Task> PlaceTriggerOrderAsync( + string symbol, + OrderSide orderSide, + NewOrderType orderType, + TriggerType triggerType, + decimal triggerPrice, + TimeSpan expiration, + decimal quantity, + TriggerAccountType accountType, + TimeInForce timeInForce, + decimal? orderPrice = null, + string? text = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("market", symbol); + parameters.Add("trigger", new Dictionary + { + { "price", triggerPrice.ToString(CultureInfo.InvariantCulture) }, + { "rule", EnumConverter.GetString(triggerType) }, + { "expiration", (int)expiration.TotalSeconds }, + }); + var order = new ParameterCollection(); + order.AddEnum("type", orderType); + order.AddEnum("side", orderSide); + order.AddString("amount", quantity); + order.AddOptionalString("price", orderPrice); + order.AddEnum("account", accountType); + order.AddEnum("time_in_force", timeInForce); + order.AddOptional("text", text); + parameters.Add("put", order); + var request = _definitions.GetOrCreate(HttpMethod.Post, "/api/v4/spot/price_orders", GateIoExchange.RateLimiter.RestSpotOrderPlacement, 1, true); + return await _baseClient.SendAsync(request, parameters, ct, 1, new Dictionary { { "X-Gate-Channel-Id", _baseClient._brokerId } }).ConfigureAwait(false); + } + + #endregion + + #region Get Trigger Orders + + /// + public async Task>> GetTriggerOrdersAsync( + bool open, + string? symbol = null, + TriggerAccountType? accountType = null, + int? limit = null, + int? offset = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.Add("status", open ? "open" : "finished"); + parameters.AddOptional("market", symbol); + parameters.AddOptionalEnum("account", accountType); + parameters.AddOptional("limit", limit); + parameters.AddOptional("offset", offset); + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/price_orders", GateIoExchange.RateLimiter.RestSpotOrderCancelation, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel All Trigger Orders + + /// + public async Task>> CancelAllTriggerOrdersAsync(string? symbol = null, TriggerAccountType? accountType = null, CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddOptional("market", symbol); + parameters.AddOptionalEnum("account", accountType); + var request = _definitions.GetOrCreate(HttpMethod.Delete, "/api/v4/spot/price_orders", GateIoExchange.RateLimiter.RestSpotOrderCancelation, 1, true); + return await _baseClient.SendAsync>(request, parameters, ct).ConfigureAwait(false); + } + + #endregion + + #region Get Trigger Order + + /// + public async Task> GetTriggerOrderAsync(long id, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Get, "/api/v4/spot/price_orders/" + id, GateIoExchange.RateLimiter.RestSpotOther, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + + #region Cancel Trigger Order + + /// + public async Task> CancelTriggerOrderAsync(long id, CancellationToken ct = default) + { + var request = _definitions.GetOrCreate(HttpMethod.Delete, "/api/v4/spot/price_orders/" + id, GateIoExchange.RateLimiter.RestSpotOrderCancelation, 1, true); + return await _baseClient.SendAsync(request, null, ct).ConfigureAwait(false); + } + + #endregion + } +} diff --git a/GateIo.Net/Clients/SpotApi/GateIoSocketClientSpotApi.cs b/GateIo.Net/Clients/SpotApi/GateIoSocketClientSpotApi.cs new file mode 100644 index 0000000..44f64eb --- /dev/null +++ b/GateIo.Net/Clients/SpotApi/GateIoSocketClientSpotApi.cs @@ -0,0 +1,209 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Clients; +using CryptoExchange.Net.Converters.MessageParsing; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using CryptoExchange.Net.Sockets; +using Microsoft.Extensions.Logging; +using GateIo.Net.Interfaces.Clients.SpotApi; +using GateIo.Net.Objects.Models; +using GateIo.Net.Objects.Options; +using GateIo.Net.Objects.Sockets.Subscriptions; +using CryptoExchange.Net; +using CryptoExchange.Net.Converters.SystemTextJson; +using System.Collections.Generic; +using System.Linq; +using GateIo.Net.Enums; + +namespace GateIo.Net.Clients.SpotApi +{ + /// + /// Client providing access to the GateIo spot websocket Api + /// + public class GateIoSocketClientSpotApi : SocketApiClient, IGateIoSocketClientSpotApi + { + #region fields + private static readonly MessagePath _idPath = MessagePath.Get().Property("id"); + private static readonly MessagePath _channelPath = MessagePath.Get().Property("channel"); + private static readonly MessagePath _symbolPath = MessagePath.Get().Property("result").Property("currency_pair"); + private static readonly MessagePath _symbolPath2 = MessagePath.Get().Property("result").Property("s"); + private static readonly MessagePath _klinePath = MessagePath.Get().Property("result").Property("n"); + #endregion + + #region constructor/destructor + + /// + /// ctor + /// + internal GateIoSocketClientSpotApi(ILogger logger, GateIoSocketOptions options) : + base(logger, options.Environment.SpotSocketClientAddress!, options, options.SpotOptions) + { + } + #endregion + + /// + protected override IMessageSerializer CreateSerializer() => new SystemTextJsonMessageSerializer(); + /// + protected override IByteMessageAccessor CreateAccessor() => new SystemTextJsonByteMessageAccessor(); + + /// + protected override AuthenticationProvider CreateAuthenticationProvider(ApiCredentials credentials) + => new GateIoAuthenticationProvider(credentials); + + /// + public async Task> SubscribeToTradeUpdatesAsync(string symbol, Action> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription(_logger, "spot.trades", new[] { "spot.trades." + symbol }, new[] { symbol }, x => onMessage(x.WithSymbol(x.Data.Symbol)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToTradeUpdatesAsync(IEnumerable symbols, Action> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription(_logger, "spot.trades", symbols.Select(x => "spot.trades." + x), symbols, x => onMessage(x.WithSymbol(x.Data.Symbol)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToTickerUpdatesAsync(string symbol, Action> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription(_logger, "spot.tickers", new[] { "spot.tickers." + symbol }, new[] { symbol }, x => onMessage(x.WithSymbol(x.Data.Symbol)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToTickerUpdatesAsync(IEnumerable symbols, Action> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription(_logger, "spot.tickers", symbols.Select(x => "spot.tickers." + x), symbols, x => onMessage(x.WithSymbol(x.Data.Symbol)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToKlineUpdatesAsync(string symbol, KlineInterval interval, Action> onMessage, CancellationToken ct = default) + { + var intervalStr = EnumConverter.GetString(interval); + var subscription = new GateIoSubscription(_logger, "spot.candlesticks", new[] { "spot.candlesticks." + intervalStr + "_" + symbol }, new[] { intervalStr, symbol }, x => onMessage(x.WithSymbol(x.Data.Symbol).WithStreamId(x.StreamId + "." + x.Data.Interval)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToBookTickerUpdatesAsync(string symbol, Action> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription(_logger, "spot.book_ticker", new[] { "spot.book_ticker." + symbol }, new[] { symbol }, x => onMessage(x.WithSymbol(x.Data.Symbol)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToBookTickerUpdatesAsync(IEnumerable symbols, Action> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoSubscription(_logger, "spot.book_ticker", symbols.Select(x => "spot.book_ticker." + x), symbols, x => onMessage(x.WithSymbol(x.Data.Symbol)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToOrderBookUpdatesAsync(string symbol, int? updateMs, Action> onMessage, CancellationToken ct = default) + { + updateMs ??= 1000; + updateMs.Value.ValidateIntValues(nameof(updateMs), 100, 1000); + + var subscription = new GateIoSubscription(_logger, "spot.order_book_update", new[] { "spot.order_book_update." + symbol }, new[] { symbol, updateMs + "ms" }, x => onMessage(x.WithSymbol(x.Data.Symbol)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToPartialOrderBookUpdatesAsync(string symbol, int depth, int? updateMs, Action> onMessage, CancellationToken ct = default) + { + updateMs ??= 1000; + depth.ValidateIntValues(nameof(depth), 5, 10, 20, 50, 100); + updateMs.Value.ValidateIntValues(nameof(updateMs), 100, 1000); + + var subscription = new GateIoSubscription(_logger, "spot.order_book", new[] { "spot.order_book." + symbol }, new[] { symbol, depth.ToString(), updateMs + "ms" }, x => onMessage(x.WithSymbol(x.Data.Symbol)), false); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToOrderUpdatesAsync(Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "spot.orders", new[] { "spot.orders" }, new[] { "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToUserTradeUpdatesAsync(Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "spot.usertrades", new[] { "spot.usertrades" }, new[] { "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToBalanceUpdatesAsync(Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "spot.balances", new[] { "spot.balances" }, null, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToMarginBalanceUpdatesAsync(Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "spot.margin_balances", new[] { "spot.margin_balances" }, null, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToFundingBalanceUpdatesAsync(Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "spot.funding_balances", new[] { "spot.funding_balances" }, null, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToCrossMarginBalanceUpdatesAsync(Action>> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription>(_logger, "spot.cross_balances", new[] { "spot.cross_balances" }, null, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public async Task> SubscribeToTriggerOrderUpdatesAsync(Action> onMessage, CancellationToken ct = default) + { + var subscription = new GateIoAuthSubscription(_logger, "spot.priceorders", new[] { "spot.priceorders" }, new[] { "!all" }, onMessage); + return await SubscribeAsync(BaseAddress.AppendPath("ws/v4/") + "/", subscription, ct).ConfigureAwait(false); + } + + /// + public override string? GetListenerIdentifier(IMessageAccessor message) + { + var id = message.GetValue(_idPath); + if (id != null) + return id.ToString(); + + var channel = message.GetValue(_channelPath); + + if (string.Equals(channel, "spot.trades") + || string.Equals(channel, "spot.tickers")) + { + return channel + "." + message.GetValue(_symbolPath); + } + + if (string.Equals(channel, "spot.candlesticks")) + return channel + "." + message.GetValue(_klinePath); + + if (string.Equals(channel, "spot.book_ticker") + || string.Equals(channel, "spot.order_book_update") + || string.Equals(channel, "spot.order_book")) + return channel + "." + message.GetValue(_symbolPath2); + + return channel; + } + + /// + protected override Query? GetAuthenticationRequest() => null; + + /// + public override string FormatSymbol(string baseAsset, string quoteAsset) => baseAsset.ToUpperInvariant() + "_" + quoteAsset.ToUpperInvariant(); + } +} diff --git a/GateIo.Net/Enums/AccountType.cs b/GateIo.Net/Enums/AccountType.cs new file mode 100644 index 0000000..ee3416f --- /dev/null +++ b/GateIo.Net/Enums/AccountType.cs @@ -0,0 +1,41 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Account type + /// + public enum AccountType + { + /// + /// Spot + /// + [Map("spot")] + Spot, + /// + /// Margin + /// + [Map("margin")] + Margin, + /// + /// Perpetual futures + /// + [Map("futures")] + PerpertualFutures, + /// + /// Delivery futures + /// + [Map("delivery")] + DeliveryFutures, + /// + /// Cross margin + /// + [Map("cross_margin")] + CrossMargin, + /// + /// Options + /// + [Map("options")] + Options + } +} diff --git a/GateIo.Net/Enums/BalanceChangeType.cs b/GateIo.Net/Enums/BalanceChangeType.cs new file mode 100644 index 0000000..73a95c4 --- /dev/null +++ b/GateIo.Net/Enums/BalanceChangeType.cs @@ -0,0 +1,61 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Reason for balance change + /// + public enum BalanceChangeType + { + /// + /// Withdrawal + /// + [Map("withdraw")] + Withdraw, + /// + /// Deposit + /// + [Map("deposit")] + Deposit, + /// + /// Trade fee deduction + /// + [Map("trade-fee-deduct")] + TradeFeeDeduct, + /// + /// Order creation + /// + [Map("order-create")] + OrderCreate, + /// + /// Order match + /// + [Map("order-match")] + OrderMatch, + /// + /// Order update + /// + [Map("order-update")] + OrderUpdate, + /// + /// Margin transfer + /// + [Map("margin-transfer")] + MarginTransfer, + /// + /// Futures transfer + /// + [Map("future-transfer")] + FutureTransfer, + /// + /// Cross margin transfer + /// + [Map("cross-margin-transfer")] + CrossMarginTransfer, + /// + /// Other + /// + [Map("other")] + Other + } +} diff --git a/GateIo.Net/Enums/BorrowDirection.cs b/GateIo.Net/Enums/BorrowDirection.cs new file mode 100644 index 0000000..18355ad --- /dev/null +++ b/GateIo.Net/Enums/BorrowDirection.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Borrow direction + /// + public enum BorrowDirection + { + /// + /// Borrow + /// + [Map("borrow")] + Borrow, + /// + /// Repay + /// + [Map("repay")] + Repay + } +} diff --git a/GateIo.Net/Enums/BorrowStatus.cs b/GateIo.Net/Enums/BorrowStatus.cs new file mode 100644 index 0000000..5171088 --- /dev/null +++ b/GateIo.Net/Enums/BorrowStatus.cs @@ -0,0 +1,26 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Borrow loan status + /// + public enum BorrowStatus + { + /// + /// Failed to borrow + /// + [Map("1")] + Failed, + /// + /// Borrowed but not repaid + /// + [Map("2")] + Borrowed, + /// + /// Repaid + /// + [Map("3")] + Repaid + } +} diff --git a/GateIo.Net/Enums/CloseSide.cs b/GateIo.Net/Enums/CloseSide.cs new file mode 100644 index 0000000..db2d3b0 --- /dev/null +++ b/GateIo.Net/Enums/CloseSide.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Close side + /// + public enum CloseSide + { + /// + /// Close long + /// + [Map("close_long")] + CloseLong, + /// + /// Close short + /// + [Map("close_short")] + CloseShort + } +} diff --git a/GateIo.Net/Enums/ContractType.cs b/GateIo.Net/Enums/ContractType.cs new file mode 100644 index 0000000..bbd4adb --- /dev/null +++ b/GateIo.Net/Enums/ContractType.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Contract type + /// + public enum ContractType + { + /// + /// Inverse + /// + [Map("inverse")] + Inverse, + /// + /// Direct + /// + [Map("direct")] + Direct + } +} diff --git a/GateIo.Net/Enums/FuturesTriggerOrderStatus.cs b/GateIo.Net/Enums/FuturesTriggerOrderStatus.cs new file mode 100644 index 0000000..036276d --- /dev/null +++ b/GateIo.Net/Enums/FuturesTriggerOrderStatus.cs @@ -0,0 +1,31 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Trigger order status + /// + public enum FuturesTriggerOrderStatus + { + /// + /// Active + /// + [Map("open")] + Open, + /// + /// Finished + /// + [Map("finished")] + Finished, + /// + /// Order is not active, only for close-long-order or close-short-order + /// + [Map("inactive")] + Inactive, + /// + /// Order is invalid, only for close-long-order or close-short-order + /// + [Map("invalid")] + Invalid + } +} diff --git a/GateIo.Net/Enums/KlineInterval.cs b/GateIo.Net/Enums/KlineInterval.cs new file mode 100644 index 0000000..6842794 --- /dev/null +++ b/GateIo.Net/Enums/KlineInterval.cs @@ -0,0 +1,66 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Kline interval + /// + public enum KlineInterval + { + /// + /// 10 seconds + /// + [Map("10s")] + TenSeconds, + /// + /// 1 minute + /// + [Map("1m")] + OneMinute, + /// + /// 5 minutes + /// + [Map("5m")] + FiveMinutes, + /// + /// 15 minutes + /// + [Map("15m")] + FifteenMinutes, + /// + /// 30 minutes + /// + [Map("30m")] + ThirtyMinutes, + /// + /// 1 hour + /// + [Map("1h")] + OneHour, + /// + /// 4 hours + /// + [Map("4h")] + FourHours, + /// + /// 8 hours + /// + [Map("8h")] + EightHours, + /// + /// 1 day + /// + [Map("1d")] + OneDay, + /// + /// 1 week + /// + [Map("7d")] + OneWeek, + /// + /// 1 month + /// + [Map("30d")] + OneMonth + } +} diff --git a/GateIo.Net/Enums/LoanType.cs b/GateIo.Net/Enums/LoanType.cs new file mode 100644 index 0000000..867dabe --- /dev/null +++ b/GateIo.Net/Enums/LoanType.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Loan type + /// + public enum LoanType + { + /// + /// Platform + /// + [Map("platform")] + Platform, + /// + /// Margin + /// + [Map("margin")] + Margin + } +} diff --git a/GateIo.Net/Enums/MarkType.cs b/GateIo.Net/Enums/MarkType.cs new file mode 100644 index 0000000..2a30ea2 --- /dev/null +++ b/GateIo.Net/Enums/MarkType.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Mark type + /// + public enum MarkType + { + /// + /// Internal + /// + [Map("internal")] + Internal, + /// + /// Index + /// + [Map("index")] + Index + } +} diff --git a/GateIo.Net/Enums/NewOrderType.cs b/GateIo.Net/Enums/NewOrderType.cs new file mode 100644 index 0000000..eb92cf6 --- /dev/null +++ b/GateIo.Net/Enums/NewOrderType.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Order type + /// + public enum NewOrderType + { + /// + /// LImit order + /// + [Map("limit")] + Limit, + /// + /// Market order + /// + [Map("market")] + Market + } +} diff --git a/GateIo.Net/Enums/OrderFinishType.cs b/GateIo.Net/Enums/OrderFinishType.cs new file mode 100644 index 0000000..cfbe751 --- /dev/null +++ b/GateIo.Net/Enums/OrderFinishType.cs @@ -0,0 +1,61 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// How an order was finished + /// + public enum OrderFinishType + { + /// + /// New order + /// + [Map("_new")] + New, + /// + /// Still open + /// + [Map("open")] + Open, + /// + /// Filled + /// + [Map("filled")] + Filled, + /// + /// Manually canceled + /// + [Map("cancelled")] + Canceled, + /// + /// IOC order was immediately canceled + /// + [Map("ioc")] + ImmediatelyCanceled, + /// + /// Canceled because of STP + /// + [Map("stp")] + SelfTradePrevention, + /// + /// Canceled because of liquidation + /// + [Map("liquidated")] + Liquidated, + /// + /// Finished by ADL + /// + [Map("auto_deleveraged")] + AutoDeleveraged, + /// + /// Canceled because of increasing position while reduce-only set + /// + [Map("reduce_only")] + ReduceOnly, + /// + /// Canceled because of position close + /// + [Map("position_closed")] + PositionClosed + } +} diff --git a/GateIo.Net/Enums/OrderSide.cs b/GateIo.Net/Enums/OrderSide.cs new file mode 100644 index 0000000..a646590 --- /dev/null +++ b/GateIo.Net/Enums/OrderSide.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Side of an order + /// + public enum OrderSide + { + /// + /// Buy order + /// + [Map("buy")] + Buy, + /// + /// Sell order + /// + [Map("sell")] + Sell + } +} diff --git a/GateIo.Net/Enums/OrderStatus.cs b/GateIo.Net/Enums/OrderStatus.cs new file mode 100644 index 0000000..20ae5bd --- /dev/null +++ b/GateIo.Net/Enums/OrderStatus.cs @@ -0,0 +1,26 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Order status + /// + public enum OrderStatus + { + /// + /// Open + /// + [Map("open")] + Open, + /// + /// Closed + /// + [Map("closed", "finished")] + Closed, + /// + /// Cancelled + /// + [Map("cancelled")] + Canceled + } +} diff --git a/GateIo.Net/Enums/OrderType.cs b/GateIo.Net/Enums/OrderType.cs new file mode 100644 index 0000000..af2bdeb --- /dev/null +++ b/GateIo.Net/Enums/OrderType.cs @@ -0,0 +1,46 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Order type + /// + public enum OrderType + { + /// + /// LImit order + /// + [Map("limit")] + Limit, + /// + /// Market order + /// + [Map("market")] + Market, + /// + /// Limit repay + /// + [Map("limit_repay")] + LimitRepay, + /// + /// Market repay + /// + [Map("market_repay")] + MarketRepay, + /// + /// Limit borrow + /// + [Map("limit_borrow")] + LimitBorrow, + /// + /// Market borrow + /// + [Map("market_borrow")] + MarketBorrow, + /// + /// Limit borrow/repay + /// + [Map("limit_borrow_repay")] + LimitBorrowRepay + } +} diff --git a/GateIo.Net/Enums/PositionMode.cs b/GateIo.Net/Enums/PositionMode.cs new file mode 100644 index 0000000..c24cdfc --- /dev/null +++ b/GateIo.Net/Enums/PositionMode.cs @@ -0,0 +1,26 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Position mode + /// + public enum PositionMode + { + /// + /// Single + /// + [Map("single")] + Single, + /// + /// Dual long mode + /// + [Map("dual_long")] + DualLong, + /// + /// Dual short mode + /// + [Map("dual_short")] + DualShort + } +} diff --git a/GateIo.Net/Enums/PositionSide.cs b/GateIo.Net/Enums/PositionSide.cs new file mode 100644 index 0000000..591ba48 --- /dev/null +++ b/GateIo.Net/Enums/PositionSide.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Position side + /// + public enum PositionSide + { + /// + /// Long position + /// + [Map("long")] + Long, + /// + /// Short position + /// + [Map("short")] + Short + } +} diff --git a/GateIo.Net/Enums/PriceType.cs b/GateIo.Net/Enums/PriceType.cs new file mode 100644 index 0000000..f1e0d92 --- /dev/null +++ b/GateIo.Net/Enums/PriceType.cs @@ -0,0 +1,26 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Price type + /// + public enum PriceType + { + /// + /// Last trade price + /// + [Map("0")] + LastTradePrice, + /// + /// Mark price + /// + [Map("1")] + MarkPrice, + /// + /// Index price + /// + [Map("2")] + IndexPrice + } +} diff --git a/GateIo.Net/Enums/RepayType.cs b/GateIo.Net/Enums/RepayType.cs new file mode 100644 index 0000000..1eb4cd0 --- /dev/null +++ b/GateIo.Net/Enums/RepayType.cs @@ -0,0 +1,31 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Repay type + /// + public enum RepayType + { + /// + /// No repay + /// + [Map("none")] + None, + /// + /// Manual repayment + /// + [Map("manual_repay")] + ManualRepay, + /// + /// Automatic repayment + /// + [Map("auto_repay")] + AutoRepay, + /// + /// Automatic repayment after cancelation + /// + [Map("cancel_auto_repay")] + CancelAutoRepay + } +} diff --git a/GateIo.Net/Enums/Role.cs b/GateIo.Net/Enums/Role.cs new file mode 100644 index 0000000..8f06e3c --- /dev/null +++ b/GateIo.Net/Enums/Role.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Role + /// + public enum Role + { + /// + /// Taker + /// + [Map("taker")] + Taker, + /// + /// Maker + /// + [Map("maker")] + Maker + } +} diff --git a/GateIo.Net/Enums/SelfTradePreventionMode.cs b/GateIo.Net/Enums/SelfTradePreventionMode.cs new file mode 100644 index 0000000..353e795 --- /dev/null +++ b/GateIo.Net/Enums/SelfTradePreventionMode.cs @@ -0,0 +1,31 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Self trade prevention mode + /// + public enum SelfTradePreventionMode + { + /// + /// None + /// + [Map("", "-")] + None, + /// + /// Cancel newest + /// + [Map("cn")] + CancelNewest, + /// + /// Cancel oldest + /// + [Map("co")] + CancelOldest, + /// + /// Cancel both + /// + [Map("cb")] + CancelBoth + } +} diff --git a/GateIo.Net/Enums/SpotAccountType.cs b/GateIo.Net/Enums/SpotAccountType.cs new file mode 100644 index 0000000..a341685 --- /dev/null +++ b/GateIo.Net/Enums/SpotAccountType.cs @@ -0,0 +1,31 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Spot account type + /// + public enum SpotAccountType + { + /// + /// Spot account + /// + [Map("spot")] + Spot, + /// + /// Margin account + /// + [Map("margin")] + Margin, + /// + /// Unified account + /// + [Map("unified")] + Unified, + /// + /// Cross margin + /// + [Map("cross_margin")] + CrossMargin + } +} diff --git a/GateIo.Net/Enums/SymbolStatus.cs b/GateIo.Net/Enums/SymbolStatus.cs new file mode 100644 index 0000000..2d01f4b --- /dev/null +++ b/GateIo.Net/Enums/SymbolStatus.cs @@ -0,0 +1,31 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Symbol trade status + /// + public enum SymbolStatus + { + /// + /// Not tradeable + /// + [Map("untradable")] + Untradable, + /// + /// Only buyable + /// + [Map("buyable")] + Buyable, + /// + /// Only sellable + /// + [Map("sellable")] + Sellable, + /// + /// Can be bought and sold + /// + [Map("tradable")] + Tradable, + } +} diff --git a/GateIo.Net/Enums/TimeInForce.cs b/GateIo.Net/Enums/TimeInForce.cs new file mode 100644 index 0000000..bd14268 --- /dev/null +++ b/GateIo.Net/Enums/TimeInForce.cs @@ -0,0 +1,31 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Time in force + /// + public enum TimeInForce + { + /// + /// Good till canceled + /// + [Map("gtc")] + GoodTillCancel, + /// + /// Immediate or cancel + /// + [Map("ioc")] + ImmediateOrCancel, + /// + /// Post only order + /// + [Map("poc")] + PendingOrCancel, + /// + /// Fill or kill + /// + [Map("fok")] + FillOrKill + } +} diff --git a/GateIo.Net/Enums/TriggerAccountType.cs b/GateIo.Net/Enums/TriggerAccountType.cs new file mode 100644 index 0000000..ef95f91 --- /dev/null +++ b/GateIo.Net/Enums/TriggerAccountType.cs @@ -0,0 +1,26 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Trigger account type + /// + public enum TriggerAccountType + { + /// + /// Normal spot + /// + [Map("normal")] + Normal, + /// + /// Margin + /// + [Map("margin")] + Margin, + /// + /// Cross margin + /// + [Map("cross_margin")] + CrossMargin + } +} diff --git a/GateIo.Net/Enums/TriggerFinishType.cs b/GateIo.Net/Enums/TriggerFinishType.cs new file mode 100644 index 0000000..01e560b --- /dev/null +++ b/GateIo.Net/Enums/TriggerFinishType.cs @@ -0,0 +1,31 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// How a trigger order was finished + /// + public enum TriggerFinishType + { + /// + /// Filled + /// + [Map("succeeded")] + Succeeeded, + /// + /// Manually canceled + /// + [Map("cancelled")] + Canceled, + /// + /// Failed + /// + [Map("failed")] + Failed, + /// + /// Expired + /// + [Map("expired")] + Expired + } +} diff --git a/GateIo.Net/Enums/TriggerOrderStatus.cs b/GateIo.Net/Enums/TriggerOrderStatus.cs new file mode 100644 index 0000000..f50b967 --- /dev/null +++ b/GateIo.Net/Enums/TriggerOrderStatus.cs @@ -0,0 +1,36 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Trigger order status + /// + public enum TriggerOrderStatus + { + /// + /// Active + /// + [Map("open")] + Open, + /// + /// Canceled + /// + [Map("cancelled")] + Canceled, + /// + /// Finished + /// + [Map("finish")] + Finished, + /// + /// Failed to execute + /// + [Map("failed")] + Failed, + /// + /// Trigger expired + /// + [Map("expired")] + Expired + } +} diff --git a/GateIo.Net/Enums/TriggerOrderType.cs b/GateIo.Net/Enums/TriggerOrderType.cs new file mode 100644 index 0000000..506b71c --- /dev/null +++ b/GateIo.Net/Enums/TriggerOrderType.cs @@ -0,0 +1,41 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Trigger order type + /// + public enum TriggerOrderType + { + /// + /// Order take-profit/stop-loss, close long position + /// + [Map("close-long-order")] + CloseLongOrder, + /// + /// Order take-profit/stop-loss, close short position + /// + [Map("close-short-order")] + CloseShortOrder, + /// + /// Position take-profit/stop-loss, close long position + /// + [Map("close-long-position")] + CloseLongPosition, + /// + /// Position take-profit/stop-loss, close short position + /// + [Map("close-short-position")] + CloseShortPosition, + /// + /// Position planned take-profit/stop-loss, close long position + /// + [Map("plan-close-long-position")] + PlanCloseLongPosition, + /// + /// Position planned take-profit/stop-loss, close short position + /// + [Map("plan-close-short-position")] + PlanCloseShortPosition + } +} diff --git a/GateIo.Net/Enums/TriggerType.cs b/GateIo.Net/Enums/TriggerType.cs new file mode 100644 index 0000000..ebc3009 --- /dev/null +++ b/GateIo.Net/Enums/TriggerType.cs @@ -0,0 +1,21 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Price trigger type + /// + public enum TriggerType + { + /// + /// Trigger when price is higher or equal to trigger price + /// + [Map(">=", "1")] + EqualOrHigher, + /// + /// Trigger when price is lower or equal to trigger price + /// + [Map("<=", "2")] + EqualOrLower + } +} diff --git a/GateIo.Net/Enums/UnifiedAccountMode.cs b/GateIo.Net/Enums/UnifiedAccountMode.cs new file mode 100644 index 0000000..61eedf5 --- /dev/null +++ b/GateIo.Net/Enums/UnifiedAccountMode.cs @@ -0,0 +1,26 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Account mode + /// + public enum UnifiedAccountMode + { + /// + /// Classic account mode + /// + [Map("classic")] + Classic, + /// + /// Multi-currency margin mode + /// + [Map("multi_currency")] + MultiAsset, + /// + /// Portfolio margin mode + /// + [Map("portfolio")] + Portfolio + } +} diff --git a/GateIo.Net/Enums/WithdrawalStatus.cs b/GateIo.Net/Enums/WithdrawalStatus.cs new file mode 100644 index 0000000..ebb2562 --- /dev/null +++ b/GateIo.Net/Enums/WithdrawalStatus.cs @@ -0,0 +1,76 @@ +using CryptoExchange.Net.Attributes; + +namespace GateIo.Net.Enums +{ + /// + /// Withdrawal status + /// + public enum WithdrawalStatus + { + /// + /// Done + /// + [Map("DONE")] + Done, + /// + /// Canceled + /// + [Map("CANCEL")] + Canceled, + /// + /// Requested + /// + [Map("REQUEST")] + Requested, + /// + /// Pending manual approval + /// + [Map("MANUAL")] + PendingApproval, + /// + /// GateCode operation + /// + [Map("BCODE")] + GateCode, + /// + /// Pending confirmation after sending + /// + [Map("EXTPEND")] + PendingConfirmation, + /// + /// Failed confirmation + /// + [Map("FAIL")] + FailedConfirmation, + /// + /// Invalid order + /// + [Map("INVALID")] + Invalid, + /// + /// Verifying + /// + [Map("VERIFY")] + Verifying, + /// + /// Processing + /// + [Map("PROCES")] + Processing, + /// + /// Pending + /// + [Map("PEND")] + Pending, + /// + /// Requires manual approval + /// + [Map("DMOVE")] + RequiresManualApproval, + /// + /// The order is automatically split due to large quantity + /// + [Map("SPLITPEND")] + SplitPending + } +} diff --git a/GateIo.Net/ExtensionMethods/CryptoClientExtensions.cs b/GateIo.Net/ExtensionMethods/CryptoClientExtensions.cs new file mode 100644 index 0000000..0d2dc98 --- /dev/null +++ b/GateIo.Net/ExtensionMethods/CryptoClientExtensions.cs @@ -0,0 +1,25 @@ +using GateIo.Net.Clients; +using GateIo.Net.Interfaces.Clients; + +namespace CryptoExchange.Net.Interfaces +{ + /// + /// Extensions for the ICryptoRestClient and ICryptoSocketClient interfaces + /// + public static class CryptoClientExtensions + { + /// + /// Get the Gate.io REST Api client + /// + /// + /// + public static IGateIoRestClient GateIo(this ICryptoRestClient baseClient) => baseClient.TryGet(() => new GateIoRestClient()); + + /// + /// Get the Gate.io Websocket Api client + /// + /// + /// + public static IGateIoSocketClient GateIo(this ICryptoSocketClient baseClient) => baseClient.TryGet(() => new GateIoSocketClient()); + } +} diff --git a/GateIo.Net/ExtensionMethods/GateIoExtensionMethods.cs b/GateIo.Net/ExtensionMethods/GateIoExtensionMethods.cs new file mode 100644 index 0000000..8522f31 --- /dev/null +++ b/GateIo.Net/ExtensionMethods/GateIoExtensionMethods.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace GateIo.Net.ExtensionMethods +{ + /// + /// Extension methods specific to using the Gate.io API + /// + public static class GateIoExtensionMethods + { + /// + /// Get the weight left from the response headers + /// + /// + /// + public static int? GateIoWeightLeft(this IEnumerable>>? headers) + { + if (headers == null) + return null; + + var headerValues = headers.FirstOrDefault(s => s.Key.Equals("X-Gate-RateLimit-Requests-Remain", StringComparison.InvariantCultureIgnoreCase)).Value; + if (headerValues != null && int.TryParse(headerValues.First(), out var value)) + return value; + return null; + } + + /// + /// Get the weight limit from the response headers + /// + /// + /// + public static int? GateIoWeightLimit(this IEnumerable>>? headers) + { + if (headers == null) + return null; + + var headerValues = headers.FirstOrDefault(s => s.Key.Equals("X-Gate-RateLimit-Limit", StringComparison.InvariantCultureIgnoreCase)).Value; + if (headerValues != null && int.TryParse(headerValues.First(), out var value)) + return value; + return null; + } + } +} diff --git a/GateIo.Net/ExtensionMethods/ServiceCollectionExtensions.cs b/GateIo.Net/ExtensionMethods/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..9f036b6 --- /dev/null +++ b/GateIo.Net/ExtensionMethods/ServiceCollectionExtensions.cs @@ -0,0 +1,72 @@ +using CryptoExchange.Net.Clients; +using CryptoExchange.Net.Interfaces; +using System; +using System.Net; +using System.Net.Http; +using GateIo.Net.Clients; +using GateIo.Net.Interfaces; +using GateIo.Net.Interfaces.Clients; +using GateIo.Net.Objects.Options; +using GateIo.Net.SymbolOrderBooks; + +namespace Microsoft.Extensions.DependencyInjection +{ + /// + /// Extensions for DI + /// + public static class ServiceCollectionExtensions + { + /// + /// Add the IGateIoClient and IGateIoSocketClient to the sevice collection so they can be injected + /// + /// The service collection + /// Set default options for the rest client + /// Set default options for the socket client + /// The lifetime of the IGateIoSocketClient for the service collection. Defaults to Singleton. + /// + public static IServiceCollection AddGateIo( + this IServiceCollection services, + Action? defaultRestOptionsDelegate = null, + Action? defaultSocketOptionsDelegate = null, + ServiceLifetime? socketClientLifeTime = null) + { + var restOptions = GateIoRestOptions.Default.Copy(); + + if (defaultRestOptionsDelegate != null) + { + defaultRestOptionsDelegate(restOptions); + GateIoRestClient.SetDefaultOptions(defaultRestOptionsDelegate); + } + + if (defaultSocketOptionsDelegate != null) + GateIoSocketClient.SetDefaultOptions(defaultSocketOptionsDelegate); + + services.AddHttpClient(options => + { + options.Timeout = restOptions.RequestTimeout; + }).ConfigurePrimaryHttpMessageHandler(() => + { + var handler = new HttpClientHandler(); + if (restOptions.Proxy != null) + { + handler.Proxy = new WebProxy + { + Address = new Uri($"{restOptions.Proxy.Host}:{restOptions.Proxy.Port}"), + Credentials = restOptions.Proxy.Password == null ? null : new NetworkCredential(restOptions.Proxy.Login, restOptions.Proxy.Password) + }; + } + return handler; + }); + + services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); + services.AddTransient(x => x.GetRequiredService().SpotApi.CommonSpotClient); + if (socketClientLifeTime == null) + services.AddSingleton(); + else + services.Add(new ServiceDescriptor(typeof(IGateIoSocketClient), typeof(GateIoSocketClient), socketClientLifeTime.Value)); + return services; + } + } +} diff --git a/GateIo.Net/GateIo.Net.csproj b/GateIo.Net/GateIo.Net.csproj new file mode 100644 index 0000000..46a35e1 --- /dev/null +++ b/GateIo.Net/GateIo.Net.csproj @@ -0,0 +1,62 @@ + + + netstandard2.0;netstandard2.1 + 10.0 + enable + + + GateIo.Net + JKorf + 0.1.0 + 0.1.0 + 0.1.0 + GateIo.Net is a client library for accessing the GateIo REST and Websocket API. All data is mapped to readable models and enum values. Additional features include an implementation for maintaining a client side order book, easy integration with other exchange client libraries and more. + false + GateIo;GateIo.Net;GateIo Client;GateIo API;CryptoCurrency;CryptoCurrency Exchange + git + https://github.com/JKorf/GateIo.Net.git + https://github.com/JKorf/GateIo.Net + icon.png + README.md + MIT + en + true + https://github.com/JKorf/GateIo.Net?tab=readme-ov-file#release-notes + + + true + true + snupkg + true + true + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + GateIo.Net.xml + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + \ No newline at end of file diff --git a/GateIo.Net/GateIo.Net.xml b/GateIo.Net/GateIo.Net.xml new file mode 100644 index 0000000..527755e --- /dev/null +++ b/GateIo.Net/GateIo.Net.xml @@ -0,0 +1,9338 @@ + + + + GateIo.Net + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Client providing access to the GateIo futures websocket Api + + + + + ctor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create a new instance of the GateIoRestClient using provided options + + Option configuration delegate + + + + Create a new instance of the GateIoRestClient using provided options + + Option configuration delegate + The logger factory + Http client for this client + + + + Set the default options to be used when creating new clients + + Option configuration delegate + + + + + + + + + + + + + + + + Create a new instance of GateIoSocketClient + + The logger factory + + + + Create a new instance of GateIoSocketClient + + Option configuration delegate + + + + Create a new instance of GateIoSocketClient + + The logger factory + Option configuration delegate + + + + Set the default options to be used when creating new clients + + Option configuration delegate + + + + + + + + + + + + + + + + + + + + + + Event triggered when an order is placed via this client. Only available for Spot orders + + + + + Event triggered when an order is canceled via this client. Note that this does not trigger when using CancelAllOrdersAsync. Only available for Spot orders + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Client providing access to the GateIo spot websocket Api + + + + + ctor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Account type + + + + + Spot + + + + + Margin + + + + + Perpetual futures + + + + + Delivery futures + + + + + Cross margin + + + + + Options + + + + + Reason for balance change + + + + + Withdrawal + + + + + Deposit + + + + + Trade fee deduction + + + + + Order creation + + + + + Order match + + + + + Order update + + + + + Margin transfer + + + + + Futures transfer + + + + + Cross margin transfer + + + + + Other + + + + + Borrow direction + + + + + Borrow + + + + + Repay + + + + + Borrow loan status + + + + + Failed to borrow + + + + + Borrowed but not repaid + + + + + Repaid + + + + + Close side + + + + + Close long + + + + + Close short + + + + + Contract type + + + + + Inverse + + + + + Direct + + + + + Trigger order status + + + + + Active + + + + + Finished + + + + + Order is not active, only for close-long-order or close-short-order + + + + + Order is invalid, only for close-long-order or close-short-order + + + + + Kline interval + + + + + 10 seconds + + + + + 1 minute + + + + + 5 minutes + + + + + 15 minutes + + + + + 30 minutes + + + + + 1 hour + + + + + 4 hours + + + + + 8 hours + + + + + 1 day + + + + + 1 week + + + + + 1 month + + + + + Loan type + + + + + Platform + + + + + Margin + + + + + Mark type + + + + + Internal + + + + + Index + + + + + Order type + + + + + LImit order + + + + + Market order + + + + + How an order was finished + + + + + New order + + + + + Still open + + + + + Filled + + + + + Manually canceled + + + + + IOC order was immediately canceled + + + + + Canceled because of STP + + + + + Canceled because of liquidation + + + + + Finished by ADL + + + + + Canceled because of increasing position while reduce-only set + + + + + Canceled because of position close + + + + + Side of an order + + + + + Buy order + + + + + Sell order + + + + + Order status + + + + + Open + + + + + Closed + + + + + Cancelled + + + + + Order type + + + + + LImit order + + + + + Market order + + + + + Limit repay + + + + + Market repay + + + + + Limit borrow + + + + + Market borrow + + + + + Limit borrow/repay + + + + + Position mode + + + + + Single + + + + + Dual long mode + + + + + Dual short mode + + + + + Position side + + + + + Long position + + + + + Short position + + + + + Price type + + + + + Last trade price + + + + + Mark price + + + + + Index price + + + + + Repay type + + + + + No repay + + + + + Manual repayment + + + + + Automatic repayment + + + + + Automatic repayment after cancelation + + + + + Role + + + + + Taker + + + + + Maker + + + + + Self trade prevention mode + + + + + None + + + + + Cancel newest + + + + + Cancel oldest + + + + + Cancel both + + + + + Spot account type + + + + + Spot account + + + + + Margin account + + + + + Unified account + + + + + Cross margin + + + + + Symbol trade status + + + + + Not tradeable + + + + + Only buyable + + + + + Only sellable + + + + + Can be bought and sold + + + + + Time in force + + + + + Good till canceled + + + + + Immediate or cancel + + + + + Post only order + + + + + Fill or kill + + + + + Trigger account type + + + + + Normal spot + + + + + Margin + + + + + Cross margin + + + + + How a trigger order was finished + + + + + Filled + + + + + Manually canceled + + + + + Failed + + + + + Expired + + + + + Trigger order status + + + + + Active + + + + + Canceled + + + + + Finished + + + + + Failed to execute + + + + + Trigger expired + + + + + Trigger order type + + + + + Order take-profit/stop-loss, close long position + + + + + Order take-profit/stop-loss, close short position + + + + + Position take-profit/stop-loss, close long position + + + + + Position take-profit/stop-loss, close short position + + + + + Position planned take-profit/stop-loss, close long position + + + + + Position planned take-profit/stop-loss, close short position + + + + + Price trigger type + + + + + Trigger when price is higher or equal to trigger price + + + + + Trigger when price is lower or equal to trigger price + + + + + Account mode + + + + + Classic account mode + + + + + Multi-currency margin mode + + + + + Portfolio margin mode + + + + + Withdrawal status + + + + + Done + + + + + Canceled + + + + + Requested + + + + + Pending manual approval + + + + + GateCode operation + + + + + Pending confirmation after sending + + + + + Failed confirmation + + + + + Invalid order + + + + + Verifying + + + + + Processing + + + + + Pending + + + + + Requires manual approval + + + + + The order is automatically split due to large quantity + + + + + Extension methods specific to using the Gate.io API + + + + + Get the weight left from the response headers + + + + + + + Get the weight limit from the response headers + + + + + + + GateIo environments + + + + + Rest API address + + + + + Socket API spot address + + + + + Socket API futures address + + + + + Live environment + + + + + Create a custom environment + + + + + + + + + + Gate.io exchange information and configuration + + + + + Exchange name + + + + + Url to the main website + + + + + Urls to the API documentation + + + + + Rate limiter configuration for the Gate.io API + + + + + Rate limiter configuration for the GateIo API + + + + + Event for when a rate limit is triggered + + + + + Client for accessing the Gate.io Rest API. + + + + + Spot API endpoints + + + + + Perpetual Futures API endpoints + + + + + Set the API credentials for this client. All Api clients in this client will use the new credentials, regardless of earlier set options. + + The credentials to set + + + + Client for accessing the Gate.io websocket API + + + + + Spot streams + + + + + Perpetual Futures streams + + + + + Set the API credentials for this client. All Api clients in this client will use the new credentials, regardless of earlier set options. + + The credentials to set + + + + GateIo futures API endpoints + + + + + Endpoints related to account settings, info or actions + + + + + Endpoints related to retrieving market data + + + + + Endpoints related to orders and trades + + + + + GateIo futures account endpoints. Account endpoints include balance info, withdraw/deposit info and requesting and account settings + + + + + Get futures account info + + + The settlement asset. btc, usdt or usd + Cancellation token + + + + + Get futures account ledger + + + The settlement asset. btc, usdt or usd + Filter by contract + Filter by start time + Filter by end time + Page number + Max amount of results + Filter by type + Cancellation token + + + + + Set dual position mode + + + The settlement asset. btc, usdt or usd + Dual mode enabled + Cancellation token + + + + + Get user trading fees + + + The settlement asset. btc, usdt or usd + Filter by contract + Cancellation token + + + + + GateIo futures exchange data endpoints. Exchange data includes market data (tickers, order books, etc) and system status. + + + + + + + + Cancellation token + + + + + Get list of contract + + + The settlement asset. btc, usdt or usd + Cancellation token + + + + + Get a specific contract + + + The settlement asset. btc, usdt or usd + Contract name + Cancellation token + + + + + Get order book + + + The settlement asset. btc, usdt or usd + Contract name + Merge depth + Number of rows + Cancellation token + + + + + Get recent trades + + + The settlement asset. btc, usdt or usd + Contract name + Max number of results + Offset + Specify the starting point for this list based on a previously retrieved id + Filter by start time + Filter by end time + Cancellation token + + + + + Get kline/candlesticks + + + The settlement asset. btc, usdt or usd + Contract name + Interval + Max number of results + Filter by start time + Filter by end time + Cancellation token + + + + + Get premium index kline/candlesticks + + + The settlement asset. btc, usdt or usd + Contract name + Interval + Max number of results + Filter by start time + Filter by end time + Cancellation token + + + + + Get ticker info + + + The settlement asset. btc, usdt or usd + Contract + Cancellation token + + + + + Get funding rate history + + + The settlement asset. btc, usdt or usd + Contract + Max number of results + Cancellation token + + + + + Get insurance balance history + + + The settlement asset. btc, usdt or usd + Max number of results + Cancellation token + + + + + Get contract statistics + + + The settlement asset. btc, usdt or usd + Contract + Limit + Filter by start time + Cancellation token + + + + + Get constituents for a contract + + + The settlement asset. btc, usdt or usd + Contract + Cancellation token + + + + + Get liquidation history + + + The settlement asset. btc, usdt or usd + Contract + Filter by start time + Fitler by end time + Max number of results + Cancellation token + + + + + Get risk limit tiers + + + The settlement asset. btc, usdt or usd + Contract + Result offset + Max number of results + Cancellation token + + + + + GateIo futures trading endpoints, placing and mananging orders. + + + + + Get positions + + + The settlement asset. btc, usdt or usd + True to return only active positions, false to return all + Page number + Max amount of results + Cancellation token + + + + + Get single position + + + The settlement asset. btc, usdt or usd + Contract + Cancellation token + + + + + Update position margin + + + The settlement asset. btc, usdt or usd + Contract + Change margin + Cancellation token + + + + + Update position leverage + + + The settlement asset. btc, usdt or usd + Contract + New leverage + Cross margin leverage + Cancellation token + + + + + Update position risk limit + + + The settlement asset. btc, usdt or usd + Contract + Risk limit + Cancellation token + + + + + Get positions in dual mode + + + The settlement asset. btc, usdt or usd + Contract + Cancellation token + + + + + Update position margin for dual position mode + + + The settlement asset. btc, usdt or usd + Contract + Change + Side + Cancellation token + + + + + Update position leverage in dual position mode + + + The settlement asset. btc, usdt or usd + Contract + Leverage + Cross margin leverage + Cancellation token + + + + + Update position risk limit in dual position mode + + + The settlement asset. btc, usdt or usd + Contract + Risk limit + Cancellation token + + + + + Place a new order + + + The settlement asset. btc, usdt or usd + Contract + Order side + Order quantity in number of contracts. Use the `Multiplier` property of the ExchangeData.GetContractsAsync endpoint to see how much currency 1 size contract represents + Limit price + Close position flag, set as true to close the position, with quantity set to 0 + Set as true to be reduce-only order + Time in force + Iceberg quantity + Set side to close dual-mode position + Self-Trading Prevention action + User defined text + Cancellation token + + + + + Place multiple new orders + + + The settlement asset. btc, usdt or usd + Order info + Cancellation token + + + + + Get orders + + + The settlement asset. btc, usdt or usd + Filter by contract + Filter by status + Max number of results + Offset + Filter by last order id of previous result + Cancellation token + + + + + Cancel orders after a certain period. Can be called at interval to act as a deadmans switch. Using TimeSpan.Zero cancels the countdown + + + The settlement asset. btc, usdt or usd + Timespan after which to cancel, TimeSpan.Zero to cancel the countdown + Filter by contract + Cancellation token + + + + + Cancel orders by id + + + The settlement asset. btc, usdt or usd + Ids of orders to cancel + Cancellation token + + + + + Get orders with timestamp filtering + + + The settlement asset. btc, usdt or usd + Filter by contract + Filter by status + Max number of results + Offset + Filter by start time + Filter by end time + Cancellation token + + + + + Cancel all open orders + + + The settlement asset. btc, usdt or usd + Filter by contract + Filter by order side + Cancellation token + + + + + Get order by id + + + The settlement asset. btc, usdt or usd + Order id + Cancellation token + + + + + Cancel an order + + + The settlement asset. btc, usdt or usd + Order id + Cancellation token + + + + + Edit an existing order + + + The settlement asset. btc, usdt or usd + Order id + New quantity + New price + Amend text + Cancellation token + + + + + Get user trades + + + The settlement asset. btc, usdt or usd + Filter by contract + Filter by order id + Max number of results + Offset + Last id + Cancellation token + + + + + Get user trades by timestamp filter + + + The settlement asset. btc, usdt or usd + Filter by contract + Filter by order id + Filter by start time + Filter by end time + Max number of results + Offset + Filter by role + Cancellation token + + + + + Get position closing history + + + The settlement asset. btc, usdt or usd + Filter by contract + Filter by start time + Filter by end time + Max number of results + Offset + Filter by role + Filter by side + Cancellation token + + + + + Get user liquidation history + + + The settlement asset. btc, usdt or usd + Filter by contract + Max number of results + Cancellation token + + + + + Get user auto deleveraging history + + + The settlement asset. btc, usdt or usd + Filter by contract + Max number of results + Cancellation token + + + + + Place a new trigger order + + + The settlement asset. btc, usdt or usd + Contract + Order side + Quantity + Trigger type + Trigger price + Order price + Set to true if trying to close the position + Set to true to create a reduce-only order + Set side to close dual-mode position + Price type + Trigger order type + Time in force + User text + Trigger expiration time + Cancellation token + + + + + Get trigger orders + + + The settlement asset. btc, usdt or usd + True for open orders, false for closed + Filter by contract + Max number of results + Offset + Cancellation token + + + + + Cancel all trigger orders on a contract + + + The settlement asset. btc, usdt or usd + Contract + Cancellation token + + + + + Get a trigger order by id + + + The settlement asset. btc, usdt or usd + Order id + Cancellation token + + + + + Cancel a trigger order + + + The settlement asset. btc, usdt or usd + Order id + Cancellation token + + + + + GateIo futures streams + + + + + Subscribe to public trade updates + + + The settlement asset. btc, usdt or usd + Contract + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to ticker updates + + + The settlement asset. btc, usdt or usd + Contract + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to best book price updates + + + The settlement asset. btc, usdt or usd + Contract + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to order book updates + + + The settlement asset. btc, usdt or usd + Contract + Update interval in ms. 20, 100 or 1000 + Book depth. 5, 10, 20, 50 or 100. For the 20ms update interval only 20 depth is supported + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to kline updates + + + The settlement asset. btc, usdt or usd + Contract + Kline interval + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to user order updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to user trade updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to user liquidation updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to user auto deleverage updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to user position close updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to balance updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to user reduce risk limit updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to position updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to trigger order updates + + + The settlement asset. btc, usdt or usd + User id + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + GateIo Spot API endpoints + + + + + Endpoints related to account settings, info or actions + + + + + Endpoints related to retrieving market and system data + + + + + Endpoints related to orders and trades + + + + + Get the ISpotClient for this client. This is a common interface which allows for some basic operations without knowing any details of the exchange. + + + + + + GateIo Spot account endpoints. Account endpoints include balance info, withdraw/deposit info and requesting and account settings + + + + + Get spot account balances + + + Filter by asset + Cancelation token + + + + + Get a list of balance changes for the user + + + Filter by asset + Filter by start time + Filter by end time + Page number + Max amount of results + Filter by type + Cancelation token + + + + + Withdraw + + + Asset to withdraw + Quantity to withdraw + Withdrawal address + Network to use + Memo + Client specified id + Cancellation token + + + + + Cancel a pending withdrawal + + + Id + Cancellation token + + + + + Generate deposit address + + + Asset name + Cancellation token + + + + + Get withdrawal history + + + Filter by asset + Filter by start time + Filter by end time + Max number of results + Offset + Cancellation token + + + + + Get deposit history + + + Filter by asset + Filter by start time + Filter by end time + Max number of results + Offset + Cancellation token + + + + + Transfer between accounts + + + Asset to transfer + From account + To account + Quantity to transfer + Margin symbol, required when from or to account is margin + Settle asset, required when from or to is futures + Cancellation token + + + + + Get account withdrawal status + + + Filter for a single asset + Cancellation token + + + + + Get saved addresses + + + The asset + Filter by network + Max number of results + Page number + Cancellation token + + + + + Get trading fees + + + Specify a symbol to retrieve precise fee rate + Specify the settlement asset of the contract to get more accurate rate settings + Cancellation token + + + + + Get account balance values + + + Asset unit used to calculate the balance amount + Cancellation token + + + + + Get small balances + + + Cancellation token + + + + + Convert small balances + + + Assets to convert + Convert all + Cancellation token + + + + + Get small balances conversion history + + + Filter by asset + Page + Max number of results + Cancellation token + + + + + Get unified account info + + + Filter by asset + Cancellation token + + + + + Get max borrowable amount + + + Asset + Cancellation token + + + + + Get max transferable amount + + + Asset + Cancellation token + + + + + Borrow or repay + + + Asset name + Direction + Quantity + When set to 'true,' it overrides the 'amount,' allowing for direct full repayment. + User defined text + Cancellation token + + + + + Get loans + + + Asset + Page + Limit + Loan type + Cancellation token + + + + + Get loan history + + + Asset + Direction + Page + Max number of results + Cancellation token + + + + + Get interest history + + + Filter by asset + Page + Max number of results + Filter by type + Cancellation token + + + + + Get user risk unit details + + + Cancellation token + + + + + Set unified account mode + + + New mode + USDT contract switch. This parameter is required when the mode is multi-currency margin mode + Spot hedging switch. This parameter is required when the mode is portfolio margin mode + When the mode is set to combined margin mode, will funds be used as margin + Cancellation token + + + + + Get unified account mode + + + Cancellation token + + + + + Get estimated lending rates + + + Up to 10 assets + Cancellation token + + + + + Get account and API key info + + + Cancellation token + + + + + Get margin account list + + + Filter by symbol + Cancellation token + + + + + Get margin accounts balance change history + + + Filter by asset + Filter by symbol + Filter by type + Filter by start time + Filter by end time + Page number + Max number of results + Cancellation token + + + + + Get margin funding accounts + + + Filter by asset + Cancellation token + + + + + Set auto repayment + + + True for auto repayment on, false for auto repayment off + Cancellation token + + + + + Get auto repayment setting + + + Cancellation token + + + + + Get max transferable quantity + + + Asset + Symbol + Cancellation token + + + + + Get cross margin accounts + + + Cancellation token + + + + + Get margin accounts balance change history + + + Filter by asset + Filter by type + Filter by start time + Filter by end time + Page number + Max number of results + Cancellation token + + + + + Create a cross margin borrow loan + + + Asset + Quantity + User defined text + Cancellation token + + + + + List cross margin borrow history + + + Filter by asset + Max number of results + Offset + Reverse results + Cancellation token + + + + + Get a cross margin loan by id + + + Loan id + Cancellation token + + + + + Cross margin repayment + + + Asset + Quantity + Cancellation token + + + + + Get cross margin loan repayments + + + Filter by asset + Loan id + Max number of results + Offset + Reverse results + Cancellation token + + + + + Get cross margin interest records + + + Filter by asset + Page + Max number of results + Filter by start time + Filter by end time + Cancellation token + + + + + Get max cross margin transferable + + + Asset + Cancellation token + + + + + Get cross margin estimated interest rates + + + Assets, max 10 + Cancellation token + + + + + Get max borrowable for a cross margin asset + + + Asset + Cancellation token + + + + + Get margin estimated interest rates + + + Assets, max 10 + Cancellation token + + + + + Borrow or repay margin loan + + + Asset + Symbol + Borrow or repay + Quantity + Repay all instead of specifying quantity + Cancellation token + + + + + List margin loans + + + Filter by asset + Filter by symbol + Page + Max number of results + Cancellation token + + + + + List margin loan history + + + Filter by asset + Filter by symbol + Filter by direction + Page + Max number of results + Cancellation token + + + + + List margin interest records + + + Filter by asset + Filter by symbol + Page + Max number of results + Filter by start time + Filter by end time + Cancellation token + + + + + Get margin max borrowable quantity + + + Asset + Symbol + Cancellation token + + + + + GateIo Spot exchange data endpoints. Exchange data includes market data (tickers, order books, etc) and system status. + + + + + Get the current server time + + + Cancellation token + + + + + Get a list of supported assets + + + Cancellation token + + + + + Get info on a specific asset + + + Asset name + Cancellation token + + + + + Get info on a specific symbol + + + Symbol name + Cancellation token + + + + + Get a list of supported symbols + + + Cancellation token + + + + + Get tickers for all or a single symbol + + + Filter for a single symbol + Timezone, utc0, utc8 or all + Cancellation token + + + + + Get the orderbook for a symbol + + + Symbol name + Merge depth, defaults to 0 + Book depth to return, defaults to 10 + Cancellation token + + + + + Get market trades for a symbol + + + Symbol name + Max amount of results + Specify list staring point using the id of last record in previous list-query results + Whether the id of records to be retrieved should be less than the last_id specified. Default to false. + Filter by start time + Filter by end time + Page number + Cancellation token + + + + + Get kline/candlesticks for a symbol + + + Symbol name + The kline interval + Filter by start time + Filter by end time + Number of results + Cancellation token + + + + + Get a list of networks for an asset + + + Asset + Cancellation token + + + + + Get discount tiers + + + Cancellation token + + + + + Get loan margin tiers + + + Cancellation token + + + + + Get supported cross margin asset + + + Asset name + Cancellation token + + + + + Get supported cross margin assets + + + Cancellation token + + + + + Get lending symbols + + + Cancellation token + + + + + Get lending symbol + + + Symbol + Cancellation token + + + + + GateIo Spot trading endpoints, placing and managing orders. + + + + + Place a new order + + + Symbol + Order type + Order side + Order quantity in base asset. For Market Buy orders it's in quote asset + Price of the order for limit orders + Time in force + Iceberg quantity + Account type + Auto borrow enabled + Auto repay enabled + Self trade prevention mode + User defined info + Cancellation token + + + + + Get all open orders + + + Page + Max amount of results + Filter by account type + Cancellation token + + + + + Get orders + + + Open orders (true) or closed orders (false) + Filter by symbol, required for open orders + Page + Max amount of results + Filter by account type + Filter by start time + Filter by end time + Filter by order side + Cancellation token + + + + + Get a specific order by id + + + Symbol + Order id + Filter by account type + Cancellation token + + + + + Cancel all orders on a specific symbol + + + The symbol + Only cancel orders on this side + Account type + Cancellation token + + + + + Cancel multiple orders. Check the individual response models to see if cancelation succeeded + + + Orders to cancel + Cancellation token + + + + + Edit an active order + + + Symbol + Order id + New price + New quantity + Custom info during amending order + Specify operation account. Default to spot ,portfolio and margin account if not specified. Set to cross_margin to operate against margin account. Portfolio margin account must set to cross_margin only + Cancellation token + + + + + Cancel an order + + + Symbol of the order + Order id + Account type + Cancellation token + + + + + Get a list of trades for the current user + + + Filter by symbol + Filter by order id + Max number of results + Page number + Filter by start time + Filter by end time + Filter by account type + Cancellation token + + + + + Cancel orders after a certain period. Can be called at interval to act as a deadmans switch. Using TimeSpan.Zero cancels the countdown + + + Cancel after period + Only cancel on this symbol + Cancellation token + + + + + Place a new price triggered order + + + Symbol + Order side + Order type + Type of trigger + Trigger price + Time before trigger is cancelled + Order quantity + Order price + Time in force + Account type + User text + Cancellation token + + + + + Get list of trigger orders + + + True for open orders, false for closed orders + Filter by symbol + Filter by account type + Max amount of results + Offset + Cancellation token + + + + + Cancel all trigger orders + + + Filter by symbol + Filter by account type + Cancellation token + + + + + Get a trigger order by id + + + Id of the trigger order + Cancellation token + + + + + Cancel price trigger order + + + Id of the trigger order + Cancellation token + + + + + Place multiple orders in a single call + + + Orders to place + Cancellation token + + + + + Edit multiple orders in a single call + + + Orders to edit + Cancellation token + + + + + Gate.io spot streams + + + + + Subscribe to public trade updates + + + Symbol + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to public trade updates + + + Symbols + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to ticker updates + + + Symbol + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to ticker updates + + + Symbols + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to kline/candlestick updates + + + Symbol + Kline interval + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to book ticker updates + + + Symbol + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to book ticker updates + + + Symbols + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to order book change events. Only the changed entries will be pushed + + + Symbol + Update speed in milliseconds. 100 or 1000 + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to partial full order book updates, Full order book will be pushed for a limited depth + + + Symbol + Depth of the book. 5, 10, 20, 50 or 100 + Update speed in milliseconds. 100 or 1000 + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to order updates + + + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to user trade updates + + + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to balance updates + + + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to margin balance updates + + + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to funding balance updates + + + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to cross margin balance updates + + + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Subscribe to trigger order updates + + + The event handler for the received data + Cancellation token for closing this subscription + A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + + + + Gate.io local order book factory + + + + + Spot order book factory methods + + + + + BTC perpetual futures order book factory methods + + + + + USD perpetual futures order book factory methods + + + + + USDT perpetual futures order book factory methods + + + + + Create a new perpetual futures local order book instance + + + + + + + + + Create a new spot local order book instance + + + + + + + + Api addresses + + + + + The address used by the GateIoRestClient for the API + + + + + The address used by the GateIoSocketClient for the spot websocket API + + + + + The address used by the GateIoSocketClient for the futures websocket API + + + + + The default addresses to connect to the Gate.io API + + + + + Account info + + + + + User id + + + + + IP whitelist for this API Key + + + + + Symbol whitelist for this API Key + + + + + VIP tier + + + + + Key info + + + + + Key info + + + + + Mode: 1 - classic account 2 - portfolio margin account + + + + + Account valuation + + + + + Details + + + + + Total value + + + + + Account values + + + + + Cross margin value + + + + + Spot value + + + + + Finance value + + + + + Margin value + + + + + Quant value + + + + + Futures value + + + + + Delivery value + + + + + Warrant value + + + + + CBBC value + + + + + Account value + + + + + Asset + + + + + Total account balance + + + + + Unrelealised profit and loss + + + + + Borrowed + + + + + Asset info + + + + + Asset name + + + + + Whether the asset is delisted + + + + + Whether the asset has withdrawals disabled + + + + + Whether the asset has withdrawals delayed + + + + + Whether the asset has deposits disabled + + + + + Whether the asset has trading disabled + + + + + Fixed fee rate + + + + + Network of the asset + + + + + Balance info + + + + + Asset name + + + + + Available quantity + + + + + Locked quantity + + + + + Update id + + + + + Balance update + + + + + Timestamp + + + + + User id + + + + + Asset + + + + + Change + + + + + Total + + + + + Available + + + + + Frozen + + + + + Change in frozen quantity + + + + + Change type + + + + + Batch order cancellation request + + + + + The symbol the order is on + + + + + The order id + + + + + The type of account + + + + + Batch order edit request + + + + + The order id + + + + + The symbol the order is on + + + + + amend text + + + + + Quantity + + + + + Order price + + + + + The type of account + + + + + Batch order placement request + + + + + The symbol the order is on + + + + + Text + + + + + Order type + + + + + Order side + + + + + Time in force + + + + + Quantity + + + + + Order price + + + + + Iceberg quantity + + + + + The type of account + + + + + Auto borrow + + + + + Auto repay + + + + + STP mode + + + + + Book ticker update + + + + + Timestamp + + + + + Update id + + + + + Symbol + + + + + Best bid price + + + + + Best bid quantity + + + + + Best ask price + + + + + Best ask quantity + + + + + Cancel after results + + + + + Time the cancellation is triggered + + + + + Cancel result info + + + + + Symbol + + + + + Order id + + + + + Order info + + + + + Whether the operation succeeded + + + + + Error code when operation failed + + + + + Error message when operation failed + + + + + Cross margin account + + + + + User id + + + + + Locked + + + + + Total value in USD + + + + + Borrowed value in USD + + + + + Interest value in USD + + + + + Risk rate + + + + + Total initial margin + + + + + Total margin balance + + + + + Total maintenance margin + + + + + Total initial margin rate + + + + + Total maintenance margin rate + + + + + Total available margin + + + + + Total amount of the portfolio margin account + + + + + Total liabilities of the portfolio margin account + + + + + Total equity of the portfolio margin account + + + + + Balances + + + + + Unified account balance + + + + + Available quantity + + + + + Frozen quantity + + + + + Borrowed quantity + + + + + Interest + + + + + Negative liabilities + + + + + Borrowing to open futures positions + + + + + Equity + + + + + Total frozen + + + + + Total liabilities + + + + + Cross margin asset + + + + + Asset name + + + + + Minimum lending rate + + + + + Asset precision + + + + + Discount + + + + + Min borrow quantity + + + + + Max borrow quantity per user in USDT + + + + + Max borrow quantity total in USDT + + + + + Price + + + + + Asset is loanable + + + + + Status + + + + + Cross margin account balance change + + + + + Id + + + + + Timestamp + + + + + Asset + + + + + Change + + + + + Balance after + + + + + Type of change + + + + + Cross Margin Balance update + + + + + Timestamp + + + + + User id + + + + + Asset + + + + + Change + + + + + Total + + + + + Available + + + + + Frozen + + + + + Change in frozen quantity + + + + + Change type + + + + + Cross margin borrow loan + + + + + Id + + + + + Create time + + + + + Update time + + + + + Asset + + + + + Quantity + + + + + Text + + + + + Status + + + + + Repaid + + + + + Repaid interest + + + + + Unpaid interest + + + + + Cross margin interest + + + + + Create time + + + + + Asset + + + + + Symbol + + + + + Actual rate + + + + + Interest + + + + + Type + + + + + Success + + + + + Cross margin repayment + + + + + Id + + + + + Loan id + + + + + Create time + + + + + Asset + + + + + Principal + + + + + Interest + + + + + Repayment type + + + + + Deposit info + + + + + Withdrawal id + + + + + Client specified id + + + + + Asset + + + + + Address + + + + + Network + + + + + Memo + + + + + Quantity + + + + + Timestamp + + + + + Transaction id + + + + + Withdrawal status + + + + + Deposit address info + + + + + Asset + + + + + Address + + + + + Min deposit quantity + + + + + Min number of confirmations + + + + + Multichain addresses + + + + + Multichain address info + + + + + Network + + + + + Address + + + + + Notes that some currencies required(e.g., Tag, Memo) when depositing + + + + + Note type; tag or memo + + + + + Failed + + + + + Min number of confirmations + + + + + Discount tier + + + + + Asset + + + + + Tiers + + + + + Discount tier item + + + + + Tier + + + + + Discount. 1 means full price + + + + + Lower volume limit + + + + + Upper volume limit. Note that this is a string as '+' is returned for the most upper tier + + + + + Fee rate info + + + + + User id + + + + + Taker fee + + + + + Maker fee + + + + + Futures maker fee + + + + + Futures taker fee + + + + + If GT deduction is enabled + + + + + Maker fee rate if using GT deduction. It will be 0 if GT deduction is disabled + + + + + Taker fee rate if using GT deduction. It will be 0 if GT deduction is disabled + + + + + Loan fee rate of margin lending + + + + + Delivery futures trading taker fee + + + + + Delivery futures trading maker fee + + + + + Deduction types for rates, 1 - GT deduction, 2 - Point card deduction, 3 - VIP rates + + + + + Funding Balance update + + + + + Timestamp + + + + + User id + + + + + Asset + + + + + Change + + + + + Frozen + + + + + Lent + + + + + Futures account + + + + + User id + + + + + Asset + + + + + The balance after the user's accumulated deposit, withdraw, profit and loss + + + + + Unrealized profit and loss + + + + + Position margin + + + + + Order margin + + + + + Available + + + + + Point quantity + + + + + Perpetual Contract Bonus + + + + + Dual mode + + + + + Classic account margin mode + + + + + Total history + + + + + Account history + + + + + Total amount of deposit and withdraw + + + + + Total Profit and loss + + + + + Total amount of fee paid + + + + + Total amount of referrer rebates + + + + + Total amount of funding costs + + + + + Total amount of point deposit and withdraw + + + + + Total amount of point fee + + + + + Total amountof point referrer rebates + + + + + Total amount of perpetual contract bonus transfer + + + + + Total amount of perpetual contract bonus deduction + + + + + Cancel result + + + + + User id + + + + + Order id + + + + + Succeeded + + + + + Message + + + + + Id reference + + + + + Id + + + + + Interest record + + + + + Status + + + + + Symbol + + + + + Asset + + + + + Actual interest rate + + + + + Interest + + + + + Loan type + + + + + Create time + + + + + Kline/candlestick info + + + + + Open timestamp + + + + + Quote volume + + + + + Close price + + + + + High price + + + + + Low price + + + + + Open price + + + + + Base volume + + + + + Is the kline final/closed + + + + + Kline update + + + + + Open time + + + + + Volume in quote asset + + + + + Close price + + + + + High price + + + + + Low price + + + + + Open price + + + + + Stream + + + + + Open price + + + + + Is final update for this timeframe + + + + + The symbol + + + + + The interval + + + + + Account ledger entry + + + + + Entry id + + + + + Timestamp + + + + + Asset + + + + + Change quantity + + + + + Balance after change + + + + + Change type + + + + + Additional info + + + + + Lending symbol + + + + + Symbol + + + + + Min borrow quantity in the base asset + + + + + Min borrow quantity in the quote asset + + + + + Leverage + + + + + Liquidation + + + + + Timestamp + + + + + Contract + + + + + Quantity + + + + + Order price + + + + + Fill price + + + + + Left + + + + + Loan info + + + + + Asset name + + + + + Symbol + + + + + Quantity + + + + + Loan type + + + + + Last update time + + + + + Create time + + + + + Margin tier + + + + + Asset + + + + + Tiers + + + + + Margin tier entry + + + + + Tier + + + + + Margin rate + + + + + Lower volume limit + + + + + Upper volume limit + + + + + Loan history record + + + + + Id + + + + + Type + + + + + Margin mode + + + + + Symbol + + + + + Asset + + + + + Quantity + + + + + Create time + + + + + Repay type + + + + + Margin account + + + + + Symbol + + + + + Account is locked + + + + + Current risk rate + + + + + Base asset + + + + + Quote asset + + + + + Margin account asset + + + + + Asset + + + + + Available quantity + + + + + Locked quantity + + + + + Borrowed quantity + + + + + Interest quantity + + + + + Repay status + + + + + Status, on or off + + + + + Margin account balance change + + + + + Id + + + + + Timestamp + + + + + Asset + + + + + Symbol + + + + + Change + + + + + Balance after + + + + + Type of change + + + + + Margin Balance update + + + + + Timestamp + + + + + User id + + + + + Asset + + + + + Symbol + + + + + Change + + + + + Available + + + + + Frozen + + + + + Borrowed + + + + + Interest + + + + + Funding account + + + + + Asset + + + + + Available + + + + + Locked + + + + + Lent + + + + + Total lent + + + + + Loan record + + + + + Type + + + + + Symbol + + + + + Asset + + + + + Quantity + + + + + Create time + + + + + Max borrowable info + + + + + Asset + + + + + Symbol + + + + + Max borrowable + + + + + Transferable + + + + + Asset + + + + + Symbol + + + + + Max transferable + + + + + Asset network info + + + + + Network name + + + + + Network name in Chinese + + + + + Network name in English + + + + + Contract address + + + + + Withdrawal precision + + + + + Is network disabled + + + + + Is deposit disabled + + + + + Is withdrawal disabled + + + + + Is tag + + + + + Order info + + + + + Order id + + + + + Symbol + + + + + User defined text + + + + + Custom data that the user remarked when amending the order + + + + + Creation time + + + + + Last update time + + + + + Order status + + + + + Order type + + + + + Order side + + + + + Account type + + + + + Time in force + + + + + Quantity + + + + + Quantity remaining + + + + + Quantity filled + + + + + Quote quantity filled + + + + + Order price + + + + + Average fill price + + + + + Fee paid + + + + + Fee asset + + + + + Points used to deduct fee + + + + + GT used to deduct fee + + + + + GT used to deduct maker fee + + + + + GT used to deduct taker fee + + + + + Whether GT fee discount is used + + + + + Rebated fee + + + + + Rebated fee currency unit + + + + + Orders between users in the same SelfTradePreventionId group are not allowed to be self-traded + + + + + Self trade prevention mode + + + + + Order finish type + + + + + Iceberg quantity + + + + + Auto borrow + + + + + Auto repay + + + + + Order operation result + + + + + Whether the operation succeeded + + + + + Error code when operation failed + + + + + Error message when operation failed + + + + + Order book + + + + + Book sync id + + + + + The timestamp the book was requested + + + + + The timestamp the book was last updated + + + + + Asks list + + + + + Bids list + + + + + Order book entry + + + + + Price + + + + + Quantity + + + + + Order book update + + + + + Timestamp + + + + + Update id + + + + + Update id + + + + + Symbol + + + + + Event + + + + + Updated bids + + + + + Updated asks + + + + + Order update + + + + + Order id + + + + + Text + + + + + Create time + + + + + Update time + + + + + Symbol + + + + + Order type + + + + + Order side + + + + + Account type + + + + + Order quantity + + + + + Order price + + + + + Time in force + + + + + Quantity still open + + + + + Quote asset quantity filled + + + + + Average fill price + + + + + Fee paid + + + + + Asset the fee is in + + + + + Points used to deduct fee + + + + + GT used to deduct fee + + + + + Whether GT fee discount is used + + + + + Rebated fee + + + + + Rebated fee currency unit + + + + + Orders between users in the same SelfTradePreventionId group are not allowed to be self-traded + + + + + Self trade prevention mode + + + + + User id + + + + + Trigger event + + + + + Order finish type + + + + + Custom data that the user remarked when amending the order + + + + + Auto borrow + + + + + Auto repay + + + + + Order book update + + + + + Timestamp + + + + + Update id + + + + + Symbol + + + + + Updated bids + + + + + Updated asks + + + + + Auto deleverage + + + + + Timestamp + + + + + Contract + + + + + Entry price + + + + + Order price + + + + + Order id + + + + + User id + + + + + Cross leverage limit + + + + + Leverage + + + + + Position quantity + + + + + Trade quantity + + + + + Balance update + + + + + Balance after change + + + + + Changed quantity + + + + + Text + + + + + Timestamp + + + + + Change type + + + + + User id + + + + + Asset + + + + + Batch order placement item + + + + + Contract + + + + + Quantity + + + + + Iceberg quantity + + + + + Order price + + + + + Time in force + + + + + Text + + + + + Close position + + + + + Reduce only + + + + + Close side + + + + + Self trade prevention mode + + + + + Book ticker update + + + + + Timestamp + + + + + Update id + + + + + Contract + + + + + Best bid price + + + + + Best bid quantity + + + + + Best ask price + + + + + Best ask quantity + + + + + Index constituents + + + + + Index name + + + + + Constituents + + + + + Reference + + + + + Exchange + + + + + Symbols + + + + + Contract statistics + + + + + Timestamp + + + + + Long/short account number ratio + + + + + Long/short taker size ratio + + + + + Long liquidation size + + + + + Short liquidation size + + + + + Open interest + + + + + Short liquidation volume(quote currency) + + + + + Mark price + + + + + Top trader long/short position ratio + + + + + Short liquidation amount(base currency) + + + + + Long liquidation amount(base currency) + + + + + Open interest volume(quote currency) + + + + + Top trader long/short account ratio + + + + + Long liquidation volume(quote currency) + + + + + Fee info + + + + + Taker fee rate + + + + + Maker fee rate + + + + + Funding rate + + + + + Time + + + + + Funding rate + + + + + Contract info + + + + + Contract name + + + + + Contract type + + + + + Multiplier used in converting from invoicing to settlement asset + + + + + Referral fee rate discount + + + + + Deviation between order price and current index price + + + + + Maintenance rate of margin + + + + + Mark type + + + + + Mark price + + + + + Last price + + + + + Index price + + + + + Funding rate indicative + + + + + Minimum mark price increment + + + + + Funding offset + + + + + Delisting + + + + + Interest rate + + + + + Minimum order price increment + + + + + Minimum order quantity + + + + + Referral fee rate discount + + + + + Funding application interval, unit in seconds + + + + + Min leverage + + + + + Max leverage + + + + + Maker fee rate + + + + + Taker fee rate + + + + + Funding rate + + + + + Max order quantity + + + + + Next funding time + + + + + Config change time + + + + + Short users + + + + + Historical accumulated trade size + + + + + Current total long position size + + + + + Long users + + + + + Funding impact value + + + + + Maximum number of open orders + + + + + Last trade id + + + + + Last book sequence id + + + + + Whether bonus is enabled + + + + + Whether portfolio margin account is enabled + + + + + Create time + + + + + The factor for the maximum of the funding rate. + + + + + Voucher leverage + + + + + Kline info + + + + + Open time + + + + + Close price + + + + + High price + + + + + Low price + + + + + Open price + + + + + Insurance + + + + + Time + + + + + Funding rate + + + + + Kline info + + + + + Open time + + + + + Volume + + + + + Close price + + + + + High price + + + + + Low price + + + + + Open price + + + + + Volume + + + + + Kline update + + + + + Open time + + + + + Volume in quote asset + + + + + Close price + + + + + High price + + + + + Low price + + + + + Open price + + + + + Stream + + + + + The contract + + + + + The interval + + + + + Account ledger entry + + + + + Timestamp + + + + + Contract + + + + + Change quantity + + + + + Balance after change + + + + + Change type + + + + + Additional info + + + + + Trade id + + + + + User liquidation info + + + + + User id + + + + + Timestamp + + + + + Contract + + + + + Quantity + + + + + Leverage + + + + + Margin + + + + + Entry price + + + + + Liquidation price + + + + + Mark price + + + + + Order id + + + + + Order price + + + + + Order price + + + + + Left + + + + + Futures order info + + + + + Id + + + + + User id + + + + + Contract + + + + + Create time + + + + + Quantity + + + + + Iceberg quantity + + + + + Open quantity + + + + + Order price + + + + + Fill price + + + + + Maker fee + + + + + Taker fee + + + + + Time in force + + + + + Reference user ID + + + + + Is reduce only order + + + + + Is close position order + + + + + Is liquidation position order + + + + + Text + + + + + Status + + + + + Finish time + + + + + Finish type + + + + + STP group id + + + + + STP mode + + + + + Amend text + + + + + Order book + + + + + Book sync id + + + + + The timestamp the book was requested + + + + + The timestamp the book was last updated + + + + + Asks list + + + + + Bids list + + + + + Order book entry + + + + + Price + + + + + Quantity + + + + + Order book update + + + + + Timestamp + + + + + Update id + + + + + Update id + + + + + Contract + + + + + Event + + + + + Updated bids + + + + + Updated asks + + + + + Position close info + + + + + Timestamp + + + + + Profit and loss + + + + + Realized profit and loss position + + + + + Realized PNL - Funding Fees + + + + + Realized PNL - Transaction Fees + + + + + Position side + + + + + Contract + + + + + Text + + + + + Max Trade Size + + + + + First opening time + + + + + When 'side' is 'long,' it indicates the opening average price; when 'side' is 'short,' it indicates the closing average price. + + + + + When 'side' is 'long,' it indicates the opening average price; when 'side' is 'short,' it indicates the closing average price + + + + + Position close info + + + + + Timestamp + + + + + Profit and loss + + + + + Position side + + + + + Contract + + + + + Text + + + + + User id + + + + + Risk limit update + + + + + Cancel orders + + + + + Contract + + + + + Max leverage + + + + + Liquidation price + + + + + Maintenance rate + + + + + Risk limit + + + + + Timestamp + + + + + User id + + + + + Ticker info + + + + + Contract + + + + + Last price + + + + + 24h low price + + + + + 24h high price + + + + + 24h Change percentage + + + + + Total contract size + + + + + 24h Volume + + + + + 24h Volume in BTC + + + + + 24h Volume in USD + + + + + 24h Base asset volume + + + + + 24h Quote asset volume + + + + + 24h Settle asset volume + + + + + Mark price + + + + + Funding rate + + + + + Funding rate indicative + + + + + Index price + + + + + Best ask price + + + + + Best bid price + + + + + Perpetual ticker update + + + + + Contract + + + + + Last trade price + + + + + Change percentage compared to 24h ago + + + + + 24h high price + + + + + 24h low price + + + + + Mark price + + + + + Index price + + + + + Funding rate + + + + + Funding rate indicative + + + + + Total contract size + + + + + 24h Volume + + + + + 24h Volume in BTC + + + + + 24h Volume in USD + + + + + 24h Base asset volume + + + + + 24h Quote asset volume + + + + + 24h Settle asset volume + + + + + Exchange rate of base currency and settlement currency in Quanto contract. Does not exists in contracts of other types + + + + + Trade info + + + + + Trade id + + + + + Contract + + + + + Timestamp + + + + + Quantity + + + + + Trade price + + + + + Trade update + + + + + Trade id + + + + + Create time + + + + + Contract + + + + + Trade quantity, negative means sell, positive is buy + + + + + Trade price + + + + + Whether internal trade. Internal trade refers to the takeover of liquidation orders by the insurance fund and ADL users + + + + + Trigger order + + + + + Trigger order id + + + + + User id + + + + + Create time + + + + + Finish time + + + + + Trade id + + + + + Status + + + + + Finish type + + + + + Reason + + + + + Order type + + + + + Order info + + + + + Trigger info + + + + + Trigger info + + + + + Price type + + + + + Price + + + + + Trigger type + + + + + Expire time in seconds + + + + + Order info + + + + + Contract + + + + + Quantity + + + + + Price + + + + + Close position order + + + + + Reduce only order + + + + + Time in force + + + + + Text + + + + + Close side + + + + + Trigger order + + + + + Corresponding order ID of order take-profit/stop-loss. + + + + + Is stop order + + + + + Name + + + + + Trigger order id + + + + + User id + + + + + Create time + + + + + Finish time + + + + + Trade id + + + + + Status + + + + + Finish type + + + + + Reason + + + + + Order type + + + + + Order info + + + + + Trigger info + + + + + User trade info + + + + + Trade id + + + + + Contract + + + + + Timestamp + + + + + Quantity + + + + + Trade price + + + + + Order id + + + + + Text + + + + + Trade fee + + + + + Trade point fee + + + + + Role + + + + + Position info + + + + + User id + + + + + Contract + + + + + Position size + + + + + Leverage + + + + + Risk limit + + + + + Max leverage + + + + + Maintenance rate + + + + + Position value + + + + + Margin + + + + + Entry price + + + + + Liquidation price + + + + + Mark price + + + + + Unrealized profit and less + + + + + Realized profit and less + + + + + Realized profit and loss position + + + + + Realized PNL - Funding Fees + + + + + Realized PNL - Transaction Fees + + + + + History realized PNL + + + + + Last close pnl + + + + + Realized POINT PNL + + + + + History realized POINT PNL + + + + + Auto deleverage ranking + + + + + Open orders + + + + + Position mode + + + + + Update time + + + + + Cross margin leverage + + + + + Close order + + + + + Close order info + + + + + Order id + + + + + Close order price + + + + + Is liquidation order + + + + + Position update + + + + + User id + + + + + Update id + + + + + Contract + + + + + Position size + + + + + Leverage + + + + + Risk limit + + + + + Max leverage + + + + + Maintenance rate + + + + + Margin + + + + + Entry price + + + + + Liquidation price + + + + + Realized profit and less + + + + + History realized PNL + + + + + Last close pnl + + + + + Realized POINT PNL + + + + + History realized POINT PNL + + + + + Position mode + + + + + Cross margin leverage + + + + + Risk limit tier + + + + + Maintenance rate + + + + + Tier + + + + + Initial margin rate + + + + + Max leverage + + + + + Risk limit + + + + + Risk units + + + + + User id + + + + + Spot hedge status + + + + + Risk units + + + + + Risk unit details + + + + + Symbol + + + + + Spot hedging usage + + + + + Maintenance margin + + + + + Initial margin + + + + + Delta + + + + + Gamma + + + + + Theta + + + + + Vega + + + + + Saved address + + + + + Asset + + + + + Address + + + + + Network + + + + + Name + + + + + Tag + + + + + Is verified + + + + + Small balance info + + + + + Asset name + + + + + Available balance + + + + + Estimated value in BTC + + + + + Estimated value in GT + + + + + Small balance conversion + + + + + Id + + + + + Asset name + + + + + Create time + + + + + Input amount + + + + + Output GT + + + + + Symbol info + + + + + Name + + + + + Base asset + + + + + Quote asset + + + + + Trade fee + + + + + Min base asset order quantity + + + + + Min quote asset order quantity + + + + + Max base asset order quantity + + + + + Max quote asset order quantity + + + + + Quantity decimal precision + + + + + Price decimal precision + + + + + Trading status + + + + + Sell start time + + + + + Buy start time + + + + + Orders for a symbol + + + + + Symbol + + + + + Total count + + + + + Orders + + + + + Asset info + + + + + Symbol name + + + + + Last traded price + + + + + Best ask price + + + + + Best bid price + + + + + Change percentage last 24h + + + + + Change percentage UTC+0 timezone + + + + + Change percentage UTC+8 timezone + + + + + Volume last 24h in the base asset + + + + + Volume last 24h in the quote asset + + + + + Highest price in last 24h + + + + + Lowest price in last 24h + + + + + ETF Net value + + + + + ETF previous net value + + + + + ETF previous rebalance time + + + + + ETF current leverage + + + + + Ticker update + + + + + Symbol + + + + + Last trade price + + + + + Best ask price + + + + + Best bid price + + + + + Change percentage compared to 24h ago + + + + + Volume in base asset + + + + + Volume in quote asset + + + + + 24h high price + + + + + 24h low price + + + + + Trade info + + + + + Trade id + + + + + Symbol + + + + + Timestamp + + + + + Order side + + + + + Quantity + + + + + Trade price + + + + + Sequence id + + + + + User trade info + + + + + Role + + + + + Order id + + + + + Trade fee + + + + + Asset the fee is in + + + + + Points used to deduct fee + + + + + GT used to deduct fee. + + + + + The custom data that the user remarked when amending the order + + + + + User defined information + + + + + Trade update + + + + + Trade id + + + + + Create time + + + + + Side + + + + + Symbol + + + + + Trade quantity + + + + + Trade price + + + + + The start and end sequence id + + + + + Transfer + + + + + Transation id + + + + + Trigger order info + + + + + Order info + + + + + Order info + + + + + Trigger order id + + + + + User id + + + + + Symbol + + + + + Create time + + + + + Trigger time + + + + + Id of the create order + + + + + Trigger status + + + + + Additional info + + + + + Trigger order trigger info + + + + + Trigger price + + + + + Trigger type + + + + + Expiration in seconds + + + + + Order info + + + + + User defined text + + + + + Order type + + + + + Order side + + + + + Account type + + + + + Time in force + + + + + Quantity + + + + + Order price + + + + + Trigger order update + + + + + Symbol + + + + + User id + + + + + Id + + + + + Base asset + + + + + Quote asset + + + + + Reason + + + + + Error message + + + + + Id of the order which was placed after triggering + + + + + Instant cancel + + + + + Trigger price + + + + + Trigger type + + + + + Expiration in seconds + + + + + Price + + + + + Quantity + + + + + Source + + + + + Order type + + + + + Side + + + + + Engine type + + + + + Is stop order + + + + + Stop trigger price + + + + + Stop trigger rule + + + + + Stop price + + + + + Create time + + + + + Fire time + + + + + Unified account info + + + + + User id + + + + + Locked + + + + + Total value in USD + + + + + Borrowed value in USD + + + + + Total initial margin + + + + + Total margin balance + + + + + Total maintenance margin + + + + + Total initial margin rate + + + + + Total maintenance margin rate + + + + + Total available margin + + + + + Unified account total + + + + + Unified account total liabilities + + + + + Unified account total equity + + + + + Leverage + + + + + Total order loss, in USDT + + + + + Spot hedging status + + + + + Whether to use funds as margin + + + + + Balances + + + + + Unified account balance + + + + + Available quantity + + + + + Frozen quantity + + + + + Borrowed quantity + + + + + Negative liabilities + + + + + Borrowing to open futures positions + + + + + Equity + + + + + Total frozen + + + + + Total liabilities + + + + + Spot hedging utilization + + + + + Max borrowable info + + + + + Asset + + + + + Symbol + + + + + Max borrowable + + + + + Unified account mode + + + + + Account mode + + + + + Settings + + + + + Unified account settings + + + + + USDT contract switch + + + + + Spot hedging switch + + + + + When the mode is set to combined margin mode, will funds be used as margin + + + + + User trade updates + + + + + Order id + + + + + Trade id + + + + + Text + + + + + Create time + + + + + Symbol + + + + + Role + + + + + Order side + + + + + Order quantity + + + + + Order price + + + + + Fee paid + + + + + Points used to deduct fee + + + + + GT used to deduct fee + + + + + User id + + + + + Withdrawal info + + + + + Withdrawal id + + + + + Client specified id + + + + + Asset + + + + + Address + + + + + Network + + + + + Memo + + + + + Quantity + + + + + Fee + + + + + Timestamp + + + + + Transaction id + + + + + Withdrawal status + + + + + Withdraw status + + + + + Asset + + + + + Asset name + + + + + Asset name in Chinese + + + + + Deposit fee + + + + + Withdrawal fee percentage + + + + + Withdrawal fee fixed quantity + + + + + Withdrawal day limit + + + + + Withdrawal day limit left + + + + + Minimal quantity that can be withdrawn + + + + + Max quantity per withdrawal + + + + + Fixed withdrawal fee on multiple networks + + + + + Percentage withdrawal fee on multiple networks + + + + + Options for the GateIo SymbolOrderBook + + + + + Default options for new clients + + + + + The top amount of results to keep in sync. If for example limit=10 is used, the order book will contain the 10 best bids and 10 best asks. Leaving this null will sync the full order book + + + + + Update interval in milliseconds, either 100 or 1000. Defaults to 1000 + + + + + After how much time we should consider the connection dropped if no data is received for this time after the initial subscriptions + + + + + Options for the GateIoRestClient + + + + + Default options for new clients + + + + + Broker id + + + + + Spot API options + + + + + Futures API options + + + + + Options for the GateIoSocketClient + + + + + Default options for new clients + + + + + Options for the Spot API + + + + + Options for the Perpetual Futures API + + + + + + + + + + + + + + ctor + + + + + + + + + + + + + + + + + + + + + + + + + + + + ctor + + + + + + + + + + + + + + + + + + + + GateIo order book factory + + + + + ctor + + Service provider for resolving logging and clients + + + + + + + + + + + + + + + + + + + + + + Implementation for a synchronized order book. After calling Start the order book will sync itself and keep up to date with new data. It will automatically try to reconnect and resync in case of a lost/interrupted connection. + Make sure to check the State property to see if the order book is synced. + + + + + Create a new order book instance + + The settlement asset. btc, usdt or usd + The symbol the order book is for + Option configuration delegate + + + + Create a new order book instance + + The settlement asset. btc, usdt or usd + The symbol the order book is for + Option configuration delegate + Logger + Rest client instance + Socket client instance + + + + + + + + + + + + + + + + Implementation for a synchronized order book. After calling Start the order book will sync itself and keep up to date with new data. It will automatically try to reconnect and resync in case of a lost/interrupted connection. + Make sure to check the State property to see if the order book is synced. + + + + + Create a new order book instance + + The symbol the order book is for + Option configuration delegate + + + + Create a new order book instance + + The symbol the order book is for + Option configuration delegate + Logger + Rest client instance + Socket client instance + + + + + + + + + + + + + + + + Extensions for the ICryptoRestClient and ICryptoSocketClient interfaces + + + + + Get the Gate.io REST Api client + + + + + + + Get the Gate.io Websocket Api client + + + + + + + Extensions for DI + + + + + Add the IGateIoClient and IGateIoSocketClient to the sevice collection so they can be injected + + The service collection + Set default options for the rest client + Set default options for the socket client + The lifetime of the IGateIoSocketClient for the service collection. Defaults to Singleton. + + + + diff --git a/GateIo.Net/GateIoAuthenticationProvider.cs b/GateIo.Net/GateIoAuthenticationProvider.cs new file mode 100644 index 0000000..fb43d37 --- /dev/null +++ b/GateIo.Net/GateIoAuthenticationProvider.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using CryptoExchange.Net; +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Clients; +using CryptoExchange.Net.Converters.SystemTextJson; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Objects; + +namespace GateIo.Net +{ + internal class GateIoAuthenticationProvider : AuthenticationProvider + { + private static IMessageSerializer _serializer = new SystemTextJsonMessageSerializer(); + + public string GetApiKey() => _credentials.Key!.GetString(); + + public GateIoAuthenticationProvider(ApiCredentials credentials) : base(credentials) + { + } + + public override void AuthenticateRequest(RestApiClient apiClient, Uri uri, HttpMethod method, IDictionary uriParameters, IDictionary bodyParameters, Dictionary headers, bool auth, ArrayParametersSerialization arraySerialization, RequestBodyFormat requestBodyFormat) + { + if (!auth) + return; + + uri = uri.SetParameters(uriParameters, arraySerialization); + var timestamp = long.Parse(GetMillisecondTimestamp(apiClient)) / 1000; + var payload = SignSHA512(bodyParameters.Any() ? GetSerializedBody(_serializer, bodyParameters) : "").ToLowerInvariant(); + var signStr = $"{method.ToString().ToUpper()}\n{uri.AbsolutePath}\n{uri.Query.Replace("?", "")}\n{payload}\n{timestamp}"; + var signed = SignHMACSHA512(signStr).ToLowerInvariant(); + + headers["KEY"] = GetApiKey(); + headers["Timestamp"] = timestamp.ToString(); + headers["SIGN"] = signed; + } + + public string SignSocketRequest(string signStr) => SignHMACSHA512(signStr).ToLowerInvariant(); + } +} diff --git a/GateIo.Net/GateIoEnvironment.cs b/GateIo.Net/GateIoEnvironment.cs new file mode 100644 index 0000000..921c95c --- /dev/null +++ b/GateIo.Net/GateIoEnvironment.cs @@ -0,0 +1,62 @@ +using CryptoExchange.Net.Objects; +using GateIo.Net.Objects; + +namespace GateIo.Net +{ + /// + /// GateIo environments + /// + public class GateIoEnvironment : TradeEnvironment + { + /// + /// Rest API address + /// + public string RestClientAddress { get; } + + /// + /// Socket API spot address + /// + public string SpotSocketClientAddress { get; } + + /// + /// Socket API futures address + /// + public string FuturesSocketClientAddress { get; } + + internal GateIoEnvironment( + string name, + string restAddress, + string spotWebsocketAddress, + string futuresWebsocketAddress) : + base(name) + { + RestClientAddress = restAddress; + SpotSocketClientAddress = spotWebsocketAddress; + FuturesSocketClientAddress = futuresWebsocketAddress; + } + + /// + /// Live environment + /// + public static GateIoEnvironment Live { get; } + = new GateIoEnvironment(TradeEnvironmentNames.Live, + GateIoApiAddresses.Default.RestClientAddress, + GateIoApiAddresses.Default.SpotSocketClientAddress, + GateIoApiAddresses.Default.FuturesSocketClientAddress); + + /// + /// Create a custom environment + /// + /// + /// + /// + /// + /// + public static GateIoEnvironment CreateCustom( + string name, + string spotRestAddress, + string spotSocketStreamsAddress, + string futuresSocketStreamsAddress) + => new GateIoEnvironment(name, spotRestAddress, spotSocketStreamsAddress, futuresSocketStreamsAddress); + } +} diff --git a/GateIo.Net/GateIoExchange.cs b/GateIo.Net/GateIoExchange.cs new file mode 100644 index 0000000..2a36765 --- /dev/null +++ b/GateIo.Net/GateIoExchange.cs @@ -0,0 +1,97 @@ +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.RateLimiting.Guards; +using CryptoExchange.Net.RateLimiting.Interfaces; +using CryptoExchange.Net.RateLimiting; +using System; + +namespace GateIo.Net +{ + /// + /// Gate.io exchange information and configuration + /// + public static class GateIoExchange + { + /// + /// Exchange name + /// + public static string ExchangeName => "Gate.io"; + + /// + /// Url to the main website + /// + public static string Url { get; } = "https://www.gate.io"; + + /// + /// Urls to the API documentation + /// + public static string[] ApiDocsUrl { get; } = new[] { + "https://www.gate.io/docs/developers/apiv4/en/" + }; + + /// + /// Rate limiter configuration for the Gate.io API + /// + public static GateIoRateLimiters RateLimiter { get; } = new GateIoRateLimiters(); + } + + /// + /// Rate limiter configuration for the GateIo API + /// + public class GateIoRateLimiters + { + /// + /// Event for when a rate limit is triggered + /// + public event Action RateLimitTriggered; + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + internal GateIoRateLimiters() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + Initialize(); + } + + private void Initialize() + { + Public = new RateLimitGate("Public") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerEndpoint, Array.Empty(), 200, TimeSpan.FromSeconds(10), RateLimitWindowType.FixedAfterFirst)); // IP limit of 200 request per endpoint per 10 seconds + RestSpotOrderPlacement = new RateLimitGate("SpotOrderPlacement") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerApiKey, Array.Empty(), 10, TimeSpan.FromSeconds(1), RateLimitWindowType.FixedAfterFirst)); // Uid limit of 10 request per second + RestSpotOrderCancelation = new RateLimitGate("SpotOrderCancelation") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerApiKey, Array.Empty(), 200, TimeSpan.FromSeconds(1), RateLimitWindowType.FixedAfterFirst)); // Uid limit of 200 request per second + RestFuturesOrderPlacement = new RateLimitGate("FuturesOrderPlacement") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerApiKey, Array.Empty(), 100, TimeSpan.FromSeconds(1), RateLimitWindowType.FixedAfterFirst)); // Uid limit of 100 request per second + RestFuturesOrderCancelation = new RateLimitGate("FuturesOrderCancelation") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerApiKey, Array.Empty(), 200, TimeSpan.FromSeconds(1), RateLimitWindowType.FixedAfterFirst)); // Uid limit of 200 request per second + RestSpotOther = new RateLimitGate("SpotOther") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerApiKeyPerEndpoint, Array.Empty(), 200, TimeSpan.FromSeconds(10), RateLimitWindowType.FixedAfterFirst)); // Uid limit of 200 request per 10 seconds + RestFuturesOther = new RateLimitGate("FuturesOther") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerApiKeyPerEndpoint, Array.Empty(), 200, TimeSpan.FromSeconds(10), RateLimitWindowType.FixedAfterFirst)); // Uid limit of 200 request per 10 seconds + RestPrivate = new RateLimitGate("PrivateOther") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerApiKeyPerEndpoint, Array.Empty(), 150, TimeSpan.FromSeconds(10), RateLimitWindowType.FixedAfterFirst)); // Uid limit of 150 request per 10 seconds + RestOther = new RateLimitGate("Other") + .AddGuard(new RateLimitGuard(RateLimitGuard.PerApiKeyPerEndpoint, Array.Empty(), 150, TimeSpan.FromSeconds(10), RateLimitWindowType.FixedAfterFirst)); // Uid limit of 150 request per 10 seconds + + Public.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + RestSpotOrderPlacement.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + RestSpotOrderCancelation.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + RestFuturesOrderPlacement.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + RestFuturesOrderCancelation.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + RestSpotOther.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + RestFuturesOther.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + RestPrivate.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + RestOther.RateLimitTriggered += (x) => RateLimitTriggered?.Invoke(x); + } + + + internal IRateLimitGate Public { get; private set; } + internal IRateLimitGate RestSpotOrderPlacement { get; private set; } + internal IRateLimitGate RestSpotOrderCancelation { get; private set; } + internal IRateLimitGate RestFuturesOrderPlacement { get; private set; } + internal IRateLimitGate RestFuturesOrderCancelation { get; private set; } + internal IRateLimitGate RestSpotOther { get; private set; } + internal IRateLimitGate RestFuturesOther { get; private set; } + internal IRateLimitGate RestPrivate { get; private set; } + internal IRateLimitGate RestOther { get; private set; } + } +} diff --git a/GateIo.Net/Icon/icon.png b/GateIo.Net/Icon/icon.png new file mode 100644 index 0000000..5a3a3ff Binary files /dev/null and b/GateIo.Net/Icon/icon.png differ diff --git a/GateIo.Net/Interfaces/Clients/IGateIoRestClient.cs b/GateIo.Net/Interfaces/Clients/IGateIoRestClient.cs new file mode 100644 index 0000000..20d454f --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/IGateIoRestClient.cs @@ -0,0 +1,28 @@ +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Interfaces; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; +using GateIo.Net.Interfaces.Clients.SpotApi; + +namespace GateIo.Net.Interfaces.Clients +{ + /// + /// Client for accessing the Gate.io Rest API. + /// + public interface IGateIoRestClient : IRestClient + { + /// + /// Spot API endpoints + /// + IGateIoRestClientSpotApi SpotApi { get; } + /// + /// Perpetual Futures API endpoints + /// + IGateIoRestClientPerpetualFuturesApi PerpetualFuturesApi { get; } + + /// + /// Set the API credentials for this client. All Api clients in this client will use the new credentials, regardless of earlier set options. + /// + /// The credentials to set + void SetApiCredentials(ApiCredentials credentials); + } +} diff --git a/GateIo.Net/Interfaces/Clients/IGateIoSocketClient.cs b/GateIo.Net/Interfaces/Clients/IGateIoSocketClient.cs new file mode 100644 index 0000000..d893174 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/IGateIoSocketClient.cs @@ -0,0 +1,28 @@ +using CryptoExchange.Net.Authentication; +using CryptoExchange.Net.Interfaces; +using GateIo.Net.Interfaces.Clients.PerpetualFuturesApi; +using GateIo.Net.Interfaces.Clients.SpotApi; + +namespace GateIo.Net.Interfaces.Clients +{ + /// + /// Client for accessing the Gate.io websocket API + /// + public interface IGateIoSocketClient : ISocketClient + { + /// + /// Spot streams + /// + IGateIoSocketClientSpotApi SpotApi { get; } + /// + /// Perpetual Futures streams + /// + IGateIoSocketClientPerpetualFuturesApi PerpetualFuturesApi { get; } + + /// + /// Set the API credentials for this client. All Api clients in this client will use the new credentials, regardless of earlier set options. + /// + /// The credentials to set + void SetApiCredentials(ApiCredentials credentials); + } +} diff --git a/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApi.cs b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApi.cs new file mode 100644 index 0000000..5d52587 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApi.cs @@ -0,0 +1,26 @@ +using CryptoExchange.Net.Interfaces; +using System; + +namespace GateIo.Net.Interfaces.Clients.PerpetualFuturesApi +{ + /// + /// GateIo futures API endpoints + /// + public interface IGateIoRestClientPerpetualFuturesApi : IRestApiClient, IDisposable + { + /// + /// Endpoints related to account settings, info or actions + /// + public IGateIoRestClientPerpetualFuturesApiAccount Account { get; } + + /// + /// Endpoints related to retrieving market data + /// + public IGateIoRestClientPerpetualFuturesApiExchangeData ExchangeData { get; } + + /// + /// Endpoints related to orders and trades + /// + public IGateIoRestClientPerpetualFuturesApiTrading Trading { get; } + } +} diff --git a/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiAccount.cs b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiAccount.cs new file mode 100644 index 0000000..f472544 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiAccount.cs @@ -0,0 +1,61 @@ +using CryptoExchange.Net.Objects; +using GateIo.Net.Objects.Models; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace GateIo.Net.Interfaces.Clients.PerpetualFuturesApi +{ + /// + /// GateIo futures account endpoints. Account endpoints include balance info, withdraw/deposit info and requesting and account settings + /// + public interface IGateIoRestClientPerpetualFuturesApiAccount + { + /// + /// Get futures account info + /// + /// + /// The settlement asset. btc, usdt or usd + /// Cancellation token + /// + Task> GetAccountAsync( + string settlementAsset, + CancellationToken ct = default); + + /// + /// Get futures account ledger + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Filter by start time + /// Filter by end time + /// Page number + /// Max amount of results + /// Filter by type + /// Cancellation token + /// + Task>> GetLedgerAsync(string settlementAsset, string? contract = null, DateTime? startTime = null, DateTime? endTime = null, int? page = null, int? limit = null, string? type = null, CancellationToken ct = default); + + /// + /// Set dual position mode + /// + /// + /// The settlement asset. btc, usdt or usd + /// Dual mode enabled + /// Cancellation token + /// + Task> UpdatePositionModeAsync(string settlementAsset, bool dualMode, CancellationToken ct = default); + + /// + /// Get user trading fees + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Cancellation token + /// + Task>> GetTradingFeeAsync(string settlementAsset, string? contract = null, CancellationToken ct = default); + } +} diff --git a/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiExchangeData.cs b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiExchangeData.cs new file mode 100644 index 0000000..30399c3 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiExchangeData.cs @@ -0,0 +1,227 @@ +using CryptoExchange.Net.Objects; +using GateIo.Net.Objects.Models; +using GateIo.Net.Enums; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace GateIo.Net.Interfaces.Clients.PerpetualFuturesApi +{ + /// + /// GateIo futures exchange data endpoints. Exchange data includes market data (tickers, order books, etc) and system status. + /// + public interface IGateIoRestClientPerpetualFuturesApiExchangeData + { + /// + /// + /// + /// + /// Cancellation token + /// + Task> GetServerTimeAsync(CancellationToken ct = default); + + /// + /// Get list of contract + /// + /// + /// The settlement asset. btc, usdt or usd + /// Cancellation token + /// + Task>> GetContractsAsync(string settlementAsset, CancellationToken ct = default); + + /// + /// Get a specific contract + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract name + /// Cancellation token + /// + Task> GetContractAsync(string settlementAsset, string contract, CancellationToken ct = default); + + /// + /// Get order book + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract name + /// Merge depth + /// Number of rows + /// Cancellation token + /// + Task> GetOrderBookAsync(string settlementAsset, string contract, int? mergeDepth = null, int? depth = null, CancellationToken ct = default); + + /// + /// Get recent trades + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract name + /// Max number of results + /// Offset + /// Specify the starting point for this list based on a previously retrieved id + /// Filter by start time + /// Filter by end time + /// Cancellation token + /// + Task>> GetTradesAsync( + string settlementAsset, + string contract, + int? limit = null, + int? offset = null, + string? lastId = null, + DateTime? startime = null, + DateTime? endTime = null, + CancellationToken ct = default); + + /// + /// Get kline/candlesticks + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract name + /// Interval + /// Max number of results + /// Filter by start time + /// Filter by end time + /// Cancellation token + /// + Task>> GetKlinesAsync( + string settlementAsset, + string contract, + KlineInterval interval, + int? limit = null, + DateTime? startime = null, + DateTime? endTime = null, + CancellationToken ct = default); + + /// + /// Get premium index kline/candlesticks + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract name + /// Interval + /// Max number of results + /// Filter by start time + /// Filter by end time + /// Cancellation token + /// + Task>> GetIndexKlinesAsync( + string settlementAsset, + string contract, + KlineInterval interval, + int? limit = null, + DateTime? startime = null, + DateTime? endTime = null, + CancellationToken ct = default); + + /// + /// Get ticker info + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Cancellation token + /// + Task>> GetTickersAsync( + string settlementAsset, + string? contract = null, + CancellationToken ct = default); + + /// + /// Get funding rate history + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Max number of results + /// Cancellation token + /// + Task>> GetFundingRateHistoryAsync( + string settlementAsset, + string contract, + int? limit = null, + CancellationToken ct = default); + + /// + /// Get insurance balance history + /// + /// + /// The settlement asset. btc, usdt or usd + /// Max number of results + /// Cancellation token + /// + Task>> GetInsuranceBalanceHistoryAsync( + string settlementAsset, + int? limit = null, + CancellationToken ct = default); + + /// + /// Get contract statistics + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Limit + /// Filter by start time + /// Cancellation token + /// + Task>> GetContractStatsAsync( + string settlementAsset, + string contract, + int? limit = null, + DateTime? startTime = null, + CancellationToken ct = default); + + /// + /// Get constituents for a contract + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Cancellation token + /// + Task> GetIndexConstituentsAsync( + string settlementAsset, + string contract, + CancellationToken ct = default); + + /// + /// Get liquidation history + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Filter by start time + /// Fitler by end time + /// Max number of results + /// Cancellation token + /// + Task>> GetLiquidationsAsync( + string settlementAsset, + string? contract = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// Get risk limit tiers + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Result offset + /// Max number of results + /// Cancellation token + /// + Task>> GetRiskLimitTiersAsync( + string settlementAsset, + string contract, + int? offset = null, + int? limit = null, + CancellationToken ct = default); + } +} diff --git a/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiTrading.cs b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiTrading.cs new file mode 100644 index 0000000..e422864 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoRestClientPerpetualFuturesApiTrading.cs @@ -0,0 +1,482 @@ +using CryptoExchange.Net.Objects; +using GateIo.Net.Objects.Models; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using GateIo.Net.Enums; +using System; + +namespace GateIo.Net.Interfaces.Clients.PerpetualFuturesApi +{ + /// + /// GateIo futures trading endpoints, placing and mananging orders. + /// + public interface IGateIoRestClientPerpetualFuturesApiTrading + { + /// + /// Get positions + /// + /// + /// The settlement asset. btc, usdt or usd + /// True to return only active positions, false to return all + /// Page number + /// Max amount of results + /// Cancellation token + /// + Task>> GetPositionsAsync(string settlementAsset, bool? holding = null, int? page = null, int? limit = null, CancellationToken ct = default); + + /// + /// Get single position + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Cancellation token + /// + Task> GetPositionAsync(string settlementAsset, string contract, CancellationToken ct = default); + + /// + /// Update position margin + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Change margin + /// Cancellation token + /// + Task> UpdatePositionMarginAsync(string settlementAsset, string contract, decimal change, CancellationToken ct = default); + + /// + /// Update position leverage + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// New leverage + /// Cross margin leverage + /// Cancellation token + /// + Task> UpdatePositionLeverageAsync(string settlementAsset, string contract, decimal leverage, decimal? crossLeverageLimit = null, CancellationToken ct = default); + + /// + /// Update position risk limit + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Risk limit + /// Cancellation token + /// + Task> UpdatePositionRiskLimitAsync(string settlementAsset, string contract, decimal riskLimit, CancellationToken ct = default); + + /// + /// Get positions in dual mode + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Cancellation token + /// + Task>> GetDualModePositionsAsync(string settlementAsset, string contract, CancellationToken ct = default); + + /// + /// Update position margin for dual position mode + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Change + /// Side + /// Cancellation token + /// + Task>> UpdateDualModePositionMarginAsync(string settlementAsset, string contract, decimal change, PositionMode mode, CancellationToken ct = default); + + /// + /// Update position leverage in dual position mode + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Leverage + /// Cross margin leverage + /// Cancellation token + /// + Task>> UpdateDualModePositionLeverageAsync(string settlementAsset, string contract, decimal leverage, decimal? crossLeverageLimit = null, CancellationToken ct = default); + + /// + /// Update position risk limit in dual position mode + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Risk limit + /// Cancellation token + /// + Task>> UpdateDualModePositionRiskLimitAsync(string settlementAsset, string contract, int riskLimit, CancellationToken ct = default); + + /// + /// Place a new order + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Order side + /// Order quantity in number of contracts. Use the `Multiplier` property of the ExchangeData.GetContractsAsync endpoint to see how much currency 1 size contract represents + /// Limit price + /// Close position flag, set as true to close the position, with quantity set to 0 + /// Set as true to be reduce-only order + /// Time in force + /// Iceberg quantity + /// Set side to close dual-mode position + /// Self-Trading Prevention action + /// User defined text + /// Cancellation token + /// + Task> PlaceOrderAsync( + string settlementAsset, + string contract, + OrderSide orderSide, + int quantity, + decimal? price = null, + bool? closePosition = null, + bool? reduceOnly = null, + TimeInForce? timeInForce = null, + int? icebergQuantity = null, + CloseSide? closeSide = null, + SelfTradePreventionMode? stpMode = null, + string? text = null, + CancellationToken ct = default); + + /// + /// Place multiple new orders + /// + /// + /// The settlement asset. btc, usdt or usd + /// Order info + /// Cancellation token + /// + Task>> PlaceMultipleOrderAsync( + string settlementAsset, + IEnumerable orders, + CancellationToken ct = default); + + /// + /// Get orders + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Filter by status + /// Max number of results + /// Offset + /// Filter by last order id of previous result + /// Cancellation token + /// + Task>> GetOrdersAsync( + string settlementAsset, + string? contract = null, + OrderStatus? status = null, + int? limit = null, + int? offset = null, + string? lastId = null, + CancellationToken ct = default); + + /// + /// Cancel orders after a certain period. Can be called at interval to act as a deadmans switch. Using TimeSpan.Zero cancels the countdown + /// + /// + /// The settlement asset. btc, usdt or usd + /// Timespan after which to cancel, TimeSpan.Zero to cancel the countdown + /// Filter by contract + /// Cancellation token + /// + Task> CancelOrdersAfterAsync(string settlementAsset, TimeSpan cancelAfter, string? contract = null, CancellationToken ct = default); + + /// + /// Cancel orders by id + /// + /// + /// The settlement asset. btc, usdt or usd + /// Ids of orders to cancel + /// Cancellation token + /// + Task>> CancelOrdersAsync(string settlementAsset, IEnumerable orderIds, CancellationToken ct = default); + + /// + /// Get orders with timestamp filtering + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Filter by status + /// Max number of results + /// Offset + /// Filter by start time + /// Filter by end time + /// Cancellation token + /// + Task>> GetOrdersByTimestampAsync( + string settlementAsset, + string? contract = null, + OrderStatus? status = null, + int? limit = null, + int? offset = null, + DateTime? startTime = null, + DateTime? endTime = null, + CancellationToken ct = default); + + /// + /// Cancel all open orders + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Filter by order side + /// Cancellation token + /// + Task>> CancelAllOrdersAsync(string settlementAsset, string contract, OrderSide? side = null, CancellationToken ct = default); + + /// + /// Get order by id + /// + /// + /// The settlement asset. btc, usdt or usd + /// Order id + /// Cancellation token + /// + Task> GetOrderAsync( + string settlementAsset, + long orderId, + CancellationToken ct = default); + + /// + /// Cancel an order + /// + /// + /// The settlement asset. btc, usdt or usd + /// Order id + /// Cancellation token + /// + Task> CancelOrderAsync( + string settlementAsset, + long orderId, + CancellationToken ct = default); + + /// + /// Edit an existing order + /// + /// + /// The settlement asset. btc, usdt or usd + /// Order id + /// New quantity + /// New price + /// Amend text + /// Cancellation token + /// + Task> EditOrderAsync( + string settlementAsset, + long orderId, + int? quantity = null, + decimal? price = null, + string? amendText = null, + CancellationToken ct = default); + + /// + /// Get user trades + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Filter by order id + /// Max number of results + /// Offset + /// Last id + /// Cancellation token + /// + Task>> GetUserTradesAsync( + string settlementAsset, + string? contract = null, + long? orderId = null, + int? limit = null, + int? offset = null, + long? lastId = null, + CancellationToken ct = default); + + /// + /// Get user trades by timestamp filter + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Filter by order id + /// Filter by start time + /// Filter by end time + /// Max number of results + /// Offset + /// Filter by role + /// Cancellation token + /// + Task>> GetUserTradesByTimestampAsync( + string settlementAsset, + string? contract = null, + long? orderId = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + int? offset = null, + Role? role = null, + CancellationToken ct = default); + + /// + /// Get position closing history + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Filter by start time + /// Filter by end time + /// Max number of results + /// Offset + /// Filter by role + /// Filter by side + /// Cancellation token + /// + Task>> GetPositionCloseHistoryAsync( + string settlementAsset, + string? contract = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + int? offset = null, + Role? role = null, + PositionSide? side = null, + CancellationToken ct = default); + + /// + /// Get user liquidation history + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Max number of results + /// Cancellation token + /// + Task>> GetLiquidationHistoryAsync( + string settlementAsset, + string? contract = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// Get user auto deleveraging history + /// + /// + /// The settlement asset. btc, usdt or usd + /// Filter by contract + /// Max number of results + /// Cancellation token + /// + Task>> GetAutoDeleveragingHistoryAsync( + string settlementAsset, + string? contract = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// Place a new trigger order + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Order side + /// Quantity + /// Trigger type + /// Trigger price + /// Order price + /// Set to true if trying to close the position + /// Set to true to create a reduce-only order + /// Set side to close dual-mode position + /// Price type + /// Trigger order type + /// Time in force + /// User text + /// Trigger expiration time + /// Cancellation token + /// + Task> PlaceTriggerOrderAsync( + string settlementAsset, + string contract, + OrderSide orderSide, + int quantity, + TriggerType triggerType, + decimal triggerPrice, + decimal? orderPrice = null, + bool? closePosition = null, + bool? reduceOnly = null, + CloseSide? closeSide = null, + PriceType? priceType = null, + TriggerOrderType? triggerOrderType = null, + TimeInForce? timeInForce = null, + string? text = null, + TimeSpan? expiration = null, + CancellationToken ct = default); + + /// + /// Get trigger orders + /// + /// + /// The settlement asset. btc, usdt or usd + /// True for open orders, false for closed + /// Filter by contract + /// Max number of results + /// Offset + /// Cancellation token + /// + Task>> GetTriggerOrdersAsync( + string settlementAsset, + bool open, + string? contract = null, + int? limit = null, + int? offset = null, + CancellationToken ct = default); + + /// + /// Cancel all trigger orders on a contract + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Cancellation token + /// + Task>> CancelTriggerOrdersAsync( + string settlementAsset, + string contract, + CancellationToken ct = default); + + /// + /// Get a trigger order by id + /// + /// + /// The settlement asset. btc, usdt or usd + /// Order id + /// Cancellation token + /// + Task> GetTriggerOrderAsync( + string settlementAsset, + long orderId, + CancellationToken ct = default); + + /// + /// Cancel a trigger order + /// + /// + /// The settlement asset. btc, usdt or usd + /// Order id + /// Cancellation token + /// + Task> CancelTriggerOrderAsync( + string settlementAsset, + long orderId, + CancellationToken ct = default); + } +} diff --git a/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoSocketClientPerpetualFuturesApi.cs b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoSocketClientPerpetualFuturesApi.cs new file mode 100644 index 0000000..e947868 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/PerpetualFuturesApi/IGateIoSocketClientPerpetualFuturesApi.cs @@ -0,0 +1,175 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Objects.Sockets; +using GateIo.Net.Objects.Models; +using System.Collections.Generic; +using GateIo.Net.Enums; + +namespace GateIo.Net.Interfaces.Clients.PerpetualFuturesApi +{ + /// + /// GateIo futures streams + /// + public interface IGateIoSocketClientPerpetualFuturesApi : ISocketApiClient, IDisposable + { + /// + /// Subscribe to public trade updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToTradeUpdatesAsync(string settlementAsset, string contract, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to ticker updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToTickerUpdatesAsync(string settlementAsset, string contract, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to best book price updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToBookTickerUpdatesAsync(string settlementAsset, string contract, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to order book updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Update interval in ms. 20, 100 or 1000 + /// Book depth. 5, 10, 20, 50 or 100. For the 20ms update interval only 20 depth is supported + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToOrderBookUpdatesAsync(string settlementAsset, string contract, int updateMs, int depth, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to kline updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// Contract + /// Kline interval + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToKlineUpdatesAsync(string settlementAsset, string contract, KlineInterval interval, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to user order updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToOrderUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to user trade updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToUserTradeUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to user liquidation updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToUserLiquidationUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to user auto deleverage updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToUserAutoDeleverageUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to user position close updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToPositionCloseUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to balance updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToBalanceUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to user reduce risk limit updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToReduceRiskLimitUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to position updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToPositionUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to trigger order updates + /// + /// + /// The settlement asset. btc, usdt or usd + /// User id + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToTriggerOrderUpdatesAsync(long userId, string settlementAsset, Action>> onMessage, CancellationToken ct = default); + } +} diff --git a/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApi.cs b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApi.cs new file mode 100644 index 0000000..e78cb10 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApi.cs @@ -0,0 +1,33 @@ +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Interfaces.CommonClients; +using System; + +namespace GateIo.Net.Interfaces.Clients.SpotApi +{ + /// + /// GateIo Spot API endpoints + /// + public interface IGateIoRestClientSpotApi : IRestApiClient, IDisposable + { + /// + /// Endpoints related to account settings, info or actions + /// + public IGateIoRestClientSpotApiAccount Account { get; } + + /// + /// Endpoints related to retrieving market and system data + /// + public IGateIoRestClientSpotApiExchangeData ExchangeData { get; } + + /// + /// Endpoints related to orders and trades + /// + public IGateIoRestClientSpotApiTrading Trading { get; } + + /// + /// Get the ISpotClient for this client. This is a common interface which allows for some basic operations without knowing any details of the exchange. + /// + /// + public ISpotClient CommonSpotClient { get; } + } +} diff --git a/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiAccount.cs b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiAccount.cs new file mode 100644 index 0000000..637eb3f --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiAccount.cs @@ -0,0 +1,685 @@ +using CryptoExchange.Net.Objects; +using GateIo.Net.Objects.Models; +using GateIo.Net.Enums; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace GateIo.Net.Interfaces.Clients.SpotApi +{ + /// + /// GateIo Spot account endpoints. Account endpoints include balance info, withdraw/deposit info and requesting and account settings + /// + public interface IGateIoRestClientSpotApiAccount + { + /// + /// Get spot account balances + /// + /// + /// Filter by asset + /// Cancelation token + /// + Task>> GetBalancesAsync(string? asset = null, CancellationToken ct = default); + + /// + /// Get a list of balance changes for the user + /// + /// + /// Filter by asset + /// Filter by start time + /// Filter by end time + /// Page number + /// Max amount of results + /// Filter by type + /// Cancelation token + /// + Task>> GetLedgerAsync(string? asset = null, DateTime? startTime = null, DateTime? endTime = null, int? page = null, int? limit = null, string? type = null, CancellationToken ct = default); + + /// + /// Withdraw + /// + /// + /// Asset to withdraw + /// Quantity to withdraw + /// Withdrawal address + /// Network to use + /// Memo + /// Client specified id + /// Cancellation token + /// + Task> WithdrawAsync(string asset, decimal quantity, string address, string network, string? memo = null, string? clientOrderId = null, CancellationToken ct = default); + + /// + /// Cancel a pending withdrawal + /// + /// + /// Id + /// Cancellation token + /// + Task> CancelWithdrawalAsync(string withdrawalId, CancellationToken ct = default); + + /// + /// Generate deposit address + /// + /// + /// Asset name + /// Cancellation token + /// + Task> GenerateDepositAddressAsync(string asset, CancellationToken ct = default); + + /// + /// Get withdrawal history + /// + /// + /// Filter by asset + /// Filter by start time + /// Filter by end time + /// Max number of results + /// Offset + /// Cancellation token + /// + Task>> GetWithdrawalsAsync( + string? asset = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + int? offset = null, + CancellationToken ct = default); + + /// + /// Get deposit history + /// + /// + /// Filter by asset + /// Filter by start time + /// Filter by end time + /// Max number of results + /// Offset + /// Cancellation token + /// + Task>> GetDepositsAsync( + string? asset = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? limit = null, + int? offset = null, + CancellationToken ct = default); + + /// + /// Transfer between accounts + /// + /// + /// Asset to transfer + /// From account + /// To account + /// Quantity to transfer + /// Margin symbol, required when from or to account is margin + /// Settle asset, required when from or to is futures + /// Cancellation token + /// + Task> TransferAsync( + string asset, + AccountType from, + AccountType to, + decimal quantity, + string? marginSymbol = null, + string? settleAsset = null, + CancellationToken ct = default); + + /// + /// Get account withdrawal status + /// + /// + /// Filter for a single asset + /// Cancellation token + /// + Task>> GetWithdrawStatusAsync( + string? asset = null, + CancellationToken ct = default); + + /// + /// Get saved addresses + /// + /// + /// The asset + /// Filter by network + /// Max number of results + /// Page number + /// Cancellation token + /// + Task>> GetSavedAddressAsync( + string asset, + string? network = null, + int? limit = null, + int? page = null, + CancellationToken ct = default); + + /// + /// Get trading fees + /// + /// + /// Specify a symbol to retrieve precise fee rate + /// Specify the settlement asset of the contract to get more accurate rate settings + /// Cancellation token + /// + Task> GetTradingFeeAsync( + string? symbol = null, + string? settleAsset = null, + CancellationToken ct = default); + + /// + /// Get account balance values + /// + /// + /// Asset unit used to calculate the balance amount + /// Cancellation token + /// + Task> GetAccountBalancesAsync( + string? valuationAsset = null, + CancellationToken ct = default); + + /// + /// Get small balances + /// + /// + /// Cancellation token + /// + Task>> GetSmallBalancesAsync( + CancellationToken ct = default); + + /// + /// Convert small balances + /// + /// + /// Assets to convert + /// Convert all + /// Cancellation token + /// + Task ConvertSmallBalancesAsync( + IEnumerable? assets = null, + bool? all = null, + CancellationToken ct = default); + + /// + /// Get small balances conversion history + /// + /// + /// Filter by asset + /// Page + /// Max number of results + /// Cancellation token + /// + Task>> GetSmallBalanceConversionsAsync( + string? asset = null, + int? page = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// Get unified account info + /// + /// + /// Filter by asset + /// Cancellation token + /// + Task> GetUnifiedAccountInfoAsync( + string? asset = null, + CancellationToken ct = default); + + /// + /// Get max borrowable amount + /// + /// + /// Asset + /// Cancellation token + /// + Task> GetUnifiedAccountBorrowableAsync( + string asset, + CancellationToken ct = default); + + /// + /// Get max transferable amount + /// + /// + /// Asset + /// Cancellation token + /// + Task> GetUnifiedAccountTransferableAsync( + string asset, + CancellationToken ct = default); + + /// + /// Borrow or repay + /// + /// + /// Asset name + /// Direction + /// Quantity + /// When set to 'true,' it overrides the 'amount,' allowing for direct full repayment. + /// User defined text + /// Cancellation token + /// + Task UnifiedAccountBorrowOrRepayAsync( + string asset, + BorrowDirection direction, + decimal quantity, + bool? repayAll = null, + string? text = null, + CancellationToken ct = default); + + /// + /// Get loans + /// + /// + /// Asset + /// Page + /// Limit + /// Loan type + /// Cancellation token + /// + Task>> GetUnifiedAccountLoansAsync( + string? asset = null, + int? page = null, + int? limit = null, + LoanType? type = null, + CancellationToken ct = default); + + /// + /// Get loan history + /// + /// + /// Asset + /// Direction + /// Page + /// Max number of results + /// Cancellation token + /// + Task>> GetUnifiedAccountLoanHistoryAsync( + string? asset = null, + BorrowDirection? direction = null, + int? page = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// Get interest history + /// + /// + /// Filter by asset + /// Page + /// Max number of results + /// Filter by type + /// Cancellation token + /// + Task>> GetUnifiedAccountInterestHistoryAsync( + string? asset = null, + int? page = null, + int? limit = null, + LoanType? type = null, + CancellationToken ct = default); + + /// + /// Get user risk unit details + /// + /// + /// Cancellation token + /// + Task> GetUnifiedAccountRiskUnitsAsync(CancellationToken ct = default); + + /// + /// Set unified account mode + /// + /// + /// New mode + /// USDT contract switch. This parameter is required when the mode is multi-currency margin mode + /// Spot hedging switch. This parameter is required when the mode is portfolio margin mode + /// When the mode is set to combined margin mode, will funds be used as margin + /// Cancellation token + /// + Task SetUnifiedAccountModeAsync(UnifiedAccountMode mode, bool? usdtFutures = null, bool? spotHedge = null, bool? useFunding = null, CancellationToken ct = default); + + /// + /// Get unified account mode + /// + /// + /// Cancellation token + /// + Task> GetUnifiedAccountModeAsync(CancellationToken ct = default); + + /// + /// Get estimated lending rates + /// + /// + /// Up to 10 assets + /// Cancellation token + /// + Task>> GetUnifiedAccountEstimatedLendingRatesAsync(IEnumerable assets, CancellationToken ct = default); + + /// + /// Get account and API key info + /// + /// + /// Cancellation token + /// + Task> GetAccountInfoAsync(CancellationToken ct = default); + + /// + /// Get margin account list + /// + /// + /// Filter by symbol + /// Cancellation token + /// + Task>> GetMarginAccountsAsync(string? symbol = null, CancellationToken ct = default); + + /// + /// Get margin accounts balance change history + /// + /// + /// Filter by asset + /// Filter by symbol + /// Filter by type + /// Filter by start time + /// Filter by end time + /// Page number + /// Max number of results + /// Cancellation token + /// + Task>> GetMarginBalanceHistoryAsync( + string? asset = null, + string? symbol = null, + string? type = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? page = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// Get margin funding accounts + /// + /// + /// Filter by asset + /// Cancellation token + /// + Task>> GetMarginFundingAccountsAsync( + string? asset = null, + CancellationToken ct = default); + + /// + /// Set auto repayment + /// + /// + /// True for auto repayment on, false for auto repayment off + /// Cancellation token + /// + Task> SetMarginAutoRepayAsync( + bool enabled, + CancellationToken ct = default); + + /// + /// Get auto repayment setting + /// + /// + /// Cancellation token + /// + Task> GetMarginAutoRepayAsync(CancellationToken ct = default); + + /// + /// Get max transferable quantity + /// + /// + /// Asset + /// Symbol + /// Cancellation token + /// + Task> GetMarginMaxTransferableAsync(string asset, string? symbol = null, CancellationToken ct = default); + + /// + /// Get cross margin accounts + /// + /// + /// Cancellation token + /// + Task> GetCrossMarginAccountsAsync(CancellationToken ct = default); + + /// + /// Get margin accounts balance change history + /// + /// + /// Filter by asset + /// Filter by type + /// Filter by start time + /// Filter by end time + /// Page number + /// Max number of results + /// Cancellation token + /// + Task>> GetCrossMarginBalanceHistoryAsync(string? asset = null, + string? type = null, + DateTime? startTime = null, + DateTime? endTime = null, + int? page = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// Create a cross margin borrow loan + /// + /// + /// Asset + /// Quantity + /// User defined text + /// Cancellation token + /// + Task> CreateCrossMarginLoanAsync( + string asset, + decimal quantity, + string? text = null, + CancellationToken ct = default); + + /// + /// List cross margin borrow history + /// + /// + /// Filter by asset + /// Max number of results + /// Offset + /// Reverse results + /// Cancellation token + /// + Task>> GetCrossMarginLoansAsync( + string? asset = null, + int? limit = null, + int? offset = null, + bool? reverse = null, + CancellationToken ct = default); + + /// + /// Get a cross margin loan by id + /// + /// + /// Loan id + /// Cancellation token + /// + Task> GetCrossMarginLoanAsync(string id, + CancellationToken ct = default); + + /// + /// Cross margin repayment + /// + /// + /// Asset + /// Quantity + /// Cancellation token + /// + Task>> CrossMarginRepayAsync( + string asset, + decimal quantity, + CancellationToken ct = default); + + /// + /// Get cross margin loan repayments + /// + /// + /// Filter by asset + /// Loan id + /// Max number of results + /// Offset + /// Reverse results + /// Cancellation token + /// + Task>> GetCrossMarginRepaymentsAsync( + string? asset = null, + string? loanId = null, + int? limit = null, + int? offset = null, + bool? reverse = null, + CancellationToken ct = default); + + /// + /// Get cross margin interest records + /// + /// + /// Filter by asset + /// Page + /// Max number of results + /// Filter by start time + /// Filter by end time + /// Cancellation token + /// + Task>> GetCrossMarginInterestHistoryAsync( + string? asset = null, + int? page = null, + int? limit = null, + DateTime? startTime = null, + DateTime? endTime = null, + CancellationToken ct = default); + + /// + /// Get max cross margin transferable + /// + /// + /// Asset + /// Cancellation token + /// + Task> GetCrossMarginMaxTransferableAsync(string asset, CancellationToken ct = default); + + /// + /// Get cross margin estimated interest rates + /// + /// + /// Assets, max 10 + /// Cancellation token + /// + Task>> GetCrossMarginEstimatedInterestRatesAsync(IEnumerable assets, CancellationToken ct = default); + + /// + /// Get max borrowable for a cross margin asset + /// + /// + /// Asset + /// Cancellation token + /// + Task> GetCrossMarginMaxBorrowableAsync(string asset, CancellationToken ct = default); + + /// + /// Get margin estimated interest rates + /// + /// + /// Assets, max 10 + /// Cancellation token + /// + Task>> GetMarginEstimatedInterestRatesAsync(IEnumerable assets, CancellationToken ct = default); + + /// + /// Borrow or repay margin loan + /// + /// + /// Asset + /// Symbol + /// Borrow or repay + /// Quantity + /// Repay all instead of specifying quantity + /// Cancellation token + /// + Task BorrowOrRepayAsync( + string asset, + string symbol, + BorrowDirection direction, + decimal quantity, + bool? repayAll = null, + CancellationToken ct = default); + + /// + /// List margin loans + /// + /// + /// Filter by asset + /// Filter by symbol + /// Page + /// Max number of results + /// Cancellation token + /// + Task>> GetMarginLoansAsync( + string? asset = null, + string? symbol = null, + int? page = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// List margin loan history + /// + /// + /// Filter by asset + /// Filter by symbol + /// Filter by direction + /// Page + /// Max number of results + /// Cancellation token + /// + Task>> GetMarginLoanHistoryAsync( + string? asset = null, + string? symbol = null, + BorrowDirection? direction = null, + int? page = null, + int? limit = null, + CancellationToken ct = default); + + /// + /// List margin interest records + /// + /// + /// Filter by asset + /// Filter by symbol + /// Page + /// Max number of results + /// Filter by start time + /// Filter by end time + /// Cancellation token + /// + Task>> GetMarginInterestHistoryAsync( + string? asset = null, + string? symbol = null, + int? page = null, + int? limit = null, + DateTime? startTime = null, + DateTime? endTime = null, + CancellationToken ct = default); + + /// + /// Get margin max borrowable quantity + /// + /// + /// Asset + /// Symbol + /// Cancellation token + /// + Task> GetMarginMaxBorrowableAsync( + string asset, + string symbol, + CancellationToken ct = default); + } +} diff --git a/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiExchangeData.cs b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiExchangeData.cs new file mode 100644 index 0000000..03265e3 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiExchangeData.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Objects; +using GateIo.Net.Objects.Models; +using GateIo.Net.Enums; + +namespace GateIo.Net.Interfaces.Clients.SpotApi +{ + /// + /// GateIo Spot exchange data endpoints. Exchange data includes market data (tickers, order books, etc) and system status. + /// + public interface IGateIoRestClientSpotApiExchangeData + { + /// + /// Get the current server time + /// + /// + /// Cancellation token + /// + Task> GetServerTimeAsync(CancellationToken ct = default); + + /// + /// Get a list of supported assets + /// + /// + /// Cancellation token + /// + Task>> GetAssetsAsync(CancellationToken ct = default); + + /// + /// Get info on a specific asset + /// + /// + /// Asset name + /// Cancellation token + /// + Task> GetAssetAsync(string asset, CancellationToken ct = default); + + /// + /// Get info on a specific symbol + /// + /// + /// Symbol name + /// Cancellation token + /// + Task> GetSymbolAsync(string symbol, CancellationToken ct = default); + + /// + /// Get a list of supported symbols + /// + /// + /// Cancellation token + /// + Task>> GetSymbolsAsync(CancellationToken ct = default); + + /// + /// Get tickers for all or a single symbol + /// + /// + /// Filter for a single symbol + /// Timezone, utc0, utc8 or all + /// Cancellation token + /// + Task>> GetTickersAsync(string? symbol = null, string? timezone = null, CancellationToken ct = default); + + /// + /// Get the orderbook for a symbol + /// + /// + /// Symbol name + /// Merge depth, defaults to 0 + /// Book depth to return, defaults to 10 + /// Cancellation token + /// + Task> GetOrderBookAsync(string symbol, int? mergeDepth = null, int? limit = null, CancellationToken ct = default); + + /// + /// Get market trades for a symbol + /// + /// + /// Symbol name + /// Max amount of results + /// Specify list staring point using the id of last record in previous list-query results + /// Whether the id of records to be retrieved should be less than the last_id specified. Default to false. + /// Filter by start time + /// Filter by end time + /// Page number + /// Cancellation token + /// + Task>> GetTradesAsync(string symbol, int? limit = null, string? lastId = null, bool? reverse = null, DateTime? startTime = null, DateTime? endTime = null, int? page = null, CancellationToken ct = default); + + /// + /// Get kline/candlesticks for a symbol + /// + /// + /// Symbol name + /// The kline interval + /// Filter by start time + /// Filter by end time + /// Number of results + /// Cancellation token + /// + Task>> GetKlinesAsync(string symbol, KlineInterval interval, DateTime? startTime = null, DateTime? endTime = null, int? limit = null, CancellationToken ct = default); + + /// + /// Get a list of networks for an asset + /// + /// + /// Asset + /// Cancellation token + /// + Task>> GetNetworksAsync(string asset, CancellationToken ct = default); + + /// + /// Get discount tiers + /// + /// + /// Cancellation token + /// + Task>> GetDiscountTiersAsync(CancellationToken ct = default); + + /// + /// Get loan margin tiers + /// + /// + /// Cancellation token + /// + Task>> GetLoanMarginTiersAsync(CancellationToken ct = default); + + /// + /// Get supported cross margin asset + /// + /// + /// Asset name + /// Cancellation token + /// + Task> GetCrossMarginAssetAsync(string asset, CancellationToken ct = default); + + /// + /// Get supported cross margin assets + /// + /// + /// Cancellation token + /// + Task>> GetCrossMarginAssetsAsync(CancellationToken ct = default); + + /// + /// Get lending symbols + /// + /// + /// Cancellation token + /// + Task>> GetLendingSymbolsAsync(CancellationToken ct = default); + + /// + /// Get lending symbol + /// + /// + /// Symbol + /// Cancellation token + /// + Task> GetLendingSymbolAsync(string symbol, CancellationToken ct = default); + } +} diff --git a/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiTrading.cs b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiTrading.cs new file mode 100644 index 0000000..ac8024c --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoRestClientSpotApiTrading.cs @@ -0,0 +1,302 @@ +using CryptoExchange.Net.Objects; +using GateIo.Net.Objects.Models; +using GateIo.Net.Enums; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using System; + +namespace GateIo.Net.Interfaces.Clients.SpotApi +{ + /// + /// GateIo Spot trading endpoints, placing and managing orders. + /// + public interface IGateIoRestClientSpotApiTrading + { + /// + /// Place a new order + /// + /// + /// Symbol + /// Order type + /// Order side + /// Order quantity in base asset. For Market Buy orders it's in quote asset + /// Price of the order for limit orders + /// Time in force + /// Iceberg quantity + /// Account type + /// Auto borrow enabled + /// Auto repay enabled + /// Self trade prevention mode + /// User defined info + /// Cancellation token + /// + Task> PlaceOrderAsync( + string symbol, + OrderSide side, + NewOrderType type, + decimal quantity, + decimal? price = null, + TimeInForce? timeInForce = null, + decimal? icebergQuantity = null, + SpotAccountType? accountType = null, + bool? autoBorrow = null, + bool? autoRepay = null, + SelfTradePreventionMode? selfTradePreventionMode = null, + string? text = null, + CancellationToken ct = default); + + /// + /// Get all open orders + /// + /// + /// Page + /// Max amount of results + /// Filter by account type + /// Cancellation token + /// + Task>> GetOpenOrdersAsync( + int? page = null, + int? limit = null, + SpotAccountType? accountType = null, + CancellationToken ct = default); + + /// + /// Get orders + /// + /// + /// Open orders (true) or closed orders (false) + /// Filter by symbol, required for open orders + /// Page + /// Max amount of results + /// Filter by account type + /// Filter by start time + /// Filter by end time + /// Filter by order side + /// Cancellation token + /// + Task>> GetOrdersAsync( + bool open, + string? symbol = null, + int? page = null, + int? limit = null, + SpotAccountType? accountType = null, + DateTime? startTime = null, + DateTime? endTime = null, + OrderSide? side = null, + CancellationToken ct = default); + + /// + /// Get a specific order by id + /// + /// + /// Symbol + /// Order id + /// Filter by account type + /// Cancellation token + /// + Task> GetOrderAsync( + string symbol, + long orderId, + SpotAccountType? accountType = null, + CancellationToken ct = default); + + /// + /// Cancel all orders on a specific symbol + /// + /// + /// The symbol + /// Only cancel orders on this side + /// Account type + /// Cancellation token + /// + Task>> CancelAllOrdersAsync( + string symbol, + OrderSide? side = null, + SpotAccountType? accountType = null, + CancellationToken ct = default); + + /// + /// Cancel multiple orders. Check the individual response models to see if cancelation succeeded + /// + /// + /// Orders to cancel + /// Cancellation token + /// + Task>> CancelOrdersAsync( + IEnumerable orders, + CancellationToken ct = default); + + /// + /// Edit an active order + /// + /// + /// Symbol + /// Order id + /// New price + /// New quantity + /// Custom info during amending order + /// Specify operation account. Default to spot ,portfolio and margin account if not specified. Set to cross_margin to operate against margin account. Portfolio margin account must set to cross_margin only + /// Cancellation token + /// + Task> EditOrderAsync( + string symbol, + long orderId, + decimal? price = null, + decimal? quantity = null, + string? amendText = null, + SpotAccountType? accountType = null, + CancellationToken ct = default); + + /// + /// Cancel an order + /// + /// + /// Symbol of the order + /// Order id + /// Account type + /// Cancellation token + /// + Task> CancelOrderAsync( + string symbol, + long orderId, + SpotAccountType? accountType = null, + CancellationToken ct = default); + + /// + /// Get a list of trades for the current user + /// + /// + /// Filter by symbol + /// Filter by order id + /// Max number of results + /// Page number + /// Filter by start time + /// Filter by end time + /// Filter by account type + /// Cancellation token + /// + Task>> GetUserTradesAsync( + string? symbol = null, + long? orderId = null, + int? limit = null, + int? page = null, + DateTime? startTime = null, + DateTime? endTime = null, + SpotAccountType? accountType = null, + CancellationToken ct = default); + + /// + /// Cancel orders after a certain period. Can be called at interval to act as a deadmans switch. Using TimeSpan.Zero cancels the countdown + /// + /// + /// Cancel after period + /// Only cancel on this symbol + /// Cancellation token + /// + Task> CancelOrdersAfterAsync( + TimeSpan cancelAfter, + string? symbol = null, + CancellationToken ct = default); + + /// + /// Place a new price triggered order + /// + /// + /// Symbol + /// Order side + /// Order type + /// Type of trigger + /// Trigger price + /// Time before trigger is cancelled + /// Order quantity + /// Order price + /// Time in force + /// Account type + /// User text + /// Cancellation token + /// + Task> PlaceTriggerOrderAsync( + string symbol, + OrderSide orderSide, + NewOrderType orderType, + TriggerType triggerType, + decimal triggerPrice, + TimeSpan expiration, + decimal quantity, + TriggerAccountType accountType, + TimeInForce timeInForce, + decimal? orderPrice = null, + string? text = null, + CancellationToken ct = default); + + /// + /// Get list of trigger orders + /// + /// + /// True for open orders, false for closed orders + /// Filter by symbol + /// Filter by account type + /// Max amount of results + /// Offset + /// Cancellation token + /// + Task>> GetTriggerOrdersAsync( + bool open, + string? symbol = null, + TriggerAccountType? accountType = null, + int? limit = null, + int? offset = null, + CancellationToken ct = default); + + /// + /// Cancel all trigger orders + /// + /// + /// Filter by symbol + /// Filter by account type + /// Cancellation token + /// + Task>> CancelAllTriggerOrdersAsync(string? symbol = null, TriggerAccountType? accountType = null, CancellationToken ct = default); + + /// + /// Get a trigger order by id + /// + /// + /// Id of the trigger order + /// Cancellation token + /// + Task> GetTriggerOrderAsync(long id, CancellationToken ct = default); + + /// + /// Cancel price trigger order + /// + /// + /// Id of the trigger order + /// Cancellation token + /// + Task> CancelTriggerOrderAsync(long id, CancellationToken ct = default); + + /// + /// Place multiple orders in a single call + /// + /// + /// Orders to place + /// Cancellation token + /// + Task>> PlaceMultipleOrderAsync( + IEnumerable orders, + CancellationToken ct = default); + + /// + /// Edit multiple orders in a single call + /// + /// + /// Orders to edit + /// Cancellation token + /// + Task>> EditMultipleOrderAsync( + IEnumerable orders, + CancellationToken ct = default); + } +} diff --git a/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoSocketClientSpotApi.cs b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoSocketClientSpotApi.cs new file mode 100644 index 0000000..efa2f24 --- /dev/null +++ b/GateIo.Net/Interfaces/Clients/SpotApi/IGateIoSocketClientSpotApi.cs @@ -0,0 +1,175 @@ +using CryptoExchange.Net.Objects; +using System; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Objects.Sockets; +using GateIo.Net.Objects.Models; +using GateIo.Net.Enums; +using System.Collections.Generic; + +namespace GateIo.Net.Interfaces.Clients.SpotApi +{ + /// + /// Gate.io spot streams + /// + public interface IGateIoSocketClientSpotApi : ISocketApiClient, IDisposable + { + /// + /// Subscribe to public trade updates + /// + /// + /// Symbol + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToTradeUpdatesAsync(string symbol, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to public trade updates + /// + /// + /// Symbols + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToTradeUpdatesAsync(IEnumerable symbols, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to ticker updates + /// + /// + /// Symbol + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToTickerUpdatesAsync(string symbol, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to ticker updates + /// + /// + /// Symbols + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToTickerUpdatesAsync(IEnumerable symbols, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to kline/candlestick updates + /// + /// + /// Symbol + /// Kline interval + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToKlineUpdatesAsync(string symbol, KlineInterval interval, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to book ticker updates + /// + /// + /// Symbol + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToBookTickerUpdatesAsync(string symbol, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to book ticker updates + /// + /// + /// Symbols + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToBookTickerUpdatesAsync(IEnumerable symbols, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to order book change events. Only the changed entries will be pushed + /// + /// + /// Symbol + /// Update speed in milliseconds. 100 or 1000 + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToOrderBookUpdatesAsync(string symbol, int? updateMs, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to partial full order book updates, Full order book will be pushed for a limited depth + /// + /// + /// Symbol + /// Depth of the book. 5, 10, 20, 50 or 100 + /// Update speed in milliseconds. 100 or 1000 + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToPartialOrderBookUpdatesAsync(string symbol, int depth, int? updateMs, Action> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to order updates + /// + /// + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToOrderUpdatesAsync(Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to user trade updates + /// + /// + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToUserTradeUpdatesAsync(Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to balance updates + /// + /// + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToBalanceUpdatesAsync(Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to margin balance updates + /// + /// + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToMarginBalanceUpdatesAsync(Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to funding balance updates + /// + /// + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToFundingBalanceUpdatesAsync(Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to cross margin balance updates + /// + /// + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToCrossMarginBalanceUpdatesAsync(Action>> onMessage, CancellationToken ct = default); + + /// + /// Subscribe to trigger order updates + /// + /// + /// The event handler for the received data + /// Cancellation token for closing this subscription + /// A stream subscription. This stream subscription can be used to be notified when the socket is disconnected/reconnected + Task> SubscribeToTriggerOrderUpdatesAsync(Action> onMessage, CancellationToken ct = default); + } +} diff --git a/GateIo.Net/Interfaces/IGateIoOrderBookFactory.cs b/GateIo.Net/Interfaces/IGateIoOrderBookFactory.cs new file mode 100644 index 0000000..5280173 --- /dev/null +++ b/GateIo.Net/Interfaces/IGateIoOrderBookFactory.cs @@ -0,0 +1,46 @@ +using CryptoExchange.Net.Interfaces; +using System; +using GateIo.Net.Objects.Options; + +namespace GateIo.Net.Interfaces +{ + /// + /// Gate.io local order book factory + /// + public interface IGateIoOrderBookFactory + { + /// + /// Spot order book factory methods + /// + public IOrderBookFactory Spot { get; } + /// + /// BTC perpetual futures order book factory methods + /// + public IOrderBookFactory PerpetualFuturesBtc { get; } + /// + /// USD perpetual futures order book factory methods + /// + public IOrderBookFactory PerpetualFuturesUsd { get; } + /// + /// USDT perpetual futures order book factory methods + /// + public IOrderBookFactory PerpetualFuturesUsdt { get; } + + /// + /// Create a new perpetual futures local order book instance + /// + /// + /// + /// + /// + ISymbolOrderBook CreatePerpetualFutures(string settlementAsset, string symbol, Action? options = null); + + /// + /// Create a new spot local order book instance + /// + /// + /// + /// + ISymbolOrderBook CreateSpot(string symbol, Action? options = null); + } +} \ No newline at end of file diff --git a/GateIo.Net/Objects/GateIoApiAddresses.cs b/GateIo.Net/Objects/GateIoApiAddresses.cs new file mode 100644 index 0000000..0e9a545 --- /dev/null +++ b/GateIo.Net/Objects/GateIoApiAddresses.cs @@ -0,0 +1,31 @@ +namespace GateIo.Net.Objects +{ + /// + /// Api addresses + /// + public class GateIoApiAddresses + { + /// + /// The address used by the GateIoRestClient for the API + /// + public string RestClientAddress { get; set; } = ""; + /// + /// The address used by the GateIoSocketClient for the spot websocket API + /// + public string SpotSocketClientAddress { get; set; } = ""; + /// + /// The address used by the GateIoSocketClient for the futures websocket API + /// + public string FuturesSocketClientAddress { get; set; } = ""; + + /// + /// The default addresses to connect to the Gate.io API + /// + public static GateIoApiAddresses Default = new GateIoApiAddresses + { + RestClientAddress = "https://api.gateio.ws", + SpotSocketClientAddress = "wss://api.gateio.ws", + FuturesSocketClientAddress = "wss://fx-ws.gateio.ws" + }; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoAccountInfo.cs b/GateIo.Net/Objects/Models/GateIoAccountInfo.cs new file mode 100644 index 0000000..84c2e61 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoAccountInfo.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Account info + /// + public record GateIoAccountInfo + { + /// + /// User id + /// + [JsonPropertyName("user_id")] + public long UserId { get; set; } + /// + /// IP whitelist for this API Key + /// + [JsonPropertyName("ip_whitelist")] + public IEnumerable IpWhitelist { get; set; } = Array.Empty(); + /// + /// Symbol whitelist for this API Key + /// + [JsonPropertyName("currency_pairs")] + public IEnumerable SymbolWhitelist { get; set; } = Array.Empty(); + /// + /// VIP tier + /// + [JsonPropertyName("tier")] + public int VipLevel { get; set; } + + /// + /// Key info + /// + [JsonPropertyName("key")] + public GateIoKeyInfo KeyInfo { get; set; } = null!; + } + + /// + /// Key info + /// + public record GateIoKeyInfo + { + /// + /// Mode: 1 - classic account 2 - portfolio margin account + /// + [JsonPropertyName("mode")] + public int Mode { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoAccountValuation.cs b/GateIo.Net/Objects/Models/GateIoAccountValuation.cs new file mode 100644 index 0000000..e020c65 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoAccountValuation.cs @@ -0,0 +1,100 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Account valuation + /// + public record GateIoAccountValuation + { + /// + /// Details + /// + [JsonPropertyName("details")] + public GateIoAccountValues Details { get; set; } = null!; + /// + /// Total value + /// + [JsonPropertyName("total")] + public GateIoAccountValue Total { get; set; } = null!; + } + + /// + /// Account values + /// + public record GateIoAccountValues + { + /// + /// Cross margin value + /// + [JsonPropertyName("cross_margin")] + public GateIoAccountValue CrossMargin { get; set; } = null!; + /// + /// Spot value + /// + [JsonPropertyName("spot")] + public GateIoAccountValue Spot { get; set; } = null!; + /// + /// Finance value + /// + [JsonPropertyName("finance")] + public GateIoAccountValue Finance { get; set; } = null!; + /// + /// Margin value + /// + [JsonPropertyName("margin")] + public GateIoAccountValue Margin { get; set; } = null!; + /// + /// Quant value + /// + [JsonPropertyName("quant")] + public GateIoAccountValue Quant { get; set; } = null!; + /// + /// Futures value + /// + [JsonPropertyName("futures")] + public GateIoAccountValue Futures { get; set; } = null!; + /// + /// Delivery value + /// + [JsonPropertyName("delivery")] + public GateIoAccountValue Delivery { get; set; } = null!; + /// + /// Warrant value + /// + [JsonPropertyName("warrant")] + public GateIoAccountValue Warrant { get; set; } = null!; + /// + /// CBBC value + /// + [JsonPropertyName("cbbc")] + public GateIoAccountValue Cbbc { get; set; } = null!; + } + + /// + /// Account value + /// + public record GateIoAccountValue + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Total account balance + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Unrelealised profit and loss + /// + [JsonPropertyName("unrealised_pnl")] + public decimal? UnrealisedPnl { get; set; } + /// + /// Borrowed + /// + [JsonPropertyName("borrowed")] + public decimal? Borrowed { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoAsset.cs b/GateIo.Net/Objects/Models/GateIoAsset.cs new file mode 100644 index 0000000..42aeeec --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoAsset.cs @@ -0,0 +1,51 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Asset info + /// + public record GateIoAsset + { + /// + /// Asset name + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Whether the asset is delisted + /// + [JsonPropertyName("delisted")] + public bool Delisted { get; set; } + /// + /// Whether the asset has withdrawals disabled + /// + [JsonPropertyName("withdraw_disabled")] + public bool WithdrawDisabled { get; set; } + /// + /// Whether the asset has withdrawals delayed + /// + [JsonPropertyName("withdraw_delayed")] + public bool WithdrawDelayed { get; set; } + /// + /// Whether the asset has deposits disabled + /// + [JsonPropertyName("deposit_disabled")] + public bool DepositDisabled { get; set; } + /// + /// Whether the asset has trading disabled + /// + [JsonPropertyName("trade_disabled")] + public bool TradeDisabled { get; set; } + /// + /// Fixed fee rate + /// + [JsonPropertyName("fixed_rate")] + public decimal? FixedFeeRate { get; set; } + /// + /// Network of the asset + /// + [JsonPropertyName("chain")] + public string? Network { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoBalance.cs b/GateIo.Net/Objects/Models/GateIoBalance.cs new file mode 100644 index 0000000..ff1d0d9 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoBalance.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Balance info + /// + public record GateIoBalance + { + /// + /// Asset name + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Available quantity + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Locked quantity + /// + [JsonPropertyName("locked")] + public decimal Locked { get; set; } + /// + /// Update id + /// + [JsonPropertyName("update_id")] + public long UpdateId { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoBalanceUpdate.cs b/GateIo.Net/Objects/Models/GateIoBalanceUpdate.cs new file mode 100644 index 0000000..0c47618 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoBalanceUpdate.cs @@ -0,0 +1,58 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Balance update + /// + public record GateIoBalanceUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("timestamp_ms")] + public DateTime Timestamp { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public string UserId { get; set; } = string.Empty; + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Change + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Total + /// + [JsonPropertyName("total")] + public decimal Total { get; set; } + /// + /// Available + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Frozen + /// + [JsonPropertyName("freeze")] + public decimal Frozen { get; set; } + /// + /// Change in frozen quantity + /// + [JsonPropertyName("freeze_change")] + public decimal FrozenChange { get; set; } + /// + /// Change type + /// + [JsonPropertyName("change_type")] + public BalanceChangeType ChangeType { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoBatchCancelRequest.cs b/GateIo.Net/Objects/Models/GateIoBatchCancelRequest.cs new file mode 100644 index 0000000..61e558d --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoBatchCancelRequest.cs @@ -0,0 +1,28 @@ +using CryptoExchange.Net.Converters.SystemTextJson; +using GateIo.Net.Enums; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Batch order cancellation request + /// + public record GateIoBatchCancelRequest + { + /// + /// The symbol the order is on + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// The order id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// The type of account + /// + [JsonPropertyName("account"), JsonConverter(typeof(EnumConverter)), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public SpotAccountType? AccountType { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoBatchEditRequest.cs b/GateIo.Net/Objects/Models/GateIoBatchEditRequest.cs new file mode 100644 index 0000000..a14d2a5 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoBatchEditRequest.cs @@ -0,0 +1,44 @@ +using CryptoExchange.Net.Converters.SystemTextJson; +using GateIo.Net.Enums; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Batch order edit request + /// + public record GateIoBatchEditRequest + { + /// + /// The order id + /// + [JsonPropertyName("order_id")] + public string OrderId { get; set; } = string.Empty; + /// + /// The symbol the order is on + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// amend text + /// + [JsonPropertyName("amend_text")] + public string AmendText { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("amount"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public decimal? Quantity { get; set; } + /// + /// Order price + /// + [JsonPropertyName("price"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public decimal? Price { get; set; } + /// + /// The type of account + /// + [JsonPropertyName("account"), JsonConverter(typeof(EnumConverter))] + public SpotAccountType AccountType { get; set; } + + } +} diff --git a/GateIo.Net/Objects/Models/GateIoBatchPlaceRequest.cs b/GateIo.Net/Objects/Models/GateIoBatchPlaceRequest.cs new file mode 100644 index 0000000..2208355 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoBatchPlaceRequest.cs @@ -0,0 +1,73 @@ +using CryptoExchange.Net.Converters.SystemTextJson; +using GateIo.Net.Enums; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Batch order placement request + /// + public record GateIoBatchPlaceRequest + { + /// + /// The symbol the order is on + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Text + /// + [JsonPropertyName("text")] + public string Text { get; set; } = string.Empty; + /// + /// Order type + /// + [JsonPropertyName("type"), JsonConverter(typeof(EnumConverter))] + public NewOrderType Type { get; set; } + /// + /// Order side + /// + [JsonPropertyName("side"), JsonConverter(typeof(EnumConverter))] + public OrderSide Side { get; set; } + /// + /// Time in force + /// + [JsonPropertyName("time_in_force"), JsonConverter(typeof(EnumConverter))] + public TimeInForce TimeInForce { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Order price + /// + [JsonPropertyName("price"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public decimal? Price { get; set; } + /// + /// Iceberg quantity + /// + [JsonPropertyName("iceberg"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public decimal? IcebergQuantity { get; set; } + /// + /// The type of account + /// + [JsonPropertyName("account"), JsonConverter(typeof(EnumConverter))] + public SpotAccountType AccountType { get; set; } + /// + /// Auto borrow + /// + [JsonPropertyName("auto_borrow"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? AutoBorrow { get; set; } + /// + /// Auto repay + /// + [JsonPropertyName("auto_repay"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? AutoRepay { get; set; } + /// + /// STP mode + /// + [JsonPropertyName("stp_act"), JsonConverter(typeof(EnumConverter)), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public SelfTradePreventionMode? SelfTradePreventionMode { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoBookTickerUpdate.cs b/GateIo.Net/Objects/Models/GateIoBookTickerUpdate.cs new file mode 100644 index 0000000..fca47af --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoBookTickerUpdate.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Book ticker update + /// + public record GateIoBookTickerUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("t")] + public DateTime Timestamp { get; set; } + /// + /// Update id + /// + [JsonPropertyName("u")] + public long UpdateId { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("s")] + public string Symbol { get; set; } = string.Empty; + /// + /// Best bid price + /// + [JsonPropertyName("b")] + public decimal BestBidPrice { get; set; } + /// + /// Best bid quantity + /// + [JsonPropertyName("B")] + public decimal BestBidQuantity { get; set; } + /// + /// Best ask price + /// + [JsonPropertyName("a")] + public decimal BestAskPrice { get; set; } + /// + /// Best ask quantity + /// + [JsonPropertyName("A")] + public decimal BestAskQuantity { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCancelAfter.cs b/GateIo.Net/Objects/Models/GateIoCancelAfter.cs new file mode 100644 index 0000000..14832dd --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCancelAfter.cs @@ -0,0 +1,17 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cancel after results + /// + public record GateIoCancelAfter + { + /// + /// Time the cancellation is triggered + /// + [JsonPropertyName("triggerTime")] + public DateTime TriggerTime { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCancelResult.cs b/GateIo.Net/Objects/Models/GateIoCancelResult.cs new file mode 100644 index 0000000..a05d34e --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCancelResult.cs @@ -0,0 +1,43 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cancel result info + /// + public record GateIoCancelResult + { + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Order id + /// + [JsonPropertyName("id")] + public string OrderId { get; set; } = string.Empty; + /// + /// Order info + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + + /// + /// Whether the operation succeeded + /// + [JsonPropertyName("succeeded")] + public bool Succeeded { get; set; } + + /// + /// Error code when operation failed + /// + [JsonPropertyName("label")] + public string? ErrorCode { get; set; } + /// + /// Error message when operation failed + /// + [JsonPropertyName("message")] + public string? ErrorMessage { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCrossMarginAccount.cs b/GateIo.Net/Objects/Models/GateIoCrossMarginAccount.cs new file mode 100644 index 0000000..1128584 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCrossMarginAccount.cs @@ -0,0 +1,144 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cross margin account + /// + public record GateIoCrossMarginAccount + { + /// + /// User id + /// + [JsonPropertyName("user_id")] + public long UserId { get; set; } + /// + /// Locked + /// + [JsonPropertyName("locked")] + public bool Locked { get; set; } + /// + /// Total value in USD + /// + [JsonPropertyName("total")] + public decimal Total { get; set; } + /// + /// Borrowed value in USD + /// + [JsonPropertyName("borrowed")] + public decimal Borrowed { get; set; } + /// + /// Interest value in USD + /// + [JsonPropertyName("interest")] + public decimal Interest { get; set; } + /// + /// Risk rate + /// + [JsonPropertyName("risk")] + public decimal Risk { get; set; } + /// + /// Total initial margin + /// + [JsonPropertyName("total_initial_margin")] + public decimal TotalInitialMargin { get; set; } + /// + /// Total margin balance + /// + [JsonPropertyName("total_margin_balance")] + public decimal TotalMarginBalance { get; set; } + /// + /// Total maintenance margin + /// + [JsonPropertyName("total_maintenance_margin")] + public decimal TotalMaintenanceMargin { get; set; } + /// + /// Total initial margin rate + /// + [JsonPropertyName("total_initial_margin_rate")] + public decimal TotalInitialMarginRate { get; set; } + /// + /// Total maintenance margin rate + /// + [JsonPropertyName("total_maintenance_margin_rate")] + public decimal TotalMaintenanceMarginRate { get; set; } + /// + /// Total available margin + /// + [JsonPropertyName("total_available_margin")] + public decimal TotalAvailableMargin { get; set; } + /// + /// Total amount of the portfolio margin account + /// + [JsonPropertyName("portfolio_margin_total")] + public decimal PortfolioMarginTotal { get; set; } + /// + /// Total liabilities of the portfolio margin account + /// + [JsonPropertyName("portfolio_margin_total_liab")] + public decimal PortfolioMarginTotalLiabilities { get; set; } + /// + /// Total equity of the portfolio margin account + /// + [JsonPropertyName("portfolio_margin_total_equity")] + public decimal PortfolioMarginTotalEquity { get; set; } + /// + /// Balances + /// + [JsonPropertyName("balances")] + public Dictionary Balances { get; set; } = new Dictionary(); + } + + /// + /// Unified account balance + /// + public record GateIoCrossMarginAccountBalance + { + /// + /// Available quantity + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Frozen quantity + /// + [JsonPropertyName("freeze")] + public decimal Frozen { get; set; } + /// + /// Borrowed quantity + /// + [JsonPropertyName("borrowed")] + public decimal Borrowed { get; set; } + /// + /// Interest + /// + [JsonPropertyName("interest")] + public decimal Interest { get; set; } + /// + /// Negative liabilities + /// + [JsonPropertyName("negative_liab")] + public decimal NegativeLiabilities { get; set; } + /// + /// Borrowing to open futures positions + /// + [JsonPropertyName("futures_pos_liab")] + public decimal FuturesPositionLiabilities { get; set; } + /// + /// Equity + /// + [JsonPropertyName("equity")] + public decimal Equity { get; set; } + /// + /// Total frozen + /// + [JsonPropertyName("total_freeze")] + public decimal TotalFrozen { get; set; } + /// + /// Total liabilities + /// + [JsonPropertyName("total_liab")] + public decimal TotalLiabilities { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCrossMarginAsset.cs b/GateIo.Net/Objects/Models/GateIoCrossMarginAsset.cs new file mode 100644 index 0000000..df897c4 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCrossMarginAsset.cs @@ -0,0 +1,61 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cross margin asset + /// + public record GateIoCrossMarginAsset + { + /// + /// Asset name + /// + [JsonPropertyName("name")] + public string Asset { get; set; } = string.Empty; + /// + /// Minimum lending rate + /// + [JsonPropertyName("rate")] + public decimal MinLendingRate { get; set; } + /// + /// Asset precision + /// + [JsonPropertyName("prec")] + public decimal AssetPrecision { get; set; } + /// + /// Discount + /// + [JsonPropertyName("discount")] + public decimal Discount { get; set; } + /// + /// Min borrow quantity + /// + [JsonPropertyName("min_borrow_amount")] + public decimal MinBorrowQuantity { get; set; } + /// + /// Max borrow quantity per user in USDT + /// + [JsonPropertyName("user_max_borrow_amount")] + public decimal UserMaxBorrowQuantity { get; set; } + /// + /// Max borrow quantity total in USDT + /// + [JsonPropertyName("total_max_borrow_amount")] + public decimal TotalMaxBorrowQuantity { get; set; } + /// + /// Price + /// + [JsonPropertyName("price")] + public decimal Price { get; set; } + /// + /// Asset is loanable + /// + [JsonPropertyName("loanable")] + public bool Loanable { get; set; } + /// + /// Status + /// + [JsonPropertyName("status")] + public bool Enabled { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCrossMarginBalanceChange.cs b/GateIo.Net/Objects/Models/GateIoCrossMarginBalanceChange.cs new file mode 100644 index 0000000..99adf96 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCrossMarginBalanceChange.cs @@ -0,0 +1,42 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cross margin account balance change + /// + public record GateIoCrossMarginBalanceChange + { + /// + /// Id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Timestamp + /// + [JsonPropertyName("time")] + public DateTime Timestamp { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Change + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Balance after + /// + [JsonPropertyName("balance")] + public decimal Balance { get; set; } + /// + /// Type of change + /// + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCrossMarginBalanceUpdate.cs b/GateIo.Net/Objects/Models/GateIoCrossMarginBalanceUpdate.cs new file mode 100644 index 0000000..9432e51 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCrossMarginBalanceUpdate.cs @@ -0,0 +1,58 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cross Margin Balance update + /// + public record GateIoCrossMarginBalanceUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("timestamp_ms")] + public DateTime Timestamp { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public string UserId { get; set; } = string.Empty; + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Change + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Total + /// + [JsonPropertyName("total")] + public decimal Total { get; set; } + /// + /// Available + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Frozen + /// + [JsonPropertyName("freeze")] + public decimal Frozen { get; set; } + /// + /// Change in frozen quantity + /// + [JsonPropertyName("freeze_change")] + public decimal FrozenChange { get; set; } + /// + /// Change type + /// + [JsonPropertyName("change_type")] + public BalanceChangeType ChangeType { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCrossMarginBorrowLoan.cs b/GateIo.Net/Objects/Models/GateIoCrossMarginBorrowLoan.cs new file mode 100644 index 0000000..729cd2e --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCrossMarginBorrowLoan.cs @@ -0,0 +1,64 @@ +using System; +using System.Text.Json.Serialization; +using CryptoExchange.Net.Converters.SystemTextJson; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cross margin borrow loan + /// + public record GateIoCrossMarginBorrowLoan + { + /// + /// Id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Update time + /// + [JsonPropertyName("update_time")] + public DateTime? UpdateTime { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Status + /// + [JsonPropertyName("status"), JsonConverter(typeof(EnumConverter))] + public BorrowStatus Status { get; set; } + /// + /// Repaid + /// + [JsonPropertyName("repaid")] + public decimal Repaid { get; set; } + /// + /// Repaid interest + /// + [JsonPropertyName("repaid_interest")] + public decimal RepaidInterest { get; set; } + /// + /// Unpaid interest + /// + [JsonPropertyName("unpaid_interest")] + public decimal UnpaidInterest { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCrossMarginInterest.cs b/GateIo.Net/Objects/Models/GateIoCrossMarginInterest.cs new file mode 100644 index 0000000..90849ff --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCrossMarginInterest.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cross margin interest + /// + public record GateIoCrossMarginInterest + { + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Actual rate + /// + [JsonPropertyName("actual_rate")] + public decimal ActualRate { get; set; } + /// + /// Interest + /// + [JsonPropertyName("interest")] + public decimal Interest { get; set; } + /// + /// Type + /// + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; + /// + /// Success + /// + [JsonPropertyName("status")] + public bool Success { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoCrossMarginRepayment.cs b/GateIo.Net/Objects/Models/GateIoCrossMarginRepayment.cs new file mode 100644 index 0000000..c04744f --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoCrossMarginRepayment.cs @@ -0,0 +1,48 @@ +using System; +using System.Text.Json.Serialization; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cross margin repayment + /// + public record GateIoCrossMarginRepayment + { + /// + /// Id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Loan id + /// + [JsonPropertyName("loan_id")] + public string LoanId { get; set; } = string.Empty; + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Principal + /// + [JsonPropertyName("principal")] + public decimal Principal { get; set; } + /// + /// Interest + /// + [JsonPropertyName("interest")] + public decimal Interest { get; set; } + /// + /// Repayment type + /// + [JsonPropertyName("repayment_type")] + public RepayType Type { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoDeposit.cs b/GateIo.Net/Objects/Models/GateIoDeposit.cs new file mode 100644 index 0000000..f75671d --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoDeposit.cs @@ -0,0 +1,63 @@ +using System; +using System.Text.Json.Serialization; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Deposit info + /// + public record GateIoDeposit + { + /// + /// Withdrawal id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Client specified id + /// + [JsonPropertyName("withdraw_order_id")] + public string? ClientOrderId { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Address + /// + [JsonPropertyName("address")] + public string Address { get; set; } = string.Empty; + /// + /// Network + /// + [JsonPropertyName("chain")] + public string Network { get; set; } = string.Empty; + /// + /// Memo + /// + [JsonPropertyName("memo")] + public string? Memo { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Timestamp + /// + [JsonPropertyName("timestamp")] + public DateTime Timestamp { get; set; } + /// + /// Transaction id + /// + [JsonPropertyName("txid")] + public string TransactionId { get; set; } = string.Empty; + /// + /// Withdrawal status + /// + [JsonPropertyName("status")] + public WithdrawalStatus Status { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoDepositAddress.cs b/GateIo.Net/Objects/Models/GateIoDepositAddress.cs new file mode 100644 index 0000000..30454de --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoDepositAddress.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Deposit address info + /// + public record GateIoDepositAddress + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Address + /// + [JsonPropertyName("address")] + public string Address { get; set; } = string.Empty; + /// + /// Min deposit quantity + /// + [JsonPropertyName("min_deposit_amount")] + public decimal? MinDepositQuantity { get; set; } + /// + /// Min number of confirmations + /// + [JsonPropertyName("min_confirms")] + public int? MinConfirmations { get; set; } + /// + /// Multichain addresses + /// + [JsonPropertyName("multichain_addresses")] + public IEnumerable MultichainAddress { get; set; } = Array.Empty(); + } + + /// + /// Multichain address info + /// + public record GateIoMultiChainDepositAddress + { + /// + /// Network + /// + [JsonPropertyName("chain")] + public string Network { get; set; } = string.Empty; + /// + /// Address + /// + [JsonPropertyName("address")] + public string Address { get; set; } = string.Empty; + /// + /// Notes that some currencies required(e.g., Tag, Memo) when depositing + /// + [JsonPropertyName("payment_id")] + public string PaymentId { get; set; } = string.Empty; + /// + /// Note type; tag or memo + /// + [JsonPropertyName("payment_name")] + public string PaymentName { get; set; } = string.Empty; + /// + /// Failed + /// + [JsonPropertyName("obtain_failed")] + public bool Failed { get; set; } + + /// + /// Min number of confirmations + /// + [JsonPropertyName("min_confirms")] + public int MinConfirmations { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoDiscountTier.cs b/GateIo.Net/Objects/Models/GateIoDiscountTier.cs new file mode 100644 index 0000000..c1c2d34 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoDiscountTier.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Discount tier + /// + public record GateIoDiscountTier + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + + /// + /// Tiers + /// + [JsonPropertyName("discount_tiers")] + public IEnumerable Tiers { get; set; } = Array.Empty(); + } + + /// + /// Discount tier item + /// + public record GateIoDiscountTierEntry + { + /// + /// Tier + /// + [JsonPropertyName("tier")] + public string Tier { get; set; } = string.Empty; + /// + /// Discount. 1 means full price + /// + [JsonPropertyName("discount")] + public decimal Discount { get; set; } + /// + /// Lower volume limit + /// + [JsonPropertyName("lower_limit")] + public decimal LowerLimit { get; set; } + /// + /// Upper volume limit. Note that this is a string as '+' is returned for the most upper tier + /// + [JsonPropertyName("upper_limit")] + public string UpperLimit { get; set; } = string.Empty; + + } +} diff --git a/GateIo.Net/Objects/Models/GateIoFeeRate.cs b/GateIo.Net/Objects/Models/GateIoFeeRate.cs new file mode 100644 index 0000000..c0d5e71 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoFeeRate.cs @@ -0,0 +1,71 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Fee rate info + /// + public record GateIoFeeRate + { + /// + /// User id + /// + [JsonPropertyName("user_id")] + public long UserId { get; set; } + /// + /// Taker fee + /// + [JsonPropertyName("taker_fee")] + public decimal TakerFee { get; set; } + /// + /// Maker fee + /// + [JsonPropertyName("maker_fee")] + public decimal MakerFee { get; set; } + /// + /// Futures maker fee + /// + [JsonPropertyName("futures_taker_fee")] + public decimal FuturesTakerFee { get; set; } + /// + /// Futures taker fee + /// + [JsonPropertyName("futures_maker_fee")] + public decimal FuturesMakerFee { get; set; } + /// + /// If GT deduction is enabled + /// + [JsonPropertyName("gt_discount")] + public bool GtDiscount { get; set; } + /// + /// Maker fee rate if using GT deduction. It will be 0 if GT deduction is disabled + /// + [JsonPropertyName("gt_taker_fee")] + public decimal GtTakerFee { get; set; } + /// + /// Taker fee rate if using GT deduction. It will be 0 if GT deduction is disabled + /// + [JsonPropertyName("gt_maker_fee")] + public decimal GtMakerFee { get; set; } + /// + /// Loan fee rate of margin lending + /// + [JsonPropertyName("loan_fee")] + public decimal LoanFee { get; set; } + /// + /// Delivery futures trading taker fee + /// + [JsonPropertyName("delivery_taker_fee")] + public decimal DeliveryTakerFee { get; set; } + /// + /// Delivery futures trading maker fee + /// + [JsonPropertyName("delivery_maker_fee")] + public decimal DeliveryMakerFee { get; set; } + /// + /// Deduction types for rates, 1 - GT deduction, 2 - Point card deduction, 3 - VIP rates + /// + [JsonPropertyName("debit_fee")] + public int DebitFee { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoFundingBalanceUpdate.cs b/GateIo.Net/Objects/Models/GateIoFundingBalanceUpdate.cs new file mode 100644 index 0000000..49866cf --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoFundingBalanceUpdate.cs @@ -0,0 +1,42 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Funding Balance update + /// + public record GateIoFundingBalanceUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("timestamp_ms")] + public DateTime Timestamp { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public string UserId { get; set; } = string.Empty; + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Change + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Frozen + /// + [JsonPropertyName("freeze")] + public decimal Frozen { get; set; } + /// + /// Lent + /// + [JsonPropertyName("lent")] + public decimal Lent { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoFuturesAccount.cs b/GateIo.Net/Objects/Models/GateIoFuturesAccount.cs new file mode 100644 index 0000000..2fcfcfd --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoFuturesAccount.cs @@ -0,0 +1,128 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Futures account + /// + public record GateIoFuturesAccount + { + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// The balance after the user's accumulated deposit, withdraw, profit and loss + /// + [JsonPropertyName("total")] + public decimal Total { get; set; } + /// + /// Unrealized profit and loss + /// + [JsonPropertyName("unrealised_pnl")] + public decimal UnrealisedPnl { get; set; } + /// + /// Position margin + /// + [JsonPropertyName("position_margin")] + public decimal PositionMargin { get; set; } + /// + /// Order margin + /// + [JsonPropertyName("order_margin")] + public decimal OrderMargin { get; set; } + /// + /// Available + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Point quantity + /// + [JsonPropertyName("point")] + public decimal PointQuantity { get; set; } + /// + /// Perpetual Contract Bonus + /// + [JsonPropertyName("bonus")] + public decimal Bonus { get; set; } + /// + /// Dual mode + /// + [JsonPropertyName("in_dual_mode")] + public bool DualMode { get; set; } + /// + /// Classic account margin mode + /// + [JsonPropertyName("enable_evolved_classic")] + public bool ClassicMarginMode { get; set; } + /// + /// Total history + /// + [JsonPropertyName("history")] + public GateIoFuturesAccountHistory Totals { get; set; } = null!; + } + + /// + /// Account history + /// + public record GateIoFuturesAccountHistory + { + /// + /// Total amount of deposit and withdraw + /// + [JsonPropertyName("dnw")] + public decimal DepositWithdrawalQuantity { get; set; } + /// + /// Total Profit and loss + /// + [JsonPropertyName("pnl")] + public decimal TotalProfitAndLoss { get; set; } + /// + /// Total amount of fee paid + /// + [JsonPropertyName("fee")] + public decimal TotalFee { get; set; } + /// + /// Total amount of referrer rebates + /// + [JsonPropertyName("refr")] + public decimal TotalReferenceRebate { get; set; } + /// + /// Total amount of funding costs + /// + [JsonPropertyName("fund")] + public decimal TotalFundingCosts { get; set; } + /// + /// Total amount of point deposit and withdraw + /// + [JsonPropertyName("point_dnw")] + public decimal TotalPointDepositWithdrawal { get; set; } + /// + /// Total amount of point fee + /// + [JsonPropertyName("point_fee")] + public decimal TotalPointFee { get; set; } + /// + /// Total amountof point referrer rebates + /// + [JsonPropertyName("point_refr")] + public decimal TotalPointReferenceRebate { get; set; } + /// + /// Total amount of perpetual contract bonus transfer + /// + [JsonPropertyName("bonus_dnw")] + public decimal TotalBonusDepositAndWithdrawal { get; set; } + /// + /// Total amount of perpetual contract bonus deduction + /// + [JsonPropertyName("bonus_offset")] + public decimal TotalBonusDeduction { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoFuturesCancelResult.cs b/GateIo.Net/Objects/Models/GateIoFuturesCancelResult.cs new file mode 100644 index 0000000..ce7cb6a --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoFuturesCancelResult.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Cancel result + /// + public record GateIoFuturesCancelResult + { + /// + /// User id + /// + [JsonPropertyName("user_id")] + public long UserId { get; set; } + /// + /// Order id + /// + [JsonPropertyName("id")] + public long OrderId { get; set; } + /// + /// Succeeded + /// + [JsonPropertyName("succeeded")] + public bool Success { get; set; } + /// + /// Message + /// + [JsonPropertyName("message")] + public string? Message { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoId.cs b/GateIo.Net/Objects/Models/GateIoId.cs new file mode 100644 index 0000000..a8a2dc7 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoId.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Id reference + /// + public record GateIoId + { + /// + /// Id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoInterestRecord.cs b/GateIo.Net/Objects/Models/GateIoInterestRecord.cs new file mode 100644 index 0000000..9f3c438 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoInterestRecord.cs @@ -0,0 +1,48 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Interest record + /// + public record GateIoInterestRecord + { + /// + /// Status + /// + [JsonPropertyName("status")] + public bool Success { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Actual interest rate + /// + [JsonPropertyName("actual_rate")] + public decimal ActualRate { get; set; } + /// + /// Interest + /// + [JsonPropertyName("interest")] + public decimal Interest { get; set; } + /// + /// Loan type + /// + [JsonPropertyName("type")] + public LoanType Type { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime Timestamp { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoKline.cs b/GateIo.Net/Objects/Models/GateIoKline.cs new file mode 100644 index 0000000..cc9ac9e --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoKline.cs @@ -0,0 +1,55 @@ +using CryptoExchange.Net.Converters; +using CryptoExchange.Net.Converters.SystemTextJson; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Kline/candlestick info + /// + [JsonConverter(typeof(ArrayConverter))] + public record GateIoKline + { + /// + /// Open timestamp + /// + [ArrayProperty(0), JsonConverter(typeof(DateTimeConverter))] + public DateTime OpenTime { get; set; } + /// + /// Quote volume + /// + [ArrayProperty(1)] + public decimal QuoteVolume { get; set; } + /// + /// Close price + /// + [ArrayProperty(2)] + public decimal ClosePrice { get; set; } + /// + /// High price + /// + [ArrayProperty(3)] + public decimal HighPrice { get; set; } + /// + /// Low price + /// + [ArrayProperty(4)] + public decimal LowPrice { get; set; } + /// + /// Open price + /// + [ArrayProperty(5)] + public decimal OpenPrice { get; set; } + /// + /// Base volume + /// + [ArrayProperty(6)] + public decimal BaseVolume { get; set; } + /// + /// Is the kline final/closed + /// + [ArrayProperty(7)] + public bool Final { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoKlineUpdate.cs b/GateIo.Net/Objects/Models/GateIoKlineUpdate.cs new file mode 100644 index 0000000..dd7d4b6 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoKlineUpdate.cs @@ -0,0 +1,67 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Kline update + /// + public record GateIoKlineUpdate + { + /// + /// Open time + /// + [JsonPropertyName("t")] + public DateTime OpenTime { get; set; } + /// + /// Volume in quote asset + /// + [JsonPropertyName("v")] + public decimal QuoteVolume { get; set; } + /// + /// Close price + /// + [JsonPropertyName("c")] + public decimal ClosePrice { get; set; } + /// + /// High price + /// + [JsonPropertyName("h")] + public decimal HighPrice { get; set; } + /// + /// Low price + /// + [JsonPropertyName("l")] + public decimal LowPrice { get; set; } + /// + /// Open price + /// + [JsonPropertyName("o")] + public decimal OpenPrice { get; set; } + /// + /// Stream + /// + [JsonPropertyName("n")] + public string Stream { get; set; } = string.Empty; + /// + /// Open price + /// + [JsonPropertyName("a")] + public decimal BaseVolume { get; set; } + /// + /// Is final update for this timeframe + /// + [JsonPropertyName("w")] + public bool Final { get; set; } + + /// + /// The symbol + /// + public string Symbol => Stream.Substring(Stream.IndexOf('_') + 1); + + /// + /// The interval + /// + public string Interval => Stream.Substring(0, Stream.IndexOf('_')); + } +} diff --git a/GateIo.Net/Objects/Models/GateIoLedgerEntry.cs b/GateIo.Net/Objects/Models/GateIoLedgerEntry.cs new file mode 100644 index 0000000..be39383 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoLedgerEntry.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Account ledger entry + /// + public record GateIoLedgerEntry + { + /// + /// Entry id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Timestamp + /// + [JsonPropertyName("time")] + public DateTime Timestamp { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Change quantity + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Balance after change + /// + [JsonPropertyName("balance")] + public decimal Balance { get; set; } + /// + /// Change type + /// + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; + /// + /// Additional info + /// + [JsonPropertyName("text")] + public string? Text { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoLendingSymbol.cs b/GateIo.Net/Objects/Models/GateIoLendingSymbol.cs new file mode 100644 index 0000000..d84ee28 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoLendingSymbol.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Lending symbol + /// + public record GateIoLendingSymbol + { + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Min borrow quantity in the base asset + /// + [JsonPropertyName("base_min_borrow_amount")] + public decimal BaseAssetMinBorrowQuantity { get; set; } + /// + /// Min borrow quantity in the quote asset + /// + [JsonPropertyName("quote_min_borrow_amount")] + public decimal QuoteAssetMinBorrowQuantity { get; set; } + /// + /// Leverage + /// + [JsonPropertyName("leverage")] + public decimal Leverage { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoLiquidation.cs b/GateIo.Net/Objects/Models/GateIoLiquidation.cs new file mode 100644 index 0000000..1c5cdb9 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoLiquidation.cs @@ -0,0 +1,42 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Liquidation + /// + public record GateIoLiquidation + { + /// + /// Timestamp + /// + [JsonPropertyName("time")] + public DateTime Timestamp { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("size")] + public decimal Quantity { get; set; } + /// + /// Order price + /// + [JsonPropertyName("order_price")] + public decimal OrderPrice { get; set; } + /// + /// Fill price + /// + [JsonPropertyName("fill_price")] + public decimal FillPrice { get; set; } + /// + /// Left + /// + [JsonPropertyName("left")] + public decimal Left { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoLoan.cs b/GateIo.Net/Objects/Models/GateIoLoan.cs new file mode 100644 index 0000000..d89950c --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoLoan.cs @@ -0,0 +1,43 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Loan info + /// + public record GateIoLoan + { + /// + /// Asset name + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Loan type + /// + [JsonPropertyName("type")] + public LoanType Type { get; set; } + /// + /// Last update time + /// + [JsonPropertyName("change_time")] + public DateTime? UpdateTime { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoLoanMarginTier.cs b/GateIo.Net/Objects/Models/GateIoLoanMarginTier.cs new file mode 100644 index 0000000..a467847 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoLoanMarginTier.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Margin tier + /// + public record GateIoLoanMarginTier + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Tiers + /// + [JsonPropertyName("margin_tiers")] + public IEnumerable MarginTiers { get; set; } = Array.Empty(); + } + + /// + /// Margin tier entry + /// + public record GateIoLoanMarginTierEntry + { + /// + /// Tier + /// + [JsonPropertyName("tier")] + public string Tier { get; set; } = string.Empty; + /// + /// Margin rate + /// + [JsonPropertyName("margin_rate")] + public decimal MarginRate { get; set; } + /// + /// Lower volume limit + /// + [JsonPropertyName("lower_limit")] + public decimal LowerLimit { get; set; } + /// + /// Upper volume limit + /// + [JsonPropertyName("upper_limit")] + public decimal? UpperLimit { get; set; } + + } +} diff --git a/GateIo.Net/Objects/Models/GateIoLoanRecord.cs b/GateIo.Net/Objects/Models/GateIoLoanRecord.cs new file mode 100644 index 0000000..96428ab --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoLoanRecord.cs @@ -0,0 +1,53 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Loan history record + /// + public record GateIoLoanRecord + { + /// + /// Id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// Type + /// + [JsonPropertyName("type")] + public BorrowDirection Type { get; set; } + /// + /// Margin mode + /// + [JsonPropertyName("margin_mode")] + public string Mode { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Repay type + /// + [JsonPropertyName("repayment_type")] + public RepayType RepaymentType { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoMarginAccount.cs b/GateIo.Net/Objects/Models/GateIoMarginAccount.cs new file mode 100644 index 0000000..19c3ca2 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoMarginAccount.cs @@ -0,0 +1,68 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Margin account + /// + public record GateIoMarginAccount + { + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Account is locked + /// + [JsonPropertyName("locked")] + public bool Locked { get; set; } + /// + /// Current risk rate + /// + [JsonPropertyName("risk")] + public decimal RiskRate { get; set; } + /// + /// Base asset + /// + [JsonPropertyName("base")] + public GateIoMarginAccountAsset Base { get; set; } = null!; + /// + /// Quote asset + /// + [JsonPropertyName("quote")] + public GateIoMarginAccountAsset Quote { get; set; } = null!; + } + + /// + /// Margin account asset + /// + public record GateIoMarginAccountAsset + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Available quantity + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Locked quantity + /// + [JsonPropertyName("locked")] + public decimal Locked { get; set; } + /// + /// Borrowed quantity + /// + [JsonPropertyName("borrowed")] + public decimal Borrowed { get; set; } + /// + /// Interest quantity + /// + [JsonPropertyName("interest")] + public decimal Interest { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoMarginAutoRepayStatus.cs b/GateIo.Net/Objects/Models/GateIoMarginAutoRepayStatus.cs new file mode 100644 index 0000000..a33b028 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoMarginAutoRepayStatus.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Repay status + /// + public record GateIoMarginAutoRepayStatus + { + /// + /// Status, on or off + /// + [JsonPropertyName("status")] + public string Status { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoMarginBalanceChange.cs b/GateIo.Net/Objects/Models/GateIoMarginBalanceChange.cs new file mode 100644 index 0000000..0845f1e --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoMarginBalanceChange.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Margin account balance change + /// + public record GateIoMarginBalanceChange + { + /// + /// Id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Timestamp + /// + [JsonPropertyName("time_ms")] + public DateTime Timestamp { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Change + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Balance after + /// + [JsonPropertyName("balance")] + public decimal Balance { get; set; } + /// + /// Type of change + /// + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoMarginBalanceUpdate.cs b/GateIo.Net/Objects/Models/GateIoMarginBalanceUpdate.cs new file mode 100644 index 0000000..9f668ca --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoMarginBalanceUpdate.cs @@ -0,0 +1,57 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Margin Balance update + /// + public record GateIoMarginBalanceUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("timestamp_ms")] + public DateTime Timestamp { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public string UserId { get; set; } = string.Empty; + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Change + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Available + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Frozen + /// + [JsonPropertyName("freeze")] + public decimal Frozen { get; set; } + /// + /// Borrowed + /// + [JsonPropertyName("borrowed")] + public decimal Borrowed { get; set; } + /// + /// Interest + /// + [JsonPropertyName("interest")] + public decimal Interest { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoMarginFundingAccount.cs b/GateIo.Net/Objects/Models/GateIoMarginFundingAccount.cs new file mode 100644 index 0000000..4104438 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoMarginFundingAccount.cs @@ -0,0 +1,36 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Funding account + /// + public record GateIoMarginFundingAccount + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Available + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Locked + /// + [JsonPropertyName("locked")] + public decimal Locked { get; set; } + /// + /// Lent + /// + [JsonPropertyName("lent")] + public decimal Lent { get; set; } + /// + /// Total lent + /// + [JsonPropertyName("total_lent")] + public decimal TotalLent { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoMarginLoanRecord.cs b/GateIo.Net/Objects/Models/GateIoMarginLoanRecord.cs new file mode 100644 index 0000000..e022cfa --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoMarginLoanRecord.cs @@ -0,0 +1,38 @@ +using System; +using System.Text.Json.Serialization; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Loan record + /// + public record GateIoMarginLoanRecord + { + /// + /// Type + /// + [JsonPropertyName("type")] + public BorrowDirection Type { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoMarginMaxBorrowable.cs b/GateIo.Net/Objects/Models/GateIoMarginMaxBorrowable.cs new file mode 100644 index 0000000..a365dad --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoMarginMaxBorrowable.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Max borrowable info + /// + public record GateIoMarginMaxBorrowable + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string? Symbol { get; set; } + /// + /// Max borrowable + /// + [JsonPropertyName("borrowable")] + public decimal MaxBorrowable { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoMarginMaxTransferable.cs b/GateIo.Net/Objects/Models/GateIoMarginMaxTransferable.cs new file mode 100644 index 0000000..d50d3fb --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoMarginMaxTransferable.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Transferable + /// + public record GateIoMarginMaxTransferable + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string? Symbol { get; set; } + /// + /// Max transferable + /// + [JsonPropertyName("amount")] + public decimal MaxTransferable { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoNetwork.cs b/GateIo.Net/Objects/Models/GateIoNetwork.cs new file mode 100644 index 0000000..dd11628 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoNetwork.cs @@ -0,0 +1,56 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Asset network info + /// + public record GateIoNetwork + { + /// + /// Network name + /// + [JsonPropertyName("chain")] + public string Network { get; set; } = string.Empty; + /// + /// Network name in Chinese + /// + [JsonPropertyName("name_cn")] + public string NetworkCn { get; set; } = string.Empty; + /// + /// Network name in English + /// + [JsonPropertyName("name_en")] + public string NetworkEn { get; set; } = string.Empty; + /// + /// Contract address + /// + [JsonPropertyName("contract_address")] + public string? ContractAddress { get; set; } + /// + /// Withdrawal precision + /// + [JsonPropertyName("decimal")] + public int? WithdrawalPrecision { get; set; } + /// + /// Is network disabled + /// + [JsonPropertyName("is_disabled")] + public bool IsDisabled { get; set; } + /// + /// Is deposit disabled + /// + [JsonPropertyName("is_deposit_disabled")] + public bool IsDepositDisabled { get; set; } + /// + /// Is withdrawal disabled + /// + [JsonPropertyName("is_withdraw_disabled")] + public bool IsWithdrawalDisabled { get; set; } + /// + /// Is tag + /// + [JsonPropertyName("is_tag")] + public bool IsTag { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoOrder.cs b/GateIo.Net/Objects/Models/GateIoOrder.cs new file mode 100644 index 0000000..1a8077a --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoOrder.cs @@ -0,0 +1,196 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Order info + /// + public record GateIoOrder + { + /// + /// Order id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// User defined text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Custom data that the user remarked when amending the order + /// + [JsonPropertyName("amend_text")] + public string? AmendText { get; set; } + /// + /// Creation time + /// + [JsonPropertyName("create_time_ms")] + public DateTime CreateTime { get; set; } + /// + /// Last update time + /// + [JsonPropertyName("update_time_ms")] + public DateTime? UpdateTime { get; set; } + /// + /// Order status + /// + [JsonPropertyName("status")] + public OrderStatus Status { get; set; } + /// + /// Order type + /// + [JsonPropertyName("type")] + public OrderType Type { get; set; } + /// + /// Order side + /// + [JsonPropertyName("side")] + public OrderSide Side { get; set; } + /// + /// Account type + /// + [JsonPropertyName("account")] + public SpotAccountType AccountType { get; set; } + /// + /// Time in force + /// + [JsonPropertyName("time_in_force")] + public TimeInForce TimeInForce { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Quantity remaining + /// + [JsonPropertyName("left")] + public decimal QuantityRemaining { get; set; } + /// + /// Quantity filled + /// + [JsonPropertyName("filled_amount")] + public decimal QuantityFilled { get; set; } + /// + /// Quote quantity filled + /// + [JsonPropertyName("filled_total")] + public decimal QuoteQuantityFilled { get; set; } + /// + /// Order price + /// + [JsonPropertyName("price")] + public decimal? Price { get; set; } + /// + /// Average fill price + /// + [JsonPropertyName("avg_deal_price")] + public decimal? AveragePrice { get; set; } + /// + /// Fee paid + /// + [JsonPropertyName("fee")] + public decimal? Fee { get; set; } + /// + /// Fee asset + /// + [JsonPropertyName("fee_currency")] + public string? FeeAsset { get; set; } + /// + /// Points used to deduct fee + /// + [JsonPropertyName("point_fee")] + public decimal? PointFee { get; set; } + /// + /// GT used to deduct fee + /// + [JsonPropertyName("gt_fee")] + public decimal? GtFee { get; set; } + /// + /// GT used to deduct maker fee + /// + [JsonPropertyName("gt_maker_fee")] + public decimal? GtMakerFee { get; set; } + /// + /// GT used to deduct taker fee + /// + [JsonPropertyName("gt_taker_fee")] + public decimal? GtTakerFee { get; set; } + /// + /// Whether GT fee discount is used + /// + [JsonPropertyName("gt_discount")] + public bool? GtDiscount { get; set; } + /// + /// Rebated fee + /// + [JsonPropertyName("rebated_fee")] + public decimal? RebatedFee { get; set; } + /// + /// Rebated fee currency unit + /// + [JsonPropertyName("rebated_fee_currency")] + public string? RebateFeeAsset { get; set; } + /// + /// Orders between users in the same SelfTradePreventionId group are not allowed to be self-traded + /// + [JsonPropertyName("stp_id")] + public int? SelfTradePreventionId { get; set; } + /// + /// Self trade prevention mode + /// + [JsonPropertyName("stp_act")] + public SelfTradePreventionMode SelfTradePreventionMode { get; set; } + /// + /// Order finish type + /// + [JsonPropertyName("finish_as")] + public OrderFinishType? FinishType { get; set; } + /// + /// Iceberg quantity + /// + [JsonPropertyName("iceberg")] + public decimal? IcebergQuantity { get; set; } + /// + /// Auto borrow + /// + [JsonPropertyName("auto_borrow")] + public bool? AutoBorrow { get; set; } + /// + /// Auto repay + /// + [JsonPropertyName("auto_repay")] + public bool? AutoRepay { get; set; } + } + + /// + /// Order operation result + /// + public record GateIoOrderOperation : GateIoOrder + { + /// + /// Whether the operation succeeded + /// + [JsonPropertyName("succeeded")] + public bool Succeeded { get; set; } + + /// + /// Error code when operation failed + /// + [JsonPropertyName("label")] + public string? ErrorCode { get; set; } + /// + /// Error message when operation failed + /// + [JsonPropertyName("message")] + public string? ErrorMessage { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoOrderBook.cs b/GateIo.Net/Objects/Models/GateIoOrderBook.cs new file mode 100644 index 0000000..492e8e0 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoOrderBook.cs @@ -0,0 +1,63 @@ +using CryptoExchange.Net.Converters; +using CryptoExchange.Net.Converters.SystemTextJson; +using CryptoExchange.Net.Interfaces; +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Order book + /// + public record GateIoOrderBook + { + /// + /// Book sync id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + + /// + /// The timestamp the book was requested + /// + [JsonPropertyName("current")] + public DateTime Timestamp { get; set; } + + /// + /// The timestamp the book was last updated + /// + [JsonPropertyName("update")] + public DateTime UpdateTime { get; set; } + + /// + /// Asks list + /// + [JsonPropertyName("asks")] + public IEnumerable Asks { get; set; } = Array.Empty(); + + /// + /// Bids list + /// + [JsonPropertyName("bids")] + public IEnumerable Bids { get; set; } = Array.Empty(); + } + + /// + /// Order book entry + /// + [JsonConverter(typeof(ArrayConverter))] + public record GateIoOrderBookEntry : ISymbolOrderBookEntry + { + /// + /// Price + /// + [ArrayProperty(0)] + public decimal Price { get; set; } + /// + /// Quantity + /// + [ArrayProperty(1)] + public decimal Quantity { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoOrderBookUpdate.cs b/GateIo.Net/Objects/Models/GateIoOrderBookUpdate.cs new file mode 100644 index 0000000..3261312 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoOrderBookUpdate.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Order book update + /// + public record GateIoOrderBookUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("t")] + public DateTime Timestamp { get; set; } + /// + /// Update id + /// + [JsonPropertyName("u")] + public long LastUpdateId { get; set; } + /// + /// Update id + /// + [JsonPropertyName("U")] + public long FirstUpdateId { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("s")] + public string Symbol { get; set; } = string.Empty; + /// + /// Event + /// + [JsonPropertyName("e")] + public string Event { get; set; } = string.Empty; + /// + /// Updated bids + /// + [JsonPropertyName("b")] + public IEnumerable Bids { get; set; } = Array.Empty(); + /// + /// Updated asks + /// + [JsonPropertyName("a")] + public IEnumerable Asks { get; set; } = Array.Empty(); + } +} diff --git a/GateIo.Net/Objects/Models/GateIoOrderUpdate.cs b/GateIo.Net/Objects/Models/GateIoOrderUpdate.cs new file mode 100644 index 0000000..c495a6f --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoOrderUpdate.cs @@ -0,0 +1,158 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Order update + /// + public record GateIoOrderUpdate + { + /// + /// Order id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time_ms")] + public DateTime CreateTime { get; set; } + /// + /// Update time + /// + [JsonPropertyName("update_time_ms")] + public DateTime? UpdateTime { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Order type + /// + [JsonPropertyName("type")] + public OrderType OrderType { get; set; } + /// + /// Order side + /// + [JsonPropertyName("side")] + public OrderSide Side { get; set; } + /// + /// Account type + /// + [JsonPropertyName("account")] + public SpotAccountType AccountType { get; set; } + /// + /// Order quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Order price + /// + [JsonPropertyName("price")] + public decimal? Price { get; set; } + /// + /// Time in force + /// + [JsonPropertyName("time_in_force")] + public TimeInForce TimeInForce { get; set; } + /// + /// Quantity still open + /// + [JsonPropertyName("left")] + public decimal QuantityRemaining { get; set; } + /// + /// Quote asset quantity filled + /// + [JsonPropertyName("filled_total")] + public decimal QuoteQuantityFilled { get; set; } + /// + /// Average fill price + /// + [JsonPropertyName("avg_deal_price")] + public decimal? AveragePrice { get; set; } + /// + /// Fee paid + /// + [JsonPropertyName("fee")] + public decimal Fee { get; set; } + /// + /// Asset the fee is in + /// + [JsonPropertyName("fee_currency")] + public string FeeAsset { get; set; } = string.Empty; + /// + /// Points used to deduct fee + /// + [JsonPropertyName("point_fee")] + public decimal? PointFee { get; set; } + /// + /// GT used to deduct fee + /// + [JsonPropertyName("gt_fee")] + public decimal? GtFee { get; set; } + /// + /// Whether GT fee discount is used + /// + [JsonPropertyName("gt_discount")] + public bool? GtDiscount { get; set; } + /// + /// Rebated fee + /// + [JsonPropertyName("rebated_fee")] + public bool? RebatedFee { get; set; } + /// + /// Rebated fee currency unit + /// + [JsonPropertyName("rebated_fee_currency")] + public string? RebateFeeAsset { get; set; } + /// + /// Orders between users in the same SelfTradePreventionId group are not allowed to be self-traded + /// + [JsonPropertyName("stp_id")] + public int? SelfTradePreventionId { get; set; } + /// + /// Self trade prevention mode + /// + [JsonPropertyName("stp_act")] + public SelfTradePreventionMode SelfTradePreventionMode { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public long? UserId { get; set; } + /// + /// Trigger event + /// + [JsonPropertyName("event")] + public string Event { get; set; } = string.Empty; + /// + /// Order finish type + /// + [JsonPropertyName("finish_as")] + public OrderFinishType? FinishType { get; set; } + /// + /// Custom data that the user remarked when amending the order + /// + [JsonPropertyName("amend_text")] + public string? AmendText { get; set; } + /// + /// Auto borrow + /// + [JsonPropertyName("auto_borrow")] + public bool? AutoBorrow { get; set; } + /// + /// Auto repay + /// + [JsonPropertyName("auto_repay")] + public bool? AutoRepay { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPartialOrderBookUpdate.cs b/GateIo.Net/Objects/Models/GateIoPartialOrderBookUpdate.cs new file mode 100644 index 0000000..2fb72a9 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPartialOrderBookUpdate.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Order book update + /// + public record GateIoPartialOrderBookUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("t")] + public DateTime Timestamp { get; set; } + /// + /// Update id + /// + [JsonPropertyName("lastUpdateId")] + public long LastUpdateId { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("s")] + public string Symbol { get; set; } = string.Empty; + /// + /// Updated bids + /// + [JsonPropertyName("bids")] + public IEnumerable Bids { get; set; } = Array.Empty(); + /// + /// Updated asks + /// + [JsonPropertyName("asks")] + public IEnumerable Asks { get; set; } = Array.Empty(); + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpAutoDeleverage.cs b/GateIo.Net/Objects/Models/GateIoPerpAutoDeleverage.cs new file mode 100644 index 0000000..1875ee7 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpAutoDeleverage.cs @@ -0,0 +1,62 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Auto deleverage + /// + public record GateIoPerpAutoDeleverage + { + /// + /// Timestamp + /// + [JsonPropertyName("time")] + public DateTime Timestamp { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Entry price + /// + [JsonPropertyName("entry_price")] + public decimal EntryPrice { get; set; } + /// + /// Order price + /// + [JsonPropertyName("fill_price")] + public decimal FillPrice { get; set; } + /// + /// Order id + /// + [JsonPropertyName("order_id")] + public long OrderId { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Cross leverage limit + /// + [JsonPropertyName("cross_leverage_limit")] + public decimal CrossLeverageLimit { get; set; } + /// + /// Leverage + /// + [JsonPropertyName("leverage")] + public decimal Leverage { get; set; } + /// + /// Position quantity + /// + [JsonPropertyName("position_size")] + public int PositionQuantity { get; set; } + /// + /// Trade quantity + /// + [JsonPropertyName("trade_size")] + public int TradeQuantity { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpBalanceUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpBalanceUpdate.cs new file mode 100644 index 0000000..94859b0 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpBalanceUpdate.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Balance update + /// + public record GateIoPerpBalanceUpdate + { + /// + /// Balance after change + /// + [JsonPropertyName("balance")] + public decimal Balance { get; set; } + /// + /// Changed quantity + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Timestamp + /// + [JsonPropertyName("time_ms")] + public DateTime Timestamp { get; set; } + /// + /// Change type + /// + [JsonPropertyName("type")] + public string ChangeType { get; set; } = string.Empty; + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpBatchPlaceRequest.cs b/GateIo.Net/Objects/Models/GateIoPerpBatchPlaceRequest.cs new file mode 100644 index 0000000..100c477 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpBatchPlaceRequest.cs @@ -0,0 +1,63 @@ +using GateIo.Net.Enums; +using System.Text.Json.Serialization; +using CryptoExchange.Net.Converters.SystemTextJson; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Batch order placement item + /// + public record GateIoPerpBatchPlaceRequest + { + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("size")] + public int Quantity { get; set; } + /// + /// Iceberg quantity + /// + [JsonPropertyName("iceberg")] + public int IcebergQuantity { get; set; } + /// + /// Order price + /// + [JsonPropertyName("price"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public decimal? Price { get; set; } + /// + /// Time in force + /// + [JsonPropertyName("tif"), JsonConverter(typeof(EnumConverter)), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public TimeInForce? TimeInForce { get; set; } + /// + /// Text + /// + [JsonPropertyName("text"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Text { get; set; } + /// + /// Close position + /// + [JsonPropertyName("close"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? ClosePosition { get; set; } + /// + /// Reduce only + /// + [JsonPropertyName("reduce_only"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? ReduceOnly { get; set; } + /// + /// Close side + /// + [JsonPropertyName("auto_size"), JsonConverter(typeof(EnumConverter)), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public CloseSide? CloseSide { get; set; } + /// + /// Self trade prevention mode + /// + [JsonPropertyName("stp_act"), JsonConverter(typeof(EnumConverter)), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public SelfTradePreventionMode? StpMode { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpBookTickerUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpBookTickerUpdate.cs new file mode 100644 index 0000000..7f49d8c --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpBookTickerUpdate.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Book ticker update + /// + public record GateIoPerpBookTickerUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("t")] + public DateTime Timestamp { get; set; } + /// + /// Update id + /// + [JsonPropertyName("u")] + public long UpdateId { get; set; } + /// + /// Contract + /// + [JsonPropertyName("s")] + public string Contract { get; set; } = string.Empty; + /// + /// Best bid price + /// + [JsonPropertyName("b")] + public decimal BestBidPrice { get; set; } + /// + /// Best bid quantity + /// + [JsonPropertyName("B")] + public int BestBidQuantity { get; set; } + /// + /// Best ask price + /// + [JsonPropertyName("a")] + public decimal BestAskPrice { get; set; } + /// + /// Best ask quantity + /// + [JsonPropertyName("A")] + public int BestAskQuantity { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpConstituent.cs b/GateIo.Net/Objects/Models/GateIoPerpConstituent.cs new file mode 100644 index 0000000..d25a68c --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpConstituent.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Index constituents + /// + public record GateIoPerpConstituent + { + /// + /// Index name + /// + [JsonPropertyName("index")] + public string Index { get; set; } = string.Empty; + /// + /// Constituents + /// + [JsonPropertyName("constituents")] + public IEnumerable Constituents { get; set; } = Array.Empty(); + } + + /// + /// Reference + /// + public record GateIoPerpConstituentReference + { + /// + /// Exchange + /// + [JsonPropertyName("exchange")] + public string Exchange { get; set; } = string.Empty; + /// + /// Symbols + /// + [JsonPropertyName("symbols")] + public IEnumerable Symbols { get; set; } = Array.Empty(); + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpContractStats.cs b/GateIo.Net/Objects/Models/GateIoPerpContractStats.cs new file mode 100644 index 0000000..efae556 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpContractStats.cs @@ -0,0 +1,82 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Contract statistics + /// + public record GateIoPerpContractStats + { + /// + /// Timestamp + /// + [JsonPropertyName("time")] + public DateTime Timestamp { get; set; } + /// + /// Long/short account number ratio + /// + [JsonPropertyName("lsr_taker")] + public decimal LongShortAccountRatio { get; set; } + /// + /// Long/short taker size ratio + /// + [JsonPropertyName("lsr_account")] + public decimal LongShortTakerRatio { get; set; } + /// + /// Long liquidation size + /// + [JsonPropertyName("long_liq_size")] + public decimal LongLiquidationSize { get; set; } + /// + /// Short liquidation size + /// + [JsonPropertyName("short_liq_size")] + public decimal ShotLiquidationSize { get; set; } + /// + /// Open interest + /// + [JsonPropertyName("open_interest")] + public decimal OpenInterest { get; set; } + /// + /// Short liquidation volume(quote currency) + /// + [JsonPropertyName("short_liq_usd")] + public decimal ShortLiquidationUsd { get; set; } + /// + /// Mark price + /// + [JsonPropertyName("mark_price")] + public decimal MarkPrice { get; set; } + /// + /// Top trader long/short position ratio + /// + [JsonPropertyName("top_lsr_size")] + public decimal TopTraderLongShorPositionRatio { get; set; } + /// + /// Short liquidation amount(base currency) + /// + [JsonPropertyName("short_liq_amount")] + public decimal ShortLiquidationAmount { get; set; } + /// + /// Long liquidation amount(base currency) + /// + [JsonPropertyName("long_liq_amount")] + public decimal LongLiquidationAmount { get; set; } + /// + /// Open interest volume(quote currency) + /// + [JsonPropertyName("open_interest_usd")] + public decimal OpenInterestUsd { get; set; } + /// + /// Top trader long/short account ratio + /// + [JsonPropertyName("top_lsr_account")] + public decimal TopTraderLongShortAccountRatio { get; set; } + /// + /// Long liquidation volume(quote currency) + /// + [JsonPropertyName("long_liq_usd")] + public decimal LongLiquidationUsd { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpFee.cs b/GateIo.Net/Objects/Models/GateIoPerpFee.cs new file mode 100644 index 0000000..bf0085b --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpFee.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Fee info + /// + public record GateIoPerpFee + { + /// + /// Taker fee rate + /// + [JsonPropertyName("taker_fee")] + public decimal TakerFee { get; set; } + /// + /// Maker fee rate + /// + [JsonPropertyName("maker_fee")] + public decimal MakerFee { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpFundingRate.cs b/GateIo.Net/Objects/Models/GateIoPerpFundingRate.cs new file mode 100644 index 0000000..9c08a1c --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpFundingRate.cs @@ -0,0 +1,22 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Funding rate + /// + public record GateIoPerpFundingRate + { + /// + /// Time + /// + [JsonPropertyName("t")] + public DateTime Timestamp { get; set; } + /// + /// Funding rate + /// + [JsonPropertyName("r")] + public decimal FundingRate { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpFuturesContract.cs b/GateIo.Net/Objects/Models/GateIoPerpFuturesContract.cs new file mode 100644 index 0000000..fc2f4c8 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpFuturesContract.cs @@ -0,0 +1,213 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Contract info + /// + public record GateIoPerpFuturesContract + { + /// + /// Contract name + /// + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + /// + /// Contract type + /// + [JsonPropertyName("type")] + public ContractType Type { get; set; } + /// + /// Multiplier used in converting from invoicing to settlement asset + /// + [JsonPropertyName("quanto_multiplier")] + public decimal Mulitplier { get; set; } + /// + /// Referral fee rate discount + /// + [JsonPropertyName("ref_discount_rate")] + public decimal ReferalDiscount { get; set; } + /// + /// Deviation between order price and current index price + /// + [JsonPropertyName("order_price_deviate")] + public decimal OrderPriceDeviation { get; set; } + /// + /// Maintenance rate of margin + /// + [JsonPropertyName("maintenance_rate")] + public decimal MaintenanceRate { get; set; } + /// + /// Mark type + /// + [JsonPropertyName("mark_type")] + public MarkType MarkType { get; set; } + /// + /// Mark price + /// + [JsonPropertyName("mark_price")] + public decimal MarkPrice { get; set; } + /// + /// Last price + /// + [JsonPropertyName("last_price")] + public decimal LastPrice { get; set; } + /// + /// Index price + /// + [JsonPropertyName("index_price")] + public decimal IndexPrice { get; set; } + /// + /// Funding rate indicative + /// + [JsonPropertyName("funding_rate_indicative")] + public decimal FundingRateIndicative { get; set; } + /// + /// Minimum mark price increment + /// + [JsonPropertyName("mark_price_round")] + public decimal MarkPriceStep { get; set; } + /// + /// Funding offset + /// + [JsonPropertyName("funding_offset")] + public decimal FundingOffset { get; set; } + /// + /// Delisting + /// + [JsonPropertyName("in_delisting")] + public bool Delisting { get; set; } + /// + /// Interest rate + /// + [JsonPropertyName("interest_rate")] + public decimal InterestRate { get; set; } + /// + /// Minimum order price increment + /// + [JsonPropertyName("order_price_round")] + public decimal OrderPriceStep { get; set; } + /// + /// Minimum order quantity + /// + [JsonPropertyName("order_size_min")] + public decimal MinOrderQuantity { get; set; } + /// + /// Referral fee rate discount + /// + [JsonPropertyName("ref_rebate_rate")] + public decimal ReferalRebateRate { get; set; } + /// + /// Funding application interval, unit in seconds + /// + [JsonPropertyName("funding_interval")] + public int? FundingInterval { get; set; } + /// + /// Min leverage + /// + [JsonPropertyName("leverage_min")] + public decimal MinLeverage { get; set; } + /// + /// Max leverage + /// + [JsonPropertyName("leverage_max")] + public decimal MaxLeverage { get; set; } + /// + /// Maker fee rate + /// + [JsonPropertyName("maker_fee_rate")] + public decimal MakerFeeRate { get; set; } + /// + /// Taker fee rate + /// + [JsonPropertyName("taker_fee_rate")] + public decimal TakerFeeRate { get; set; } + /// + /// Funding rate + /// + [JsonPropertyName("funding_rate")] + public decimal FundingRate { get; set; } + /// + /// Max order quantity + /// + [JsonPropertyName("order_size_max")] + public decimal MaxOrderQuantity { get; set; } + /// + /// Next funding time + /// + [JsonPropertyName("funding_next_apply")] + public DateTime NextFundingTime { get; set; } + /// + /// Config change time + /// + [JsonPropertyName("config_change_time")] + public DateTime ConfigChangeTime { get; set; } + /// + /// Short users + /// + [JsonPropertyName("short_users")] + public int ShortUsers { get; set; } + /// + /// Historical accumulated trade size + /// + [JsonPropertyName("trade_size")] + public decimal TotalTradeSize { get; set; } + /// + /// Current total long position size + /// + [JsonPropertyName("position_size")] + public decimal PositionSize { get; set; } + /// + /// Long users + /// + [JsonPropertyName("long_users")] + public int LongUsers { get; set; } + /// + /// Funding impact value + /// + [JsonPropertyName("funding_impact_value")] + public decimal FundingImpactValue { get; set; } + /// + /// Maximum number of open orders + /// + [JsonPropertyName("orders_limit")] + public int MaxOrders { get; set; } + /// + /// Last trade id + /// + [JsonPropertyName("trade_id")] + public long CurrentTradeId { get; set; } + /// + /// Last book sequence id + /// + [JsonPropertyName("orderbook_id")] + public long CurrentOrderbookId { get; set; } + /// + /// Whether bonus is enabled + /// + [JsonPropertyName("enable_bonus")] + public bool BonusEnabled { get; set; } + /// + /// Whether portfolio margin account is enabled + /// + [JsonPropertyName("enable_credit")] + public bool CreditEnabled { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime? CreateTime { get; set; } + /// + /// The factor for the maximum of the funding rate. + /// + [JsonPropertyName("funding_cap_ratio")] + public decimal FundingCapRatio { get; set; } + /// + /// Voucher leverage + /// + [JsonPropertyName("voucher_leverage")] + public decimal VoucherLeverage { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpIndexKline.cs b/GateIo.Net/Objects/Models/GateIoPerpIndexKline.cs new file mode 100644 index 0000000..74f1624 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpIndexKline.cs @@ -0,0 +1,37 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Kline info + /// + public record GateIoPerpIndexKline + { + /// + /// Open time + /// + [JsonPropertyName("t")] + public DateTime OpenTime { get; set; } + /// + /// Close price + /// + [JsonPropertyName("c")] + public decimal ClosePrice { get; set; } + /// + /// High price + /// + [JsonPropertyName("h")] + public decimal HighPrice { get; set; } + /// + /// Low price + /// + [JsonPropertyName("l")] + public decimal LowPrice { get; set; } + /// + /// Open price + /// + [JsonPropertyName("o")] + public decimal OpenPrice { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpInsurance.cs b/GateIo.Net/Objects/Models/GateIoPerpInsurance.cs new file mode 100644 index 0000000..dfa8746 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpInsurance.cs @@ -0,0 +1,22 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Insurance + /// + public record GateIoPerpInsurance + { + /// + /// Time + /// + [JsonPropertyName("t")] + public DateTime Timestamp { get; set; } + /// + /// Funding rate + /// + [JsonPropertyName("b")] + public decimal Insurance { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpKline.cs b/GateIo.Net/Objects/Models/GateIoPerpKline.cs new file mode 100644 index 0000000..0c2c509 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpKline.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Kline info + /// + public record GateIoPerpKline + { + /// + /// Open time + /// + [JsonPropertyName("t")] + public DateTime OpenTime { get; set; } + /// + /// Volume + /// + [JsonPropertyName("v")] + public decimal Volume { get; set; } + /// + /// Close price + /// + [JsonPropertyName("c")] + public decimal ClosePrice { get; set; } + /// + /// High price + /// + [JsonPropertyName("h")] + public decimal HighPrice { get; set; } + /// + /// Low price + /// + [JsonPropertyName("l")] + public decimal LowPrice { get; set; } + /// + /// Open price + /// + [JsonPropertyName("o")] + public decimal OpenPrice { get; set; } + /// + /// Volume + /// + [JsonPropertyName("sum")] + public decimal QuoteVolume { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpKlineUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpKlineUpdate.cs new file mode 100644 index 0000000..552fd7c --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpKlineUpdate.cs @@ -0,0 +1,57 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Kline update + /// + public record GateIoPerpKlineUpdate + { + /// + /// Open time + /// + [JsonPropertyName("t")] + public DateTime OpenTime { get; set; } + /// + /// Volume in quote asset + /// + [JsonPropertyName("v")] + public long QuoteVolume { get; set; } + /// + /// Close price + /// + [JsonPropertyName("c")] + public decimal ClosePrice { get; set; } + /// + /// High price + /// + [JsonPropertyName("h")] + public decimal HighPrice { get; set; } + /// + /// Low price + /// + [JsonPropertyName("l")] + public decimal LowPrice { get; set; } + /// + /// Open price + /// + [JsonPropertyName("o")] + public decimal OpenPrice { get; set; } + /// + /// Stream + /// + [JsonPropertyName("n")] + public string Stream { get; set; } = string.Empty; + + /// + /// The contract + /// + public string Contract => Stream.Substring(Stream.IndexOf('_') + 1); + + /// + /// The interval + /// + public string Interval => Stream.Substring(0, Stream.IndexOf('_')); + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpLedgerEntry.cs b/GateIo.Net/Objects/Models/GateIoPerpLedgerEntry.cs new file mode 100644 index 0000000..3d38c84 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpLedgerEntry.cs @@ -0,0 +1,47 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Account ledger entry + /// + public record GateIoPerpLedgerEntry + { + /// + /// Timestamp + /// + [JsonPropertyName("time")] + public DateTime Timestamp { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Change quantity + /// + [JsonPropertyName("change")] + public decimal Change { get; set; } + /// + /// Balance after change + /// + [JsonPropertyName("balance")] + public decimal Balance { get; set; } + /// + /// Change type + /// + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; + /// + /// Additional info + /// + [JsonPropertyName("text")] + public string? Text { get; set; } = string.Empty; + /// + /// Trade id + /// + [JsonPropertyName("trade_id")] + public string? TradeId { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpLiquidation.cs b/GateIo.Net/Objects/Models/GateIoPerpLiquidation.cs new file mode 100644 index 0000000..4efc62b --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpLiquidation.cs @@ -0,0 +1,77 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// User liquidation info + /// + public record GateIoPerpLiquidation + { + /// + /// User id + /// + [JsonPropertyName("user")] + public long? UserId { get; set; } + /// + /// Timestamp + /// + [JsonPropertyName("time")] + public DateTime Timestamp { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("size")] + public int Quantity { get; set; } + /// + /// Leverage + /// + [JsonPropertyName("leverage")] + public decimal Leverage { get; set; } + /// + /// Margin + /// + [JsonPropertyName("margin")] + public decimal Margin { get; set; } + /// + /// Entry price + /// + [JsonPropertyName("entry_price")] + public decimal EntryPrice { get; set; } + /// + /// Liquidation price + /// + [JsonPropertyName("liq_price")] + public decimal LiquidationPrice { get; set; } + /// + /// Mark price + /// + [JsonPropertyName("mark_price")] + public decimal MarkPrice { get; set; } + /// + /// Order id + /// + [JsonPropertyName("order_id")] + public long OrderId { get; set; } + /// + /// Order price + /// + [JsonPropertyName("order_price")] + public decimal OrderPrice { get; set; } + /// + /// Order price + /// + [JsonPropertyName("fill_price")] + public decimal FillPrice { get; set; } + /// + /// Left + /// + [JsonPropertyName("left")] + public decimal QuantityRemaining { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpOrder.cs b/GateIo.Net/Objects/Models/GateIoPerpOrder.cs new file mode 100644 index 0000000..8d260c5 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpOrder.cs @@ -0,0 +1,128 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Futures order info + /// + public record GateIoPerpOrder + { + /// + /// Id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("size")] + public int Quantity { get; set; } + /// + /// Iceberg quantity + /// + [JsonPropertyName("iceberg")] + public int? IcebergQuantity { get; set; } + /// + /// Open quantity + /// + [JsonPropertyName("left")] + public int QuantityRemaining { get; set; } + /// + /// Order price + /// + [JsonPropertyName("price")] + public decimal? Price { get; set; } + /// + /// Fill price + /// + [JsonPropertyName("fill_price")] + public decimal? FillPrice { get; set; } + /// + /// Maker fee + /// + [JsonPropertyName("mkfr")] + public decimal? MakerFee { get; set; } + /// + /// Taker fee + /// + [JsonPropertyName("tkfr")] + public decimal? TakerFee { get; set; } + /// + /// Time in force + /// + [JsonPropertyName("tif")] + public TimeInForce? TimeInForce { get; set; } + /// + /// Reference user ID + /// + [JsonPropertyName("refu")] + public long? ReferenceUserId { get; set; } + /// + /// Is reduce only order + /// + [JsonPropertyName("is_reduce_only")] + public bool IsReduceOnly { get; set; } + /// + /// Is close position order + /// + [JsonPropertyName("is_close")] + public bool IsClose { get; set; } + /// + /// Is liquidation position order + /// + [JsonPropertyName("is_liq")] + public bool IsLiquidation { get; set; } + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Status + /// + [JsonPropertyName("status")] + public OrderStatus Status { get; set; } + /// + /// Finish time + /// + [JsonPropertyName("finish_time")] + public DateTime? FinishTime { get; set; } + /// + /// Finish type + /// + [JsonPropertyName("finish_as")] + public OrderFinishType? FinishedAs { get; set; } + /// + /// STP group id + /// + [JsonPropertyName("stp_id")] + public long? SelfTradePreventionId { get; set; } + /// + /// STP mode + /// + [JsonPropertyName("stp_act")] + public SelfTradePreventionMode? SelfTradePreventionAction { get; set; } + /// + /// Amend text + /// + [JsonPropertyName("amend_text")] + public string? AmendText { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpOrderBook.cs b/GateIo.Net/Objects/Models/GateIoPerpOrderBook.cs new file mode 100644 index 0000000..c106aaa --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpOrderBook.cs @@ -0,0 +1,60 @@ +using CryptoExchange.Net.Interfaces; +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Order book + /// + public record GateIoPerpOrderBook + { + /// + /// Book sync id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + + /// + /// The timestamp the book was requested + /// + [JsonPropertyName("current")] + public DateTime Timestamp { get; set; } + + /// + /// The timestamp the book was last updated + /// + [JsonPropertyName("update")] + public DateTime UpdateTime { get; set; } + + /// + /// Asks list + /// + [JsonPropertyName("asks")] + public IEnumerable Asks { get; set; } = Array.Empty(); + + /// + /// Bids list + /// + [JsonPropertyName("bids")] + public IEnumerable Bids { get; set; } = Array.Empty(); + } + + /// + /// Order book entry + /// + public record GateIoPerpOrderBookEntry : ISymbolOrderBookEntry + { + /// + /// Price + /// + [JsonPropertyName("p")] + public decimal Price { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("s")] + public decimal Quantity { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpOrderBookUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpOrderBookUpdate.cs new file mode 100644 index 0000000..f65b3ec --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpOrderBookUpdate.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Order book update + /// + public record GateIoPerpOrderBookUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("t")] + public DateTime Timestamp { get; set; } + /// + /// Update id + /// + [JsonPropertyName("u")] + public long LastUpdateId { get; set; } + /// + /// Update id + /// + [JsonPropertyName("U")] + public long FirstUpdateId { get; set; } + /// + /// Contract + /// + [JsonPropertyName("s")] + public string Contract { get; set; } = string.Empty; + /// + /// Event + /// + [JsonPropertyName("e")] + public string Event { get; set; } = string.Empty; + /// + /// Updated bids + /// + [JsonPropertyName("b")] + public IEnumerable Bids { get; set; } = Array.Empty(); + /// + /// Updated asks + /// + [JsonPropertyName("a")] + public IEnumerable Asks { get; set; } = Array.Empty(); + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpPositionClose.cs b/GateIo.Net/Objects/Models/GateIoPerpPositionClose.cs new file mode 100644 index 0000000..c841820 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpPositionClose.cs @@ -0,0 +1,73 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Position close info + /// + public record GateIoPerpPositionClose + { + /// + /// Timestamp + /// + [JsonPropertyName("time")] + public DateTime Timestamp { get; set; } + /// + /// Profit and loss + /// + [JsonPropertyName("pnl")] + public decimal ProfitAndLoss { get; set; } + /// + /// Realized profit and loss position + /// + [JsonPropertyName("pnl_pnl")] + public decimal? RealisedPnlPosition { get; set; } + /// + /// Realized PNL - Funding Fees + /// + [JsonPropertyName("pnl_fund")] + public decimal? RealisedPnlFundingFees { get; set; } + /// + /// Realized PNL - Transaction Fees + /// + [JsonPropertyName("pnl_fee")] + public decimal? RealisedPnlFee { get; set; } + /// + /// Position side + /// + [JsonPropertyName("side")] + public PositionSide Side { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Max Trade Size + /// + [JsonPropertyName("max_size")] + public decimal? MaxSize { get; set; } + /// + /// First opening time + /// + [JsonPropertyName("first_open_time")] + public DateTime? FirstOpenTime { get; set; } + /// + /// When 'side' is 'long,' it indicates the opening average price; when 'side' is 'short,' it indicates the closing average price. + /// + [JsonPropertyName("long_price")] + public decimal LongPrice { get; set; } + /// + /// When 'side' is 'long,' it indicates the opening average price; when 'side' is 'short,' it indicates the closing average price + /// + [JsonPropertyName("short_price")] + public decimal ShortPrice { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpPositionCloseUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpPositionCloseUpdate.cs new file mode 100644 index 0000000..2422cce --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpPositionCloseUpdate.cs @@ -0,0 +1,43 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Position close info + /// + public record GateIoPerpPositionCloseUpdate + { + /// + /// Timestamp + /// + [JsonPropertyName("time_ms")] + public DateTime Timestamp { get; set; } + /// + /// Profit and loss + /// + [JsonPropertyName("pnl")] + public decimal ProfitAndLoss { get; set; } + /// + /// Position side + /// + [JsonPropertyName("side")] + public PositionSide Side { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpRiskLimitUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpRiskLimitUpdate.cs new file mode 100644 index 0000000..084f235 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpRiskLimitUpdate.cs @@ -0,0 +1,52 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Risk limit update + /// + public record GateIoPerpRiskLimitUpdate + { + /// + /// Cancel orders + /// + [JsonPropertyName("cancel_orders")] + public int CancelOrders { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Max leverage + /// + [JsonPropertyName("leverage_max")] + public decimal MaxLeverage { get; set; } + /// + /// Liquidation price + /// + [JsonPropertyName("liq_price")] + public decimal LiquidationPrice { get; set; } + /// + /// Maintenance rate + /// + [JsonPropertyName("maintenance_rate")] + public decimal MaintenanceRate { get; set; } + /// + /// Risk limit + /// + [JsonPropertyName("risk_limit")] + public int RiskLimit { get; set; } + /// + /// Timestamp + /// + [JsonPropertyName("time_ms")] + public DateTime Timestamp { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpTicker.cs b/GateIo.Net/Objects/Models/GateIoPerpTicker.cs new file mode 100644 index 0000000..de57a71 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpTicker.cs @@ -0,0 +1,101 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Ticker info + /// + public record GateIoPerpTicker + { + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Last price + /// + [JsonPropertyName("last")] + public decimal LastPrice { get; set; } + /// + /// 24h low price + /// + [JsonPropertyName("low_24h")] + public decimal LowPrice { get; set; } + /// + /// 24h high price + /// + [JsonPropertyName("high_24h")] + public decimal HighPrice { get; set; } + /// + /// 24h Change percentage + /// + [JsonPropertyName("change_percentage")] + public decimal ChangePercentage { get; set; } + /// + /// Total contract size + /// + [JsonPropertyName("total_size")] + public decimal TotalSize { get; set; } + /// + /// 24h Volume + /// + [JsonPropertyName("volume_24h")] + public decimal Volume { get; set; } + /// + /// 24h Volume in BTC + /// + [JsonPropertyName("volume_24h_btc")] + public decimal VolumeBtc { get; set; } + /// + /// 24h Volume in USD + /// + [JsonPropertyName("volume_24h_usd")] + public decimal VolumeUsd { get; set; } + /// + /// 24h Base asset volume + /// + [JsonPropertyName("volume_24h_base")] + public decimal BaseVolume { get; set; } + /// + /// 24h Quote asset volume + /// + [JsonPropertyName("volume_24h_quote")] + public decimal QuoteVolume { get; set; } + /// + /// 24h Settle asset volume + /// + [JsonPropertyName("volume_24h_settle")] + public decimal SettleVolume { get; set; } + /// + /// Mark price + /// + [JsonPropertyName("mark_price")] + public decimal MarkPrice { get; set; } + /// + /// Funding rate + /// + [JsonPropertyName("funding_rate")] + public decimal FundingRate { get; set; } + /// + /// Funding rate indicative + /// + [JsonPropertyName("funding_rate_indicative")] + public decimal IndicativeFundingRate { get; set; } + /// + /// Index price + /// + [JsonPropertyName("index_price")] + public decimal IndexPrice { get; set; } + /// + /// Best ask price + /// + [JsonPropertyName("highest_bid")] + public decimal BestBidPrice { get; set; } + /// + /// Best bid price + /// + [JsonPropertyName("lowest_ask")] + public decimal BestAskPrice { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpTickerUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpTickerUpdate.cs new file mode 100644 index 0000000..a4f4b6c --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpTickerUpdate.cs @@ -0,0 +1,96 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Perpetual ticker update + /// + public record GateIoPerpTickerUpdate + { + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Last trade price + /// + [JsonPropertyName("last")] + public decimal LastPrice { get; set; } + /// + /// Change percentage compared to 24h ago + /// + [JsonPropertyName("change_percentage")] + public decimal ChangePercentage24h { get; set; } + /// + /// 24h high price + /// + [JsonPropertyName("high_24h")] + public decimal HighPrice { get; set; } + /// + /// 24h low price + /// + [JsonPropertyName("low_24h")] + public decimal LowPrice { get; set; } + /// + /// Mark price + /// + [JsonPropertyName("mark_price")] + public decimal MarkPrice { get; set; } + /// + /// Index price + /// + [JsonPropertyName("index_price")] + public decimal IndexPrice { get; set; } + /// + /// Funding rate + /// + [JsonPropertyName("funding_rate")] + public decimal FundingRate { get; set; } + /// + /// Funding rate indicative + /// + [JsonPropertyName("funding_rate_indicative")] + public decimal FundingRateIndicative { get; set; } + /// + /// Total contract size + /// + [JsonPropertyName("total_size")] + public decimal TotalSize { get; set; } + /// + /// 24h Volume + /// + [JsonPropertyName("volume_24h")] + public decimal Volume { get; set; } + /// + /// 24h Volume in BTC + /// + [JsonPropertyName("volume_24h_btc")] + public decimal VolumeBtc { get; set; } + /// + /// 24h Volume in USD + /// + [JsonPropertyName("volume_24h_usd")] + public decimal VolumeUsd { get; set; } + /// + /// 24h Base asset volume + /// + [JsonPropertyName("volume_24h_base")] + public decimal BaseVolume { get; set; } + /// + /// 24h Quote asset volume + /// + [JsonPropertyName("volume_24h_quote")] + public decimal QuoteVolume { get; set; } + /// + /// 24h Settle asset volume + /// + [JsonPropertyName("volume_24h_settle")] + public decimal SettleVolume { get; set; } + /// + /// Exchange rate of base currency and settlement currency in Quanto contract. Does not exists in contracts of other types + /// + [JsonPropertyName("quanto_base_rate")] + public decimal? QuantoBaseRate { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpTrade.cs b/GateIo.Net/Objects/Models/GateIoPerpTrade.cs new file mode 100644 index 0000000..3bd2332 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpTrade.cs @@ -0,0 +1,37 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Trade info + /// + public record GateIoPerpTrade + { + /// + /// Trade id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Timestamp + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("size")] + public decimal Quantity { get; set; } + /// + /// Trade price + /// + [JsonPropertyName("price")] + public decimal Price { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpTradeUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpTradeUpdate.cs new file mode 100644 index 0000000..3c11e3c --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpTradeUpdate.cs @@ -0,0 +1,42 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Trade update + /// + public record GateIoPerpTradeUpdate + { + /// + /// Trade id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time_ms")] + public DateTime CreateTime { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Trade quantity, negative means sell, positive is buy + /// + [JsonPropertyName("size")] + public int Quantity { get; set; } + /// + /// Trade price + /// + [JsonPropertyName("price")] + public decimal Price { get; set; } + /// + /// Whether internal trade. Internal trade refers to the takeover of liquidation orders by the insurance fund and ADL users + /// + [JsonPropertyName("is_internal")] + public bool IsInternal { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpTriggerOrder.cs b/GateIo.Net/Objects/Models/GateIoPerpTriggerOrder.cs new file mode 100644 index 0000000..8b73f66 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpTriggerOrder.cs @@ -0,0 +1,142 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Trigger order + /// + public record GateIoPerpTriggerOrder + { + /// + /// Trigger order id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Finish time + /// + [JsonPropertyName("finish_time")] + public DateTime? FinishTime { get; set; } + /// + /// Trade id + /// + [JsonPropertyName("trade_id")] + public long? TradeId { get; set; } + /// + /// Status + /// + [JsonPropertyName("status")] + public FuturesTriggerOrderStatus Status { get; set; } + /// + /// Finish type + /// + [JsonPropertyName("finish_as")] + public TriggerFinishType? FinishType { get; set; } + /// + /// Reason + /// + [JsonPropertyName("reason")] + public string? Reason { get; set; } + /// + /// Order type + /// + [JsonPropertyName("order_type")] + public TriggerOrderType? OrderType { get; set; } + /// + /// Order info + /// + [JsonPropertyName("initial")] + public GateIoPerpTriggerOrderInitial Order { get; set; } = null!; + /// + /// Trigger info + /// + [JsonPropertyName("trigger")] + public GateIoPerpTriggerOrderTrigger Trigger { get; set; } = null!; + } + + /// + /// Trigger info + /// + public record GateIoPerpTriggerOrderTrigger + { + /// + /// Price type + /// + [JsonPropertyName("price_type")] + public PriceType PriceType { get; set; } + /// + /// Price + /// + [JsonPropertyName("price")] + public decimal Price { get; set; } + /// + /// Trigger type + /// + [JsonPropertyName("rule")] + public TriggerType TriggerType { get; set; } + /// + /// Expire time in seconds + /// + [JsonPropertyName("expiration")] + public int Expiration { get; set; } + } + + /// + /// Order info + /// + public record GateIoPerpTriggerOrderInitial + { + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Quantity + /// + [JsonPropertyName("size")] + public int Quantity { get; set; } + /// + /// Price + /// + [JsonPropertyName("price")] + public decimal? Price { get; set; } + /// + /// Close position order + /// + [JsonPropertyName("is_close")] + public bool ClosePosition { get; set; } + /// + /// Reduce only order + /// + [JsonPropertyName("is_reduce_only")] + public bool ReduceOnly { get; set; } + /// + /// Time in force + /// + [JsonPropertyName("tif")] + public TimeInForce? TimeInForce { get; set; } + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Close side + /// + [JsonPropertyName("auto_size")] + public CloseSide? CloseSide { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpTriggerOrderUpdate.cs b/GateIo.Net/Objects/Models/GateIoPerpTriggerOrderUpdate.cs new file mode 100644 index 0000000..d7c0044 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpTriggerOrderUpdate.cs @@ -0,0 +1,83 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Trigger order + /// + public record GateIoPerpTriggerOrderUpdate + { + /// + /// Corresponding order ID of order take-profit/stop-loss. + /// + [JsonPropertyName("me_order_id")] + public long? TriggerdOrderId { get; set; } + /// + /// Is stop order + /// + [JsonPropertyName("is_stop_order")] + public bool IsStopOrder { get; set; } + /// + /// Name + /// + [JsonPropertyName("name")] + public string? Name { get; set; } + /// + /// Trigger order id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Finish time + /// + [JsonPropertyName("finish_time")] + public DateTime? FinishTime { get; set; } + /// + /// Trade id + /// + [JsonPropertyName("trade_id")] + public long? TradeId { get; set; } + /// + /// Status + /// + [JsonPropertyName("status")] + public FuturesTriggerOrderStatus Status { get; set; } + /// + /// Finish type + /// + [JsonPropertyName("finish_as")] + public TriggerFinishType? FinishType { get; set; } + /// + /// Reason + /// + [JsonPropertyName("reason")] + public string? Reason { get; set; } + /// + /// Order type + /// + [JsonPropertyName("order_type")] + public TriggerOrderType? OrderType { get; set; } + /// + /// Order info + /// + [JsonPropertyName("initial")] + public GateIoPerpTriggerOrderInitial Order { get; set; } = null!; + /// + /// Trigger info + /// + [JsonPropertyName("trigger")] + public GateIoPerpTriggerOrderTrigger Trigger { get; set; } = null!; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPerpUserTrade.cs b/GateIo.Net/Objects/Models/GateIoPerpUserTrade.cs new file mode 100644 index 0000000..8c8e549 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPerpUserTrade.cs @@ -0,0 +1,63 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// User trade info + /// + public record GateIoPerpUserTrade + { + /// + /// Trade id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Timestamp + /// + [JsonPropertyName("create_time")] + public DateTime CreateTime { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("size")] + public int Quantity { get; set; } + /// + /// Trade price + /// + [JsonPropertyName("price")] + public decimal Price { get; set; } + /// + /// Order id + /// + [JsonPropertyName("order_id")] + public long OrderId { get; set; } + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Trade fee + /// + [JsonPropertyName("fee")] + public decimal Fee { get; set; } + /// + /// Trade point fee + /// + [JsonPropertyName("point_fee")] + public decimal PointFee { get; set; } + /// + /// Role + /// + [JsonPropertyName("role")] + public Role Role { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPosition.cs b/GateIo.Net/Objects/Models/GateIoPosition.cs new file mode 100644 index 0000000..fe6acb9 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPosition.cs @@ -0,0 +1,170 @@ +using System; +using System.Text.Json.Serialization; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Position info + /// + public record GateIoPosition + { + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Position size + /// + [JsonPropertyName("size")] + public long Size { get; set; } + /// + /// Leverage + /// + [JsonPropertyName("leverage")] + public decimal Leverage { get; set; } + /// + /// Risk limit + /// + [JsonPropertyName("risk_limit")] + public decimal RiskLimit { get; set; } + /// + /// Max leverage + /// + [JsonPropertyName("leverage_max")] + public decimal MaxLeverage { get; set; } + /// + /// Maintenance rate + /// + [JsonPropertyName("maintenance_rate")] + public decimal MaintenanceRate { get; set; } + /// + /// Position value + /// + [JsonPropertyName("value")] + public decimal PositionValue { get; set; } + /// + /// Margin + /// + [JsonPropertyName("margin")] + public decimal Margin { get; set; } + /// + /// Entry price + /// + [JsonPropertyName("entry_price")] + public decimal? EntryPrice { get; set; } + /// + /// Liquidation price + /// + [JsonPropertyName("liq_price")] + public decimal? LiquidationPrice { get; set; } + /// + /// Mark price + /// + [JsonPropertyName("mark_price")] + public decimal? MarkPrice { get; set; } + /// + /// Unrealized profit and less + /// + [JsonPropertyName("unrealised_pnl")] + public decimal? UnrealisedPnl { get; set; } + /// + /// Realized profit and less + /// + [JsonPropertyName("realised_pnl")] + public decimal? RealisedPnl { get; set; } + /// + /// Realized profit and loss position + /// + [JsonPropertyName("pnl_pnl")] + public decimal? RealisedPnlPosition { get; set; } + /// + /// Realized PNL - Funding Fees + /// + [JsonPropertyName("pnl_fund")] + public decimal? RealisedPnlFundingFees { get; set; } + /// + /// Realized PNL - Transaction Fees + /// + [JsonPropertyName("pnl_fee")] + public decimal? RealisedPnlFee { get; set; } + /// + /// History realized PNL + /// + [JsonPropertyName("history_pnl")] + public decimal? HistoryPnl { get; set; } + /// + /// Last close pnl + /// + [JsonPropertyName("last_close_pnl")] + public decimal? LastClosePnl { get; set; } + /// + /// Realized POINT PNL + /// + [JsonPropertyName("realised_point")] + public decimal? RealsedPoinPnl { get; set; } + /// + /// History realized POINT PNL + /// + [JsonPropertyName("history_point")] + public decimal? HistoryPoinPnl { get; set; } + /// + /// Auto deleverage ranking + /// + [JsonPropertyName("adl_ranking")] + public int? AdlRanking { get; set; } + /// + /// Open orders + /// + [JsonPropertyName("pending_orders")] + public int? PendingOrders { get; set; } + /// + /// Position mode + /// + [JsonPropertyName("mode")] + public PositionMode? PositionMode { get; set; } + /// + /// Update time + /// + [JsonPropertyName("update_time")] + public DateTime? UpdateTime { get; set; } + /// + /// Cross margin leverage + /// + [JsonPropertyName("cross_leverage_limit")] + public int? CrossLeverageLimit { get; set; } + /// + /// Close order + /// + [JsonPropertyName("close_order")] + public GateIoPositionCloseOrder? CloseOrder { get; set; } + } + + /// + /// Close order info + /// + public record GateIoPositionCloseOrder + { + /// + /// Order id + /// + [JsonPropertyName("id")] + public long? Id { get; set; } + /// + /// Close order price + /// + [JsonPropertyName("price")] + public decimal? Price { get; set; } + /// + /// Is liquidation order + /// + [JsonPropertyName("is_liq")] + public bool? IsLiquidation { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoPositionUpdate.cs b/GateIo.Net/Objects/Models/GateIoPositionUpdate.cs new file mode 100644 index 0000000..9e7a975 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoPositionUpdate.cs @@ -0,0 +1,102 @@ +using System.Text.Json.Serialization; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Position update + /// + public record GateIoPositionUpdate + { + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Update id + /// + [JsonPropertyName("update_id")] + public long UpdateId { get; set; } + /// + /// Contract + /// + [JsonPropertyName("contract")] + public string Contract { get; set; } = string.Empty; + /// + /// Position size + /// + [JsonPropertyName("size")] + public long Size { get; set; } + /// + /// Leverage + /// + [JsonPropertyName("leverage")] + public decimal Leverage { get; set; } + /// + /// Risk limit + /// + [JsonPropertyName("risk_limit")] + public decimal RiskLimit { get; set; } + /// + /// Max leverage + /// + [JsonPropertyName("leverage_max")] + public decimal MaxLeverage { get; set; } + /// + /// Maintenance rate + /// + [JsonPropertyName("maintenance_rate")] + public decimal MaintenanceRate { get; set; } + /// + /// Margin + /// + [JsonPropertyName("margin")] + public decimal Margin { get; set; } + /// + /// Entry price + /// + [JsonPropertyName("entry_price")] + public decimal? EntryPrice { get; set; } + /// + /// Liquidation price + /// + [JsonPropertyName("liq_price")] + public decimal? LiquidationPrice { get; set; } + /// + /// Realized profit and less + /// + [JsonPropertyName("realised_pnl")] + public decimal? RealisedPnl { get; set; } + /// + /// History realized PNL + /// + [JsonPropertyName("history_pnl")] + public decimal? HistoryPnl { get; set; } + /// + /// Last close pnl + /// + [JsonPropertyName("last_close_pnl")] + public decimal? LastClosePnl { get; set; } + /// + /// Realized POINT PNL + /// + [JsonPropertyName("realised_point")] + public decimal? RealsedPoinPnl { get; set; } + /// + /// History realized POINT PNL + /// + [JsonPropertyName("history_point")] + public decimal? HistoryPoinPnl { get; set; } + /// + /// Position mode + /// + [JsonPropertyName("mode")] + public PositionMode? PositionMode { get; set; } + /// + /// Cross margin leverage + /// + [JsonPropertyName("cross_leverage_limit")] + public int? CrossLeverageLimit { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoRiskLimitTier.cs b/GateIo.Net/Objects/Models/GateIoRiskLimitTier.cs new file mode 100644 index 0000000..8834d65 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoRiskLimitTier.cs @@ -0,0 +1,36 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Risk limit tier + /// + public record GateIoRiskLimitTier + { + /// + /// Maintenance rate + /// + [JsonPropertyName("maintenance_rate")] + public decimal MaintenanceRate { get; set; } + /// + /// Tier + /// + [JsonPropertyName("tier")] + public int Tier { get; set; } + /// + /// Initial margin rate + /// + [JsonPropertyName("initial_rate")] + public decimal InitialRate { get; set; } + /// + /// Max leverage + /// + [JsonPropertyName("leverage_max")] + public decimal MaxLeverage { get; set; } + /// + /// Risk limit + /// + [JsonPropertyName("risk_limit")] + public decimal RiskLimit { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoRiskUnits.cs b/GateIo.Net/Objects/Models/GateIoRiskUnits.cs new file mode 100644 index 0000000..7d5a215 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoRiskUnits.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Risk units + /// + public record GateIoRiskUnits + { + /// + /// User id + /// + [JsonPropertyName("user_id")] + public long UserId { get; set; } + /// + /// Spot hedge status + /// + [JsonPropertyName("spot_hedge")] + public bool SpotHedge { get; set; } + /// + /// Risk units + /// + [JsonPropertyName("risk_units")] + public IEnumerable RiskUnits { get; set; } = Array.Empty(); + } + + /// + /// Risk unit details + /// + public record GateIoRiskUnitsDetails + { + /// + /// Symbol + /// + [JsonPropertyName("symbol")] + public string Symbol { get; set; } = string.Empty; + /// + /// Spot hedging usage + /// + [JsonPropertyName("spot_in_use")] + public decimal SpotInUse { get; set; } + /// + /// Maintenance margin + /// + [JsonPropertyName("maintain_margin")] + public decimal MaintenanceMargin { get; set; } + /// + /// Initial margin + /// + [JsonPropertyName("initial_margin")] + public decimal InitialMargin { get; set; } + /// + /// Delta + /// + [JsonPropertyName("delta")] + public decimal Delta { get; set; } + /// + /// Gamma + /// + [JsonPropertyName("gamma")] + public decimal Gamma { get; set; } + /// + /// Theta + /// + [JsonPropertyName("theta")] + public decimal Theta { get; set; } + /// + /// Vega + /// + [JsonPropertyName("vega")] + public decimal Vega { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoSavedAddress.cs b/GateIo.Net/Objects/Models/GateIoSavedAddress.cs new file mode 100644 index 0000000..a1b1f09 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoSavedAddress.cs @@ -0,0 +1,41 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Saved address + /// + public record GateIoSavedAddress + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Address + /// + [JsonPropertyName("address")] + public string Address { get; set; } = string.Empty; + /// + /// Network + /// + [JsonPropertyName("chain")] + public string Network { get; set; } = string.Empty; + /// + /// Name + /// + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + /// + /// Tag + /// + [JsonPropertyName("tag")] + public string Tag { get; set; } = string.Empty; + /// + /// Is verified + /// + [JsonPropertyName("verified")] + public bool Verified { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoServerTime.cs b/GateIo.Net/Objects/Models/GateIoServerTime.cs new file mode 100644 index 0000000..a117606 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoServerTime.cs @@ -0,0 +1,11 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + internal record GateIoServerTime + { + [JsonPropertyName("server_time")] + public DateTime ServerTime { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoSmallBalance.cs b/GateIo.Net/Objects/Models/GateIoSmallBalance.cs new file mode 100644 index 0000000..eb5588c --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoSmallBalance.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Small balance info + /// + public record GateIoSmallBalance + { + /// + /// Asset name + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Available balance + /// + [JsonPropertyName("available_balance")] + public decimal AvailableBalance { get; set; } + /// + /// Estimated value in BTC + /// + [JsonPropertyName("estimated_as_btc")] + public decimal BtcValue { get; set; } + /// + /// Estimated value in GT + /// + [JsonPropertyName("convertible_to_gt")] + public decimal GtValue { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoSmallBalanceConversion.cs b/GateIo.Net/Objects/Models/GateIoSmallBalanceConversion.cs new file mode 100644 index 0000000..6ee2cfa --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoSmallBalanceConversion.cs @@ -0,0 +1,37 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Small balance conversion + /// + public record GateIoSmallBalanceConversion + { + /// + /// Id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Asset name + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Create time + /// + [JsonPropertyName("create_time")] + public DateTime Timestamp { get; set; } + /// + /// Input amount + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Output GT + /// + [JsonPropertyName("gt_amount")] + public decimal GtQuantity { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoSymbol.cs b/GateIo.Net/Objects/Models/GateIoSymbol.cs new file mode 100644 index 0000000..3ac638e --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoSymbol.cs @@ -0,0 +1,78 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Symbol info + /// + public record GateIoSymbol + { + /// + /// Name + /// + [JsonPropertyName("id")] + public string Name { get; set; } = string.Empty; + /// + /// Base asset + /// + [JsonPropertyName("base")] + public string BaseAsset { get; set; } = string.Empty; + /// + /// Quote asset + /// + [JsonPropertyName("quote")] + public string QuoteAsset { get; set; } = string.Empty; + /// + /// Trade fee + /// + [JsonPropertyName("fee")] + public decimal TradeFee { get; set; } + /// + /// Min base asset order quantity + /// + [JsonPropertyName("min_base_amount")] + public decimal MinBaseQuantity { get; set; } + /// + /// Min quote asset order quantity + /// + [JsonPropertyName("min_quote_amount")] + public decimal MinQuoteQuantity { get; set; } + /// + /// Max base asset order quantity + /// + [JsonPropertyName("max_base_amount")] + public decimal? MaxBaseQuantity { get; set; } + /// + /// Max quote asset order quantity + /// + [JsonPropertyName("max_quote_amount")] + public decimal MaxQuoteQuantity { get; set; } + /// + /// Quantity decimal precision + /// + [JsonPropertyName("amount_precision")] + public decimal QuantityPrecision { get; set; } + /// + /// Price decimal precision + /// + [JsonPropertyName("precision")] + public decimal PricePrecision { get; set; } + /// + /// Trading status + /// + [JsonPropertyName("trade_status")] + public SymbolStatus TradeStatus { get; set; } + /// + /// Sell start time + /// + [JsonPropertyName("sell_start")] + public DateTime SellStart { get; set; } + /// + /// Buy start time + /// + [JsonPropertyName("buy_start")] + public DateTime BuyStart { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoSymbolOrders.cs b/GateIo.Net/Objects/Models/GateIoSymbolOrders.cs new file mode 100644 index 0000000..f9022a0 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoSymbolOrders.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Orders for a symbol + /// + public record GateIoSymbolOrders + { + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Total count + /// + [JsonPropertyName("total")] + public int Total { get; set; } + /// + /// Orders + /// + [JsonPropertyName("orders")] + public IEnumerable Orders { get; set; } = Array.Empty(); + } +} diff --git a/GateIo.Net/Objects/Models/GateIoTicker.cs b/GateIo.Net/Objects/Models/GateIoTicker.cs new file mode 100644 index 0000000..fa9e4ad --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoTicker.cs @@ -0,0 +1,87 @@ +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Asset info + /// + public record GateIoTicker + { + /// + /// Symbol name + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Last traded price + /// + [JsonPropertyName("last")] + public decimal LastPrice { get; set; } + /// + /// Best ask price + /// + [JsonPropertyName("lowest_ask")] + public decimal? BestAskPrice { get; set; } + /// + /// Best bid price + /// + [JsonPropertyName("highest_bid")] + public decimal? BestBidPrice { get; set; } + /// + /// Change percentage last 24h + /// + [JsonPropertyName("change_percentage")] + public decimal ChangePercentage24h { get; set; } + /// + /// Change percentage UTC+0 timezone + /// + [JsonPropertyName("change_utc0")] + public decimal ChangePercentageUtc0 { get; set; } + /// + /// Change percentage UTC+8 timezone + /// + [JsonPropertyName("change_utc8")] + public decimal ChangePercentageUtc8 { get; set; } + /// + /// Volume last 24h in the base asset + /// + [JsonPropertyName("base_volume")] + public decimal BaseVolume { get; set; } + /// + /// Volume last 24h in the quote asset + /// + [JsonPropertyName("quote_volume")] + public decimal QuoteVolume { get; set; } + /// + /// Highest price in last 24h + /// + [JsonPropertyName("high_24h")] + public decimal HighPrice { get; set; } + /// + /// Lowest price in last 24h + /// + [JsonPropertyName("low_24h")] + public decimal LowPrice { get; set; } + /// + /// ETF Net value + /// + [JsonPropertyName("etf_net_value")] + public decimal EtfNetValue { get; set; } + /// + /// ETF previous net value + /// + [JsonPropertyName("etf_pre_net_value")] + public decimal? EtfPrevNetValue { get; set; } + /// + /// ETF previous rebalance time + /// + [JsonPropertyName("etf_pre_timestamp")] + public DateTime? EtfPrevRebalanceTime { get; set; } + /// + /// ETF current leverage + /// + [JsonPropertyName("etf_leverage")] + public decimal? EtfLeverage { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoTickerUpdate.cs b/GateIo.Net/Objects/Models/GateIoTickerUpdate.cs new file mode 100644 index 0000000..d3836f6 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoTickerUpdate.cs @@ -0,0 +1,56 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Ticker update + /// + public record GateIoTickerUpdate + { + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Last trade price + /// + [JsonPropertyName("last")] + public decimal LastPrice { get; set; } + /// + /// Best ask price + /// + [JsonPropertyName("lowest_ask")] + public decimal BestAskPrice { get; set; } + /// + /// Best bid price + /// + [JsonPropertyName("highest_bid")] + public decimal BestBidPrice { get; set; } + /// + /// Change percentage compared to 24h ago + /// + [JsonPropertyName("change_percentage")] + public decimal ChangePercentage24h { get; set; } + /// + /// Volume in base asset + /// + [JsonPropertyName("base_volume")] + public decimal BaseVolume { get; set; } + /// + /// Volume in quote asset + /// + [JsonPropertyName("quote_volume")] + public decimal QuoteVolume { get; set; } + /// + /// 24h high price + /// + [JsonPropertyName("high_24h")] + public decimal HighPrice { get; set; } + /// + /// 24h low price + /// + [JsonPropertyName("low_24h")] + public decimal LowPrice { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoTrade.cs b/GateIo.Net/Objects/Models/GateIoTrade.cs new file mode 100644 index 0000000..f55d0bb --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoTrade.cs @@ -0,0 +1,95 @@ +using System; +using System.Text.Json.Serialization; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Trade info + /// + public record GateIoTrade + { + /// + /// Trade id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Timestamp + /// + [JsonPropertyName("create_time_ms")] + public DateTime CreateTime { get; set; } + /// + /// Order side + /// + [JsonPropertyName("side")] + public OrderSide Side { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Trade price + /// + [JsonPropertyName("price")] + public decimal Price { get; set; } + /// + /// Sequence id + /// + [JsonPropertyName("sequence_id")] + public decimal SequenceId { get; set; } + } + + /// + /// User trade info + /// + public record GateIoUserTrade: GateIoTrade + { + /// + /// Role + /// + [JsonPropertyName("role")] + public Role Role { get; set; } + /// + /// Order id + /// + [JsonPropertyName("order_id")] + public string OrderId { get; set; } = string.Empty; + /// + /// Trade fee + /// + [JsonPropertyName("fee")] + public decimal Fee { get; set; } + /// + /// Asset the fee is in + /// + [JsonPropertyName("fee_currency")] + public string FeeAsset { get; set; } = string.Empty; + /// + /// Points used to deduct fee + /// + [JsonPropertyName("point_fee")] + public decimal PointFee { get; set; } + /// + /// GT used to deduct fee. + /// + [JsonPropertyName("gt_fee")] + public decimal GTFee { get; set; } + /// + /// The custom data that the user remarked when amending the order + /// + [JsonPropertyName("amend_text")] + public string? AmendText { get; set; } + /// + /// User defined information + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoTradeUpdate.cs b/GateIo.Net/Objects/Models/GateIoTradeUpdate.cs new file mode 100644 index 0000000..23a6132 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoTradeUpdate.cs @@ -0,0 +1,48 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Trade update + /// + public record GateIoTradeUpdate + { + /// + /// Trade id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time_ms")] + public DateTime CreateTime { get; set; } + /// + /// Side + /// + [JsonPropertyName("side")] + public OrderSide Side { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Trade quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Trade price + /// + [JsonPropertyName("price")] + public decimal Price { get; set; } + /// + /// The start and end sequence id + /// + [JsonPropertyName("range")] + public string TradeRange { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Models/GateIoTransfer.cs b/GateIo.Net/Objects/Models/GateIoTransfer.cs new file mode 100644 index 0000000..c823013 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoTransfer.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Transfer + /// + public record GateIoTransfer + { + /// + /// Transation id + /// + [JsonPropertyName("tx_id")] + public long TransactionId { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoTriggerOrder.cs b/GateIo.Net/Objects/Models/GateIoTriggerOrder.cs new file mode 100644 index 0000000..0f360fb --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoTriggerOrder.cs @@ -0,0 +1,128 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Trigger order info + /// + public record GateIoTriggerOrder + { + /// + /// Order info + /// + [JsonPropertyName("put")] + public GateIoTriggerOrderOrder Order { get; set; } = null!; + + /// + /// Order info + /// + [JsonPropertyName("trigger")] + public GateIoTriggerOrderTrigger Trigger { get; set; } = null!; + /// + /// Trigger order id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// User id + /// + [JsonPropertyName("user")] + public long UserId { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("market")] + public string Symbol { get; set; } = string.Empty; + /// + /// Create time + /// + [JsonPropertyName("ctime")] + public DateTime CreateTime { get; set; } + /// + /// Trigger time + /// + [JsonPropertyName("ftime")] + public DateTime? TriggerTime { get; set; } + /// + /// Id of the create order + /// + [JsonPropertyName("fired_order_id")] + public long? TriggeredOrderId { get; set; } + /// + /// Trigger status + /// + [JsonPropertyName("status")] + public TriggerOrderStatus? Status { get; set; } + /// + /// Additional info + /// + [JsonPropertyName("reason")] + public string? Reason { get; set; } + } + + /// + /// Trigger order trigger info + /// + public record GateIoTriggerOrderTrigger + { + /// + /// Trigger price + /// + [JsonPropertyName("price")] + public decimal Price { get; set; } + /// + /// Trigger type + /// + [JsonPropertyName("rule")] + public TriggerType TriggerType { get; set; } + /// + /// Expiration in seconds + /// + [JsonPropertyName("expiration")] + public int Expiration { get; set; } + } + + /// + /// Order info + /// + public record GateIoTriggerOrderOrder + { + /// + /// User defined text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Order type + /// + [JsonPropertyName("type")] + public NewOrderType Type { get; set; } + /// + /// Order side + /// + [JsonPropertyName("side")] + public OrderSide Side { get; set; } + /// + /// Account type + /// + [JsonPropertyName("account")] + public TriggerAccountType AccountType { get; set; } + /// + /// Time in force + /// + [JsonPropertyName("time_in_force")] + public TimeInForce TimeInForce { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Order price + /// + [JsonPropertyName("price")] + public decimal? Price { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoTriggerOrderUpdate.cs b/GateIo.Net/Objects/Models/GateIoTriggerOrderUpdate.cs new file mode 100644 index 0000000..6ff5cc9 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoTriggerOrderUpdate.cs @@ -0,0 +1,133 @@ +using GateIo.Net.Enums; +using System; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Trigger order update + /// + public record GateIoTriggerOrderUpdate + { + /// + /// Symbol + /// + [JsonPropertyName("market")] + public string Symbol { get; set; } = string.Empty; + /// + /// User id + /// + [JsonPropertyName("uid")] + public string UserId { get; set; } = string.Empty; + /// + /// Id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Base asset + /// + [JsonPropertyName("currency_type")] + public string BaseAsset { get; set; } = string.Empty; + /// + /// Quote asset + /// + [JsonPropertyName("exchange_type")] + public string QuoteAsset { get; set; } = string.Empty; + /// + /// Reason + /// + [JsonPropertyName("reason")] + public string Reason { get; set; } = string.Empty; + /// + /// Error message + /// + [JsonPropertyName("err_msg")] + public string ErrorMessage { get; set; } = string.Empty; + /// + /// Id of the order which was placed after triggering + /// + [JsonPropertyName("fired_order_id")] + public long FiredOrderId { get; set; } + /// + /// Instant cancel + /// + [JsonPropertyName("instant_cancel")] + public bool InstantCancel { get; set; } + /// + /// Trigger price + /// + [JsonPropertyName("trigger_price")] + public decimal TriggerPrice { get; set; } + /// + /// Trigger type + /// + [JsonPropertyName("trigger_rule")] + public TriggerType TriggerType { get; set; } + /// + /// Expiration in seconds + /// + [JsonPropertyName("trigger_expiration")] + public int Expiration { get; set; } + /// + /// Price + /// + [JsonPropertyName("price")] + public decimal? Price { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Source + /// + [JsonPropertyName("source")] + public string Source { get; set; } = string.Empty; + /// + /// Order type + /// + [JsonPropertyName("order_type")] + public OrderType OrderType { get; set; } + /// + /// Side + /// + [JsonPropertyName("side")] + public OrderSide OrderSide { get; set; } + /// + /// Engine type + /// + [JsonPropertyName("engine_type")] + public string EngineType { get; set; } = string.Empty; + /// + /// Is stop order + /// + [JsonPropertyName("is_stop_order")] + public bool IsStopOrder { get; set; } + /// + /// Stop trigger price + /// + [JsonPropertyName("stop_trigger_price")] + public decimal? StopTriggerPrice { get; set; } + /// + /// Stop trigger rule + /// + [JsonPropertyName("stop_trigger_rule")] + public string? StopTriggerRule { get; set; } + /// + /// Stop price + /// + [JsonPropertyName("stop_price")] + public decimal? StopPrice { get; set; } + /// + /// Create time + /// + [JsonPropertyName("ctime")] + public DateTime CreateTime { get; set; } + /// + /// Fire time + /// + [JsonPropertyName("ftime")] + public DateTime? FireTime { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoUnifiedAccountInfo.cs b/GateIo.Net/Objects/Models/GateIoUnifiedAccountInfo.cs new file mode 100644 index 0000000..3cf4504 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoUnifiedAccountInfo.cs @@ -0,0 +1,154 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Unified account info + /// + public record GateIoUnifiedAccountInfo + { + /// + /// User id + /// + [JsonPropertyName("user_id")] + public long UserId { get; set; } + /// + /// Locked + /// + [JsonPropertyName("locked")] + public bool Locked { get; set; } + /// + /// Total value in USD + /// + [JsonPropertyName("total")] + public decimal Total { get; set; } + /// + /// Borrowed value in USD + /// + [JsonPropertyName("borrowed")] + public decimal Borrowed { get; set; } + /// + /// Total initial margin + /// + [JsonPropertyName("total_initial_margin")] + public decimal TotalInitialMargin { get; set; } + /// + /// Total margin balance + /// + [JsonPropertyName("total_margin_balance")] + public decimal TotalMarginBalance { get; set; } + /// + /// Total maintenance margin + /// + [JsonPropertyName("total_maintenance_margin")] + public decimal TotalMaintenanceMargin { get; set; } + /// + /// Total initial margin rate + /// + [JsonPropertyName("total_initial_margin_rate")] + public decimal TotalInitialMarginRate { get; set; } + /// + /// Total maintenance margin rate + /// + [JsonPropertyName("total_maintenance_margin_rate")] + public decimal TotalMaintenanceMarginRate { get; set; } + /// + /// Total available margin + /// + [JsonPropertyName("total_available_margin")] + public decimal TotalAvailableMargin { get; set; } + /// + /// Unified account total + /// + [JsonPropertyName("unified_account_total")] + public decimal UnifiedAccountTotal { get; set; } + /// + /// Unified account total liabilities + /// + [JsonPropertyName("unified_account_total_liab")] + public decimal UnifiedAccountTotalLiabilities { get; set; } + /// + /// Unified account total equity + /// + [JsonPropertyName("unified_account_total_equity")] + public decimal UnifiedAccountTotalEquity { get; set; } + /// + /// Leverage + /// + [JsonPropertyName("leverage")] + public decimal Leverage { get; set; } + /// + /// Total order loss, in USDT + /// + [JsonPropertyName("spot_order_loss")] + public decimal TotalOrderLoss { get; set; } + /// + /// Spot hedging status + /// + [JsonPropertyName("spot_hedge")] + public bool SpotHedge { get; set; } + /// + /// Whether to use funds as margin + /// + [JsonPropertyName("use_funding")] + public bool? UseFunding { get; set; } + /// + /// Balances + /// + [JsonPropertyName("balances")] + public Dictionary Balances { get; set; } = new Dictionary(); + } + + /// + /// Unified account balance + /// + public record GateIoUnifiedAccountBalance + { + /// + /// Available quantity + /// + [JsonPropertyName("available")] + public decimal Available { get; set; } + /// + /// Frozen quantity + /// + [JsonPropertyName("freeze")] + public decimal Frozen { get; set; } + /// + /// Borrowed quantity + /// + [JsonPropertyName("borrowed")] + public decimal Borrowed { get; set; } + /// + /// Negative liabilities + /// + [JsonPropertyName("negative_liab")] + public decimal NegativeLiabilities { get; set; } + /// + /// Borrowing to open futures positions + /// + [JsonPropertyName("futures_pos_liab")] + public decimal FuturesPositionLiabilities { get; set; } + /// + /// Equity + /// + [JsonPropertyName("equity")] + public decimal Equity { get; set; } + /// + /// Total frozen + /// + [JsonPropertyName("total_freeze")] + public decimal TotalFrozen { get; set; } + /// + /// Total liabilities + /// + [JsonPropertyName("total_liab")] + public decimal TotalLiabilities { get; set; } + /// + /// Spot hedging utilization + /// + [JsonPropertyName("spot_in_use")] + public decimal SpotInUse { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoUnifiedAccountMax.cs b/GateIo.Net/Objects/Models/GateIoUnifiedAccountMax.cs new file mode 100644 index 0000000..2229a2f --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoUnifiedAccountMax.cs @@ -0,0 +1,26 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Max borrowable info + /// + public record GateIoUnifiedAccountMax + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string? Symbol { get; set; } + /// + /// Max borrowable + /// + [JsonPropertyName("amount")] + public decimal MaxBorrowable { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoUnifiedAccountMode.cs b/GateIo.Net/Objects/Models/GateIoUnifiedAccountMode.cs new file mode 100644 index 0000000..eec11a9 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoUnifiedAccountMode.cs @@ -0,0 +1,44 @@ +using GateIo.Net.Enums; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Unified account mode + /// + public record GateIoUnifiedAccountMode + { + /// + /// Account mode + /// + [JsonPropertyName("mode")] + public UnifiedAccountMode Mode { get; set; } + /// + /// Settings + /// + [JsonPropertyName("settings")] + public GateIoUnifiedAccountSettings Settings { get; set; } = null!; + } + + /// + /// Unified account settings + /// + public record GateIoUnifiedAccountSettings + { + /// + /// USDT contract switch + /// + [JsonPropertyName("usdt_futures")] + public bool UsdtFutures { get; set; } + /// + /// Spot hedging switch + /// + [JsonPropertyName("spot_hedge")] + public bool SpotHedge { get; set; } + /// + /// When the mode is set to combined margin mode, will funds be used as margin + /// + [JsonPropertyName("use_funding")] + public bool UseFunding { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoUserTradeUpdate.cs b/GateIo.Net/Objects/Models/GateIoUserTradeUpdate.cs new file mode 100644 index 0000000..f42324d --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoUserTradeUpdate.cs @@ -0,0 +1,78 @@ +using System; +using System.Text.Json.Serialization; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// User trade updates + /// + public record GateIoUserTradeUpdate + { + /// + /// Order id + /// + [JsonPropertyName("order_id")] + public string OrderId { get; set; } = string.Empty; + /// + /// Trade id + /// + [JsonPropertyName("id")] + public long Id { get; set; } + /// + /// Text + /// + [JsonPropertyName("text")] + public string? Text { get; set; } + /// + /// Create time + /// + [JsonPropertyName("create_time_ms")] + public DateTime CreateTime { get; set; } + /// + /// Symbol + /// + [JsonPropertyName("currency_pair")] + public string Symbol { get; set; } = string.Empty; + /// + /// Role + /// + [JsonPropertyName("role")] + public Role Role { get; set; } + /// + /// Order side + /// + [JsonPropertyName("side")] + public OrderSide Side { get; set; } + /// + /// Order quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Order price + /// + [JsonPropertyName("price")] + public decimal? Price { get; set; } + /// + /// Fee paid + /// + [JsonPropertyName("fee")] + public decimal Fee { get; set; } + /// + /// Points used to deduct fee + /// + [JsonPropertyName("point_fee")] + public decimal? PointFee { get; set; } + /// + /// GT used to deduct fee + /// + [JsonPropertyName("gt_fee")] + public decimal? GtFee { get; set; } + /// + /// User id + /// + [JsonPropertyName("user_id")] + public long? UserId { get; set; } + } +} diff --git a/GateIo.Net/Objects/Models/GateIoWithdrawStatus.cs b/GateIo.Net/Objects/Models/GateIoWithdrawStatus.cs new file mode 100644 index 0000000..21ea440 --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoWithdrawStatus.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Withdraw status + /// + public record GateIoWithdrawStatus + { + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Asset name + /// + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + /// + /// Asset name in Chinese + /// + [JsonPropertyName("name_cn")] + public string NameCn { get; set; } = string.Empty; + /// + /// Deposit fee + /// + [JsonPropertyName("deposit")] + public decimal DepositFee { get; set; } + /// + /// Withdrawal fee percentage + /// + [JsonPropertyName("withdraw_percent")] + public string WithdrawalFeePercentage { get; set; } = string.Empty; + /// + /// Withdrawal fee fixed quantity + /// + [JsonPropertyName("withdraw_fix")] + public decimal WithdrawalFeeFixed { get; set; } + /// + /// Withdrawal day limit + /// + [JsonPropertyName("withdraw_day_limit")] + public decimal WithdrawalDayLimit { get; set; } + /// + /// Withdrawal day limit left + /// + [JsonPropertyName("withdraw_day_limit_remain")] + public decimal WithdrawalDayLimitLeft { get; set; } + /// + /// Minimal quantity that can be withdrawn + /// + [JsonPropertyName("withdraw_amount_mini")] + public decimal MinimalWithdrawalQuantity { get; set; } + /// + /// Max quantity per withdrawal + /// + [JsonPropertyName("withdraw_eachtime_limit")] + public decimal MaxPerWithdrawalQuantity { get; set; } + /// + /// Fixed withdrawal fee on multiple networks + /// + [JsonPropertyName("withdraw_fix_on_chains")] + public Dictionary WithdrawalFeeNetworksFixed { get; set; } = new Dictionary(); + /// + /// Percentage withdrawal fee on multiple networks + /// + [JsonPropertyName("withdraw_percent_on_chains")] + public Dictionary WithdrawalFeeNetworksPercentage { get; set; } = new Dictionary(); + } +} diff --git a/GateIo.Net/Objects/Models/GateIoWithdrawal.cs b/GateIo.Net/Objects/Models/GateIoWithdrawal.cs new file mode 100644 index 0000000..8ce191f --- /dev/null +++ b/GateIo.Net/Objects/Models/GateIoWithdrawal.cs @@ -0,0 +1,68 @@ +using System; +using System.Text.Json.Serialization; +using GateIo.Net.Enums; + +namespace GateIo.Net.Objects.Models +{ + /// + /// Withdrawal info + /// + public record GateIoWithdrawal + { + /// + /// Withdrawal id + /// + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + /// + /// Client specified id + /// + [JsonPropertyName("withdraw_order_id")] + public string? ClientOrderId { get; set; } + /// + /// Asset + /// + [JsonPropertyName("currency")] + public string Asset { get; set; } = string.Empty; + /// + /// Address + /// + [JsonPropertyName("address")] + public string Address { get; set; } = string.Empty; + /// + /// Network + /// + [JsonPropertyName("chain")] + public string Network { get; set; } = string.Empty; + /// + /// Memo + /// + [JsonPropertyName("memo")] + public string? Memo { get; set; } + /// + /// Quantity + /// + [JsonPropertyName("amount")] + public decimal Quantity { get; set; } + /// + /// Fee + /// + [JsonPropertyName("fee")] + public decimal? Fee { get; set; } + /// + /// Timestamp + /// + [JsonPropertyName("timestamp")] + public DateTime Timestamp { get; set; } + /// + /// Transaction id + /// + [JsonPropertyName("txid")] + public string TransactionId { get; set; } = string.Empty; + /// + /// Withdrawal status + /// + [JsonPropertyName("status")] + public WithdrawalStatus Status { get; set; } + } +} diff --git a/GateIo.Net/Objects/Options/GateIoOrderBookOptions.cs b/GateIo.Net/Objects/Options/GateIoOrderBookOptions.cs new file mode 100644 index 0000000..845a919 --- /dev/null +++ b/GateIo.Net/Objects/Options/GateIoOrderBookOptions.cs @@ -0,0 +1,40 @@ +using CryptoExchange.Net.Objects.Options; +using System; + +namespace GateIo.Net.Objects.Options +{ + /// + /// Options for the GateIo SymbolOrderBook + /// + public class GateIoOrderBookOptions : OrderBookOptions + { + /// + /// Default options for new clients + /// + public static GateIoOrderBookOptions Default { get; set; } = new GateIoOrderBookOptions(); + + /// + /// The top amount of results to keep in sync. If for example limit=10 is used, the order book will contain the 10 best bids and 10 best asks. Leaving this null will sync the full order book + /// + public int? Limit { get; set; } + + /// + /// Update interval in milliseconds, either 100 or 1000. Defaults to 1000 + /// + public int? UpdateInterval { get; set; } + + /// + /// After how much time we should consider the connection dropped if no data is received for this time after the initial subscriptions + /// + public TimeSpan? InitialDataTimeout { get; set; } + + internal GateIoOrderBookOptions Copy() + { + var result = Copy(); + result.Limit = Limit; + result.UpdateInterval = UpdateInterval; + result.InitialDataTimeout = InitialDataTimeout; + return result; + } + } +} diff --git a/GateIo.Net/Objects/Options/GateIoRestOptions.cs b/GateIo.Net/Objects/Options/GateIoRestOptions.cs new file mode 100644 index 0000000..ad62b2f --- /dev/null +++ b/GateIo.Net/Objects/Options/GateIoRestOptions.cs @@ -0,0 +1,44 @@ +using CryptoExchange.Net.Objects.Options; + +namespace GateIo.Net.Objects.Options +{ + /// + /// Options for the GateIoRestClient + /// + public class GateIoRestOptions : RestExchangeOptions + { + /// + /// Default options for new clients + /// + public static GateIoRestOptions Default { get; set; } = new GateIoRestOptions() + { + Environment = GateIoEnvironment.Live, + AutoTimestamp = true + }; + + /// + /// Broker id + /// + public string? BrokerId { get; set; } + + /// + /// Spot API options + /// + public RestApiOptions SpotOptions { get; private set; } = new RestApiOptions + { + }; + + /// + /// Futures API options + /// + public RestApiOptions PerpetualFuturesOptions { get; private set; } = new RestApiOptions(); + + internal GateIoRestOptions Copy() + { + var options = Copy(); + options.SpotOptions = SpotOptions.Copy(); + options.PerpetualFuturesOptions = PerpetualFuturesOptions.Copy(); + return options; + } + } +} diff --git a/GateIo.Net/Objects/Options/GateIoSocketOptions.cs b/GateIo.Net/Objects/Options/GateIoSocketOptions.cs new file mode 100644 index 0000000..d482e43 --- /dev/null +++ b/GateIo.Net/Objects/Options/GateIoSocketOptions.cs @@ -0,0 +1,40 @@ +using CryptoExchange.Net.Objects.Options; + +namespace GateIo.Net.Objects.Options +{ + /// + /// Options for the GateIoSocketClient + /// + public class GateIoSocketOptions : SocketExchangeOptions + { + /// + /// Default options for new clients + /// + public static GateIoSocketOptions Default { get; set; } = new GateIoSocketOptions() + { + Environment = GateIoEnvironment.Live, + SocketSubscriptionsCombineTarget = 10, + MaxSocketConnections = 300 + }; + + /// + /// Options for the Spot API + /// + public SocketApiOptions SpotOptions { get; private set; } = new SocketApiOptions() + { + }; + + /// + /// Options for the Perpetual Futures API + /// + public SocketApiOptions PerpetualFuturesOptions { get; private set; } = new SocketApiOptions(); + + internal GateIoSocketOptions Copy() + { + var options = Copy(); + options.SpotOptions = SpotOptions.Copy(); + options.PerpetualFuturesOptions = PerpetualFuturesOptions.Copy(); + return options; + } + } +} diff --git a/GateIo.Net/Objects/Sockets/GateIoAuthQuery.cs b/GateIo.Net/Objects/Sockets/GateIoAuthQuery.cs new file mode 100644 index 0000000..96c88ab --- /dev/null +++ b/GateIo.Net/Objects/Sockets/GateIoAuthQuery.cs @@ -0,0 +1,29 @@ +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using CryptoExchange.Net.Sockets; +using System.Collections.Generic; +using CryptoExchange.Net; +using CryptoExchange.Net.Converters.JsonNet; +using System; + +namespace GateIo.Net.Objects.Sockets +{ + internal class GateIoAuthQuery : Query> + { + public override HashSet ListenerIdentifiers { get; set; } + + public GateIoAuthQuery(string channel, string evnt, IEnumerable? payload) + : base(new GateIoSocketAuthRequest { Channel = channel, Event = evnt, Id = ExchangeHelpers.NextId(), Payload = payload, Timestamp = (long)DateTimeConverter.ConvertToSeconds(DateTime.UtcNow) }, false, 1) + { + ListenerIdentifiers = new HashSet { ((GateIoSocketAuthRequest)Request).Id.ToString() }; + } + + public override CallResult> HandleMessage(SocketConnection connection, DataEvent> message) + { + if (message.Data.Error != null) + return message.ToCallResult>(new ServerError(message.Data.Error.Code, message.Data.Error.Message)); + + return message.ToCallResult(message.Data); + } + } +} diff --git a/GateIo.Net/Objects/Sockets/GateIoQuery.cs b/GateIo.Net/Objects/Sockets/GateIoQuery.cs new file mode 100644 index 0000000..4d3f590 --- /dev/null +++ b/GateIo.Net/Objects/Sockets/GateIoQuery.cs @@ -0,0 +1,28 @@ +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using CryptoExchange.Net.Sockets; +using System.Collections.Generic; +using CryptoExchange.Net; +using CryptoExchange.Net.Converters.JsonNet; +using System; + +namespace GateIo.Net.Objects.Sockets +{ + internal class GateIoQuery : Query> + { + public override HashSet ListenerIdentifiers { get; set; } + + public GateIoQuery(string channel, string evnt, IEnumerable? payload) : base(new GateIoSocketRequest { Channel = channel, Event = evnt, Id = ExchangeHelpers.NextId(), Payload = payload, Timestamp = (long)DateTimeConverter.ConvertToSeconds(DateTime.UtcNow) }, false, 1) + { + ListenerIdentifiers = new HashSet { ((GateIoSocketRequest)Request).Id.ToString() }; + } + + public override CallResult> HandleMessage(SocketConnection connection, DataEvent> message) + { + if (message.Data.Error != null) + return message.ToCallResult>(new ServerError(message.Data.Error.Code, message.Data.Error.Message)); + + return message.ToCallResult(message.Data); + } + } +} diff --git a/GateIo.Net/Objects/Sockets/GateIoSocketError.cs b/GateIo.Net/Objects/Sockets/GateIoSocketError.cs new file mode 100644 index 0000000..f3b452f --- /dev/null +++ b/GateIo.Net/Objects/Sockets/GateIoSocketError.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Sockets +{ + internal class GateIoSocketError + { + [JsonPropertyName("code")] + public int Code { get; set; } + [JsonPropertyName("message")] + public string Message { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Sockets/GateIoSocketMessage.cs b/GateIo.Net/Objects/Sockets/GateIoSocketMessage.cs new file mode 100644 index 0000000..391b57b --- /dev/null +++ b/GateIo.Net/Objects/Sockets/GateIoSocketMessage.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Sockets +{ + internal class GateIoSocketMessage + { + [JsonPropertyName("time_ms")] + public DateTime Timestamp { get; set; } + [JsonPropertyName("channel")] + public string Channel { get; set; } = string.Empty; + [JsonPropertyName("event")] + public string Event { get; set; } = string.Empty; + [JsonPropertyName("payload")] + public IEnumerable? Payload { get; set; } + [JsonPropertyName("error")] + public GateIoSocketError? Error { get; set; } + [JsonPropertyName("result")] + public T Result { get; set; } = default!; + } + + internal class GateIoSocketResponse: GateIoSocketMessage + { + + [JsonPropertyName("id")] + public long Id { get; set; } + } +} diff --git a/GateIo.Net/Objects/Sockets/GateIoSocketRequest.cs b/GateIo.Net/Objects/Sockets/GateIoSocketRequest.cs new file mode 100644 index 0000000..39c85c3 --- /dev/null +++ b/GateIo.Net/Objects/Sockets/GateIoSocketRequest.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Sockets +{ + internal class GateIoSocketRequest + { + [JsonPropertyName("time")] + public long Timestamp { get; set; } + [JsonPropertyName("id")] + public long Id { get; set; } + [JsonPropertyName("channel")] + public string Channel { get; set; } = string.Empty; + [JsonPropertyName("event")] + public string Event { get; set; } = string.Empty; + [JsonPropertyName("payload"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public IEnumerable? Payload { get; set; } + } + + internal class GateIoSocketAuthRequest : GateIoSocketRequest + { + [JsonPropertyName("auth"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public GateIoSocketAuth? Auth { get; set; } + } + + internal class GateIoSocketAuth + { + [JsonPropertyName("method")] + public string Method { get; set; } = string.Empty; + [JsonPropertyName("KEY")] + public string Key { get; set; } = string.Empty; + [JsonPropertyName("SIGN")] + public string Sign { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Sockets/GateIoSubscriptionResponse.cs b/GateIo.Net/Objects/Sockets/GateIoSubscriptionResponse.cs new file mode 100644 index 0000000..3d079de --- /dev/null +++ b/GateIo.Net/Objects/Sockets/GateIoSubscriptionResponse.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace GateIo.Net.Objects.Sockets +{ + internal class GateIoSubscriptionResponse + { + public bool Success => string.Equals(Status, "success"); + + [JsonPropertyName("success")] + public string Status { get; set; } = string.Empty; + } +} diff --git a/GateIo.Net/Objects/Sockets/Subscriptions/GateIoAuthSubscription.cs b/GateIo.Net/Objects/Sockets/Subscriptions/GateIoAuthSubscription.cs new file mode 100644 index 0000000..6553516 --- /dev/null +++ b/GateIo.Net/Objects/Sockets/Subscriptions/GateIoAuthSubscription.cs @@ -0,0 +1,68 @@ +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using CryptoExchange.Net.Sockets; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; + +namespace GateIo.Net.Objects.Sockets.Subscriptions +{ + /// + internal class GateIoAuthSubscription : Subscription, GateIoSocketResponse> + { + /// + public override HashSet ListenerIdentifiers { get; set; } + + private readonly Action> _handler; + private readonly string _channel; + private readonly IEnumerable? _payload; + + /// + public override Type? GetMessageType(IMessageAccessor message) + { + return typeof(GateIoSocketMessage); + } + + /// + /// ctor + /// + /// + /// + /// + /// + /// + public GateIoAuthSubscription(ILogger logger, string channel, IEnumerable identifiers, IEnumerable? payload, Action> handler) : base(logger, false) + { + _handler = handler; + _channel = channel; + _payload = payload; + ListenerIdentifiers = new HashSet(identifiers); + } + + /// + public override Query? GetSubQuery(SocketConnection connection) + { + var provider = (GateIoAuthenticationProvider)connection.ApiClient.AuthenticationProvider!; + var query = new GateIoAuthQuery(_channel, "subscribe", _payload); + var request = (GateIoSocketAuthRequest)query.Request; + var sign = provider.SignSocketRequest($"channel={_channel}&event=subscribe&time={request.Timestamp}"); + request.Auth = new GateIoSocketAuth { Key = provider.GetApiKey(), Sign = sign, Method = "api_key" }; + return query; + } + + /// + public override Query? GetUnsubQuery() + { + return new GateIoQuery(_channel, "unsubscribe", _payload); + } + + /// + public override CallResult DoHandleMessage(SocketConnection connection, DataEvent message) + { + var data = (GateIoSocketMessage)message.Data; + _handler.Invoke(message.As(data.Result, data.Channel, null, SocketUpdateType.Update)); + return new CallResult(null); + } + } +} diff --git a/GateIo.Net/Objects/Sockets/Subscriptions/GateIoSubscription.cs b/GateIo.Net/Objects/Sockets/Subscriptions/GateIoSubscription.cs new file mode 100644 index 0000000..74823f7 --- /dev/null +++ b/GateIo.Net/Objects/Sockets/Subscriptions/GateIoSubscription.cs @@ -0,0 +1,61 @@ +using CryptoExchange.Net.Interfaces; +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using CryptoExchange.Net.Sockets; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; + +namespace GateIo.Net.Objects.Sockets.Subscriptions +{ + /// + internal class GateIoSubscription : Subscription, GateIoSocketResponse> + { + /// + public override HashSet ListenerIdentifiers { get; set; } + + private readonly Action> _handler; + private readonly string _channel; + private readonly IEnumerable _payload; + + /// + public override Type? GetMessageType(IMessageAccessor message) + { + return typeof(GateIoSocketMessage); + } + + /// + /// ctor + /// + /// + /// + /// + /// + /// + /// + public GateIoSubscription(ILogger logger, string channel, IEnumerable identifiers, IEnumerable payload, Action> handler, bool auth) : base(logger, auth) + { + _handler = handler; + _channel = channel; + _payload = payload; + ListenerIdentifiers = new HashSet(identifiers); + } + + /// + public override Query? GetSubQuery(SocketConnection connection) + => new GateIoQuery(_channel, "subscribe", _payload); + + /// + public override Query? GetUnsubQuery() + => new GateIoQuery(_channel, "unsubscribe", _payload); + + + /// + public override CallResult DoHandleMessage(SocketConnection connection, DataEvent message) + { + var data = (GateIoSocketMessage)message.Data; + _handler.Invoke(message.As(data.Result, data.Channel, null, SocketUpdateType.Update)); + return new CallResult(null); + } + } +} diff --git a/GateIo.Net/Properties/AssemblyInfo.cs b/GateIo.Net/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..36851b4 --- /dev/null +++ b/GateIo.Net/Properties/AssemblyInfo.cs @@ -0,0 +1,13 @@ +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4e00b047-875a-4aac-a205-f1ef0db81fd7")] diff --git a/GateIo.Net/SymbolOrderBooks/GateIoOrderBookFactory.cs b/GateIo.Net/SymbolOrderBooks/GateIoOrderBookFactory.cs new file mode 100644 index 0000000..015a82f --- /dev/null +++ b/GateIo.Net/SymbolOrderBooks/GateIoOrderBookFactory.cs @@ -0,0 +1,60 @@ +using CryptoExchange.Net.Interfaces; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using GateIo.Net.Interfaces; +using GateIo.Net.Interfaces.Clients; +using GateIo.Net.Objects.Options; +using CryptoExchange.Net.OrderBook; + +namespace GateIo.Net.SymbolOrderBooks +{ + /// + /// GateIo order book factory + /// + public class GateIoOrderBookFactory : IGateIoOrderBookFactory + { + private readonly IServiceProvider _serviceProvider; + + /// + /// ctor + /// + /// Service provider for resolving logging and clients + public GateIoOrderBookFactory(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + + Spot = new OrderBookFactory((symbol, options) => CreateSpot(symbol, options), (baseAsset, quoteAsset, options) => CreateSpot(baseAsset + "_" + quoteAsset, options)); + PerpetualFuturesBtc = new OrderBookFactory((symbol, options) => CreatePerpetualFutures("btc", symbol, options), (baseAsset, quoteAsset, options) => CreatePerpetualFutures("btc", baseAsset + "_" + quoteAsset, options)); + PerpetualFuturesUsd = new OrderBookFactory((symbol, options) => CreatePerpetualFutures("usd", symbol, options), (baseAsset, quoteAsset, options) => CreatePerpetualFutures("usd", baseAsset + "_" + quoteAsset, options)); + PerpetualFuturesUsdt = new OrderBookFactory((symbol, options) => CreatePerpetualFutures("usdt", symbol, options), (baseAsset, quoteAsset, options) => CreatePerpetualFutures("usdt", baseAsset + "_" + quoteAsset, options)); + } + + /// + public IOrderBookFactory Spot { get; } + /// + public IOrderBookFactory PerpetualFuturesBtc { get; } + /// + public IOrderBookFactory PerpetualFuturesUsd { get; } + /// + public IOrderBookFactory PerpetualFuturesUsdt { get; } + + /// + public ISymbolOrderBook CreateSpot(string symbol, Action? options = null) + => new GateIoSpotSymbolOrderBook(symbol, + options, + _serviceProvider.GetRequiredService(), + _serviceProvider.GetRequiredService(), + _serviceProvider.GetRequiredService()); + + + /// + public ISymbolOrderBook CreatePerpetualFutures(string settlementAsset, string symbol, Action? options = null) + => new GateIoPerpetualFuturesSymbolOrderBook(settlementAsset, + symbol, + options, + _serviceProvider.GetRequiredService(), + _serviceProvider.GetRequiredService(), + _serviceProvider.GetRequiredService()); + } +} diff --git a/GateIo.Net/SymbolOrderBooks/GateIoPerpetualFuturesSymbolOrderBook.cs b/GateIo.Net/SymbolOrderBooks/GateIoPerpetualFuturesSymbolOrderBook.cs new file mode 100644 index 0000000..e5300f0 --- /dev/null +++ b/GateIo.Net/SymbolOrderBooks/GateIoPerpetualFuturesSymbolOrderBook.cs @@ -0,0 +1,135 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using CryptoExchange.Net.OrderBook; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using GateIo.Net.Clients; +using GateIo.Net.Interfaces.Clients; +using GateIo.Net.Objects.Options; +using GateIo.Net.Objects.Models; + +namespace GateIo.Net.SymbolOrderBooks +{ + /// + /// Implementation for a synchronized order book. After calling Start the order book will sync itself and keep up to date with new data. It will automatically try to reconnect and resync in case of a lost/interrupted connection. + /// Make sure to check the State property to see if the order book is synced. + /// + public class GateIoPerpetualFuturesSymbolOrderBook : SymbolOrderBook + { + private readonly IGateIoRestClient _restClient; + private readonly IGateIoSocketClient _socketClient; + private readonly bool _clientOwner; + private readonly string _settleAsset; + + /// + /// Create a new order book instance + /// + /// The settlement asset. btc, usdt or usd + /// The symbol the order book is for + /// Option configuration delegate + public GateIoPerpetualFuturesSymbolOrderBook(string settlementAsset, string symbol, Action? optionsDelegate = null) + : this(settlementAsset, symbol, optionsDelegate, null, null, null) + { + _clientOwner = true; + } + + /// + /// Create a new order book instance + /// + /// The settlement asset. btc, usdt or usd + /// The symbol the order book is for + /// Option configuration delegate + /// Logger + /// Rest client instance + /// Socket client instance + [ActivatorUtilitiesConstructor] + public GateIoPerpetualFuturesSymbolOrderBook( + string settlementAsset, + string contract, + Action? optionsDelegate, + ILoggerFactory? logger, + IGateIoRestClient? restClient, + IGateIoSocketClient? socketClient) : base(logger, "GateIo", "PerpetualFutures", contract) + { + var options = GateIoOrderBookOptions.Default.Copy(); + if (optionsDelegate != null) + optionsDelegate(options); + Initialize(options); + + _strictLevels = false; + _settleAsset = settlementAsset; + _sequencesAreConsecutive = options?.Limit == null; + + Levels = options?.Limit ?? 20; + _clientOwner = socketClient == null; + _socketClient = socketClient ?? new GateIoSocketClient(); + _restClient = restClient ?? new GateIoRestClient(); + } + + /// + protected override async Task> DoStartAsync(CancellationToken ct) + { + var subResult = await _socketClient.PerpetualFuturesApi.SubscribeToOrderBookUpdatesAsync(_settleAsset, Symbol, 20, Levels!.Value, HandleUpdate).ConfigureAwait(false); + + if (!subResult) + return new CallResult(subResult.Error!); + + if (ct.IsCancellationRequested) + { + await subResult.Data.CloseAsync().ConfigureAwait(false); + return subResult.AsError(new CancellationRequestedError()); + } + + Status = OrderBookStatus.Syncing; + + // Small delay to make sure the snapshot is from after our first stream update + await Task.Delay(200).ConfigureAwait(false); + var bookResult = await _restClient.PerpetualFuturesApi.ExchangeData.GetOrderBookAsync(_settleAsset, Symbol, null, Levels!.Value).ConfigureAwait(false); + if (!bookResult) + { + _logger.Log(LogLevel.Debug, $"{Api} order book {Symbol} failed to retrieve initial order book"); + await _socketClient.UnsubscribeAsync(subResult.Data).ConfigureAwait(false); + return new CallResult(bookResult.Error!); + } + + SetInitialOrderBook(bookResult.Data.Id, bookResult.Data.Bids, bookResult.Data.Asks); + return new CallResult(subResult.Data); + } + + private void HandleUpdate(DataEvent data) + { + UpdateOrderBook(data.Data.FirstUpdateId, data.Data.LastUpdateId, data.Data.Bids, data.Data.Asks); + } + + /// + protected override void DoReset() + { + } + + /// + protected override async Task> DoResyncAsync(CancellationToken ct) + { + var bookResult = await _restClient.PerpetualFuturesApi.ExchangeData.GetOrderBookAsync(_settleAsset, Symbol, null, Levels ?? 100).ConfigureAwait(false); + if (!bookResult) + return new CallResult(bookResult.Error!); + + SetInitialOrderBook(bookResult.Data.Id, bookResult.Data.Bids, bookResult.Data.Asks); + return new CallResult(true); + } + + /// + protected override void Dispose(bool disposing) + { + if (_clientOwner) + { + _restClient?.Dispose(); + _socketClient?.Dispose(); + } + + base.Dispose(disposing); + } + } +} diff --git a/GateIo.Net/SymbolOrderBooks/GateIoSpotSymbolOrderBook.cs b/GateIo.Net/SymbolOrderBooks/GateIoSpotSymbolOrderBook.cs new file mode 100644 index 0000000..4c3ee5f --- /dev/null +++ b/GateIo.Net/SymbolOrderBooks/GateIoSpotSymbolOrderBook.cs @@ -0,0 +1,153 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using CryptoExchange.Net.Objects; +using CryptoExchange.Net.Objects.Sockets; +using CryptoExchange.Net.OrderBook; +using Microsoft.Extensions.Logging; +using GateIo.Net.Clients; +using GateIo.Net.Interfaces.Clients; +using GateIo.Net.Objects.Options; +using GateIo.Net.Objects.Models; + +namespace GateIo.Net.SymbolOrderBooks +{ + /// + /// Implementation for a synchronized order book. After calling Start the order book will sync itself and keep up to date with new data. It will automatically try to reconnect and resync in case of a lost/interrupted connection. + /// Make sure to check the State property to see if the order book is synced. + /// + public class GateIoSpotSymbolOrderBook : SymbolOrderBook + { + private readonly bool _clientOwner; + private readonly IGateIoRestClient _restClient; + private readonly IGateIoSocketClient _socketClient; + private readonly TimeSpan _initialDataTimeout; + private readonly int? _updateInterval; + + /// + /// Create a new order book instance + /// + /// The symbol the order book is for + /// Option configuration delegate + public GateIoSpotSymbolOrderBook(string symbol, Action? optionsDelegate = null) + : this(symbol, optionsDelegate, null, null, null) + { + _clientOwner = true; + } + + /// + /// Create a new order book instance + /// + /// The symbol the order book is for + /// Option configuration delegate + /// Logger + /// Rest client instance + /// Socket client instance + public GateIoSpotSymbolOrderBook( + string symbol, + Action? optionsDelegate, + ILoggerFactory? logger, + IGateIoRestClient? restClient, + IGateIoSocketClient? socketClient) : base(logger, "GateIo", "GateIo", symbol) + { + var options = GateIoOrderBookOptions.Default.Copy(); + if (optionsDelegate != null) + optionsDelegate(options); + Initialize(options); + + _strictLevels = false; + _sequencesAreConsecutive = options?.Limit == null; + _updateInterval = options?.UpdateInterval; + + Levels = options?.Limit; + _initialDataTimeout = options?.InitialDataTimeout ?? TimeSpan.FromSeconds(30); + _clientOwner = socketClient == null; + _socketClient = socketClient ?? new GateIoSocketClient(); + _restClient = restClient ?? new GateIoRestClient(); + } + + + /// + protected override async Task> DoStartAsync(CancellationToken ct) + { + CallResult subResult; + if (Levels == null) + subResult = await _socketClient.SpotApi.SubscribeToOrderBookUpdatesAsync(Symbol, _updateInterval, HandleUpdate).ConfigureAwait(false); + else + subResult = await _socketClient.SpotApi.SubscribeToPartialOrderBookUpdatesAsync(Symbol, Levels.Value, _updateInterval, HandleUpdate).ConfigureAwait(false); + + if (!subResult) + return new CallResult(subResult.Error!); + + if (ct.IsCancellationRequested) + { + await subResult.Data.CloseAsync().ConfigureAwait(false); + return subResult.AsError(new CancellationRequestedError()); + } + + Status = OrderBookStatus.Syncing; + if (Levels == null) + { + // Small delay to make sure the snapshot is from after our first stream update + await Task.Delay(200).ConfigureAwait(false); + var bookResult = await _restClient.SpotApi.ExchangeData.GetOrderBookAsync(Symbol, null, 100).ConfigureAwait(false); + if (!bookResult) + { + _logger.Log(LogLevel.Debug, $"{Api} order book {Symbol} failed to retrieve initial order book"); + await _socketClient.UnsubscribeAsync(subResult.Data).ConfigureAwait(false); + return new CallResult(bookResult.Error!); + } + + SetInitialOrderBook(bookResult.Data.Id, bookResult.Data.Bids, bookResult.Data.Asks); + } + else + { + var setResult = await WaitForSetOrderBookAsync(_initialDataTimeout, ct).ConfigureAwait(false); + return setResult ? subResult : new CallResult(setResult.Error!); + } + + return new CallResult(subResult.Data); + } + + private void HandleUpdate(DataEvent data) + { + UpdateOrderBook(data.Data.FirstUpdateId, data.Data.LastUpdateId, data.Data.Bids, data.Data.Asks); + } + + private void HandleUpdate(DataEvent data) + { + SetInitialOrderBook(data.Data.LastUpdateId, data.Data.Bids, data.Data.Asks); + } + + /// + protected override void DoReset() + { + } + + /// + protected override async Task> DoResyncAsync(CancellationToken ct) + { + if (Levels != null) + return await WaitForSetOrderBookAsync(_initialDataTimeout, ct).ConfigureAwait(false); + + var bookResult = await _restClient.SpotApi.ExchangeData.GetOrderBookAsync(Symbol, null, Levels ?? 100).ConfigureAwait(false); + if (!bookResult) + return new CallResult(bookResult.Error!); + + SetInitialOrderBook(bookResult.Data.Id, bookResult.Data.Bids, bookResult.Data.Asks); + return new CallResult(true); + } + + /// + protected override void Dispose(bool disposing) + { + if (_clientOwner) + { + _restClient?.Dispose(); + _socketClient?.Dispose(); + } + + base.Dispose(disposing); + } + } +} diff --git a/LICENSE b/LICENSE index 9542fc8..4870860 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 JKorf +Copyright (c) 2017 JKorf Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6677a90..7d8db67 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,139 @@ -# GateIo.Net - +# ![GateIo.Net](https://raw.githubusercontent.com/JKorf/GateIo.Net/main/GateIo.Net/Icon/icon.png) GateIo.Net + +[![.NET](https://img.shields.io/github/actions/workflow/status/JKorf/GateIo.Net/dotnet.yml?style=for-the-badge)](https://github.com/JKorf/GateIo.Net/actions/workflows/dotnet.yml) ![License](https://img.shields.io/github/license/JKorf/GateIo.Net?style=for-the-badge) + +GateIo.Net is a client library for accessing the [Gate.io REST and Websocket API](https://www.gate.io/docs/developers/apiv4). All data is mapped to readable models and enum values. Additional features include an implementation for maintaining a client side order book, easy integration with other exchange client libraries and more. + +## Supported Frameworks +The library is targeting both `.NET Standard 2.0` and `.NET Standard 2.1` for optimal compatibility + +|.NET implementation|Version Support| +|--|--| +|.NET Core|`2.0` and higher| +|.NET Framework|`4.6.1` and higher| +|Mono|`5.4` and higher| +|Xamarin.iOS|`10.14` and higher| +|Xamarin.Android|`8.0` and higher| +|UWP|`10.0.16299` and higher| +|Unity|`2018.1` and higher| + +## Get the library +[![Nuget version](https://img.shields.io/nuget/v/GateIo.net.svg?style=for-the-badge)](https://www.nuget.org/packages/GateIo.Net) [![Nuget downloads](https://img.shields.io/nuget/dt/GateIo.Net.svg?style=for-the-badge)](https://www.nuget.org/packages/GateIo.Net) + + dotnet add package GateIo.Net + +## How to use +* REST Endpoints + ```csharp + // Get the ETH/USDT ticker via rest request + var restClient = new GateIoRestClient(); + var tickerResult = await restClient.SpotApi.ExchangeData.GetTickersAsync("ETH_USDT"); + var lastPrice = tickerResult.Data.First().LastPrice; + ``` +* Websocket streams + ```csharp + // Subscribe to ETH/USDT ticker updates via the websocket API + var socketClient = new GateIoSocketClient(); + var tickerSubscriptionResult = socketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH_USDT", data => + { + var lastPrice = data.Data.LastPrice; + }); + ``` + +For information on the clients, dependency injection, response processing and more see the [documentation](https://jkorf.github.io/GateIo.Net), or have a look at the examples [here](https://github.com/JKorf/GateIo.Net/tree/master/Examples) or [here](https://github.com/JKorf/CryptoExchange.Net/tree/master/Examples). + +## CryptoExchange.Net +GateIo.Net is based on the [CryptoExchange.Net](https://github.com/JKorf/CryptoExchange.Net) base library. Other exchange API implementations based on the CryptoExchange.Net base library are available and follow the same logic. + +CryptoExchange.Net also allows for [easy access to different exchange API's](https://jkorf.github.io/CryptoExchange.Net#idocs_common). + +|Exchange|Repository|Nuget| +|--|--|--| +|Binance|[JKorf/Binance.Net](https://github.com/JKorf/Binance.Net)|[![Nuget version](https://img.shields.io/nuget/v/Binance.net.svg?style=flat-square)](https://www.nuget.org/packages/Binance.Net)| +|BingX|[JKorf/BingX.Net](https://github.com/JKorf/BingX.Net)|[![Nuget version](https://img.shields.io/nuget/v/JK.BingX.net.svg?style=flat-square)](https://www.nuget.org/packages/JK.BingX.Net)| +|Bitfinex|[JKorf/Bitfinex.Net](https://github.com/JKorf/Bitfinex.Net)|[![Nuget version](https://img.shields.io/nuget/v/Bitfinex.net.svg?style=flat-square)](https://www.nuget.org/packages/Bitfinex.Net)| +|Bitget|[JKorf/Bitget.Net](https://github.com/JKorf/Bitget.Net)|[![Nuget version](https://img.shields.io/nuget/v/JK.Bitget.net.svg?style=flat-square)](https://www.nuget.org/packages/JK.Bitget.Net)| +|Bybit|[JKorf/Bybit.Net](https://github.com/JKorf/Bybit.Net)|[![Nuget version](https://img.shields.io/nuget/v/Bybit.net.svg?style=flat-square)](https://www.nuget.org/packages/Bybit.Net)| +|CoinEx|[JKorf/CoinEx.Net](https://github.com/JKorf/CoinEx.Net)|[![Nuget version](https://img.shields.io/nuget/v/CoinEx.net.svg?style=flat-square)](https://www.nuget.org/packages/CoinEx.Net)| +|CoinGecko|[JKorf/CoinGecko.Net](https://github.com/JKorf/CoinGecko.Net)|[![Nuget version](https://img.shields.io/nuget/v/CoinGecko.net.svg?style=flat-square)](https://www.nuget.org/packages/CoinGecko.Net)| +|Huobi/HTX|[JKorf/Huobi.Net](https://github.com/JKorf/Huobi.Net)|[![Nuget version](https://img.shields.io/nuget/v/Huobi.net.svg?style=flat-square)](https://www.nuget.org/packages/Huobi.Net)| +|Kraken|[JKorf/Kraken.Net](https://github.com/JKorf/Kraken.Net)|[![Nuget version](https://img.shields.io/nuget/v/KrakenExchange.net.svg?style=flat-square)](https://www.nuget.org/packages/KrakenExchange.Net)| +|Kucoin|[JKorf/Kucoin.Net](https://github.com/JKorf/Kucoin.Net)|[![Nuget version](https://img.shields.io/nuget/v/Kucoin.net.svg?style=flat-square)](https://www.nuget.org/packages/Kucoin.Net)| +|Mexc|[JKorf/Mexc.Net](https://github.com/JKorf/Mexc.Net)|[![Nuget version](https://img.shields.io/nuget/v/JK.Mexc.net.svg?style=flat-square)](https://www.nuget.org/packages/JK.Mexc.Net)| +|OKX|[JKorf/OKX.Net](https://github.com/JKorf/OKX.Net)|[![Nuget version](https://img.shields.io/nuget/v/JK.OKX.net.svg?style=flat-square)](https://www.nuget.org/packages/JK.OKX.Net)| + +When using multiple of these API's the [CryptoClients.Net](https://github.com/JKorf/CryptoClients.Net) package can be used which combines this and the other packages and allows easy access to all exchange API's. + +## Discord +[![Nuget version](https://img.shields.io/discord/847020490588422145?style=for-the-badge)](https://discord.gg/MSpeEtSY8t) +A Discord server is available [here](https://discord.gg/MSpeEtSY8t). For discussion and/or questions around the CryptoExchange.Net and implementation libraries, feel free to join. + +## Supported functionality +The following modules are supported of the latest V4 API. +### Account & Margin +|API|Supported|Location| +|--|--:|--| +|Withdrawal|✓|`restClient.SpotApi.Account`| +|Wallet|✓|`restClient.SpotApi.Account`| +|Subaccount|X|| +|Unified|✓|`restClient.SpotApi.Account` / `restClient.SpotApi.ExchangeData`| +|Margin|✓|`restClient.SpotApi.Account` / `restClient.SpotApi.ExchangeData`| +|Marginuni|✓|`restClient.SpotApi.Account` / `restClient.SpotApi.ExchangeData`| +|Flash_swap|X|| +|Earnuni|X|| +|Collateral-Loan|X|| +|Multi-Collateral-Loan|X|| +|Earn|X|| +|Account|✓|`restClient.SpotApi.Account`| +|Rebates|X|| + +### Spot Rest +|API|Supported|Location| +|--|--:|--| +|Account|✓|`restClient.SpotApi.Account`| +|Public data|✓|`restClient.SpotApi.ExchangeData`| +|Trading|✓|`restClient.SpotApi.Trading`| + +### Spot Websocket +|API|Supported|Location| +|--|--:|--| +|Public data|✓|`socketClient.SpotApi`| +|Trading|✓|`socketClient.SpotApi`| + +### Perpetual Futures Rest +|API|Supported|Location| +|--|--:|--| +|Account|✓|`restClient.PerpetualFuturesApi.Account`| +|Public data|✓|`restClient.PerpetualFuturesApi.ExchangeData`| +|Trading|✓|`restClient.PerpetualFuturesApi.Trading`| + +### Perpetual Futures Websocket +|API|Supported|Location| +|--|--:|--| +|Public data|✓|`socketClient.PerpetualFuturesApi`| +|Trading|✓|`socketClient.PerpetualFuturesApi`| + +### Delivery Futures +|API|Supported|Location| +|--|--:|--| +|*|X|| + +### Options +|API|Supported|Location| +|--|--:|--| +|*|X|| + +## Support the project +I develop and maintain this package on my own for free in my spare time, any support is greatly appreciated. + +### Donate +Make a one time donation in a crypto currency of your choice. If you prefer to donate a currency not listed here please contact me. + +**Btc**: bc1q277a5n54s2l2mzlu778ef7lpkwhjhyvghuv8qf +**Eth**: 0xcb1b63aCF9fef2755eBf4a0506250074496Ad5b7 +**USDT (TRX)** TKigKeJPXZYyMVDgMyXxMf17MWYia92Rjd + +### Sponsor +Alternatively, sponsor me on Github using [Github Sponsors](https://github.com/sponsors/JKorf). + +## Release notes diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..f52415b --- /dev/null +++ b/docs/README.md @@ -0,0 +1 @@ +Source for https://jkorf.github.io/GateIo.Net \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..8e4385b --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,2 @@ +remote_theme: pmarsceill/just-the-docs +markdown: GFM \ No newline at end of file diff --git a/docs/assets/css/color-blue.css b/docs/assets/css/color-blue.css new file mode 100644 index 0000000..1caa28d --- /dev/null +++ b/docs/assets/css/color-blue.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Blue +==============================*/ +::selection { + background: #007bff; +} + +a, a:focus { + color: #007bff; +} + +a:hover, a:active { + color: #006adb; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #007bff; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #007bff; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #007bff; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #007bff; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #007bff !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #007bff; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #007bff; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #007bff; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #007bff; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #007bff; +} + +.nav-pills .nav-link:not(.active):hover { + color: #007bff; +} + +#footer .nav .nav-item .nav-link:focus { + color: #007bff; +} +#footer .nav .nav-link:hover { + color: #007bff; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #007bff; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #007bff; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #007bff !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #007bff !important; +} + +.btn-link:hover { + color: #006adb !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #006adb !important; +} + +.border-primary { + border-color: #007bff !important; +} + +.btn-primary { + background-color: #007bff; + border-color: #007bff; +} +.btn-primary:hover { + background-color: #006adb; + border-color: #006adb; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #006adb; + border-color: #006adb; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #006adb; + border-color: #006adb; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #007bff; + border-color: #007bff; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #007bff; + border-color: #007bff; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #007bff; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #007bff; + border-color: #007bff; +} + +.list-group-item.active { + background-color: #007bff; + border-color: #007bff; +} + +.page-link { + color: #007bff; +} +.page-link:hover { + color: #006adb; +} diff --git a/docs/assets/css/color-brown.css b/docs/assets/css/color-brown.css new file mode 100644 index 0000000..4fbb38c --- /dev/null +++ b/docs/assets/css/color-brown.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Brown +==============================*/ +::selection { + background: #795548; +} + +a, a:focus { + color: #795548; +} + +a:hover, a:active { + color: #63453b; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #795548; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #795548; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #795548; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #795548; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #795548 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #795548; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #795548; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #795548; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #795548; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #795548; +} + +.nav-pills .nav-link:not(.active):hover { + color: #795548; +} + +#footer .nav .nav-item .nav-link:focus { + color: #795548; +} +#footer .nav .nav-link:hover { + color: #795548; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #795548; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #795548; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #795548 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #795548 !important; +} + +.btn-link:hover { + color: #63453b !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #63453b !important; +} + +.border-primary { + border-color: #795548 !important; +} + +.btn-primary { + background-color: #795548; + border-color: #795548; +} +.btn-primary:hover { + background-color: #63453b; + border-color: #63453b; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #63453b; + border-color: #63453b; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #63453b; + border-color: #63453b; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #795548; + border-color: #795548; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #795548; + border-color: #795548; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #795548; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #795548; + border-color: #795548; +} + +.list-group-item.active { + background-color: #795548; + border-color: #795548; +} + +.page-link { + color: #795548; +} +.page-link:hover { + color: #63453b; +} diff --git a/docs/assets/css/color-cyan.css b/docs/assets/css/color-cyan.css new file mode 100644 index 0000000..fa712d8 --- /dev/null +++ b/docs/assets/css/color-cyan.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Cyan +==============================*/ +::selection { + background: #17a2b8; +} + +a, a:focus { + color: #17a2b8; +} + +a:hover, a:active { + color: #138698; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #17a2b8; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #17a2b8; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #17a2b8; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #17a2b8; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #17a2b8 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #17a2b8; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #17a2b8; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #17a2b8; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #17a2b8; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #17a2b8; +} + +.nav-pills .nav-link:not(.active):hover { + color: #17a2b8; +} + +#footer .nav .nav-item .nav-link:focus { + color: #17a2b8; +} +#footer .nav .nav-link:hover { + color: #17a2b8; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #17a2b8; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #17a2b8; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #17a2b8 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #17a2b8 !important; +} + +.btn-link:hover { + color: #138698 !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #138698 !important; +} + +.border-primary { + border-color: #17a2b8 !important; +} + +.btn-primary { + background-color: #17a2b8; + border-color: #17a2b8; +} +.btn-primary:hover { + background-color: #138698; + border-color: #138698; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #138698; + border-color: #138698; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #138698; + border-color: #138698; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #17a2b8; + border-color: #17a2b8; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #17a2b8; + border-color: #17a2b8; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #17a2b8; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #17a2b8; + border-color: #17a2b8; +} + +.list-group-item.active { + background-color: #17a2b8; + border-color: #17a2b8; +} + +.page-link { + color: #17a2b8; +} +.page-link:hover { + color: #138698; +} diff --git a/docs/assets/css/color-green.css b/docs/assets/css/color-green.css new file mode 100644 index 0000000..4810d8b --- /dev/null +++ b/docs/assets/css/color-green.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Green +==============================*/ +::selection { + background: #28a745; +} + +a, a:focus { + color: #28a745; +} + +a:hover, a:active { + color: #218a39; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #28a745; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #28a745; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #28a745; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #28a745; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #28a745 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #28a745; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #28a745; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #28a745; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #28a745; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #28a745; +} + +.nav-pills .nav-link:not(.active):hover { + color: #28a745; +} + +#footer .nav .nav-item .nav-link:focus { + color: #28a745; +} +#footer .nav .nav-link:hover { + color: #28a745; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #28a745; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #28a745; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #28a745 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #28a745 !important; +} + +.btn-link:hover { + color: #218a39 !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #218a39 !important; +} + +.border-primary { + border-color: #28a745 !important; +} + +.btn-primary { + background-color: #28a745; + border-color: #28a745; +} +.btn-primary:hover { + background-color: #218a39; + border-color: #218a39; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #218a39; + border-color: #218a39; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #218a39; + border-color: #218a39; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #28a745; + border-color: #28a745; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #28a745; + border-color: #28a745; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #28a745; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #28a745; + border-color: #28a745; +} + +.list-group-item.active { + background-color: #28a745; + border-color: #28a745; +} + +.page-link { + color: #28a745; +} +.page-link:hover { + color: #218a39; +} diff --git a/docs/assets/css/color-indigo.css b/docs/assets/css/color-indigo.css new file mode 100644 index 0000000..f9141bd --- /dev/null +++ b/docs/assets/css/color-indigo.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Indigo +==============================*/ +::selection { + background: #6610f2; +} + +a, a:focus { + color: #6610f2; +} + +a:hover, a:active { + color: #570bd3; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #6610f2; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #6610f2; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #6610f2; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #6610f2; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #6610f2 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #6610f2; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #6610f2; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #6610f2; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #6610f2; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #6610f2; +} + +.nav-pills .nav-link:not(.active):hover { + color: #6610f2; +} + +#footer .nav .nav-item .nav-link:focus { + color: #6610f2; +} +#footer .nav .nav-link:hover { + color: #6610f2; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #6610f2; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #6610f2; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #6610f2 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #6610f2 !important; +} + +.btn-link:hover { + color: #570bd3 !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #570bd3 !important; +} + +.border-primary { + border-color: #6610f2 !important; +} + +.btn-primary { + background-color: #6610f2; + border-color: #6610f2; +} +.btn-primary:hover { + background-color: #570bd3; + border-color: #570bd3; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #570bd3; + border-color: #570bd3; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #570bd3; + border-color: #570bd3; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #6610f2; + border-color: #6610f2; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #6610f2; + border-color: #6610f2; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #6610f2; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #6610f2; + border-color: #6610f2; +} + +.list-group-item.active { + background-color: #6610f2; + border-color: #6610f2; +} + +.page-link { + color: #6610f2; +} +.page-link:hover { + color: #570bd3; +} diff --git a/docs/assets/css/color-orange.css b/docs/assets/css/color-orange.css new file mode 100644 index 0000000..d7cda6b --- /dev/null +++ b/docs/assets/css/color-orange.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Orange +==============================*/ +::selection { + background: #fd7e14; +} + +a, a:focus { + color: #fd7e14; +} + +a:hover, a:active { + color: #eb6c02; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #fd7e14; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #fd7e14; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #fd7e14; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #fd7e14; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #fd7e14 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #fd7e14; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #fd7e14; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #fd7e14; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #fd7e14; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #fd7e14; +} + +.nav-pills .nav-link:not(.active):hover { + color: #fd7e14; +} + +#footer .nav .nav-item .nav-link:focus { + color: #fd7e14; +} +#footer .nav .nav-link:hover { + color: #fd7e14; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #fd7e14; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #fd7e14; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #fd7e14 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #fd7e14 !important; +} + +.btn-link:hover { + color: #eb6c02 !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #eb6c02 !important; +} + +.border-primary { + border-color: #fd7e14 !important; +} + +.btn-primary { + background-color: #fd7e14; + border-color: #fd7e14; +} +.btn-primary:hover { + background-color: #eb6c02; + border-color: #eb6c02; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #eb6c02; + border-color: #eb6c02; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #eb6c02; + border-color: #eb6c02; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #fd7e14; + border-color: #fd7e14; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #fd7e14; + border-color: #fd7e14; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #fd7e14; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #fd7e14; + border-color: #fd7e14; +} + +.list-group-item.active { + background-color: #fd7e14; + border-color: #fd7e14; +} + +.page-link { + color: #fd7e14; +} +.page-link:hover { + color: #eb6c02; +} diff --git a/docs/assets/css/color-purple.css b/docs/assets/css/color-purple.css new file mode 100644 index 0000000..f196739 --- /dev/null +++ b/docs/assets/css/color-purple.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Purple +==============================*/ +::selection { + background: #6f42c1; +} + +a, a:focus { + color: #6f42c1; +} + +a:hover, a:active { + color: #5f37a8; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #6f42c1; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #6f42c1; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #6f42c1; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #6f42c1; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #6f42c1 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #6f42c1; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #6f42c1; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #6f42c1; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #6f42c1; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #6f42c1; +} + +.nav-pills .nav-link:not(.active):hover { + color: #6f42c1; +} + +#footer .nav .nav-item .nav-link:focus { + color: #6f42c1; +} +#footer .nav .nav-link:hover { + color: #6f42c1; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #6f42c1; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #6f42c1; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #6f42c1 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #6f42c1 !important; +} + +.btn-link:hover { + color: #5f37a8 !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #5f37a8 !important; +} + +.border-primary { + border-color: #6f42c1 !important; +} + +.btn-primary { + background-color: #6f42c1; + border-color: #6f42c1; +} +.btn-primary:hover { + background-color: #5f37a8; + border-color: #5f37a8; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #5f37a8; + border-color: #5f37a8; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #5f37a8; + border-color: #5f37a8; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #6f42c1; + border-color: #6f42c1; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #6f42c1; + border-color: #6f42c1; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #6f42c1; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #6f42c1; + border-color: #6f42c1; +} + +.list-group-item.active { + background-color: #6f42c1; + border-color: #6f42c1; +} + +.page-link { + color: #6f42c1; +} +.page-link:hover { + color: #5f37a8; +} diff --git a/docs/assets/css/color-red.css b/docs/assets/css/color-red.css new file mode 100644 index 0000000..e9d68d6 --- /dev/null +++ b/docs/assets/css/color-red.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Red +==============================*/ +::selection { + background: #dc3545; +} + +a, a:focus { + color: #dc3545; +} + +a:hover, a:active { + color: #ca2333; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #dc3545; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #dc3545; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #dc3545; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #dc3545; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #dc3545 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #dc3545; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #dc3545; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #dc3545; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #dc3545; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #dc3545; +} + +.nav-pills .nav-link:not(.active):hover { + color: #dc3545; +} + +#footer .nav .nav-item .nav-link:focus { + color: #dc3545; +} +#footer .nav .nav-link:hover { + color: #dc3545; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #dc3545; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #dc3545; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #dc3545 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #dc3545 !important; +} + +.btn-link:hover { + color: #ca2333 !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #ca2333 !important; +} + +.border-primary { + border-color: #dc3545 !important; +} + +.btn-primary { + background-color: #dc3545; + border-color: #dc3545; +} +.btn-primary:hover { + background-color: #ca2333; + border-color: #ca2333; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #ca2333; + border-color: #ca2333; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #ca2333; + border-color: #ca2333; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #dc3545; + border-color: #dc3545; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #dc3545; + border-color: #dc3545; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #dc3545; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #dc3545; + border-color: #dc3545; +} + +.list-group-item.active { + background-color: #dc3545; + border-color: #dc3545; +} + +.page-link { + color: #dc3545; +} +.page-link:hover { + color: #ca2333; +} diff --git a/docs/assets/css/color-teal.css b/docs/assets/css/color-teal.css new file mode 100644 index 0000000..8b8116a --- /dev/null +++ b/docs/assets/css/color-teal.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Teal +==============================*/ +::selection { + background: #20c997; +} + +a, a:focus { + color: #20c997; +} + +a:hover, a:active { + color: #1baa80; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #20c997; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #20c997; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #20c997; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #20c997; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #20c997 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #20c997; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #20c997; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #20c997; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #20c997; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #20c997; +} + +.nav-pills .nav-link:not(.active):hover { + color: #20c997; +} + +#footer .nav .nav-item .nav-link:focus { + color: #20c997; +} +#footer .nav .nav-link:hover { + color: #20c997; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #20c997; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #20c997; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #20c997 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #20c997 !important; +} + +.btn-link:hover { + color: #1baa80 !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #1baa80 !important; +} + +.border-primary { + border-color: #20c997 !important; +} + +.btn-primary { + background-color: #20c997; + border-color: #20c997; +} +.btn-primary:hover { + background-color: #1baa80; + border-color: #1baa80; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #1baa80; + border-color: #1baa80; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #1baa80; + border-color: #1baa80; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #20c997; + border-color: #20c997; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #20c997; + border-color: #20c997; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #20c997; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #20c997; + border-color: #20c997; +} + +.list-group-item.active { + background-color: #20c997; + border-color: #20c997; +} + +.page-link { + color: #20c997; +} +.page-link:hover { + color: #1baa80; +} diff --git a/docs/assets/css/color-yellow.css b/docs/assets/css/color-yellow.css new file mode 100644 index 0000000..6c59cad --- /dev/null +++ b/docs/assets/css/color-yellow.css @@ -0,0 +1,159 @@ +/*============================ + COLOR Yellow +==============================*/ +::selection { + background: #ffc107; +} + +a, a:focus { + color: #ffc107; +} + +a:hover, a:active { + color: #f7b900; +} + +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #ffc107; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #ffc107; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + border-color: #ffc107; +} + +/*=== Side Navigation ===*/ +.idocs-navigation .nav .nav .nav-item .nav-link.active:after, .idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #ffc107; +} + +/* Accordion & Toggle */ +.accordion .card-header a:hover.collapsed { + color: #ffc107 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #ffc107; + color: #fff; +} + +/* Nav */ +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #ffc107; +} + +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + background-color: #ffc107; +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #ffc107; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + color: #ffc107; +} + +.nav-pills .nav-link:not(.active):hover { + color: #ffc107; +} + +#footer .nav .nav-item .nav-link:focus { + color: #ffc107; +} +#footer .nav .nav-link:hover { + color: #ffc107; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #ffc107; +} + +/* Back to Top */ +#back-to-top:hover { + background-color: #ffc107; +} + +/* Extras */ +.bg-primary, .badge-primary { + background-color: #ffc107 !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #ffc107 !important; +} + +.btn-link:hover { + color: #f7b900 !important; +} + +.text-muted { + color: #8e9a9d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #f7b900 !important; +} + +.border-primary { + border-color: #ffc107 !important; +} + +.btn-primary { + background-color: #ffc107; + border-color: #ffc107; +} +.btn-primary:hover { + background-color: #f7b900; + border-color: #f7b900; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #f7b900; + border-color: #f7b900; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #f7b900; + border-color: #f7b900; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #ffc107; + border-color: #ffc107; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #ffc107; + border-color: #ffc107; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #ffc107; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #ffc107; + border-color: #ffc107; +} + +.list-group-item.active { + background-color: #ffc107; + border-color: #ffc107; +} + +.page-link { + color: #ffc107; +} +.page-link:hover { + color: #f7b900; +} diff --git a/docs/assets/css/stylesheet.css b/docs/assets/css/stylesheet.css new file mode 100644 index 0000000..2d11316 --- /dev/null +++ b/docs/assets/css/stylesheet.css @@ -0,0 +1,2986 @@ +/*=========================================================== + + Template Name: iDocs - One Page Documentation HTML Template + Author: Harnish Design + Template URL: http://demo.harnishdesign.net/html/idocs + Author URL: https://themeforest.net/user/harnishdesign + File Description : Main css file of the template + +================================================= + Table of Contents +================================================= + + 1. Basic + 2. Helpers Classes + 3. Layouts + 3.1 Side Navigation + 3.2 Docs Content + 3.3 Section Divider + 4. Header + 4.1 Main Navigation + 5 Elements + 5.1 List Style + 5.2 Changelog + 5.3 Accordion & Toggle + 5.4 Nav + 5.5 Tabs + 5.6 Popup Img + 5.7 Featured Box + 6 Footer + 6.1 Social Icons + 6.2 Back to Top + 7 Extra + +=======================================================*/ +/* =================================== */ +/* 1. Basic Style +/* =================================== */ +body, html { + height: 100%; +} + +body { + background: #dddddd; + color: #4c4d4d; +} + +/*-------- Preloader --------*/ +.preloader { + position: fixed; + width: 100%; + height: 100%; + z-index: 999999999 !important; + background-color: #fff; + top: 0; + left: 0; + right: 0; + bottom: 0; +} +.preloader .lds-ellipsis { + display: inline-block; + position: absolute; + width: 80px; + height: 80px; + margin-top: -40px; + margin-left: -40px; + top: 50%; + left: 50%; +} +.preloader .lds-ellipsis div { + position: absolute; + top: 33px; + width: 13px; + height: 13px; + border-radius: 50%; + background: #000; + animation-timing-function: cubic-bezier(0, 1, 1, 0); +} +.preloader .lds-ellipsis div:nth-child(1) { + left: 8px; + animation: lds-ellipsis1 0.6s infinite; +} +.preloader .lds-ellipsis div:nth-child(2) { + left: 8px; + animation: lds-ellipsis2 0.6s infinite; +} +.preloader .lds-ellipsis div:nth-child(3) { + left: 32px; + animation: lds-ellipsis2 0.6s infinite; +} +.preloader .lds-ellipsis div:nth-child(4) { + left: 56px; + animation: lds-ellipsis3 0.6s infinite; +} + +@keyframes lds-ellipsis1 { + 0% { + transform: scale(0); + } + 100% { + transform: scale(1); + } +} +@keyframes lds-ellipsis3 { + 0% { + transform: scale(1); + } + 100% { + transform: scale(0); + } +} +@keyframes lds-ellipsis2 { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(24px, 0); + } +} +/*--- Preloader Magnific Popup ----*/ +.mfp-container .preloader { + background: transparent; +} +.mfp-container .preloader .lds-ellipsis div { + background: #fff; +} + +::selection { + background: #0366d6; + color: #fff; + text-shadow: none; +} + +code { + padding: 2px 5px; + background-color: #f9f2f4; + border-radius: 4px; +} + +form { + padding: 0; + margin: 0; + display: inline; +} + +img { + vertical-align: inherit; +} + +a, a:focus { + color: #0366d6; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} + +a:hover, a:active { + color: #0355b3; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} + +a:focus, a:active, +.btn.active.focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn:active:focus, +.btn:focus, +button:focus, +button:active { + outline: none; +} + +p { + line-height: 1.8; +} + +blockquote { + border-left: 5px solid #eee; + padding: 10px 20px; +} + +iframe { + border: 0 !important; +} + +h1, h2, h3, h4, h5, h6 { + color: #252b33; + line-height: 1.5; + margin: 0 0 1.5rem 0; + font-family: Roboto, sans-serif; +} + +h1 { + font-size: 3rem; +} + +h2 { + font-size: 2.2rem; +} + +dl, ol, ul, pre, blockquote, .table { + margin-bottom: 1.8rem; +} + +/*=== Highlight Js ===*/ +.hljs { + padding: 1.5rem; +} + +/* =================================== */ +/* 2. Helpers Classes +/* =================================== */ +/* Box Shadow */ +.shadow-md { + -webkit-box-shadow: 0px 0px 50px -35px rgba(0, 0, 0, 0.4) !important; + box-shadow: 0px 0px 50px -35px rgba(0, 0, 0, 0.4) !important; +} + +/* Border Radius */ +.rounded-lg { + border-radius: 0.6rem !important; +} + +.rounded-top-0 { + border-top-left-radius: 0px !important; + border-top-right-radius: 0px !important; +} + +.rounded-bottom-0 { + border-bottom-left-radius: 0px !important; + border-bottom-right-radius: 0px !important; +} + +.rounded-left-0 { + border-top-left-radius: 0px !important; + border-bottom-left-radius: 0px !important; +} + +.rounded-right-0 { + border-top-right-radius: 0px !important; + border-bottom-right-radius: 0px !important; +} + +/* Border Size */ +.border-1 { + border-width: 1px !important; +} + +.border-2 { + border-width: 2px !important; +} + +.border-3 { + border-width: 3px !important; +} + +.border-4 { + border-width: 4px !important; +} + +.border-5 { + border-width: 5px !important; +} + +/* Text Size */ +.text-0 { + font-size: 11px !important; + font-size: 0.6875rem !important; +} + +.text-1 { + font-size: 12px !important; + font-size: 0.75rem !important; +} + +.text-2 { + font-size: 14px !important; + font-size: 0.875rem !important; +} + +.text-3 { + font-size: 16px !important; + font-size: 1rem !important; +} + +.text-4 { + font-size: 18px !important; + font-size: 1.125rem !important; +} + +.text-5 { + font-size: 21px !important; + font-size: 1.3125rem !important; +} + +.text-6 { + font-size: 24px !important; + font-size: 1.50rem !important; +} + +.text-7 { + font-size: 28px !important; + font-size: 1.75rem !important; +} + +.text-8 { + font-size: 32px !important; + font-size: 2rem !important; +} + +.text-9 { + font-size: 36px !important; + font-size: 2.25rem !important; +} + +.text-10 { + font-size: 40px !important; + font-size: 2.50rem !important; +} + +.text-11 { + font-size: 2.75rem !important; +} +@media (max-width: 992px) { + .text-11 { + font-size: calc(1.4rem + 2.1774193548vw) !important; + } +} + +.text-12 { + font-size: 3rem !important; +} +@media (max-width: 992px) { + .text-12 { + font-size: calc(1.425rem + 2.5403225806vw) !important; + } +} + +.text-13 { + font-size: 3.25rem !important; +} +@media (max-width: 992px) { + .text-13 { + font-size: calc(1.45rem + 2.9032258065vw) !important; + } +} + +.text-14 { + font-size: 3.5rem !important; +} +@media (max-width: 992px) { + .text-14 { + font-size: calc(1.475rem + 3.2661290323vw) !important; + } +} + +.text-15 { + font-size: 3.75rem !important; +} +@media (max-width: 992px) { + .text-15 { + font-size: calc(1.5rem + 3.6290322581vw) !important; + } +} + +.text-16 { + font-size: 4rem !important; +} +@media (max-width: 992px) { + .text-16 { + font-size: calc(1.525rem + 3.9919354839vw) !important; + } +} + +.text-17 { + font-size: 4.5rem !important; +} +@media (max-width: 992px) { + .text-17 { + font-size: calc(1.575rem + 4.7177419355vw) !important; + } +} + +.text-18 { + font-size: 5rem !important; +} +@media (max-width: 992px) { + .text-18 { + font-size: calc(1.625rem + 5.4435483871vw) !important; + } +} + +.text-19 { + font-size: 5.25rem !important; +} +@media (max-width: 992px) { + .text-19 { + font-size: calc(1.65rem + 5.8064516129vw) !important; + } +} + +.text-20 { + font-size: 5.75rem !important; +} +@media (max-width: 992px) { + .text-20 { + font-size: calc(1.7rem + 6.5322580645vw) !important; + } +} + +.text-21 { + font-size: 6.5rem !important; +} +@media (max-width: 992px) { + .text-21 { + font-size: calc(1.775rem + 7.6209677419vw) !important; + } +} + +.text-22 { + font-size: 7rem !important; +} +@media (max-width: 992px) { + .text-22 { + font-size: calc(1.825rem + 8.3467741935vw) !important; + } +} + +.text-23 { + font-size: 7.75rem !important; +} +@media (max-width: 992px) { + .text-23 { + font-size: calc(1.9rem + 9.435483871vw) !important; + } +} + +.text-24 { + font-size: 8.25rem !important; +} +@media (max-width: 992px) { + .text-24 { + font-size: calc(1.95rem + 10.1612903226vw) !important; + } +} + +.text-25 { + font-size: 9rem !important; +} +@media (max-width: 992px) { + .text-25 { + font-size: calc(2.025rem + 11.25vw) !important; + } +} + +.text-11, .text-12, .text-13, .text-14, .text-15, .text-16, .text-17, .text-18, .text-19, .text-20, .text-21, .text-22, .text-23, .text-24, .text-25 { + line-height: 1.3; +} + +/* Line height */ +.line-height-07 { + line-height: 0.7 !important; +} + +.line-height-1 { + line-height: 1 !important; +} + +.line-height-2 { + line-height: 1.2 !important; +} + +.line-height-3 { + line-height: 1.4 !important; +} + +.line-height-4 { + line-height: 1.6 !important; +} + +.line-height-5 { + line-height: 1.8 !important; +} + +/* Font Weight */ +.font-weight-100 { + font-weight: 100 !important; +} + +.font-weight-200 { + font-weight: 200 !important; +} + +.font-weight-300 { + font-weight: 300 !important; +} + +.font-weight-400 { + font-weight: 400 !important; +} + +.font-weight-500 { + font-weight: 500 !important; +} + +.font-weight-600 { + font-weight: 600 !important; +} + +.font-weight-700 { + font-weight: 700 !important; +} + +.font-weight-800 { + font-weight: 800 !important; +} + +.font-weight-900 { + font-weight: 900 !important; +} + +/* Opacity */ +.opacity-0 { + opacity: 0; +} + +.opacity-1 { + opacity: 0.1; +} + +.opacity-2 { + opacity: 0.2; +} + +.opacity-3 { + opacity: 0.3; +} + +.opacity-4 { + opacity: 0.4; +} + +.opacity-5 { + opacity: 0.5; +} + +.opacity-6 { + opacity: 0.6; +} + +.opacity-7 { + opacity: 0.7; +} + +.opacity-8 { + opacity: 0.8; +} + +.opacity-9 { + opacity: 0.9; +} + +.opacity-10 { + opacity: 1; +} + +/* Background light */ +.bg-light-1 { + background-color: #e9ecef !important; +} + +.bg-light-2 { + background-color: #dee2e6 !important; +} + +.bg-light-3 { + background-color: #ced4da !important; +} + +.bg-light-4 { + background-color: #adb5bd !important; +} + +/* Background Dark */ +.bg-dark { + background-color: #111418 !important; +} + +.bg-dark-1 { + background-color: #212529 !important; +} + +.bg-dark-2 { + background-color: #343a40 !important; +} + +.bg-dark-3 { + background-color: #495057 !important; +} + +.bg-dark-4 { + background-color: #6c757d !important; +} + +/* Progress Bar */ +.progress-sm { + height: 0.5rem !important; +} + +.progress-lg { + height: 1.5rem !important; +} + +hr { + border-top: 1px solid rgba(16, 85, 96, 0.1); +} + +/* =================================== */ +/* 3. Layouts +/* =================================== */ +#main-wrapper { + background: #fff; +} + +.box #main-wrapper { + max-width: 1200px; + margin: 0 auto; + -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); +} +.box .idocs-navigation { + left: auto; +} + +@media (min-width: 1200px) { + .container { + max-width: 1170px !important; + } +} +/*=== 3.1 Side Navigation ===*/ +.idocs-navigation { + position: fixed; + top: 70px; + left: 0; + overflow: hidden; + overflow-y: auto; + width: 260px; + height: calc(100% - 70px); + z-index: 1; + border-right: 1px solid rgba(0, 0, 0, 0.05); + transition: all 0.3s; +} +.idocs-navigation > .nav { + padding: 30px 0; +} +.idocs-navigation .nav .nav-item { + position: relative; +} +.idocs-navigation .nav .nav { + margin: 0 0 5px; +} +.idocs-navigation .nav .nav-link { + position: relative; + padding: 6px 30px; + line-height: 25px; + font-weight: 600; +} +.idocs-navigation .nav .nav-item:hover > .nav-link, .idocs-navigation .nav .nav-item .nav-link.active { + font-weight: 700; +} +.idocs-navigation .nav .nav { + display: none; + border-left: 1px solid regba(0, 0, 0, 0.3); +} +.idocs-navigation .nav .nav .nav-item .nav-link:after { + content: ""; + position: absolute; + left: 30px; + height: 100%; + border-left: 1px solid rgba(0, 0, 0, 0.12); + width: 1px; + top: 0; +} +.idocs-navigation .nav .nav .nav-item .nav-link.active:after { + border-color: #0366d6; + border-width: 2px; +} +.idocs-navigation .nav .nav-item .nav-link.active + .nav { + display: block; +} +.idocs-navigation .nav .nav .nav-link { + color: #6a6a6a; + padding: 4px 30px 4px 45px; + font-size: 15px; + text-transform: none; +} +.idocs-navigation .nav .nav .nav .nav-link { + padding: 4px 30px 4px 60px; + font-size: 15px; +} +.idocs-navigation .nav .nav .nav .nav-item .nav-link:after { + left: 45px; +} +.idocs-navigation > .nav > .nav-item > .nav-link.active:after { + position: absolute; + content: " "; + top: 50%; + right: 18px; + border-color: #000; + border-top: 2px solid; + border-right: 2px solid; + width: 7px; + height: 7px; + -webkit-transform: translate(-50%, -50%) rotate(45deg); + transform: translate(-50%, -50%) rotate(45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.idocs-navigation.docs-navigation-dark .nav .nav-link { + color: rgba(250, 250, 250, 0.85); +} +.idocs-navigation.docs-navigation-dark .nav .nav .nav-link { + color: rgba(250, 250, 250, 0.7); +} +.idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link:after { + border-color: rgba(250, 250, 250, 0.2); +} +.idocs-navigation.docs-navigation-dark .nav .nav .nav-item .nav-link.active:after { + border-color: #0366d6; +} + +/*=== 3.2 Docs Content ===*/ +.idocs-content { + position: relative; + margin-left: 260px; + padding: 0px 50px 50px; + min-height: 750px; + transition: all 0.3s; +} +.idocs-content section:first-child { + padding-top: 3rem; +} +.idocs-content ol li, .idocs-content ul li { + margin-top: 10px; +} + +@media (max-width: 767.98px) { + .idocs-navigation { + margin-left: -260px; + } + .idocs-navigation.active { + margin-left: 0; + } + + .idocs-content { + margin-left: 0px; + padding: 0px; + } +} +/*=== 3.3 Section Divider ===*/ +.divider { + margin: 4rem 0; +} + +/* =================================== */ +/* 4. Header +/* =================================== */ +#header { + -webkit-transition: all 0.5s ease; + transition: all 0.5s ease; +} +#header .navbar { + padding: 0px; + min-height: 70px; +} +#header .logo { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-item-align: stretch; + align-self: stretch; +} + +/*=== 4.1 Main Navigation ===*/ +.navbar-light .navbar-nav .active > .nav-link { + color: #0c2f55; +} +.navbar-light .navbar-nav .nav-link.active, .navbar-light .navbar-nav .nav-link.show { + color: #0c2f55; +} +.navbar-light .navbar-nav .show > .nav-link { + color: #0c2f55; +} + +.primary-menu { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + height: auto !important; + -webkit-box-ordinal-group: 0; + -ms-flex-item-align: stretch; + align-self: stretch; + background: #fff; + border-bottom: 1px solid #efefef; +} +.primary-menu.bg-transparent { + position: absolute; + z-index: 999; + top: 0; + left: 0; + width: 100%; + box-shadow: none; + border-bottom: 1px solid rgba(250, 250, 250, 0.3); +} +.primary-menu.sticky-on { + position: fixed; + top: 0; + width: 100%; + z-index: 1020; + left: 0; + -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.05); + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.05); + -webkit-animation: slide-down 0.7s; + -moz-animation: slide-down 0.7s; + animation: slide-down 0.7s; +} +@-webkit-keyframes slide-down { + 0% { + opacity: 0; + transform: translateY(-100%); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} +@-moz-keyframes slide-down { + 0% { + opacity: 0; + transform: translateY(-100%); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} +@keyframes slide-down { + 0% { + opacity: 0; + transform: translateY(-100%); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} +.primary-menu.sticky-on .none-on-sticky { + display: none !important; +} +.primary-menu ul.navbar-nav > li { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + height: 100%; +} +.primary-menu ul.navbar-nav > li + li { + margin-left: 2px; +} +.primary-menu ul.navbar-nav > li a { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.primary-menu ul.navbar-nav > li > a:not(.btn) { + height: 70px; + padding: 0px 0.85em; + color: #252b33; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + position: relative; + position: relative; +} +.primary-menu ul.navbar-nav > li:hover > a:not(.btn), .primary-menu ul.navbar-nav > li > a.active:not(.btn) { + color: #0366d6; + text-decoration: none; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.primary-menu ul.navbar-nav > li a.btn { + padding: 0.4rem 1.4rem; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li > a:not(.btn) { + padding: 8px 0px; + background-color: transparent; + text-transform: none; + color: #777; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #0366d6; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.primary-menu ul.navbar-nav > li.dropdown:hover > a:after { + clear: both; + content: ' '; + display: block; + width: 0; + height: 0; + border-style: solid; + border-color: transparent transparent #fff transparent; + position: absolute; + border-width: 0px 7px 6px 7px; + bottom: 0px; + left: 50%; + margin: 0 0 0 -5px; + z-index: 1022; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu { + -webkit-box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.176); + box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.176); + border: 0px none; + padding: 10px 15px; + min-width: 220px; + margin: 0; + font-size: 14px; + font-size: 0.875rem; + z-index: 1021; +} +.primary-menu ul.navbar-nav > li.dropdown > .dropdown-toggle .arrow { + display: none; +} +.primary-menu .dropdown-menu-right { + left: auto !important; + right: 100% !important; +} +.primary-menu ul.navbar-nav > li.dropdown-mega { + position: static; +} +.primary-menu ul.navbar-nav > li.dropdown-mega > .dropdown-menu { + width: 100%; + padding: 20px 20px; + margin-left: 0px !important; +} +.primary-menu ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div { + padding: 5px 5px 5px 20px; + border-right: 1px solid #eee; +} +.primary-menu ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div:last-child { + border-right: 0; +} +.primary-menu ul.navbar-nav > li.dropdown-mega .sub-title { + display: block; + font-size: 16px; + margin-top: 1rem; + padding-bottom: 5px; +} +.primary-menu ul.navbar-nav > li.dropdown-mega .dropdown-mega-submenu { + list-style-type: none; + padding-left: 0px; +} +.primary-menu ul.navbar-nav > li a.btn { + font-size: 14px; + padding: 0.65rem 2rem; + text-transform: uppercase; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + left: 100%; + margin-top: -40px; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-toggle:after { + border-top: .4em solid transparent; + border-right: 0; + border-bottom: 0.4em solid transparent; + border-left: 0.4em solid; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-toggle .arrow { + position: absolute; + min-width: 30px; + height: 100%; + right: 0px; + top: 0; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.primary-menu ul.navbar-nav > li.dropdown .dropdown-toggle .arrow:after { + content: " "; + position: absolute; + top: 50%; + left: 50%; + border-color: #000; + border-top: 1px solid; + border-right: 1px solid; + width: 6px; + height: 6px; + -webkit-transform: translate(-50%, -50%) rotate(45deg); + transform: translate(-50%, -50%) rotate(45deg); +} +.primary-menu .dropdown-toggle:after { + content: none; +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:not(.btn):after { + position: absolute; + content: ""; + height: 2px; + width: 0; + left: 50%; + right: 0; + bottom: 14px; + background-color: transparent; + color: #fff; + border-bottom: 2px solid #0366d6; + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + transform: translate(-50%, 0) translateZ(0); + -webkit-transform: translate(-50%, 0) translateZ(0); +} +.primary-menu.navbar-line-under-text ul.navbar-nav > li > a:hover:not(.logo):after, .primary-menu.navbar-line-under-text ul.navbar-nav > li > a.active:after { + width: calc(100% - 0.99em); +} + +/*== Color Options ==*/ +.primary-menu.navbar-text-light .navbar-toggler span { + background: #fff; +} + +.primary-menu.navbar-text-light .navbar-nav > li > a:not(.btn) { + color: #fff; +} +.primary-menu.navbar-text-light .navbar-nav > li:hover > a:not(.btn), .primary-menu.navbar-text-light .navbar-nav > li > a.active:not(.btn) { + color: rgba(250, 250, 250, 0.75); +} + +.primary-menu.navbar-text-light.navbar-line-under-text .navbar-nav > li > a:not(.logo):after, .primary-menu.navbar-text-light.navbar-line-under-text .navbar-nav > li > a.active:after { + border-color: rgba(250, 250, 250, 0.6); +} + +.primary-menu.navbar-dropdown-dark ul.navbar-nav > li.dropdown .dropdown-menu { + background-color: #252A2C; + color: #fff; +} +.primary-menu.navbar-dropdown-dark ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + background-color: #272c2e; +} +.primary-menu.navbar-dropdown-dark ul.navbar-nav > li.dropdown:hover > a:after { + border-color: transparent transparent #252A2C transparent; +} +.primary-menu.navbar-dropdown-dark ul.navbar-nav > li.dropdown .dropdown-menu li > a:not(.btn) { + color: rgba(250, 250, 250, 0.8); +} +.primary-menu.navbar-dropdown-dark ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #fafafa; + font-weight: 600; +} +.primary-menu.navbar-dropdown-dark ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div { + border-color: #3a3a3a; +} +.primary-menu.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu { + background-color: #0366d6; + color: #fff; +} +.primary-menu.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + background-color: #0366d6; +} +.primary-menu.navbar-dropdown-primary ul.navbar-nav > li.dropdown:hover > a:after { + border-color: transparent transparent #0366d6 transparent; +} +.primary-menu.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu li > a:not(.btn) { + color: rgba(250, 250, 250, 0.95); +} +.primary-menu.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu li:hover > a:not(.btn) { + color: #fafafa; + font-weight: 600; +} +.primary-menu.navbar-dropdown-primary ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div { + border-color: rgba(250, 250, 250, 0.2); +} + +/* Hamburger Menu Button */ +.navbar-toggler { + width: 25px; + height: 30px; + padding: 10px; + margin: 18px 15px; + position: relative; + border: none; + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + -webkit-transition: 0.5s ease-in-out; + transition: 0.5s ease-in-out; + cursor: pointer; + display: block; +} +.navbar-toggler span { + display: block; + position: absolute; + height: 2px; + width: 100%; + background: #3c3636; + border-radius: 2px; + opacity: 1; + left: 0; + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + -webkit-transition: 0.25s ease-in-out; + transition: 0.25s ease-in-out; +} +.navbar-toggler span:nth-child(1) { + top: 7px; + -webkit-transform-origin: left center; + -moz-transform-origin: left center; + -o-transform-origin: left center; + transform-origin: left center; +} +.navbar-toggler span:nth-child(2) { + top: 14px; + -webkit-transform-origin: left center; + -moz-transform-origin: left center; + -o-transform-origin: left center; + transform-origin: left center; +} +.navbar-toggler span:nth-child(3) { + top: 21px; + -webkit-transform-origin: left center; + -moz-transform-origin: left center; + -o-transform-origin: left center; + transform-origin: left center; +} +.navbar-toggler.show span:nth-child(1) { + top: 4px; + left: 3px; + -webkit-transform: rotate(45deg); + transform: rotate(45deg); +} +.navbar-toggler.show span:nth-child(2) { + width: 0%; + opacity: 0; +} +.navbar-toggler.show span:nth-child(3) { + top: 22px; + left: 3px; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); +} + +.navbar-accordion { + position: initial; +} + +.navbar-expand-none .navbar-collapse { + position: absolute; + top: 99%; + right: 0; + left: 0; + background: #fff; + margin-top: 0px; + z-index: 1000; + -webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); +} +.navbar-expand-none .navbar-collapse .navbar-nav { + overflow: hidden; + overflow-y: auto; + max-height: 65vh; + padding: 15px; +} +.navbar-expand-none ul.navbar-nav li { + display: block; + border-bottom: 1px solid #eee; + margin: 0; + padding: 0; +} +.navbar-expand-none ul.navbar-nav li:last-child { + border: none; +} +.navbar-expand-none ul.navbar-nav li + li { + margin-left: 0px; +} +.navbar-expand-none ul.navbar-nav li.dropdown > .dropdown-toggle > .arrow.show:after { + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.navbar-expand-none ul.navbar-nav li > a:hover:after, .navbar-expand-none ul.navbar-nav li > a.active:after { + content: none !important; + width: 0px !important; +} +.navbar-expand-none ul.navbar-nav li.dropdown > .dropdown-toggle .arrow { + display: block; +} +.navbar-expand-none ul.navbar-nav > li > a:not(.btn) { + height: auto; + padding: 8px 0; + position: relative; +} +.navbar-expand-none ul.navbar-nav > li.dropdown .dropdown-menu li > a:not(.btn) { + padding: 8px 0; + position: relative; +} +.navbar-expand-none ul.navbar-nav > li.dropdown:hover > a:after { + content: none; +} +.navbar-expand-none ul.navbar-nav > li.dropdown .dropdown-toggle .arrow:after { + -webkit-transform: translate(-50%, -50%) rotate(134deg); + transform: translate(-50%, -50%) rotate(134deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.navbar-expand-none ul.navbar-nav > li.dropdown .dropdown-menu { + margin: 0; + -webkit-box-shadow: none; + box-shadow: none; + border: none; + padding: 0px 0px 0px 15px; +} +.navbar-expand-none ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + margin: 0; +} +.navbar-expand-none ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div { + padding: 0px 15px; +} +.navbar-expand-none.navbar-text-light .navbar-collapse { + background: rgba(0, 0, 0, 0.95); +} +.navbar-expand-none.navbar-text-light .navbar-collapse ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.15); +} +.navbar-expand-none.navbar-dropdown-dark .navbar-collapse { + background-color: #252A2C; +} +.navbar-expand-none.navbar-dropdown-primary .navbar-collapse { + background-color: #0366d6; +} +.navbar-expand-none.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + background-color: #0366d6; +} +.navbar-expand-none.navbar-dropdown-dark ul.navbar-nav li { + border-color: #444; +} +.navbar-expand-none.navbar-dropdown-dark ul.navbar-nav > li > a { + color: #a3a2a2; +} +.navbar-expand-none.navbar-dropdown-dark ul.navbar-nav > li:hover > a { + color: #fff; +} +.navbar-expand-none.navbar-dropdown-primary ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.2); +} +.navbar-expand-none.navbar-dropdown-primary ul.navbar-nav > li > a { + color: rgba(250, 250, 250, 0.8); +} +.navbar-expand-none.navbar-dropdown-primary ul.navbar-nav > li:hover > a { + color: #fff; +} + +@media (max-width: 575.98px) { + .navbar-expand-sm .navbar-collapse { + position: absolute; + top: 99%; + right: 0; + left: 0; + background: #fff; + margin-top: 0px; + z-index: 1000; + -webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + } + .navbar-expand-sm .navbar-collapse .navbar-nav { + overflow: hidden; + overflow-y: auto; + max-height: 65vh; + padding: 15px; + } + .navbar-expand-sm ul.navbar-nav li { + display: block; + border-bottom: 1px solid #eee; + margin: 0; + padding: 0; + } + .navbar-expand-sm ul.navbar-nav li:last-child { + border: none; + } + .navbar-expand-sm ul.navbar-nav li + li { + margin-left: 0px; + } + .navbar-expand-sm ul.navbar-nav li.dropdown > .dropdown-toggle > .arrow.show:after { + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + .navbar-expand-sm ul.navbar-nav li > a:hover:after, .navbar-expand-sm ul.navbar-nav li > a.active:after { + content: none !important; + width: 0px !important; + } + .navbar-expand-sm ul.navbar-nav li.dropdown > .dropdown-toggle .arrow { + display: block; + } + .navbar-expand-sm ul.navbar-nav > li > a:not(.btn) { + height: auto; + padding: 8px 0; + position: relative; + } + .navbar-expand-sm ul.navbar-nav > li.dropdown .dropdown-menu li > a:not(.btn) { + padding: 8px 0; + position: relative; + } + .navbar-expand-sm ul.navbar-nav > li.dropdown:hover > a:after { + content: none; + } + .navbar-expand-sm ul.navbar-nav > li.dropdown .dropdown-toggle .arrow:after { + -webkit-transform: translate(-50%, -50%) rotate(134deg); + transform: translate(-50%, -50%) rotate(134deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + .navbar-expand-sm ul.navbar-nav > li.dropdown .dropdown-menu { + margin: 0; + -webkit-box-shadow: none; + box-shadow: none; + border: none; + padding: 0px 0px 0px 15px; + } + .navbar-expand-sm ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + margin: 0; + } + .navbar-expand-sm ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div { + padding: 0px 15px; + } + .navbar-expand-sm.navbar-text-light .navbar-collapse { + background: rgba(0, 0, 0, 0.95); + } + .navbar-expand-sm.navbar-text-light .navbar-collapse ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.15); + } + .navbar-expand-sm.navbar-dropdown-dark .navbar-collapse { + background-color: #252A2C; + } + .navbar-expand-sm.navbar-dropdown-primary .navbar-collapse { + background-color: #0366d6; + } + .navbar-expand-sm.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + background-color: #0366d6; + } + .navbar-expand-sm.navbar-dropdown-dark ul.navbar-nav li { + border-color: #444; + } + .navbar-expand-sm.navbar-dropdown-dark ul.navbar-nav > li > a { + color: #a3a2a2; + } + .navbar-expand-sm.navbar-dropdown-dark ul.navbar-nav > li:hover > a { + color: #fff; + } + .navbar-expand-sm.navbar-dropdown-primary ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.2); + } + .navbar-expand-sm.navbar-dropdown-primary ul.navbar-nav > li > a { + color: rgba(250, 250, 250, 0.8); + } + .navbar-expand-sm.navbar-dropdown-primary ul.navbar-nav > li:hover > a { + color: #fff; + } +} +@media (max-width: 767.98px) { + .navbar-expand-md .navbar-collapse { + position: absolute; + top: 99%; + right: 0; + left: 0; + background: #fff; + margin-top: 0px; + z-index: 1000; + -webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + } + .navbar-expand-md .navbar-collapse .navbar-nav { + overflow: hidden; + overflow-y: auto; + max-height: 65vh; + padding: 15px; + } + .navbar-expand-md ul.navbar-nav li { + display: block; + border-bottom: 1px solid #eee; + margin: 0; + padding: 0; + } + .navbar-expand-md ul.navbar-nav li:last-child { + border: none; + } + .navbar-expand-md ul.navbar-nav li + li { + margin-left: 0px; + } + .navbar-expand-md ul.navbar-nav li.dropdown > .dropdown-toggle > .arrow.show:after { + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + .navbar-expand-md ul.navbar-nav li > a:hover:after, .navbar-expand-md ul.navbar-nav li > a.active:after { + content: none !important; + width: 0px !important; + } + .navbar-expand-md ul.navbar-nav li.dropdown > .dropdown-toggle .arrow { + display: block; + } + .navbar-expand-md ul.navbar-nav > li > a:not(.btn) { + height: auto; + padding: 8px 0; + position: relative; + } + .navbar-expand-md ul.navbar-nav > li.dropdown .dropdown-menu li > a:not(.btn) { + padding: 8px 0; + position: relative; + } + .navbar-expand-md ul.navbar-nav > li.dropdown:hover > a:after { + content: none; + } + .navbar-expand-md ul.navbar-nav > li.dropdown .dropdown-toggle .arrow:after { + -webkit-transform: translate(-50%, -50%) rotate(134deg); + transform: translate(-50%, -50%) rotate(134deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + .navbar-expand-md ul.navbar-nav > li.dropdown .dropdown-menu { + margin: 0; + -webkit-box-shadow: none; + box-shadow: none; + border: none; + padding: 0px 0px 0px 15px; + } + .navbar-expand-md ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + margin: 0; + } + .navbar-expand-md ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div { + padding: 0px 15px; + } + .navbar-expand-md.navbar-text-light .navbar-collapse { + background: rgba(0, 0, 0, 0.95); + } + .navbar-expand-md.navbar-text-light .navbar-collapse ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.15); + } + .navbar-expand-md.navbar-dropdown-dark .navbar-collapse { + background-color: #252A2C; + } + .navbar-expand-md.navbar-dropdown-primary .navbar-collapse { + background-color: #0366d6; + } + .navbar-expand-md.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + background-color: #0366d6; + } + .navbar-expand-md.navbar-dropdown-dark ul.navbar-nav li { + border-color: #444; + } + .navbar-expand-md.navbar-dropdown-dark ul.navbar-nav > li > a { + color: #a3a2a2; + } + .navbar-expand-md.navbar-dropdown-dark ul.navbar-nav > li:hover > a { + color: #fff; + } + .navbar-expand-md.navbar-dropdown-primary ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.2); + } + .navbar-expand-md.navbar-dropdown-primary ul.navbar-nav > li > a { + color: rgba(250, 250, 250, 0.8); + } + .navbar-expand-md.navbar-dropdown-primary ul.navbar-nav > li:hover > a { + color: #fff; + } +} +@media (max-width: 991.98px) { + .navbar-expand-lg .navbar-collapse { + position: absolute; + top: 99%; + right: 0; + left: 0; + background: #fff; + margin-top: 0px; + z-index: 1000; + -webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + } + .navbar-expand-lg .navbar-collapse .navbar-nav { + overflow: hidden; + overflow-y: auto; + max-height: 65vh; + padding: 15px; + } + .navbar-expand-lg ul.navbar-nav li { + display: block; + border-bottom: 1px solid #eee; + margin: 0; + padding: 0; + } + .navbar-expand-lg ul.navbar-nav li:last-child { + border: none; + } + .navbar-expand-lg ul.navbar-nav li + li { + margin-left: 0px; + } + .navbar-expand-lg ul.navbar-nav li.dropdown > .dropdown-toggle > .arrow.show:after { + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + .navbar-expand-lg ul.navbar-nav li > a:hover:after, .navbar-expand-lg ul.navbar-nav li > a.active:after { + content: none !important; + width: 0px !important; + } + .navbar-expand-lg ul.navbar-nav li.dropdown > .dropdown-toggle .arrow { + display: block; + } + .navbar-expand-lg ul.navbar-nav > li > a:not(.btn) { + height: auto; + padding: 8px 0; + position: relative; + } + .navbar-expand-lg ul.navbar-nav > li.dropdown .dropdown-menu li > a:not(.btn) { + padding: 8px 0; + position: relative; + } + .navbar-expand-lg ul.navbar-nav > li.dropdown:hover > a:after { + content: none; + } + .navbar-expand-lg ul.navbar-nav > li.dropdown .dropdown-toggle .arrow:after { + -webkit-transform: translate(-50%, -50%) rotate(134deg); + transform: translate(-50%, -50%) rotate(134deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + .navbar-expand-lg ul.navbar-nav > li.dropdown .dropdown-menu { + margin: 0; + -webkit-box-shadow: none; + box-shadow: none; + border: none; + padding: 0px 0px 0px 15px; + } + .navbar-expand-lg ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + margin: 0; + } + .navbar-expand-lg ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div { + padding: 0px 15px; + } + .navbar-expand-lg.navbar-text-light .navbar-collapse { + background: rgba(0, 0, 0, 0.95); + } + .navbar-expand-lg.navbar-text-light .navbar-collapse ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.15); + } + .navbar-expand-lg.navbar-dropdown-dark .navbar-collapse { + background-color: #252A2C; + } + .navbar-expand-lg.navbar-dropdown-primary .navbar-collapse { + background-color: #0366d6; + } + .navbar-expand-lg.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + background-color: #0366d6; + } + .navbar-expand-lg.navbar-dropdown-dark ul.navbar-nav li { + border-color: #444; + } + .navbar-expand-lg.navbar-dropdown-dark ul.navbar-nav > li > a { + color: #a3a2a2; + } + .navbar-expand-lg.navbar-dropdown-dark ul.navbar-nav > li:hover > a { + color: #fff; + } + .navbar-expand-lg.navbar-dropdown-primary ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.2); + } + .navbar-expand-lg.navbar-dropdown-primary ul.navbar-nav > li > a { + color: rgba(250, 250, 250, 0.8); + } + .navbar-expand-lg.navbar-dropdown-primary ul.navbar-nav > li:hover > a { + color: #fff; + } +} +@media (max-width: 1199.98px) { + .navbar-expand-xl .navbar-collapse { + position: absolute; + top: 99%; + right: 0; + left: 0; + background: #fff; + margin-top: 0px; + z-index: 1000; + -webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.1); + } + .navbar-expand-xl .navbar-collapse .navbar-nav { + overflow: hidden; + overflow-y: auto; + max-height: 65vh; + padding: 15px; + } + .navbar-expand-xl ul.navbar-nav li { + display: block; + border-bottom: 1px solid #eee; + margin: 0; + padding: 0; + } + .navbar-expand-xl ul.navbar-nav li:last-child { + border: none; + } + .navbar-expand-xl ul.navbar-nav li + li { + margin-left: 0px; + } + .navbar-expand-xl ul.navbar-nav li.dropdown > .dropdown-toggle > .arrow.show:after { + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + .navbar-expand-xl ul.navbar-nav li > a:hover:after, .navbar-expand-xl ul.navbar-nav li > a.active:after { + content: none !important; + width: 0px !important; + } + .navbar-expand-xl ul.navbar-nav li.dropdown > .dropdown-toggle .arrow { + display: block; + } + .navbar-expand-xl ul.navbar-nav > li > a:not(.btn) { + height: auto; + padding: 8px 0; + position: relative; + } + .navbar-expand-xl ul.navbar-nav > li.dropdown .dropdown-menu li > a:not(.btn) { + padding: 8px 0; + position: relative; + } + .navbar-expand-xl ul.navbar-nav > li.dropdown:hover > a:after { + content: none; + } + .navbar-expand-xl ul.navbar-nav > li.dropdown .dropdown-toggle .arrow:after { + -webkit-transform: translate(-50%, -50%) rotate(134deg); + transform: translate(-50%, -50%) rotate(134deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + .navbar-expand-xl ul.navbar-nav > li.dropdown .dropdown-menu { + margin: 0; + -webkit-box-shadow: none; + box-shadow: none; + border: none; + padding: 0px 0px 0px 15px; + } + .navbar-expand-xl ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + margin: 0; + } + .navbar-expand-xl ul.navbar-nav > li.dropdown-mega .dropdown-mega-content > .row > div { + padding: 0px 15px; + } + .navbar-expand-xl.navbar-text-light .navbar-collapse { + background: rgba(0, 0, 0, 0.95); + } + .navbar-expand-xl.navbar-text-light .navbar-collapse ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.15); + } + .navbar-expand-xl.navbar-dropdown-dark .navbar-collapse { + background-color: #252A2C; + } + .navbar-expand-xl.navbar-dropdown-primary .navbar-collapse { + background-color: #0366d6; + } + .navbar-expand-xl.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + background-color: #0366d6; + } + .navbar-expand-xl.navbar-dropdown-dark ul.navbar-nav li { + border-color: #444; + } + .navbar-expand-xl.navbar-dropdown-dark ul.navbar-nav > li > a { + color: #a3a2a2; + } + .navbar-expand-xl.navbar-dropdown-dark ul.navbar-nav > li:hover > a { + color: #fff; + } + .navbar-expand-xl.navbar-dropdown-primary ul.navbar-nav li { + border-color: rgba(250, 250, 250, 0.2); + } + .navbar-expand-xl.navbar-dropdown-primary ul.navbar-nav > li > a { + color: rgba(250, 250, 250, 0.8); + } + .navbar-expand-xl.navbar-dropdown-primary ul.navbar-nav > li:hover > a { + color: #fff; + } +} +/* =================================== */ +/* 5. Elements +/* =================================== */ +/*=== 5.1 List Style ===*/ +.list-style-1 > li { + position: relative; + list-style-type: none; + line-height: 24px; +} +.list-style-1 > li:after { + content: " "; + position: absolute; + top: 12px; + left: -15px; + border-color: #000; + border-top: 1px solid; + border-right: 1px solid; + width: 6px; + height: 6px; + -webkit-transform: translate(-50%, -50%) rotate(45deg); + transform: translate(-50%, -50%) rotate(45deg); +} + +.list-style-2 { + padding: 0; +} + +.list-style-2 > li { + list-style-type: none; + border-bottom: 1px solid #eaeaea; + padding-top: 12px; + padding-bottom: 12px; +} + +.list-style-2.list-style-light > li { + border-bottom: 1px solid rgba(250, 250, 250, 0.12); +} + +/*=== 5.2 Changelog ===*/ +.changelog { + list-style: none; + padding: 0; +} +.changelog .badge { + width: 90px; + margin-right: 10px; + border-radius: .20rem; + text-transform: uppercase; +} +.changelog li { + line-height: 1.8; +} + +/*=== 5.3 Accordion & Toggle ===*/ +.accordion .card { + border: none; + margin-bottom: 16px; + margin-bottom: 1rem; + background-color: transparent; +} +.accordion .card-header { + padding: 0; + border: none; + background: none; +} +.accordion .card-header a { + font-size: 16px; + font-weight: normal; + padding: 1rem 1.25rem 1rem 2.25rem; + display: block; + border-radius: 4px; + position: relative; +} +.accordion .card-header a:hover { + text-decoration: none; +} +.accordion .card-header a:hover.collapsed { + color: #0366d6 !important; +} +.accordion:not(.accordion-alternate) .card-header a { + background-color: #76ace8; + color: #fff; +} +.accordion:not(.accordion-alternate) .card-header a.collapsed { + background-color: #f1f2f4; + color: #4c4d4d; +} +.accordion .card-header a:before { + position: absolute; + content: " "; + left: 20px; + top: calc(50% + 2px); + width: 9px; + height: 9px; + border-color: #CCC; + border-top: 2px solid; + border-right: 2px solid; + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} +.accordion .card-header a.collapsed:before { + top: calc(50% - 2px); + -webkit-transform: translate(-50%, -50%) rotate(135deg); + transform: translate(-50%, -50%) rotate(135deg); +} +.accordion .card-body { + line-height: 26px; + border: 1px solid #ccc; + margin-top: -4px; + border-radius: 4px; +} +.accordion.arrow-right .card-header a { + padding-left: 1.25rem; +} +.accordion.arrow-right .card-header a:before { + right: 15px; + left: auto; +} +.accordion.accordion-alternate .card { + margin: 0; +} +.accordion.accordion-alternate .card-header a { + padding-left: 1.40rem; + border-top: 1px solid #e4e9ec; + border-radius: 0px; +} +.accordion.accordion-alternate .card:first-of-type .card-header a { + border-top: 0px; +} +.accordion.accordion-alternate .card-header a:before { + left: 6px; +} +.accordion.accordion-alternate .card-header a.collapsed { + color: #4c4d4d; +} +.accordion.accordion-alternate .card-body { + padding: 0rem 0 1rem 1.25rem; +} +.accordion.accordion-alternate.arrow-right .card-header a { + padding-left: 0; +} +.accordion.accordion-alternate.arrow-right .card-header a:before { + right: 0px; + left: auto; +} +.accordion.toggle .card-header a:before { + content: "-"; + border: none; + font-size: 20px; + height: auto; + top: calc(50% + 2px); + width: auto; + -webkit-transform: translate(-50%, -50%) rotate(180deg); + transform: translate(-50%, -50%) rotate(180deg); +} +.accordion.toggle .card-header a.collapsed:before { + content: "+"; + top: calc(50% - 1px); + -webkit-transform: translate(-50%, -50%) rotate(0deg); + transform: translate(-50%, -50%) rotate(0deg); +} +.accordion.accordion-alternate.style-2 .card-header a { + padding-left: 0px; +} +.accordion.accordion-alternate.style-2 .card-header a:before { + right: 2px; + left: auto; + -webkit-transform: translate(-50%, -50%) rotate(135deg); + transform: translate(-50%, -50%) rotate(135deg); + top: 50%; +} +.accordion.accordion-alternate.style-2 .card-header a.collapsed:before { + -webkit-transform: translate(-50%, -50%) rotate(45deg); + transform: translate(-50%, -50%) rotate(45deg); +} +.accordion.accordion-alternate.style-2 .card-body { + padding-left: 0px; +} +.accordion.accordion-alternate.popularRoutes .card-header .nav { + margin-top: 3px; +} +.accordion.accordion-alternate.popularRoutes .card-header .nav a { + font-size: 14px; +} +.accordion.accordion-alternate.popularRoutes .card-header a { + padding: 0px 8px 0px 0px; + border: none; + font-size: inherit; +} +.accordion.accordion-alternate.popularRoutes .card-header a:before { + content: none; +} +.accordion.accordion-alternate.popularRoutes .card-header h5 { + cursor: pointer; +} +.accordion.accordion-alternate.popularRoutes .card-header h5:before { + position: absolute; + content: " "; + right: 0px; + top: 24px; + width: 10px; + height: 10px; + opacity: 0.6; + border-top: 2px solid; + border-right: 2px solid; + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; +} +.accordion.accordion-alternate.popularRoutes .card-header h5.collapsed:before { + top: 24px; + -webkit-transform: translate(-50%, -50%) rotate(135deg); + transform: translate(-50%, -50%) rotate(135deg); +} +.accordion.accordion-alternate.popularRoutes .card-body { + padding: 0; +} +.accordion.accordion-alternate.popularRoutes .card { + border-bottom: 2px solid #e4e9ec; + padding: 15px 0px; +} +.accordion.accordion-alternate.popularRoutes .routes-list { + margin: 1rem 0px 0px 0px; + padding: 0px; + list-style: none; +} +.accordion.accordion-alternate.popularRoutes .routes-list a { + color: inherit; + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-align: center !important; + align-items: center !important; +} +.accordion.accordion-alternate.popularRoutes .routes-list a:hover { + color: #0071cc; + text-decoration: underline; +} + +/* 5.4 Nav */ +.nav .nav-item .nav-link { + color: #222222; +} + +.nav.nav-light .nav-item .nav-link { + color: #ddd; +} + +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover { + color: #0366d6; +} + +.nav-pills .nav-link:not(.active):hover { + color: #0366d6; +} + +.nav-pills .nav-link.active, .nav-pills.nav-light .nav-link.active, .nav-pills .show > .nav-link { + color: #fff; +} + +.nav.nav-separator .nav-item .nav-link { + position: relative; +} + +.nav.nav-separator .nav-item + .nav-item .nav-link:after { + height: 14px; + width: 1px; + content: ' '; + background-color: rgba(0, 0, 0, 0.2); + display: block; + position: absolute; + top: 50%; + left: 0; + -webkit-transform: translateY(-7px); + transform: translateY(-7px); +} + +.nav.nav-separator.nav-separator-light .nav-item + .nav-item .nav-link:after { + background-color: rgba(250, 250, 250, 0.2); +} + +.nav.nav-sm .nav-item .nav-link { + font-size: 14px; +} + +/*=== 5.5 Tabs ===*/ +.nav-tabs { + border-bottom: 1px solid #d7dee3; + padding-bottom: 16px; +} +.nav-tabs .nav-item .nav-link { + border: 0; + background: transparent; + position: relative; + border-radius: 0; + padding: 0.6rem 1rem; + color: #7b8084; + white-space: nowrap !important; +} +.nav-tabs .nav-item .nav-link.active { + color: #0c2f55; +} +.nav-tabs .nav-item .nav-link.active:after { + height: 2px; + width: 100%; + content: ' '; + background-color: #0366d6; + display: block; + position: absolute; + bottom: -3px; + left: 0; + -webkit-transform: translateY(-3px); + transform: translateY(-3px); +} +.nav-tabs .nav-item .nav-link:not(.active):after { + height: 2px; + width: calc(100% - 10px); + content: ' '; + background-color: #aaa; + display: block; + margin: 0 5px; + position: absolute; + bottom: -3px; + left: 0; + -webkit-transform: translateY(-3px); + transform: translateY(-3px); +} +.nav-tabs .nav-item .nav-link:not(.active):hover { + color: #0366d6; +} +.nav-tabs.flex-column { + border-right: 1px solid #d7dee3; + border-bottom: 0px; + padding: 1.5rem 0; +} +.nav-tabs.flex-column .nav-item .nav-link { + border: 1px solid #d7dee3; + border-right: 0px; + background-color: #f6f7f8; + font-size: 14px; + padding: 0.75rem 1rem; + color: #535b61; +} +.nav-tabs.flex-column .nav-item:first-of-type .nav-link { + border-top-left-radius: 4px; +} +.nav-tabs.flex-column .nav-item:last-of-type .nav-link { + border-bottom-left-radius: 4px; +} +.nav-tabs.flex-column .nav-item .nav-link.active { + background-color: transparent; + color: #0366d6; +} +.nav-tabs.flex-column .nav-item .nav-link.active:after { + height: 100%; + width: 2px; + background: #fff; + right: -1px; + left: auto; +} + +.nav-tabs:not(.flex-column) { + overflow: hidden; + overflow-x: auto; + -ms-overflow-style: -ms-autohiding-scrollbar; + -webkit-overflow-scrolling: touch; +} +.nav-tabs:not(.flex-column) .nav-item { + margin-bottom: 0px; +} + +@media (max-width: 575.98px) { + .nav-tabs .nav-item .nav-link { + padding-left: 0px; + padding-right: 0px; + margin-right: 10px; + font-size: 0.875rem; + } +} +/*=== 5.6 Popup Img ===*/ +.popup-img img { + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +.popup-img:hover img { + opacity: 0.8; + cursor: -webkit-zoom-in; + cursor: -moz-zoom-in; + cursor: zoom-in; +} + +/*=== 5.7 Featured Box ===*/ +.featured-box { + box-sizing: border-box; + position: relative; +} +.featured-box h3, .featured-box h4 { + font-size: 1.25rem; + font-size: 20px; + margin-bottom: 10px; + font-weight: 500; +} +.featured-box:not(.style-5) .featured-box-icon { + display: inline-block; + font-size: 48px; + min-width: 55px; + min-height: 55px; + padding: 0; + margin-top: 0; + margin-bottom: 0.8rem; + color: #4c4d4d; + border-radius: 0; +} +.featured-box.style-1, .featured-box.style-2, .featured-box.style-3 { + padding-left: 50px; + padding-top: 8px; +} +.featured-box.style-1 .featured-box-icon, .featured-box.style-2 .featured-box-icon, .featured-box.style-3 .featured-box-icon { + position: absolute; + top: 0; + left: 0; + margin-bottom: 0; + font-size: 30px; + -ms-flex-pack: center !important; + justify-content: center !important; + text-align: center; +} +.featured-box.style-2 p { + margin-left: -50px; +} +.featured-box.style-3 { + padding-left: 90px; + padding-top: 0px; +} +.featured-box.style-3 .featured-box-icon { + width: 70px; + height: 70px; + -ms-flex-negative: 0; + flex-shrink: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.featured-box.style-4 { + text-align: center; +} +.featured-box.style-4 .featured-box-icon { + margin: 0 auto 24px; + margin: 0 auto 1.5rem; + width: 120px; + height: 120px; + text-align: center; + -ms-flex-negative: 0; + flex-shrink: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-shadow: 0px 0px 50px rgba(0, 0, 0, 0.03); + box-shadow: 0px 0px 50px rgba(0, 0, 0, 0.03); +} +.featured-box.style-5 { + text-align: center; + background: #fff; + border: 1px solid #f0f2f3; + -webkit-box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.05); + box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.05); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; +} +.featured-box.style-5:hover { + border: 1px solid #ebeded; + -webkit-box-shadow: 0px 5px 1.5rem rgba(0, 0, 0, 0.15); + box-shadow: 0px 5px 1.5rem rgba(0, 0, 0, 0.15); +} +.featured-box.style-5 h3 { + background: #f1f5f6; + font-size: 16px; + padding: 8px 0; + margin-bottom: 0px; +} +.featured-box.style-5 .featured-box-icon { + font-size: 50px; + margin: 44px 0px; +} + +.featured-box.featured-box-reverse { + text-align: right; +} +.featured-box.featured-box-reverse.style-1, .featured-box.featured-box-reverse.style-2 { + padding-right: 50px; + padding-left: 0px; +} +.featured-box.featured-box-reverse.style-1 .featured-box-icon, .featured-box.featured-box-reverse.style-2 .featured-box-icon { + left: auto; + right: 0px; +} +.featured-box.featured-box-reverse.style-2 p { + margin-right: -50px; + margin-left: 0; +} +.featured-box.featured-box-reverse.style-3 { + padding-left: 0; + padding-right: 90px; +} +.featured-box.featured-box-reverse.style-3 .featured-box-icon { + left: auto; + right: 0px; +} + +.featured-box.featured-box-reverse-sm { + text-align: right; +} +.featured-box.featured-box-reverse-sm.style-1, .featured-box.featured-box-reverse-sm.style-2 { + padding-right: 50px; + padding-left: 0px; +} +.featured-box.featured-box-reverse-sm.style-1 .featured-box-icon, .featured-box.featured-box-reverse-sm.style-2 .featured-box-icon { + left: auto; + right: 0px; +} +.featured-box.featured-box-reverse-sm.style-2 p { + margin-right: -50px; + margin-left: 0; +} +.featured-box.featured-box-reverse-sm.style-3 { + padding-left: 0; + padding-right: 90px; +} +.featured-box.featured-box-reverse-sm.style-3 .featured-box-icon { + left: auto; + right: 0px; +} + +@media (min-width: 576px) { + .featured-box.featured-box-reverse-md { + text-align: right; + } + .featured-box.featured-box-reverse-md.style-1, .featured-box.featured-box-reverse-md.style-2 { + padding-right: 50px; + padding-left: 0px; + } + .featured-box.featured-box-reverse-md.style-1 .featured-box-icon, .featured-box.featured-box-reverse-md.style-2 .featured-box-icon { + left: auto; + right: 0px; + } + .featured-box.featured-box-reverse-md.style-2 p { + margin-right: -50px; + margin-left: 0; + } + .featured-box.featured-box-reverse-md.style-3 { + padding-left: 0; + padding-right: 90px; + } + .featured-box.featured-box-reverse-md.style-3 .featured-box-icon { + left: auto; + right: 0px; + } +} +@media (min-width: 768px) { + .featured-box.featured-box-reverse-lg { + text-align: right; + } + .featured-box.featured-box-reverse-lg.style-1, .featured-box.featured-box-reverse-lg.style-2 { + padding-right: 50px; + padding-left: 0px; + } + .featured-box.featured-box-reverse-lg.style-1 .featured-box-icon, .featured-box.featured-box-reverse-lg.style-2 .featured-box-icon { + left: auto; + right: 0px; + } + .featured-box.featured-box-reverse-lg.style-2 p { + margin-right: -50px; + margin-left: 0; + } + .featured-box.featured-box-reverse-lg.style-3 { + padding-left: 0; + padding-right: 90px; + } + .featured-box.featured-box-reverse-lg.style-3 .featured-box-icon { + left: auto; + right: 0px; + } +} +@media (min-width: 992px) { + .featured-box.featured-box-reverse-xl { + text-align: right; + } + .featured-box.featured-box-reverse-xl.style-1, .featured-box.featured-box-reverse-xl.style-2 { + padding-right: 50px; + padding-left: 0px; + } + .featured-box.featured-box-reverse-xl.style-1 .featured-box-icon, .featured-box.featured-box-reverse-xl.style-2 .featured-box-icon { + left: auto; + right: 0px; + } + .featured-box.featured-box-reverse-xl.style-2 p { + margin-right: -50px; + margin-left: 0; + } + .featured-box.featured-box-reverse-xl.style-3 { + padding-left: 0; + padding-right: 90px; + } + .featured-box.featured-box-reverse-xl.style-3 .featured-box-icon { + left: auto; + right: 0px; + } +} +/* =================================== */ +/* 6. Footer +/* =================================== */ +#footer { + background: #fff; + color: #252b33; + margin-left: 260px; + padding: 66px 0px; + padding: 4.125rem 0; +} +#footer .nav .nav-item { + display: inline-block; + line-height: 12px; + margin: 0; +} +#footer .nav .nav-item .nav-link { + color: #252b33; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +#footer .nav .nav-item .nav-link:focus { + color: #0366d6; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +#footer .nav .nav-item:first-child .nav-link { + padding-left: 0px; +} +#footer .nav .nav-item:last-child .nav-link { + padding-right: 0px; +} +#footer .nav .nav-link:hover { + color: #0366d6; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +#footer .footer-copyright { + border-top: 1px solid #e2e8ea; + padding: 0px 0px; + color: #67727c; +} +#footer .footer-copyright .nav .nav-item .nav-link { + color: #67727c; +} +#footer .footer-copyright .nav .nav-link:hover { + color: #0366d6; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +#footer .nav.flex-column .nav-item { + padding: 0px; +} +#footer .nav.flex-column .nav-item .nav-link { + margin: 0.7rem 0px; +} +#footer.footer-text-light { + color: rgba(250, 250, 250, 0.8); +} +#footer.footer-text-light .nav .nav-item .nav-link { + color: rgba(250, 250, 250, 0.8); +} +#footer.footer-text-light .nav .nav-item .nav-link:hover { + color: #fafafa; +} +#footer.footer-text-light .footer-copyright { + border-color: rgba(250, 250, 250, 0.15); + color: rgba(250, 250, 250, 0.5); +} +#footer.footer-text-light:not(.bg-primary) .social-icons-light.social-icons li a { + color: rgba(250, 250, 250, 0.8); +} +#footer.footer-text-light:not(.bg-primary) .social-icons-light.social-icons li a:hover { + color: #fafafa; +} +#footer.footer-text-light.bg-primary { + color: #fff; +} +#footer.footer-text-light.bg-primary .nav .nav-item .nav-link { + color: #fff; +} +#footer.footer-text-light.bg-primary .nav .nav-item .nav-link:hover { + color: rgba(250, 250, 250, 0.7); +} +#footer.footer-text-light.bg-primary .footer-copyright { + border-color: rgba(250, 250, 250, 0.15); + color: rgba(250, 250, 250, 0.9); +} +#footer.footer-text-light.bg-primary :not(.social-icons) a { + color: #fff; +} +#footer.footer-text-light.bg-primary :not(.social-icons) a:hover { + color: rgba(250, 250, 250, 0.7); +} + +@media (max-width: 767.98px) { + #footer { + margin-left: 0px; + } +} +/*=== 6.1 Social Icons ===*/ +.social-icons { + margin: 0; + padding: 0; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + list-style: none; +} +.social-icons li { + margin: 0px 6px; + padding: 0; + overflow: visible; +} +.social-icons-ce { + margin-right: 120px !important; +} +.social-icons-nuget{ + margin-right: 24px !important; +} +.social-icons li a { + display: block; + height: 26px; + line-height: 26px; + width: 26px; + font-size: 18px; + text-align: center; + color: #4d555a; + text-decoration: none; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.social-icons li i { + line-height: inherit; +} +.social-icons.social-icons-sm li { + margin: 0px 4px; +} +.social-icons.social-icons-sm li a { + font-size: 15px; + width: 22px; +} +.social-icons.social-icons-lg li a { + width: 34px; + height: 34px; + line-height: 34px; + font-size: 22px; +} +.social-icons.social-icons-light li a { + color: #eee; +} +.social-icons.social-icons-muted li a { + color: #aab1b8; +} +.social-icons li:hover a { + color: #999; +} + +/*=== 6.2 Back to Top ===*/ +#back-to-top { + display: none; + position: fixed; + z-index: 1030; + bottom: 8px; + right: 10px; + background-color: rgba(0, 0, 0, 0.22); + text-align: center; + color: #fff; + font-size: 14px; + width: 36px; + height: 36px; + line-height: 34px; + border-radius: 3px; + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + -webkit-box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); +} +#back-to-top:hover { + background-color: #0366d6; + -webkit-box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.25); + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.25); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; +} + +@media (max-width: 575.98px) { + #back-to-top { + z-index: 1029; + } +} +/* =================================== */ +/* Extras +/* =================================== */ +/* Bootstrap Specific */ +.form-control, .custom-select { + border-color: #dae1e3; + font-size: 16px; + color: #656565; +} + +.form-control:not(.form-control-sm) { + padding: .810rem .96rem; + height: inherit; +} + +.form-control-sm { + font-size: 14px; +} + +.icon-inside { + position: absolute; + right: 15px; + top: calc(50% - 11px); + pointer-events: none; + font-size: 18px; + font-size: 1.125rem; + color: #c4c3c3; + z-index: 3; +} + +.form-control-sm + .icon-inside { + font-size: 0.875rem !important; + font-size: 14px; + top: calc(50% - 13px); +} + +select.form-control:not([size]):not([multiple]):not(.form-control-sm) { + height: auto; + padding-top: .700rem; + padding-bottom: .700rem; +} + +.custom-select:not(.custom-select-sm) { + height: calc(3.05rem + 2px); + padding-top: .700rem; + padding-bottom: .700rem; +} + +.col-form-label-sm { + font-size: 13px; +} + +.custom-select-sm { + padding-left: 5px !important; + font-size: 14px; +} + +.custom-select:not(.custom-select-sm).border-0 { + height: 3.00rem; +} + +.form-control:focus, .custom-select:focus { + -webkit-box-shadow: 0 0 5px rgba(128, 189, 255, 0.5); + box-shadow: 0 0 5px rgba(128, 189, 255, 0.5); +} + +.form-control:focus[readonly] { + box-shadow: none; +} + +.input-group-text { + border-color: #dae1e3; + background-color: #f1f5f6; + color: #656565; +} + +.form-control::-webkit-input-placeholder { + color: #b1b4b6; +} +.form-control:-moz-placeholder { + /* FF 4-18 */ + color: #b1b4b6; +} +.form-control::-moz-placeholder { + /* FF 19+ */ + color: #b1b4b6; +} +.form-control:-ms-input-placeholder, .form-control::-ms-input-placeholder { + /* IE 10+ */ + color: #b1b4b6; +} + +/* Form Dark */ +.form-dark .form-control, .form-dark .custom-select { + border-color: #232a31; + background: #232a31; + color: #fff; +} +.form-dark .form-control:focus { + border-color: #80bdff !important; +} +.form-dark .form-control::-webkit-input-placeholder { + color: #777b7f; +} +.form-dark .form-control:-moz-placeholder { + /* FF 4-18 */ + color: #777b7f; +} +.form-dark .form-control::-moz-placeholder { + /* FF 19+ */ + color: #777b7f; +} +.form-dark .form-control:-ms-input-placeholder, .form-dark .form-control::-ms-input-placeholder { + /* IE 10+ */ + color: #777b7f; +} +.form-dark .custom-select { + color: #777b7f; + background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='rgba(250,250,250,0.3)' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 13px 15px; + border-color: #232a31; + background-color: #232a31; +} +.form-dark .icon-inside { + color: #777b7f; +} + +/* Input with only bottom border */ +.form-border .form-control { + background-color: transparent; + border: none; + border-bottom: 2px solid rgba(0, 0, 0, 0.12); + border-radius: 0px; + padding-left: 0px !important; + color: black; +} +.form-border .form-control::-webkit-input-placeholder { + color: rgba(0, 0, 0, 0.4); +} +.form-border .form-control:-moz-placeholder { + /* FF 4-18 */ + color: rgba(0, 0, 0, 0.4); +} +.form-border .form-control::-moz-placeholder { + /* FF 19+ */ + color: rgba(0, 0, 0, 0.4); +} +.form-border .form-control:-ms-input-placeholder, .form-border .form-control::-ms-input-placeholder { + /* IE 10+ */ + color: rgba(0, 0, 0, 0.4); +} +.form-border .custom-select { + background-color: transparent; + border: none; + border-bottom: 2px solid rgba(0, 0, 0, 0.12); + border-radius: 0px; + padding-left: 0px; + color: rgba(0, 0, 0, 0.4); + background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='rgba(0,0,0,0.3)' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 13px 15px; +} +.form-border .form-control:focus, .form-border .custom-select:focus { + box-shadow: none; + -webkit-box-shadow: none; + border-bottom: 2px solid rgba(0, 0, 0, 0.7); +} +.form-border .form-control:not(output):-moz-ui-invalid:not(:focus), .form-border .form-control:not(output):-moz-ui-invalid:-moz-focusring:not(:focus), .form-border .custom-select:not(output):-moz-ui-invalid:not(:focus), .form-border .custom-select:not(output):-moz-ui-invalid:-moz-focusring:not(:focus) { + border-bottom: 2px solid #b00708; + box-shadow: none; + -webkit-box-shadow: none; +} +.form-border .icon-inside { + color: rgba(0, 0, 0, 0.25); +} +.form-border select option { + color: #666; +} + +.form-border-light .form-control { + border-bottom: 2px solid rgba(250, 250, 250, 0.3); + color: #fafafa; +} +.form-border-light .form-control::-webkit-input-placeholder { + color: rgba(250, 250, 250, 0.7); +} +.form-border-light .form-control:-moz-placeholder { + /* FF 4-18 */ + color: rgba(250, 250, 250, 0.7); +} +.form-border-light .form-control::-moz-placeholder { + /* FF 19+ */ + color: rgba(250, 250, 250, 0.7); +} +.form-border-light .form-control:-ms-input-placeholder, .form-border-light .form-control::-ms-input-placeholder { + /* IE 10+ */ + color: rgba(250, 250, 250, 0.7); +} +.form-border-light .custom-select { + border-bottom: 2px solid rgba(250, 250, 250, 0.3); + color: #fafafa; + background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='rgba(250,250,250,0.6)' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 13px 15px; +} +.form-border-light .form-control:focus, .form-border-light .custom-select:focus { + border-bottom: 2px solid rgba(250, 250, 250, 0.8); +} +.form-border-light .icon-inside { + color: #999; +} +.form-border-light select option { + color: #333; +} + +.input-group-append .btn, .input-group-prepend .btn { + -webkit-box-shadow: none; + box-shadow: none; + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.input-group-append .btn:hover, .input-group-prepend .btn:hover { + -webkit-box-shadow: none; + box-shadow: none; +} + +@media (max-width: 575.98px) { + .input-group > .input-group-append > .btn, .input-group > .input-group-prepend > .btn { + padding: 0 0.75rem; + } +} +.bg-primary, .badge-primary { + background-color: #0366d6 !important; +} + +.bg-secondary { + background-color: #6c757d !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: #0366d6 !important; +} + +.btn-link:hover { + color: #0355b3 !important; +} + +.text-secondary { + color: #6c757d !important; +} + +.text-light { + color: #dee3e4 !important; +} + +.text-body { + color: #4c4d4d !important; +} + +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover { + background-color: #0355b3 !important; +} + +.border-primary { + border-color: #0366d6 !important; +} + +.border-secondary { + border-color: #6c757d !important; +} + +.btn-primary { + background-color: #0366d6; + border-color: #0366d6; +} +.btn-primary:hover { + background-color: #0355b3; + border-color: #0355b3; +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active { + background-color: #0355b3; + border-color: #0355b3; +} + +.btn-primary.focus, .btn-primary:focus { + background-color: #0355b3; + border-color: #0355b3; +} + +.btn-primary:not(:disabled):not(.disabled).active:focus, .btn-primary:not(:disabled):not(.disabled):active:focus, .show > .btn-primary.dropdown-toggle:focus { + -webkit-box-shadow: none; + box-shadow: none; +} + +.btn-secondary { + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active { + color: #0366d6; + border-color: #0366d6; +} +.btn-outline-primary:hover, .btn-outline-primary:not(:disabled):not(.disabled).active:hover, .btn-outline-primary:not(:disabled):not(.disabled):active:hover { + background-color: #0366d6; + border-color: #0366d6; + color: #fff; +} + +.btn-outline-secondary { + color: #6c757d; + border-color: #6c757d; +} +.btn-outline-secondary:hover { + background-color: #6c757d; + border-color: #6c757d; + color: #fff; +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active { + background-color: #0366d6; +} + +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before { + background-color: #0366d6; + border-color: #0366d6; +} + +.list-group-item.active { + background-color: #0366d6; + border-color: #0366d6; +} + +.page-link { + color: #0366d6; +} +.page-link:hover { + color: #0355b3; +} + +/* Pagination */ +.page-link { + border: none; + border-radius: 0.25rem; + margin: 0 0.22rem; + font-size: 16px; + font-size: 1rem; +} +.page-link:hover { + background-color: #e9eff0; +} + +/* Vertical Multilple input group */ +.vertical-input-group .input-group:first-child { + padding-bottom: 0; +} +.vertical-input-group .input-group:first-child * { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.vertical-input-group .input-group:last-child { + padding-top: 0; +} +.vertical-input-group .input-group:last-child * { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.vertical-input-group .input-group:not(:last-child):not(:first-child) { + padding-top: 0; + padding-bottom: 0; +} +.vertical-input-group .input-group:not(:last-child):not(:first-child) * { + border-radius: 0; +} +.vertical-input-group .input-group:not(:first-child) * { + border-top: 0; +} + +/* styles-switcher */ +#styles-switcher { + background: #fff; + width: 202px; + position: fixed; + top: 35%; + z-index: 99; + padding: 20px; + left: -202px; +} +#styles-switcher ul { + padding: 0; +} +#styles-switcher ul li { + list-style-type: none; + width: 25px; + height: 25px; + margin: 4px 2px; + border-radius: 50%; + display: inline-block; + cursor: pointer; + transition: all .2s ease-in-out; +} +#styles-switcher ul li.blue { + background: #007bff; +} +#styles-switcher ul li.brown { + background: #795548; +} +#styles-switcher ul li.purple { + background: #6f42c1; +} +#styles-switcher ul li.indigo { + background: #6610f2; +} +#styles-switcher ul li.red { + background: #dc3545; +} +#styles-switcher ul li.orange { + background: #fd7e14; +} +#styles-switcher ul li.yellow { + background: #ffc107; +} +#styles-switcher ul li.green { + background: #28a745; +} +#styles-switcher ul li.teal { + background: #20c997; +} +#styles-switcher ul li.cyan { + background: #17a2b8; +} +#styles-switcher ul li.active { + transform: scale(0.7); + cursor: default; +} +#styles-switcher .switcher-toggle { + position: absolute; + background: #333; + color: #fff; + font-size: 1.25rem; + border-radius: 0px 4px 4px 0; + right: -40px; + top: 0; + width: 40px; + height: 40px; + padding: 0; +} +#styles-switcher #reset-color { + background: #e83e8c; +} + +input:-internal-autofill-selected { + background-color: transparent; +} + +#styles-switcher.right { + left: auto; + right: -202px; +} + +#styles-switcher.right .switcher-toggle { + right: auto; + left: -40px; + border-radius: 4px 0px 0px 4px; +} + +.tab-wrap{ + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; + padding: 0 10px; + margin-bottom: 40px; +} diff --git a/docs/assets/js/theme.js b/docs/assets/js/theme.js new file mode 100644 index 0000000..8fb56af --- /dev/null +++ b/docs/assets/js/theme.js @@ -0,0 +1,162 @@ +/* +================================================================ +* Template: iDocs - One Page Documentation HTML Template +* Written by: Harnish Design - (http://www.harnishdesign.net) +* Description: Main Custom Script File +================================================================ +*/ + + +(function ($) { + "use strict"; + +// Preloader +$(window).on('load', function () { + $('.lds-ellipsis').fadeOut(); // will first fade out the loading animation + $('.preloader').delay(333).fadeOut('slow'); // will fade out the white DIV that covers the website. + $('body').delay(333); +}); + +/*------------------------------- + Primary Menu +--------------------------------- */ + +// Dropdown show on hover +$('.primary-menu ul.navbar-nav li.dropdown, .login-signup ul.navbar-nav li.dropdown').on("mouseover", function() { + if ($(window).width() > 991) { + $(this).find('> .dropdown-menu').stop().slideDown('fast'); + $(this).bind('mouseleave', function() { + $(this).find('> .dropdown-menu').stop().css('display', 'none'); + }); + } +}); + +// When dropdown going off to the out of the screen. +$('.primary-menu ul.navbar-nav .dropdown-menu').each(function() { + var menu = $('#header .container-fluid').offset(); + var dropdown = $(this).parent().offset(); + + var i = (dropdown.left + $(this).outerWidth()) - (menu.left + $('#header .container-fluid').outerWidth()); + + if (i > 0) { + $(this).css('margin-left', '-' + (i + 5) + 'px'); + } + }); +$(function () { + $(".dropdown li").on('mouseenter mouseleave', function (e) { + if ($(window).width() > 991) { + var elm = $('.dropdown-menu', this); + var off = elm.offset(); + var l = off.left; + var w = elm.width(); + var docW = $(window).width(); + var isEntirelyVisible = (l + w + 30 <= docW); + if (!isEntirelyVisible) { + $(elm).addClass('dropdown-menu-right'); + } else { + $(elm).removeClass('dropdown-menu-right'); + } + } + }); +}); + +// DropDown Arrow +$('.primary-menu ul.navbar-nav').find('a.dropdown-toggle').append($('').addClass('arrow')); + + +// Mobile Collapse Nav +$('.primary-menu .navbar-nav .dropdown-toggle[href="#"], .primary-menu .dropdown-toggle[href!="#"] .arrow').on('click', function(e) { + if ($(window).width() < 991) { + e.preventDefault(); + var $parentli = $(this).closest('li'); + $parentli.siblings('li').find('.dropdown-menu:visible').slideUp(); + $parentli.find('> .dropdown-menu').stop().slideToggle(); + $parentli.siblings('li').find('a .arrow.show').toggleClass('show'); + $parentli.find('> a .arrow').toggleClass('show'); + } +}); + + +// Mobile Menu +$('.navbar-toggler').on('click', function() { + $(this).toggleClass('show'); +}); + + +/*------------------------ + Side Navigation +-------------------------- */ + +$('#sidebarCollapse').on('click', function () { + $('#sidebarCollapse span:nth-child(3)').toggleClass('w-50'); + $('.idocs-navigation').toggleClass('active'); +}); + + +/*------------------------ + Sections Scroll +-------------------------- */ + +$('.smooth-scroll,.idocs-navigation a').on('click', function() { + event.preventDefault(); + var sectionTo = $(this).attr('href'); + $('html, body').stop().animate({ + scrollTop: $(sectionTo).offset().top - 120}, 1000, 'easeInOutExpo'); +}); + +/*----------------------------- + Magnific Popup +------------------------------- */ + +// Image on Modal +$('.popup-img').each(function() { +$(this).magnificPopup({ + type: "image", + tLoading: '
', + closeOnContentClick: !0, + mainClass: "mfp-fade", + +}); +}); + +// YouTube/Viemo Video & Gmaps +$('.popup-youtube, .popup-vimeo, .popup-gmaps').each(function() { +$(this).magnificPopup({ + type: 'iframe', + mainClass: 'mfp-fade', +}); +}); + + +/*------------------------ + Highlight Js +-------------------------- */ + +hljs.initHighlightingOnLoad(); + + +/*------------------------ + tooltips +-------------------------- */ +$('[data-toggle=\'tooltip\']').tooltip({container: 'body'}); + + +/*------------------------ + Scroll to top +-------------------------- */ +$(function () { + $(window).on('scroll', function(){ + if ($(this).scrollTop() > 400) { + $('#back-to-top').fadeIn(); + } else { + $('#back-to-top').fadeOut(); + } + }); + }); +$('#back-to-top').on("click", function() { + $('html, body').animate({scrollTop:0}, 'slow'); + return false; +}); + + +})(jQuery) \ No newline at end of file diff --git a/docs/assets/sass/_elements.scss b/docs/assets/sass/_elements.scss new file mode 100644 index 0000000..397f710 --- /dev/null +++ b/docs/assets/sass/_elements.scss @@ -0,0 +1,537 @@ +/* =================================== */ +/* 5. Elements +/* =================================== */ + +/*=== 5.1 List Style ===*/ + +.list-style-1 > li { + position: relative; + list-style-type: none; + line-height: 24px; + &:after { + content: " "; + position: absolute; + top: 12px; + left: -15px; + border-color: #000; + border-top: 1px solid; + border-right: 1px solid; + width: 6px; + height: 6px; + -webkit-transform: translate(-50%, -50%) rotate(45deg); + transform: translate(-50%, -50%) rotate(45deg); + } +} + +.list-style-2{padding:0;} + +.list-style-2 > li { + list-style-type: none; + border-bottom: 1px solid #eaeaea; + padding-top: 12px; + padding-bottom: 12px; +} +.list-style-2.list-style-light > li { + border-bottom: 1px solid rgba(250,250,250,0.12); +} + +/*=== 5.2 Changelog ===*/ + +.changelog { + list-style: none; + padding: 0; + .badge { + width: 90px; + margin-right: 10px; + border-radius: .20rem; + text-transform: uppercase; + } + li { + line-height: 1.8; + } +} + + +/*=== 5.3 Accordion & Toggle ===*/ +.accordion { + .card { + border: none; + margin-bottom: 16px; + margin-bottom: 1rem; + background-color: transparent; + } + .card-header { + padding: 0; + border: none; + background: none; + a { + font-size: 16px; + font-weight:normal; + padding: 1rem 1.25rem 1rem 2.25rem; + display: block; + border-radius: 4px; + position: relative; + &:hover{ + text-decoration:none; + } + &:hover.collapsed { + color: $primary-color!important; + } + } + } + &:not(.accordion-alternate) .card-header a { + background-color: $primary-color; + color: #fff; + &.collapsed { + background-color: #f1f2f4; + color: #4c4d4d; + } + + } + .card-header a { + &:before { + position: absolute; + content: " "; + left: 20px; + top: calc(50% + 2px); + width: 9px; + height: 9px; + border-color: #CCC; + border-top: 2px solid; + border-right: 2px solid; + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + @include transition(all 0.2s ease); + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + } + &.collapsed:before { + top: calc(50% - 2px); + -webkit-transform: translate(-50%, -50%) rotate(135deg); + transform: translate(-50%, -50%) rotate(135deg); + } + } + .card-body { + line-height: 26px; + } + &.arrow-right .card-header a{ + padding-left:1.25rem; + &:before { + right: 15px; + left: auto; + } + } + &.accordion-alternate { + .card { + margin: 0; + } + .card-header a { + padding-left: 1.40rem; + border-top: 1px solid #e4e9ec; + border-radius: 0px; + } + .card:first-of-type .card-header a { + border-top: 0px; + } + .card-header a { + &:before { + left: 6px; + } + &.collapsed { + color: #4c4d4d; + } + } + .card-body { + padding: 0rem 0 1rem 1.25rem; + } + &.arrow-right .card-header a{ + padding-left:0; + &:before { + right: 0px; + left: auto; + } + } + + } + &.toggle .card-header a { + &:before { + content: "-"; + border: none; + font-size: 20px; + height: auto; + top: calc(50% + 2px); + width: auto; + -webkit-transform: translate(-50%, -50%) rotate(180deg); + transform: translate(-50%, -50%) rotate(180deg); + } + &.collapsed:before { + content: "+"; + top: calc(50% - 1px); + -webkit-transform: translate(-50%, -50%) rotate(0deg); + transform: translate(-50%, -50%) rotate(0deg); + } + } + &.accordion-alternate.style-2 { + .card-header a { + &:before { + right: 2px; + left: auto; + -webkit-transform: translate(-50%, -50%) rotate(135deg); + transform: translate(-50%, -50%) rotate(135deg); + top: 50%; + } + &.collapsed:before { + -webkit-transform: translate(-50%, -50%) rotate(45deg); + transform: translate(-50%, -50%) rotate(45deg); + } + padding-left: 0px; + } + .card-body { + padding-left: 0px; + } + } + &.accordion-alternate.popularRoutes { + .card-header { + .nav { + margin-top: 3px; + a { + font-size: 14px; + } + } + a { + padding: 0px 8px 0px 0px; + border: none; + font-size: inherit; + &:before { + content: none; + } + } + h5 { + cursor: pointer; + &:before { + position: absolute; + content: " "; + right: 0px; + top: 24px; + width: 10px; + height: 10px; + opacity: 0.6; + border-top: 2px solid; + border-right: 2px solid; + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + } + &.collapsed:before { + top: 24px; + -webkit-transform: translate(-50%, -50%) rotate(135deg); + transform: translate(-50%, -50%) rotate(135deg); + } + } + } + .card-body { + padding: 0; + } + .card { + border-bottom: 2px solid #e4e9ec; + padding: 15px 0px; + } + .routes-list { + margin: 1rem 0px 0px 0px; + padding: 0px; + list-style: none; + a { + color: inherit; + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-align: center !important; + align-items: center !important; + &:hover { + color: #0071cc; + text-decoration: underline; + } + } + } + } +} + +/* 5.4 Nav */ + +.nav .nav-item .nav-link{color: #222222;} +.nav.nav-light .nav-item .nav-link{color: #ddd;} +.nav:not(.nav-pills) .nav-item .nav-link.active, .nav:not(.nav-pills) .nav-item .nav-link:hover{color: $primary-color;} + + +.nav-pills .nav-link:not(.active):hover{color: $primary-color;} +.nav-pills .nav-link.active,.nav-pills.nav-light .nav-link.active, .nav-pills .show > .nav-link{color:#fff;} + +.nav.nav-separator .nav-item .nav-link{position:relative;} +.nav.nav-separator .nav-item + .nav-item .nav-link:after{ + height: 14px; + width: 1px; + content: ' '; + background-color: rgba(0,0,0,0.2); + display: block; + position: absolute; + top: 50%; + left: 0; + @include translateY(-7px); +} +.nav.nav-separator.nav-separator-light .nav-item + .nav-item .nav-link:after{ +background-color: rgba(250,250,250,0.2); +} + +.nav.nav-sm .nav-item .nav-link{font-size:14px;} + + +/*=== 5.5 Tabs ===*/ + +.nav-tabs { + border-bottom: 1px solid #d7dee3; + .nav-item .nav-link { + border:0; + background: transparent; + + position: relative; + border-radius: 0; + padding:0.6rem 1rem; + color: #7b8084; + white-space: nowrap !important; + &.active { + &:after { + height: 2px; + width: 100%; + content: ' '; + background-color: $primary-color; + display: block; + position: absolute; + bottom: -3px; + left: 0; + @include translateY(-3px); + } + color: #0c2f55; + } + &:not(.active):hover { + color: $primary-color; + } + } + &.flex-column { + border-right: 1px solid #d7dee3; + border-bottom: 0px; + padding: 1.5rem 0; + .nav-item { + .nav-link { + border: 1px solid #d7dee3; + border-right: 0px; + background-color: #f6f7f8; + font-size: 14px; + padding: 0.75rem 1rem; + color: #535b61; + } + &:first-of-type .nav-link { + border-top-left-radius: 4px; + } + &:last-of-type .nav-link { + border-bottom-left-radius: 4px; + } + .nav-link.active { + &:after { + height: 100%; + width: 2px; + background: #fff; + right: -1px; + left: auto; + } + background-color: transparent; + color: $primary-color; + } + } + } +} + +.nav-tabs:not(.flex-column) { + .nav-item { + margin-bottom: 0px; + } + flex-wrap: nowrap; + overflow: hidden; + overflow-x: auto; + -ms-overflow-style: -ms-autohiding-scrollbar; + -webkit-overflow-scrolling: touch; +} + + + +@include media-breakpoint-down(xs) { + .nav-tabs .nav-item .nav-link { + padding-left: 0px; + padding-right: 0px; + margin-right: 10px; + font-size: 0.875rem; + } +} + + +/*=== 5.6 Popup Img ===*/ +.popup-img img{@include transition(all 0.2s ease-in-out);} +.popup-img:hover img{ + opacity:0.8; + cursor: -webkit-zoom-in; + cursor: -moz-zoom-in; + cursor: zoom-in; +} + + +/*=== 5.7 Featured Box ===*/ +.featured-box { + box-sizing: border-box; + position: relative; + h3, h4 { + font-size: 1.25rem; + font-size: 20px; + margin-bottom: 10px; + font-weight: 500; + } + &:not(.style-5) .featured-box-icon { + display: inline-block; + font-size: 48px; + min-width: 55px; + min-height: 55px; + padding: 0; + margin-top: 0; + margin-bottom: 0.8rem; + color: #4c4d4d; + border-radius: 0; + } + &.style-1, &.style-2, &.style-3 { + padding-left: 50px; + padding-top: 8px; + } + &.style-1 .featured-box-icon, &.style-2 .featured-box-icon, &.style-3 .featured-box-icon { + position: absolute; + top: 0; + left: 0; + margin-bottom: 0; + font-size: 30px; + -ms-flex-pack: center !important; + justify-content: center !important; + text-align: center; + } + &.style-2 p { + margin-left: -50px; + } + &.style-3 { + padding-left: 90px; + padding-top: 0px; + .featured-box-icon { + width: 70px; + height: 70px; + -ms-flex-negative: 0; + flex-shrink: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + } + &.style-4 { + text-align: center; + .featured-box-icon { + margin: 0 auto 24px; + margin: 0 auto 1.5rem; + width: 120px; + height: 120px; + text-align: center; + -ms-flex-negative: 0; + flex-shrink: 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + @include box-shadow(0px 0px 50px rgba(0, 0, 0, 0.03)); + } + } + + &.style-5 { + text-align: center; + background: #fff; + border: 1px solid #f0f2f3; + @include box-shadow(0px 2px 5px rgba(0, 0, 0, 0.05)); + @include transition(all 0.3s ease-in-out); + &:hover { + border: 1px solid #ebeded; + @include box-shadow(0px 5px 1.5rem rgba(0, 0, 0, 0.15)); + } + h3 { + background: #f1f5f6; + font-size: 16px; + padding: 8px 0; + margin-bottom: 0px; + } + .featured-box-icon { + font-size: 50px; + margin: 44px 0px; + } +} +} + + +@mixin featured-box-reverse { + text-align:right; + &.style-1, &.style-2{ + padding-right:50px; + padding-left:0px; + .featured-box-icon{ + left:auto; + right:0px; + } + } + &.style-2 p{ + margin-right: -50px; + margin-left:0; + } + &.style-3{ + padding-left:0; + padding-right:90px; + .featured-box-icon{ + left:auto; + right:0px; + } + } +} + +.featured-box.featured-box-reverse{ + @include featured-box-reverse; +} + +@include media-breakpoint-up(xs) { + .featured-box.featured-box-reverse-sm{ + @include featured-box-reverse; + } +} + +@include media-breakpoint-up(sm) { + .featured-box.featured-box-reverse-md{ + @include featured-box-reverse; + } +} + +@include media-breakpoint-up(md) { + .featured-box.featured-box-reverse-lg{ + @include featured-box-reverse; + } +} +@include media-breakpoint-up(lg) { + .featured-box.featured-box-reverse-xl{ + @include featured-box-reverse; + } +} \ No newline at end of file diff --git a/docs/assets/sass/_extras.scss b/docs/assets/sass/_extras.scss new file mode 100644 index 0000000..c07f209 --- /dev/null +++ b/docs/assets/sass/_extras.scss @@ -0,0 +1,448 @@ +/* =================================== */ +/* Extras +/* =================================== */ + +/* Bootstrap Specific */ + +.form-control, .custom-select { + border-color: #dae1e3; + font-size: 16px; + color: #656565; +} + +.form-control:not(.form-control-sm) { + padding: .810rem .96rem; + height:inherit; +} + +.form-control-sm{font-size:14px;} + +.icon-inside { + position: absolute; + right: 15px; + top: calc(50% - 11px); + pointer-events: none; + font-size: 18px; + font-size: 1.125rem; + color: #c4c3c3; + z-index:3; +} +.form-control-sm + .icon-inside { + font-size: 0.875rem !important; + font-size: 14px; + top: calc(50% - 13px); +} + +select.form-control:not([size]):not([multiple]):not(.form-control-sm) { + height: auto; + padding-top: .700rem; + padding-bottom: .700rem; +} +.custom-select:not(.custom-select-sm){ + height:calc(3.05rem + 2px); + padding-top: .700rem; + padding-bottom: .700rem;} +.col-form-label-sm{font-size:13px;} +.custom-select-sm{padding-left:5px!important; font-size:14px;} +.custom-select:not(.custom-select-sm).border-0{height:3.00rem;} + +.form-control:focus, .custom-select:focus{ + @include box-shadow(0 0 5px rgba(128, 189, 255, 0.5)); +} +.form-control:focus[readonly]{box-shadow:none;} + +.input-group-text { + border-color: #dae1e3; + background-color:#f1f5f6; + color: #656565; +} + +.form-control { + &::-webkit-input-placeholder { + color: #b1b4b6; + } + &:-moz-placeholder { + /* FF 4-18 */ + color: #b1b4b6; + } + &::-moz-placeholder { + /* FF 19+ */ + color: #b1b4b6; + } + &:-ms-input-placeholder, &::-ms-input-placeholder { + /* IE 10+ */ + color: #b1b4b6; + } +} + +/* Form Dark */ +.form-dark { + .form-control, .custom-select { + border-color: #232a31; + background:#232a31; + color: #fff; + } + .form-control:focus{border-color: #80bdff!important;} + .form-control { + &::-webkit-input-placeholder { + color: #777b7f; + } + &:-moz-placeholder { + /* FF 4-18 */ + color: #777b7f; + } + &::-moz-placeholder { + /* FF 19+ */ + color: #777b7f; + } + &:-ms-input-placeholder, &::-ms-input-placeholder { + /* IE 10+ */ + color: #777b7f; + } + } + .custom-select { + color: #777b7f; + background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='rgba(250,250,250,0.3)' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 13px 15px; + border-color: #232a31; + background-color:#232a31; + } + .icon-inside { + color: #777b7f; + } +} + +/* Input with only bottom border */ +.form-border { + .form-control { + background-color: transparent; + border: none; + border-bottom: 2px solid rgba(0, 0, 0, 0.12); + border-radius: 0px; + padding-left: 0px!important; + color: rgba(0, 0, 0, 1); + &::-webkit-input-placeholder { + color: rgba(0, 0, 0, 0.4); + } + &:-moz-placeholder { + /* FF 4-18 */ + color: rgba(0, 0, 0, 0.4); + } + &::-moz-placeholder { + /* FF 19+ */ + color: rgba(0, 0, 0, 0.4); + } + &:-ms-input-placeholder, &::-ms-input-placeholder { + /* IE 10+ */ + color: rgba(0, 0, 0, 0.4); + } + } + .custom-select { + background-color: transparent; + border: none; + border-bottom: 2px solid rgba(0, 0, 0, 0.12); + border-radius: 0px; + padding-left: 0px; + color: rgba(0, 0, 0, 0.4); + background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='rgba(0,0,0,0.3)' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 13px 15px; + } + .form-control:focus, .custom-select:focus { + box-shadow: none; + -webkit-box-shadow: none; + border-bottom: 2px solid rgba(0, 0, 0, 0.7); + } + .form-control:not(output):-moz-ui-invalid, .custom-select:not(output):-moz-ui-invalid { + &:not(:focus), &:-moz-focusring:not(:focus) { + border-bottom: 2px solid #b00708; + box-shadow: none; + -webkit-box-shadow: none; + } + } + .icon-inside { + color: rgba(0, 0, 0, 0.25); + } + select option { + color: #666; + } +} + +.form-border-light { + .form-control { + border-bottom: 2px solid rgba(250, 250, 250, 0.3); + color: rgba(250, 250, 250, 1); + &::-webkit-input-placeholder { + color: rgba(250, 250, 250, 0.7); + } + &:-moz-placeholder { + /* FF 4-18 */ + color: rgba(250, 250, 250, 0.7); + } + &::-moz-placeholder { + /* FF 19+ */ + color: rgba(250, 250, 250, 0.7); + } + &:-ms-input-placeholder, &::-ms-input-placeholder { + /* IE 10+ */ + color: rgba(250, 250, 250, 0.7); + } + } + .custom-select { + border-bottom: 2px solid rgba(250, 250, 250, 0.3); + color: rgba(250, 250, 250, 1); + background: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='rgba(250,250,250,0.6)' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 13px 15px; + } + .form-control:focus, .custom-select:focus { + border-bottom: 2px solid rgba(250, 250, 250, 0.8); + } + .icon-inside { + color: #999; + } + select option { + color: #333; + } +} + +.input-group-append .btn, .input-group-prepend .btn { + @include box-shadow(none); + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.input-group-append .btn:hover, .input-group-prepend .btn:hover { + @include box-shadow(none); +} + +@include media-breakpoint-down(xs) { + .input-group > { + .input-group-append > .btn, .input-group-prepend > .btn { + padding: 0 0.75rem; + } +} +} + +.bg-primary, .badge-primary { + background-color: $primary-color !important; +} +.bg-secondary { + background-color: $secondary-color !important; +} + +.text-primary, .btn-light, .btn-outline-light:hover, .btn-link, .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active { + color: $primary-color !important; +} + +.btn-link:hover { + color: $primary-color-hover !important; +} +.text-secondary{ + color: $secondary-color !important; +} + +.text-light{ + color:#dee3e4!important; +} +.text-body{ + color: $text-color !important; +} +a.bg-primary:focus, a.bg-primary:hover, button.bg-primary:focus, button.bg-primary:hover{background-color: $primary-color-hover!important;} + +.border-primary { + border-color: $primary-color !important; +} +.border-secondary { + border-color: $secondary-color !important; +} + +.btn-primary{ + background-color: $primary-color; + border-color: $primary-color; + &:hover { + background-color: $primary-color-hover; + border-color: $primary-color-hover; + } +} + +.btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active{ + background-color: $primary-color-hover; + border-color: $primary-color-hover; + +} + +.btn-primary.focus, .btn-primary:focus{ + background-color: $primary-color-hover; + border-color: $primary-color-hover; +} + +.btn-primary:not(:disabled):not(.disabled).active:focus, .btn-primary:not(:disabled):not(.disabled):active:focus, .show > .btn-primary.dropdown-toggle:focus{ + @include box-shadow(none); +} + +.btn-secondary { + background-color: $secondary-color; + border-color: $secondary-color; +} + +.btn-outline-primary, .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active{ + color: $primary-color; + border-color: $primary-color; + &:hover { + background-color: $primary-color; + border-color: $primary-color; + color: #fff; + } +} + +.btn-outline-secondary{ + color: $secondary-color; + border-color: $secondary-color; + &:hover { + background-color: $secondary-color; + border-color: $secondary-color; + color: #fff; + } +} + +.progress-bar, +.nav-pills .nav-link.active, .nav-pills .show > .nav-link, .dropdown-item.active, .dropdown-item:active{ + background-color: $primary-color; +} +.page-item.active .page-link, +.custom-radio .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label::before, +.custom-checkbox .custom-control-input:checked ~ .custom-control-label:before, +.custom-control-input:checked ~ .custom-control-label:before{ + background-color: $primary-color; + border-color: $primary-color; +} +.list-group-item.active{ + background-color: $primary-color; + border-color: $primary-color; +} +.page-link { + color: $primary-color; + &:hover { + color: $primary-color-hover; + } +} + +/* Pagination */ + +.page-link { + border: none; + border-radius: 0.25rem; + margin: 0 0.22rem; + font-size: 16px; + font-size: 1rem; + &:hover { + background-color: #e9eff0; + } +} + +/* Vertical Multilple input group */ + +.vertical-input-group .input-group { + &:first-child { + padding-bottom: 0; + * { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + } + &:last-child { + padding-top: 0; + * { + border-top-left-radius: 0; + border-top-right-radius: 0; + } + } + &:not(:last-child):not(:first-child) { + padding-top: 0; + padding-bottom: 0; + * { + border-radius: 0; + } + } + &:not(:first-child) * { + border-top: 0; + } +} + +/* styles-switcher */ +#styles-switcher { + background: #fff; + width: 202px; + position: fixed; + top: 35%; + z-index: 99; + padding: 20px; + left: -202px; + ul { + padding: 0; + li { + list-style-type: none; + width: 25px; + height: 25px; + margin: 4px 2px; + border-radius: 50%; + display: inline-block; + cursor: pointer; + transition: all .2s ease-in-out; + &.blue { + background: #007bff; + } + &.brown { + background: #795548; + } + &.purple { + background: #6f42c1; + } + &.indigo { + background: #6610f2; + } + &.red { + background: #dc3545; + } + &.orange { + background: #fd7e14; + } + &.yellow { + background: #ffc107; + } + &.green { + background: #28a745; + } + &.teal { + background: #20c997; + } + &.cyan { + background: #17a2b8; + } + &.active { + transform: scale(0.7); + cursor:default; + } + } + } + .switcher-toggle { + position: absolute; + background: #333; + color: #fff; + font-size: 1.25rem; + border-radius: 0px 4px 4px 0; + right: -40px; + top: 0; + width: 40px; + height: 40px; + padding: 0; + } + #reset-color{background: #e83e8c;} +} + +input:-internal-autofill-selected { + background-color: transparent; +} + +#styles-switcher.right{left:auto; right: -202px;} +#styles-switcher.right .switcher-toggle{right: auto; left: -40px; border-radius: 4px 0px 0px 4px;} \ No newline at end of file diff --git a/docs/assets/sass/_footer.scss b/docs/assets/sass/_footer.scss new file mode 100644 index 0000000..44ee02c --- /dev/null +++ b/docs/assets/sass/_footer.scss @@ -0,0 +1,188 @@ +/* =================================== */ +/* 6. Footer +/* =================================== */ + +#footer { + background: #fff; + color: #252b33; + margin-left:260px; + padding: 66px 0px; + padding: 4.125rem 0; + .nav { + .nav-item { + display: inline-block; + line-height: 12px; + margin: 0; + .nav-link { + color: #252b33; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + &:focus { + color: $primary-color; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + } + &:first-child .nav-link { + padding-left: 0px; + } + &:last-child .nav-link{ + padding-right: 0px; + } + } + .nav-link:hover { + color: $primary-color; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + } + .footer-copyright { + border-top: 1px solid #e2e8ea; + padding: 0px 0px; + color: #67727c; + .nav { + .nav-item .nav-link { + color: #67727c; + } + .nav-link:hover { + color: $primary-color; + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + } + } + } + .nav.flex-column .nav-item { + padding: 0px; + .nav-link { + margin: 0.7rem 0px; + } + } + &.footer-text-light { + color: rgba(250, 250, 250, 0.8); + .nav .nav-item .nav-link { + color: rgba(250, 250, 250, 0.8); + &:hover { + color: rgba(250, 250, 250, 1); + } + } + .footer-copyright { + border-color: rgba(250, 250, 250, 0.15); + color: rgba(250, 250, 250, 0.5); + } + &:not(.bg-primary) .social-icons-light.social-icons li a { + color: rgba(250, 250, 250, 0.8); + &:hover { + color: rgba(250, 250, 250, 1); + } + } + &.bg-primary { + color: #fff; + .nav .nav-item .nav-link { + color: #fff; + &:hover { + color: rgba(250, 250, 250, 0.7); + } + } + .footer-copyright { + border-color: rgba(250, 250, 250, 0.15); + color: rgba(250, 250, 250, 0.9); + } + :not(.social-icons) a { + color: #fff; + &:hover { + color: rgba(250, 250, 250, 0.7); + } + } + } + } +} + +@include media-breakpoint-down(sm) { +#footer { + margin-left:0px; +} +} + + +/*=== 6.1 Social Icons ===*/ +.social-icons { + margin: 0; + padding: 0; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + list-style: none; + li { + margin: 0px 6px; + padding: 0; + overflow: visible; + a { + display: block; + height: 26px; + line-height: 26px; + width: 26px; + font-size: 18px; + text-align: center; + color: #4d555a; + text-decoration: none; + @include transition(all 0.2s ease); + } + i { + line-height: inherit; + } + } + &.social-icons-sm li{ + margin: 0px 4px; + } + &.social-icons-sm li a { + font-size: 15px; + width:22px; + } + &.social-icons-lg li a { + width: 34px; + height: 34px; + line-height:34px; + font-size: 22px; + } + &.social-icons-light li a { + color: #eee; + } + &.social-icons-muted li a { + color: #aab1b8; + } + li:hover { + a { + color: #999; + } + } +} + + +/*=== 6.2 Back to Top ===*/ +#back-to-top { + display: none; + position: fixed; + z-index: 1030; + bottom: 8px; + right: 10px; + background-color: rgba(0, 0, 0, 0.22); + text-align: center; + color: #fff; + font-size: 14px; + width: 36px; + height: 36px; + line-height: 34px; + border-radius:3px; + @include transition(all 0.3s ease-in-out); + @include box-shadow(0px 5px 15px rgba(0, 0, 0, 0.15)); + &:hover { + background-color: $primary-color; + @include box-shadow(0px 5px 15px rgba(0, 0, 0, 0.25)); + @include transition(all 0.3s ease-in-out); + } +} + +@include media-breakpoint-down(xs) { + #back-to-top {z-index: 1029;} +} \ No newline at end of file diff --git a/docs/assets/sass/_header.scss b/docs/assets/sass/_header.scss new file mode 100644 index 0000000..6b00328 --- /dev/null +++ b/docs/assets/sass/_header.scss @@ -0,0 +1,554 @@ +/* =================================== */ +/* 4. Header +/* =================================== */ + +#header { + @include transition(all .5s ease); + .navbar { + padding: 0px; + min-height:70px; + } + .logo { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-item-align: stretch; + align-self: stretch; + } +} + + +/*=== 4.1 Main Navigation ===*/ + +.navbar-light .navbar-nav { + .active > .nav-link { + color: #0c2f55; + } + .nav-link { + &.active, &.show { + color: #0c2f55; + } + } + .show > .nav-link { + color: #0c2f55; + } +} + +.primary-menu { + display: -webkit-box !important; + display: -ms-flexbox !important; + display: flex !important; + height: auto !important; + -webkit-box-ordinal-group: 0; + -ms-flex-item-align: stretch; + align-self: stretch; + background: #fff; + border-bottom:1px solid #efefef; + &.bg-transparent { + position: absolute; + z-index: 999; + top: 0; + left: 0; + width: 100%; + box-shadow: none; + border-bottom: 1px solid rgba(250, 250, 250, 0.3); + } + &.sticky-on{ + position: fixed; + top: 0; + width: 100%; + z-index: 1020; + left: 0; + @include box-shadow(0px 0px 10px rgba(0, 0, 0, 0.05)); + -webkit-animation: slide-down 0.7s; + -moz-animation: slide-down 0.7s; + animation: slide-down 0.7s; + @-webkit-keyframes slide-down { 0% { opacity:0; transform:translateY(-100%);}100% { opacity:1; transform:translateY(0);}} + @-moz-keyframes slide-down { 0% { opacity:0; transform:translateY(-100%);}100% { opacity:1; transform:translateY(0);}} + @keyframes slide-down { 0% { opacity:0; transform:translateY(-100%);}100% { opacity:1; transform:translateY(0);}} + + .none-on-sticky{ + display:none!important; + } + } + + ul.navbar-nav > li { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + height: 100%; + + + li { + margin-left: 2px; + } + a { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + } + + > a:not(.btn) { + height: 70px; + padding:0px 0.85em; + color: #252b33; + @include transition(all .2s ease); + position: relative; + position:relative; + } + + &:hover > a:not(.btn), & > a.active:not(.btn) { + color: $primary-color; + text-decoration:none; + @include transition(all .2s ease); + } + a.btn{padding: 0.4rem 1.4rem;} + &.dropdown { + .dropdown-menu li { + > a:not(.btn) { + padding: 8px 0px; + background-color: transparent; + text-transform: none; + color: #777; + @include transition(all .2s ease); + } + &:hover > a:not(.btn) { + color: $primary-color; + @include transition(all .2s ease); + } + } + &:hover > a:after { + clear: both; + content: ' '; + display: block; + width: 0; + height: 0; + border-style: solid; + border-color: transparent transparent #fff transparent; + position: absolute; + border-width: 0px 7px 6px 7px; + bottom: 0px; + left: 50%; + margin: 0 0 0 -5px; + z-index: 1022; + } + .dropdown-menu { + @include box-shadow(0px 0px 12px rgba(0, 0, 0, 0.176)); + border: 0px none; + padding: 10px 15px; + min-width: 220px; + margin: 0; + font-size: 14px; + font-size: 0.875rem; + z-index:1021; + } + > .dropdown-toggle .arrow { + display: none; + + } + } + } + .dropdown-menu-right { + left: auto !important; + right: 100% !important; + } + ul.navbar-nav > li { + &.dropdown-mega { + position: static; + > .dropdown-menu { + width: 100%; + padding: 20px 20px; + margin-left: 0px !important; + } + .dropdown-mega-content > .row > div { + padding: 5px 5px 5px 20px; + border-right: 1px solid #eee; + &:last-child { + border-right: 0; + } + } + .sub-title { + display: block; + font-size: 16px; + margin-top: 1rem; + padding-bottom: 5px; + } + .dropdown-mega-submenu { + list-style-type: none; + padding-left: 0px; + } + } + a.btn{font-size:14px; padding: 0.65rem 2rem; text-transform:uppercase;} + &.dropdown { + .dropdown-menu { + .dropdown-menu { + left: 100%; + margin-top: -40px; + } + .dropdown-toggle:after { + border-top: .4em solid transparent; + border-right: 0; + border-bottom: 0.4em solid transparent; + border-left: 0.4em solid; + } + } + .dropdown-toggle .arrow { + position: absolute; + min-width: 30px; + height: 100%; + right: 0px; + top: 0; + @include transition(all .2s ease); + &:after { + content: " "; + position: absolute; + top: 50%; + left: 50%; + border-color: #000; + border-top: 1px solid; + border-right: 1px solid; + width: 6px; + height: 6px; + -webkit-transform: translate(-50%, -50%) rotate(45deg); + transform: translate(-50%, -50%) rotate(45deg); + } + } + } + } + .dropdown-toggle:after { + content: none; + } + + &.navbar-line-under-text ul.navbar-nav > li { + > a:not(.btn):after { + position: absolute; + content: ""; + height: 2px; + width: 0; + left: 50%; + right: 0; + bottom: 14px; + background-color: transparent; + color:#fff; + border-bottom: 2px solid $primary-color; + @include transition(all .3s ease-in-out); + transform: translate(-50%,0) translateZ(0); + -webkit-transform: translate(-50%,0) translateZ(0); + } + & > a:hover:not(.logo):after, & > a.active:after{ + width:calc(100% - 0.99em); + } + } + +} + +/*== Color Options ==*/ + +.primary-menu.navbar-text-light .navbar-toggler span {background:#fff;} + +.primary-menu.navbar-text-light .navbar-nav > li{ + > a:not(.btn) { + color: #fff; + } + &:hover > a:not(.btn), & > a.active:not(.btn) { + color: rgba(250, 250, 250, 0.75); + } +} + +.primary-menu.navbar-text-light.navbar-line-under-text .navbar-nav > li{ + & > a:not(.logo):after, & > a.active:after{ + border-color:rgba(250, 250, 250, 0.60); + } +} + +.primary-menu { + &.navbar-dropdown-dark ul.navbar-nav > li { + &.dropdown { + .dropdown-menu { + background-color: #252A2C; + color: #fff; + .dropdown-menu { + background-color: #272c2e; + } + } + &:hover > a:after { + border-color: transparent transparent #252A2C transparent; + } + .dropdown-menu li { + > a:not(.btn) { + color: rgba(250, 250, 250, 0.8); + } + &:hover > a:not(.btn) { + color: rgba(250, 250, 250, 1); + font-weight:600; + } + } + } + &.dropdown-mega .dropdown-mega-content > .row > div { + border-color: #3a3a3a; + } + } + &.navbar-dropdown-primary ul.navbar-nav > li { + &.dropdown { + .dropdown-menu { + background-color: $primary-color; + color: #fff; + .dropdown-menu { + background-color: $primary-color; + } + } + &:hover > a:after { + border-color: transparent transparent $primary-color transparent; + } + .dropdown-menu li { + > a:not(.btn) { + color: rgba(250, 250, 250, 0.95); + } + &:hover > a:not(.btn) { + color: rgba(250, 250, 250, 1); + font-weight:600; + } + } + } + &.dropdown-mega .dropdown-mega-content > .row > div { + border-color: rgba(250, 250, 250, 0.2); + } + } +} + + +/* Hamburger Menu Button */ +.navbar-toggler { + width: 25px; + height: 30px; + padding: 10px; + margin: 18px 15px; + position: relative; + border:none; + @include rotate(0deg); + @include transition(.5s ease-in-out); + cursor: pointer; + display: block; + span { + display: block; + position: absolute; + height: 2px; + width: 100%; + background: #3c3636; + border-radius: 2px; + opacity: 1; + left: 0; + @include rotate(0deg); + @include transition(.25s ease-in-out); + &:nth-child(1) { + top: 7px; + -webkit-transform-origin: left center; + -moz-transform-origin: left center; + -o-transform-origin: left center; + transform-origin: left center; + } + &:nth-child(2) { + top: 14px; + -webkit-transform-origin: left center; + -moz-transform-origin: left center; + -o-transform-origin: left center; + transform-origin: left center; + } + &:nth-child(3) { + top: 21px; + -webkit-transform-origin: left center; + -moz-transform-origin: left center; + -o-transform-origin: left center; + transform-origin: left center; + + } + } + &.show span { + &:nth-child(1) { + top: 4px; + left: 3px; + @include rotate(45deg); + } + &:nth-child(2) { + width: 0%; + opacity: 0; + } + &:nth-child(3) { + top: 22px; + left: 3px; + @include rotate(-45deg); + } + } + +} + +.navbar-accordion{position:initial;} + + +// For Responsive Navbar +@mixin navbar-responsive { + +.navbar-collapse { + position: absolute; + top: 99%; + right: 0; + left: 0; + background: #fff; + margin-top: 0px; + z-index: 1000; + @include box-shadow(0px 0px 15px rgba(0, 0, 0, 0.1)); + .navbar-nav { + overflow: hidden; + overflow-y: auto; + max-height: 65vh; + padding: 15px; + } +} +ul.navbar-nav { + li { + display: block; + border-bottom: 1px solid #eee; + margin: 0; + padding: 0; + &:last-child { + border: none; + } + + li { + margin-left: 0px; + } + &.dropdown > .dropdown-toggle > .arrow.show:after { + -webkit-transform: translate(-50%, -50%) rotate(-45deg); + transform: translate(-50%, -50%) rotate(-45deg); + @include transition(all .2s ease); + } + > a:hover:after, > a.active:after { + content: none!important; + width:0px!important; + } + &.dropdown{ + > .dropdown-toggle .arrow { + display: block; + + } + } + } + + > li { + > a:not(.btn) { + height: auto; + padding: 8px 0; + position: relative; + } + &.dropdown { + .dropdown-menu li > a:not(.btn) { + padding: 8px 0; + position: relative; + } + &:hover > a:after { + content: none; + } + .dropdown-toggle .arrow:after { + -webkit-transform: translate(-50%, -50%) rotate(134deg); + transform: translate(-50%, -50%) rotate(134deg); + @include transition(all .2s ease); + } + } + } + > li { + &.dropdown .dropdown-menu { + margin: 0; + @include box-shadow(none); + border: none; + padding: 0px 0px 0px 15px; + .dropdown-menu { + margin: 0; + } + } + &.dropdown-mega { + .dropdown-mega-content > .row > div { + padding: 0px 15px; + } + } + } + +} + +&.navbar-text-light .navbar-collapse{background:rgba(0,0,0,0.95);} + +&.navbar-text-light .navbar-collapse ul.navbar-nav li{ + border-color:rgba(250,250,250,0.15); +} + + +&.navbar-dropdown-dark .navbar-collapse { + background-color: #252A2C; +} + +&.navbar-dropdown-primary .navbar-collapse { + background-color: $primary-color; +} + + &.navbar-dropdown-primary ul.navbar-nav > li.dropdown .dropdown-menu .dropdown-menu { + background-color: $primary-color; + } + &.navbar-dropdown-dark ul.navbar-nav { + li { + border-color: #444; + } + > li { + > a { + color: #a3a2a2; + } + &:hover > a { + color: #fff; + } + } + } + &.navbar-dropdown-primary ul.navbar-nav { + li { + border-color: rgba(250, 250, 250, 0.2); + } + > li { + > a { + color: rgba(250, 250, 250, 0.8); + } + &:hover > a { + color: #fff; + } + } + } + +} + +.navbar-expand-none{ + @include navbar-responsive; +} + + +@include media-breakpoint-down(xs) { + .navbar-expand-sm{ + @include navbar-responsive; + } +} + +@include media-breakpoint-down(sm) { + .navbar-expand-md{ + @include navbar-responsive; + } +} + +@include media-breakpoint-down(md) { + .navbar-expand-lg{ + @include navbar-responsive; + } +} +@include media-breakpoint-down(lg) { + .navbar-expand-xl{ + @include navbar-responsive; + } +} \ No newline at end of file diff --git a/docs/assets/sass/_helpers.scss b/docs/assets/sass/_helpers.scss new file mode 100644 index 0000000..6845d7b --- /dev/null +++ b/docs/assets/sass/_helpers.scss @@ -0,0 +1,301 @@ +/* =================================== */ +/* 2. Helpers Classes +/* =================================== */ + +/* Box Shadow */ +.shadow-md { + @include box-shadow(0px 0px 50px -35px rgba(0, 0, 0, 0.4)!important); +} + +/* Border Radius */ + +.rounded-lg{ + border-radius: 0.6rem !important; +} + +.rounded-top-0{ + border-top-left-radius:0px!important; + border-top-right-radius:0px!important; +} +.rounded-bottom-0{ + border-bottom-left-radius:0px!important; + border-bottom-right-radius:0px!important; +} +.rounded-left-0{ + border-top-left-radius:0px!important; + border-bottom-left-radius:0px!important; +} +.rounded-right-0{border-top-right-radius:0px!important; + border-bottom-right-radius:0px!important; +} + + +/* Border Size */ + +.border-1{ + border-width:1px!important; +} +.border-2{ + border-width:2px!important; +} +.border-3{ + border-width:3px!important; +} +.border-4{ + border-width:4px!important; +} +.border-5{ + border-width:5px!important; +} + +/* Text Size */ +.text-0 { + font-size: 11px !important; + font-size: 0.6875rem !important; +} +.text-1 { + font-size: 12px !important; + font-size: 0.75rem !important; +} +.text-2 { + font-size: 14px !important; + font-size: 0.875rem !important; +} +.text-3 { + font-size: 16px !important; + font-size: 1rem !important; +} +.text-4 { + font-size: 18px !important; + font-size: 1.125rem !important; +} +.text-5 { + font-size: 21px !important; + font-size: 1.3125rem !important; +} +.text-6 { + font-size: 24px !important; + font-size: 1.50rem !important; +} +.text-7 { + font-size: 28px !important; + font-size: 1.75rem !important; +} +.text-8 { + font-size: 32px !important; + font-size: 2rem !important; +} +.text-9 { + font-size: 36px !important; + font-size: 2.25rem !important; +} +.text-10 { + font-size: 40px !important; + font-size: 2.50rem !important; +} +.text-11 { + @include rfs(44, true); +} +.text-12 { + @include rfs(48, true); +} +.text-13 { + @include rfs(52, true); +} +.text-14 { + @include rfs(56, true); +} +.text-15 { + @include rfs(60, true); +} +.text-16 { + @include rfs(64, true); +} +.text-17 { + @include rfs(72, true); +} +.text-18 { + @include rfs(80, true); +} +.text-19 { + @include rfs(84, true); +} +.text-20 { + @include rfs(92, true); +} +.text-21 { + @include rfs(104, true); +} +.text-22 { + @include rfs(112, true); +} +.text-23 { + @include rfs(124, true); +} +.text-24 { + @include rfs(132, true); +} +.text-25 { + @include rfs(144, true); +} + +.text-11, .text-12, .text-13, .text-14, .text-15, .text-16, .text-17, .text-18, .text-19, .text-20, .text-21, .text-22, .text-23, .text-24, .text-25{ + line-height: 1.3; +} + + +/* Line height */ +.line-height-07 { + line-height: 0.7 !important; +} + +.line-height-1 { + line-height: 1 !important; +} + +.line-height-2 { + line-height: 1.2 !important; +} + +.line-height-3 { + line-height: 1.4 !important; +} + +.line-height-4 { + line-height: 1.6 !important; +} + +.line-height-5 { + line-height: 1.8 !important; +} + +/* Font Weight */ +.font-weight-100 { + font-weight: 100 !important; +} + +.font-weight-200 { + font-weight: 200 !important; +} + +.font-weight-300 { + font-weight: 300 !important; +} + +.font-weight-400 { + font-weight: 400 !important; +} +.font-weight-500 { + font-weight: 500 !important; +} + +.font-weight-600 { + font-weight: 600 !important; +} +.font-weight-700 { + font-weight: 700 !important; +} +.font-weight-800 { + font-weight: 800 !important; +} +.font-weight-900 { + font-weight: 900 !important; +} + +/* Opacity */ +.opacity-0 { + opacity: 0; +} + +.opacity-1 { + opacity: 0.1; +} + +.opacity-2 { + opacity: 0.2; +} + +.opacity-3 { + opacity: 0.3; +} + +.opacity-4 { + opacity: 0.4; +} + +.opacity-5 { + opacity: 0.5; +} + +.opacity-6 { + opacity: 0.6; +} + +.opacity-7 { + opacity: 0.7; +} + +.opacity-8 { + opacity: 0.8; +} + +.opacity-9 { + opacity: 0.9; +} + +.opacity-10 { + opacity: 1; +} + +/* Background light */ +.bg-light-1 { + background-color: $gray-200 !important; +} + +.bg-light-2 { + background-color: $gray-300 !important; +} + +.bg-light-3 { + background-color: $gray-400 !important; +} + +.bg-light-4 { + background-color: $gray-500 !important; +} + + +/* Background Dark */ +.bg-dark { + background-color: #111418 !important; +} + +.bg-dark-1 { + background-color: $gray-900 !important; +} + +.bg-dark-2 { + background-color: $gray-800 !important; +} + +.bg-dark-3 { + background-color: $gray-700 !important; +} + +.bg-dark-4 { + background-color: $gray-600 !important; +} + + +/* Progress Bar */ +.progress-sm { + height: 0.5rem !important; +} + +.progress-lg { + height: 1.5rem !important; +} + +hr{ + border-top:1px solid rgba(16,85,96,.1); +} \ No newline at end of file diff --git a/docs/assets/sass/_layouts.scss b/docs/assets/sass/_layouts.scss new file mode 100644 index 0000000..2ec1e1a --- /dev/null +++ b/docs/assets/sass/_layouts.scss @@ -0,0 +1,171 @@ +/* =================================== */ +/* 3. Layouts +/* =================================== */ + +#main-wrapper { + background:#fff; +} + +.box { + #main-wrapper { + max-width: 1200px; + margin: 0 auto; + @include box-shadow(0px 0px 10px rgba(0, 0, 0, 0.1)); + } + .idocs-navigation { + left: auto; + } +} + + +@include media-breakpoint-up(xl) { + .container { + max-width: 1170px !important; + } +} + + +/*=== 3.1 Side Navigation ===*/ + +.idocs-navigation { + position: fixed; + top: 70px; + left: 0; + overflow: hidden; + overflow-y: auto; + width: 260px; + height: calc(100% - 70px); + z-index: 1; + border-right: 1px solid rgba(0, 0, 0, 0.05); + transition: all 0.3s; + > .nav { + padding: 30px 0; + } + .nav { + .nav-item { + position: relative; + } + .nav { + margin: 0 0 5px; + } + .nav-link { + position: relative; + padding: 6px 30px; + line-height: 25px; + font-weight: 600; + } + .nav-item { + &:hover > .nav-link, .nav-link.active { + font-weight: 700; + } + } + .nav { + .nav-item .nav-link { + &:after { + content: ""; + position: absolute; + left: 30px; + height: 100%; + border-left: 1px solid rgba(0, 0, 0, 0.12); + width: 1px; + top: 0; + } + &.active:after { + border-color: $primary-color; + border-width: 2px; + } + } + display: none; + border-left: 1px solid regba(0, 0, 0, 0.3); + } + .nav-item .nav-link.active + .nav { + display: block; + } + .nav { + .nav-link { + color: #6a6a6a; + padding: 4px 30px 4px 45px; + font-size: 15px; + text-transform: none; + } + .nav { + .nav-link { + padding: 4px 30px 4px 60px; + font-size: 15px; + } + .nav-item .nav-link:after { + left: 45px; + } + } + } + } + > .nav > .nav-item > .nav-link.active:after { + position: absolute; + content: " "; + top: 50%; + right: 18px; + border-color: #000; + border-top: 2px solid; + border-right: 2px solid; + width: 7px; + height: 7px; + -webkit-transform: translate(-50%, -50%) rotate(45deg); + transform: translate(-50%, -50%) rotate(45deg); + @include transition(all .2s ease); + } + &.docs-navigation-dark .nav { + .nav-link { + color: rgba(250, 250, 250, 0.85); + } + .nav { + .nav-link { + color: rgba(250, 250, 250, 0.7); + } + .nav-item .nav-link { + &:after { + border-color: rgba(250, 250, 250, 0.2); + } + &.active:after { + border-color: $primary-color; + } + } + } + } +} + +/*=== 3.2 Docs Content ===*/ + +.idocs-content { + position: relative; + margin-left: 260px; + padding: 0px 50px 50px; + min-height: 750px; + transition: all 0.3s; + + section:first-child { + padding-top: 3rem; + } + ol li, ul li { + margin-top: 10px; + } + +} + + +@include media-breakpoint-down(sm) { +.idocs-navigation { + margin-left: -260px; + + &.active { + margin-left: 0; + } +} +.idocs-content { + margin-left:0px; + padding:0px; +} +} + +/*=== 3.3 Section Divider ===*/ + +.divider{margin: 4rem 0;} diff --git a/docs/assets/sass/_mixins.scss b/docs/assets/sass/_mixins.scss new file mode 100644 index 0000000..a49c550 --- /dev/null +++ b/docs/assets/sass/_mixins.scss @@ -0,0 +1,31 @@ +//---------- @mixins ----------// + +@mixin box-shadow($val...) { + -webkit-box-shadow: ($val); + box-shadow: ($val); +} + +@mixin transition($val...) { + -webkit-transition: ($val); + transition: ($val); +} + +@mixin translateY($val...) { + -webkit-transform: translateY($val); + transform: translateY($val); +} + +@mixin translateX($val...) { + -webkit-transform: translateX($val); + transform: translateX($val); +} + +@mixin rotate($val){ + -webkit-transform: rotate($val); + transform: rotate($val); +} + +@mixin scale($val){ + -webkit-transform: scale($val); + transform: scale($val); +} \ No newline at end of file diff --git a/docs/assets/sass/_reset.scss b/docs/assets/sass/_reset.scss new file mode 100644 index 0000000..727986c --- /dev/null +++ b/docs/assets/sass/_reset.scss @@ -0,0 +1,164 @@ +/* =================================== */ +/* 1. Basic Style +/* =================================== */ + +body, html { +height:100%; +} + +body { + background: $body-bg; + color: $text-color; +} + +/*-------- Preloader --------*/ +.preloader { + position: fixed; + width: 100%; + height: 100%; + z-index: 999999999 !important; + background-color: #fff; + top: 0; + left: 0; + right: 0; + bottom: 0; + .lds-ellipsis { + display: inline-block; + position: absolute; + width: 80px; + height: 80px; + margin-top: -40px; + margin-left: -40px; + top: 50%; + left: 50%; + div { + position: absolute; + top: 33px; + width: 13px; + height: 13px; + border-radius: 50%; + background: #000; + animation-timing-function: cubic-bezier(0, 1, 1, 0); + &:nth-child(1) { + left: 8px; + animation: lds-ellipsis1 0.6s infinite; + } + &:nth-child(2) { + left: 8px; + animation: lds-ellipsis2 0.6s infinite; + } + &:nth-child(3) { + left: 32px; + animation: lds-ellipsis2 0.6s infinite; + } + &:nth-child(4) { + left: 56px; + animation: lds-ellipsis3 0.6s infinite; + } + } + } +} + +@keyframes lds-ellipsis1 { + 0% { + transform: scale(0); + } + 100% { + transform: scale(1); + } +} + +@keyframes lds-ellipsis3 { + 0% { + transform: scale(1); + } + + 100% { + transform: scale(0); + } +} + +@keyframes lds-ellipsis2 { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(24px, 0); + } +} + +/*--- Preloader Magnific Popup ----*/ +.mfp-container .preloader{ + background: transparent; + .lds-ellipsis div{ + background: #fff; + } +} + +::selection { + background: $primary-color; + color: #fff; + text-shadow: none; +} + +code{padding: 2px 5px; background-color: #f9f2f4; border-radius: 4px;} + +form { + padding: 0; + margin: 0; + display: inline; +} + +img { + vertical-align: inherit; +} +a, a:focus { + color: $primary-color; + @include transition(all .2s ease); +} +a:hover, a:active { + color: $primary-color-hover; + + @include transition(all .2s ease); +} + +a:focus, a:active, +.btn.active.focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn:active:focus, +.btn:focus, +button:focus, +button:active{ + outline: none; +} + +p { + line-height: 1.8; +} + +blockquote { + border-left: 5px solid #eee; + padding: 10px 20px; +} + +iframe { + border: 0 !important; +} + +h1, h2, h3, h4, h5, h6 { + color: $title-color; + line-height: 1.5; + margin: 0 0 1.5rem 0; + font-family:Roboto, sans-serif; +} + +h1{font-size:3rem;} + +h2{font-size:2.2rem;} + +dl, ol, ul, pre, blockquote, .table{margin-bottom:1.8rem;} + +/*=== Highlight Js ===*/ +.hljs {padding: 1.5rem;} \ No newline at end of file diff --git a/docs/assets/sass/_variables.scss b/docs/assets/sass/_variables.scss new file mode 100644 index 0000000..d2504f9 --- /dev/null +++ b/docs/assets/sass/_variables.scss @@ -0,0 +1,44 @@ +/*=========================================================== + + Template Name: iDocs - One Page Documentation HTML Template + Author: Harnish Design + Template URL: http://demo.harnishdesign.net/html/idocs + Author URL: https://themeforest.net/user/harnishdesign + File Description : Main css file of the template + +================================================= + Table of Contents +================================================= + + 1. Basic + 2. Helpers Classes + 3. Layouts + 3.1 Side Navigation + 3.2 Docs Content + 3.3 Section Divider + 4. Header + 4.1 Main Navigation + 5 Elements + 5.1 List Style + 5.2 Changelog + 5.3 Accordion & Toggle + 5.4 Nav + 5.5 Tabs + 5.6 Popup Img + 5.7 Featured Box + 6 Footer + 6.1 Social Icons + 6.2 Back to Top + 7 Extra + +=======================================================*/ + +//-------------------- Base Colors --------------------// + +$primary-color: #0366d6; +$primary-color-hover: darken($primary-color, 7%); +$secondary-color: $secondary; + +$body-bg: #dddddd; +$text-color: #4c4d4d; +$title-color: #252b33; \ No newline at end of file diff --git a/docs/assets/sass/bootstrap/_alert.scss b/docs/assets/sass/bootstrap/_alert.scss new file mode 100644 index 0000000..da2a98a --- /dev/null +++ b/docs/assets/sass/bootstrap/_alert.scss @@ -0,0 +1,51 @@ +// +// Base styles +// + +.alert { + position: relative; + padding: $alert-padding-y $alert-padding-x; + margin-bottom: $alert-margin-bottom; + border: $alert-border-width solid transparent; + @include border-radius($alert-border-radius); +} + +// Headings for larger alerts +.alert-heading { + // Specified to prevent conflicts of changing $headings-color + color: inherit; +} + +// Provide class for links that match alerts +.alert-link { + font-weight: $alert-link-font-weight; +} + + +// Dismissible alerts +// +// Expand the right padding and account for the close button's positioning. + +.alert-dismissible { + padding-right: $close-font-size + $alert-padding-x * 2; + + // Adjust close link position + .close { + position: absolute; + top: 0; + right: 0; + padding: $alert-padding-y $alert-padding-x; + color: inherit; + } +} + + +// Alternate styles +// +// Generate contextual modifier classes for colorizing the alert. + +@each $color, $value in $theme-colors { + .alert-#{$color} { + @include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level)); + } +} diff --git a/docs/assets/sass/bootstrap/_badge.scss b/docs/assets/sass/bootstrap/_badge.scss new file mode 100644 index 0000000..42c5d08 --- /dev/null +++ b/docs/assets/sass/bootstrap/_badge.scss @@ -0,0 +1,54 @@ +// Base class +// +// Requires one of the contextual, color modifier classes for `color` and +// `background-color`. + +.badge { + display: inline-block; + padding: $badge-padding-y $badge-padding-x; + @include font-size($badge-font-size); + font-weight: $badge-font-weight; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + @include border-radius($badge-border-radius); + @include transition($badge-transition); + + @at-root a#{&} { + @include hover-focus() { + text-decoration: none; + } + } + + // Empty badges collapse automatically + &:empty { + display: none; + } +} + +// Quick fix for badges in buttons +.btn .badge { + position: relative; + top: -1px; +} + +// Pill badges +// +// Make them extra rounded with a modifier to replace v3's badges. + +.badge-pill { + padding-right: $badge-pill-padding-x; + padding-left: $badge-pill-padding-x; + @include border-radius($badge-pill-border-radius); +} + +// Colors +// +// Contextual variations (linked badges get darker on :hover). + +@each $color, $value in $theme-colors { + .badge-#{$color} { + @include badge-variant($value); + } +} diff --git a/docs/assets/sass/bootstrap/_breadcrumb.scss b/docs/assets/sass/bootstrap/_breadcrumb.scss new file mode 100644 index 0000000..a0cf7e2 --- /dev/null +++ b/docs/assets/sass/bootstrap/_breadcrumb.scss @@ -0,0 +1,44 @@ +.breadcrumb { + display: flex; + flex-wrap: wrap; + padding: $breadcrumb-padding-y $breadcrumb-padding-x; + margin-bottom: $breadcrumb-margin-bottom; + @include font-size($breadcrumb-font-size); + list-style: none; + background-color: $breadcrumb-bg; + @include border-radius($breadcrumb-border-radius); +} + +.breadcrumb-item { + display: flex; + + // The separator between breadcrumbs (by default, a forward-slash: "/") + + .breadcrumb-item { + padding-left: $breadcrumb-item-padding; + + &::before { + display: inline-block; // Suppress underlining of the separator in modern browsers + padding-right: $breadcrumb-item-padding; + color: $breadcrumb-divider-color; + content: escape-svg($breadcrumb-divider); + } + } + + // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built + // without `