Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 73377fbb87 | |||
| 3a00d6371a | |||
| caf6d36bcd | |||
| e078a373da | |||
| 007743f5a1 | |||
| d06f891cee | |||
| 8dcbb687f5 | |||
| fcb36f7ee0 | |||
| 3cffd67518 | |||
| ecd00ea707 | |||
| 38a7b981ce | |||
| c41cc3c4c7 | |||
| 4accc8039b | |||
| 87c86ec0c0 | |||
| d9850da282 | |||
| c4a8b02054 | |||
| 34b7258496 | |||
| 69099922c9 | |||
| 64c1cd5fa8 | |||
| 936ac6640b | |||
| 68ad9ae114 | |||
| 6238c17471 | |||
| 52e6fbfe47 | |||
| 4129622d71 | |||
| 95e0aefb9f | |||
| dd1cefdc90 |
@@ -30,6 +30,14 @@ var ticker = await binance.GetSpotTickerAsync(new GetTickerRequest(symbol));
|
|||||||
|
|
||||||
`SharedSymbol(TradingMode.Spot, "BTC", "USDT")` is portable. Each library translates to its native format internally. Don't pass raw strings like `"BTCUSDT"` to shared methods.
|
`SharedSymbol(TradingMode.Spot, "BTC", "USDT")` is portable. Each library translates to its native format internally. Don't pass raw strings like `"BTCUSDT"` to shared methods.
|
||||||
|
|
||||||
|
## Symbol metadata and catalogs
|
||||||
|
|
||||||
|
In 12.2.0, `SharedSpotSymbol` and `SharedFuturesSymbol` include `DisplayName` and base/quote asset classification through `SharedAssetType` (`Crypto`, `Fiat`, `TradFi`) and `SharedAssetSubType` (`StableCoin`, `Equity`, `Commodity`). Pass the matching base/quote filters to `GetSymbolsRequest` when discovery should return only a class of markets.
|
||||||
|
|
||||||
|
After calling `GetSpotSymbolsAsync`, `ISpotSymbolRestClient.SpotSymbolCatalog` maps asset and symbol names to shared metadata. `IFuturesSymbolRestClient.FuturesSymbolCatalog` works the same way after `GetFuturesSymbolsAsync`. Treat either property as unavailable before its corresponding request has populated the cache.
|
||||||
|
|
||||||
|
When implementing an exchange library, use `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` only as best-effort classifiers and supply exchange-specific additions where needed.
|
||||||
|
|
||||||
## Result pattern
|
## Result pattern
|
||||||
|
|
||||||
REST methods return `HttpResult<T>` and websocket subscription methods return `WebSocketResult<UpdateSubscription>`. Always check `.Success`. `.Exchange` property identifies which exchange responded — useful for logging.
|
REST methods return `HttpResult<T>` and websocket subscription methods return `WebSocketResult<UpdateSubscription>`. Always check `.Success`. `.Exchange` property identifies which exchange responded — useful for logging.
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ var ticker = await binance.GetSpotTickerAsync(new GetTickerRequest(symbol));
|
|||||||
|
|
||||||
Same code works on every exchange that implements the interface. Use `Task.WhenAll` for concurrent multi-exchange calls.
|
Same code works on every exchange that implements the interface. Use `Task.WhenAll` for concurrent multi-exchange calls.
|
||||||
|
|
||||||
|
## Shared symbol metadata
|
||||||
|
|
||||||
|
CryptoExchange.Net 12.2.0 classifies the base and quote sides of `SharedSpotSymbol` and `SharedFuturesSymbol` with `SharedAssetType` (`Crypto`, `Fiat`, `TradFi`) and optional `SharedAssetSubType` (`StableCoin`, `Equity`, `Commodity`). The models also expose `DisplayName`. Use the corresponding base/quote fields on `GetSymbolsRequest` to filter symbol discovery.
|
||||||
|
|
||||||
|
`ISpotSymbolRestClient.SpotSymbolCatalog` is populated by `GetSpotSymbolsAsync`; `IFuturesSymbolRestClient.FuturesSymbolCatalog` is populated by `GetFuturesSymbolsAsync`. Do not assume a catalog is available before that request. For exchange-library implementations, `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` offer best-effort classification and can be extended with exchange-specific values.
|
||||||
|
|
||||||
## Single-exchange code uses the exchange's own client
|
## Single-exchange code uses the exchange's own client
|
||||||
|
|
||||||
For Binance-only code, use `BinanceRestClient` directly (see Binance.Net repo `AGENTS.md`). SharedApis is for portability — use it when you need that.
|
For Binance-only code, use `BinanceRestClient` directly (see Binance.Net repo `AGENTS.md`). SharedApis is for portability — use it when you need that.
|
||||||
|
|||||||
@@ -67,6 +67,24 @@ var btcusdtPerp = new SharedSymbol(TradingMode.PerpetualLinear, "BTC", "USDT");
|
|||||||
|
|
||||||
For exchanges that use exotic asset names, see the AssetAliases configuration.
|
For exchanges that use exotic asset names, see the AssetAliases configuration.
|
||||||
|
|
||||||
|
## Symbol Metadata and Asset Classification
|
||||||
|
|
||||||
|
Since CryptoExchange.Net 12.2.0, shared symbol responses describe both sides of a market with `BaseAssetType`, `BaseAssetSubType`, `QuoteAssetType`, and `QuoteAssetSubType`. `SharedAssetType` distinguishes `Crypto`, `Fiat`, and `TradFi`; `SharedAssetSubType` distinguishes `StableCoin`, `Equity`, and `Commodity`. `SharedSpotSymbol` and `SharedFuturesSymbol` also expose `DisplayName`.
|
||||||
|
|
||||||
|
The same fields on `GetSymbolsRequest` filter spot or futures symbol discovery:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var request = new GetSymbolsRequest(
|
||||||
|
baseAssetType: SharedAssetType.Crypto,
|
||||||
|
quoteAssetSubType: SharedAssetSubType.StableCoin);
|
||||||
|
|
||||||
|
var result = await symbolClient.GetSpotSymbolsAsync(request);
|
||||||
|
```
|
||||||
|
|
||||||
|
After calling `GetSpotSymbolsAsync` or `GetFuturesSymbolsAsync`, use the client's `SpotSymbolCatalog` or `FuturesSymbolCatalog` to look up normalized asset and symbol metadata by name. The catalog is unavailable until the corresponding symbol request has populated the cache.
|
||||||
|
|
||||||
|
For exchange-library implementations, `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` provide best-effort classification of known assets and accept exchange-specific additions. These helpers are heuristics, not an exhaustive source of truth.
|
||||||
|
|
||||||
## Available Shared Interfaces
|
## Available Shared Interfaces
|
||||||
|
|
||||||
**REST:**
|
**REST:**
|
||||||
|
|||||||
@@ -138,6 +138,68 @@ namespace CryptoExchange.Net.UnitTests.ClientTests
|
|||||||
Assert.That(socket2.Connected == false);
|
Assert.That(socket2.Connected == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase()]
|
||||||
|
public async Task BatchedSubscription_Should_NotExceedIndividualCombineTarget()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
var client = new TestSocketClient(options =>
|
||||||
|
{
|
||||||
|
options.SocketSubscriptionsCombineTarget = 10;
|
||||||
|
options.SocketIndividualSubscriptionCombineTarget = 10;
|
||||||
|
});
|
||||||
|
TestHelpers.ConfigureSocketClient(client, "wss://localhost");
|
||||||
|
|
||||||
|
// act
|
||||||
|
await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default, individualSubscriptionCount: 6);
|
||||||
|
TestHelpers.ConfigureSocketClient(client, "wss://localhost");
|
||||||
|
await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default, individualSubscriptionCount: 6);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.That(client.ApiClient1._socketConnections.Count == 2);
|
||||||
|
Assert.That(client.ApiClient1._socketConnections.Values.All(connection => connection.Subscriptions.Sum(subscription => subscription.IndividualSubscriptionCount) <= 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase()]
|
||||||
|
public async Task BatchedSubscription_FullIndividualConnection_Should_NotPreventEligibleConnectionReuse()
|
||||||
|
{
|
||||||
|
// arrange
|
||||||
|
var client = new TestSocketClient(options =>
|
||||||
|
{
|
||||||
|
options.SocketSubscriptionsCombineTarget = 5;
|
||||||
|
options.SocketIndividualSubscriptionCombineTarget = 10;
|
||||||
|
});
|
||||||
|
TestHelpers.ConfigureSocketClient(client, "wss://localhost");
|
||||||
|
await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default);
|
||||||
|
await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default);
|
||||||
|
|
||||||
|
TestHelpers.ConfigureSocketClient(client, "wss://localhost");
|
||||||
|
await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default, individualSubscriptionCount: 10);
|
||||||
|
|
||||||
|
TestHelpers.ConfigureSocketClient(client, "wss://localhost");
|
||||||
|
|
||||||
|
// act
|
||||||
|
await client.ApiClient1.SubscribeToUpdatesAsync<TestObject>(x => { }, false, default);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
Assert.That(
|
||||||
|
client.ApiClient1._socketConnections.Count,
|
||||||
|
Is.EqualTo(2),
|
||||||
|
"The eligible connection should be reused instead of opening a new connection after selecting a full individual-subscription connection");
|
||||||
|
|
||||||
|
var fullConnection = client.ApiClient1._socketConnections.Values
|
||||||
|
.Single(connection => connection.Subscriptions.Sum(subscription => subscription.IndividualSubscriptionCount) == 10);
|
||||||
|
Assert.That(
|
||||||
|
fullConnection.UserSubscriptionCount,
|
||||||
|
Is.EqualTo(1),
|
||||||
|
"The full connection should not receive the normal subscription");
|
||||||
|
|
||||||
|
var eligibleConnection = client.ApiClient1._socketConnections.Values.Single(connection => connection != fullConnection);
|
||||||
|
Assert.That(
|
||||||
|
eligibleConnection.UserSubscriptionCount,
|
||||||
|
Is.EqualTo(3),
|
||||||
|
"The existing eligible connection should receive the normal subscription");
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase()]
|
[TestCase()]
|
||||||
public async Task ErrorResponse_ShouldNot_ConfirmSubscription()
|
public async Task ErrorResponse_ShouldNot_ConfirmSubscription()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,17 @@ namespace CryptoExchange.Net.UnitTests.ConverterTests
|
|||||||
Assert.That(output!.Value == expected);
|
Assert.That(output!.Value == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase(1, true)]
|
||||||
|
[TestCase(2, true)]
|
||||||
|
[TestCase(0, false)]
|
||||||
|
[TestCase(-1, false)]
|
||||||
|
public void TestBoolConverterInts(int value, bool? expected)
|
||||||
|
{
|
||||||
|
var val = $"{value}";
|
||||||
|
var output = JsonSerializer.Deserialize<STJBoolObject>($"{{ \"Value\": {val} }}", SerializerOptions.WithConverters(new TestSerializerContext()));
|
||||||
|
Assert.That(output!.Value == expected);
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase("1", true)]
|
[TestCase("1", true)]
|
||||||
[TestCase("true", true)]
|
[TestCase("true", true)]
|
||||||
[TestCase("yes", true)]
|
[TestCase("yes", true)]
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace CryptoExchange.Net.UnitTests.ConverterTests
|
|||||||
[TestCase("1620777600000")]
|
[TestCase("1620777600000")]
|
||||||
[TestCase("2021-05-12T00:00:00.000Z")]
|
[TestCase("2021-05-12T00:00:00.000Z")]
|
||||||
[TestCase("2021-05-12T00:00:00.000000000Z")]
|
[TestCase("2021-05-12T00:00:00.000000000Z")]
|
||||||
|
[TestCase("2021-05-12 00:00:00.000000+00:00:00")]
|
||||||
[TestCase("0.000000", true)]
|
[TestCase("0.000000", true)]
|
||||||
[TestCase("0", true)]
|
[TestCase("0", true)]
|
||||||
[TestCase("", true)]
|
[TestCase("", true)]
|
||||||
|
|||||||
@@ -36,9 +36,13 @@ namespace CryptoExchange.Net.UnitTests.Implementations
|
|||||||
protected override TestAuthenticationProvider CreateAuthenticationProvider(TestCredentials credentials) =>
|
protected override TestAuthenticationProvider CreateAuthenticationProvider(TestCredentials credentials) =>
|
||||||
new TestAuthenticationProvider(credentials);
|
new TestAuthenticationProvider(credentials);
|
||||||
|
|
||||||
public async Task<WebSocketResult<UpdateSubscription>> SubscribeToUpdatesAsync<T>(Action<DataEvent<T>> handler, bool subQuery, CancellationToken ct)
|
public async Task<WebSocketResult<UpdateSubscription>> SubscribeToUpdatesAsync<T>(Action<DataEvent<T>> handler, bool subQuery, CancellationToken ct, int individualSubscriptionCount = 1)
|
||||||
{
|
{
|
||||||
return await base.SubscribeAsync(new TestSubscription<T>(_logger, handler, subQuery, false), ct);
|
var subscription = new TestSubscription<T>(_logger, handler, subQuery, false)
|
||||||
|
{
|
||||||
|
IndividualSubscriptionCount = individualSubscriptionCount
|
||||||
|
};
|
||||||
|
return await base.SubscribeAsync(subscription, ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,8 +156,9 @@ namespace CryptoExchange.Net.UnitTests.SocketRoutingTests
|
|||||||
MessageRouter = messageRouter;
|
MessageRouter = messageRouter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS0067 // The event is never used, but it's required by the interface
|
||||||
public event Action? OnMessageRouterUpdated;
|
public event Action? OnMessageRouterUpdated;
|
||||||
|
#pragma warning restore CS0067
|
||||||
public bool Handle(string typeIdentifier, string? topicFilter, SocketConnection socketConnection, DateTime receiveTime, string? originalData, object result)
|
public bool Handle(string typeIdentifier, string? topicFilter, SocketConnection socketConnection, DateTime receiveTime, string? originalData, object result)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -625,6 +625,21 @@ namespace CryptoExchange.Net.Clients
|
|||||||
return Task.FromResult(CallResult.Ok());
|
return Task.FromResult(CallResult.Ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the connection can be used for a new subscription or query with the provided parameters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection">The connection to check</param>
|
||||||
|
/// <param name="address">The address set by the request</param>
|
||||||
|
/// <param name="authenticated">Whether the request needs an authenticated connection</param>
|
||||||
|
/// <param name="topic">Topic of the request</param>
|
||||||
|
/// <returns>True if connection can be used</returns>
|
||||||
|
protected virtual bool ConnectionCanBeUsedFor(SocketConnection connection, string address, bool authenticated, string? topic = null)
|
||||||
|
{
|
||||||
|
return connection.ConnectionUriString.Equals(address.TrimEnd('/'), StringComparison.Ordinal)
|
||||||
|
&& connection.ApiClient.ClientName.Equals(ClientName, StringComparison.Ordinal)
|
||||||
|
&& (AllowTopicsOnTheSameConnection || !connection.Topics.Contains(topic));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a connection for a new subscription or query. Can be an existing if there are open position or a new one.
|
/// Gets a connection for a new subscription or query. Can be an existing if there are open position or a new one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -643,10 +658,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
string? topic = null,
|
string? topic = null,
|
||||||
int individualSubscriptionCount = 1)
|
int individualSubscriptionCount = 1)
|
||||||
{
|
{
|
||||||
var socketQuery = _socketConnections.Where(s => s.Value.ConnectionUriString.Equals(address.TrimEnd('/'), StringComparison.Ordinal)
|
var socketQuery = _socketConnections.Where(s => ConnectionCanBeUsedFor(s.Value, address, authenticated, topic)).Select(x => x.Value); // Don't ToList this so the query is executed again when called
|
||||||
&& s.Value.ApiClient.ClientName.Equals(ClientName, StringComparison.Ordinal)
|
|
||||||
&& (AllowTopicsOnTheSameConnection || !s.Value.Topics.Contains(topic)))
|
|
||||||
.Select(x => x.Value); // Don't ToList this so the query is executed again when called
|
|
||||||
|
|
||||||
// If all current socket connections are reconnecting or resubscribing wait for that to finish as we can probably use the existing connection
|
// If all current socket connections are reconnecting or resubscribing wait for that to finish as we can probably use the existing connection
|
||||||
var delayStart = DateTime.UtcNow;
|
var delayStart = DateTime.UtcNow;
|
||||||
@@ -679,45 +691,26 @@ namespace CryptoExchange.Net.Clients
|
|||||||
&& (s.Authenticated == authenticated || !authenticated)
|
&& (s.Authenticated == authenticated || !authenticated)
|
||||||
&& s.Connected).ToList();
|
&& s.Connected).ToList();
|
||||||
|
|
||||||
SocketConnection? connection;
|
bool maxConnectionsReached = _socketConnections.Count >= (ApiOptions.MaxSocketConnections ?? ClientOptions.MaxSocketConnections);
|
||||||
if (!dedicatedRequestConnection)
|
SocketConnection? connection = null;
|
||||||
{
|
if (dedicatedRequestConnection)
|
||||||
connection = socketQuery
|
|
||||||
.Where(s => !s.DedicatedRequestConnection.IsDedicatedRequestConnection)
|
|
||||||
.OrderBy(s => s.UserSubscriptionCount)
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
connection = socketQuery.Where(s => s.DedicatedRequestConnection.IsDedicatedRequestConnection).FirstOrDefault();
|
connection = socketQuery.Where(s => s.DedicatedRequestConnection.IsDedicatedRequestConnection).FirstOrDefault();
|
||||||
if (connection != null && !connection.DedicatedRequestConnection.Authenticated)
|
if (connection != null && !connection.DedicatedRequestConnection.Authenticated)
|
||||||
// Mark dedicated request connection as authenticated if the request is authenticated
|
// Mark dedicated request connection as authenticated if the request is authenticated
|
||||||
connection.DedicatedRequestConnection.Authenticated = authenticated;
|
connection.DedicatedRequestConnection.Authenticated = authenticated;
|
||||||
|
|
||||||
if (connection == null)
|
|
||||||
// Fall back to an existing connection if there is no dedicated request connection available
|
|
||||||
connection = socketQuery.OrderBy(s => s.UserSubscriptionCount).FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool maxConnectionsReached = _socketConnections.Count >= (ApiOptions.MaxSocketConnections ?? ClientOptions.MaxSocketConnections);
|
if (connection == null)
|
||||||
|
// Use an eligible non-dedicated connection for subscriptions, or as fallback when no dedicated request connection is available
|
||||||
|
connection = socketQuery
|
||||||
|
.Where(s => !s.DedicatedRequestConnection.IsDedicatedRequestConnection)
|
||||||
|
.Where(s => IsConnectionEligible(s, individualSubscriptionCount, maxConnectionsReached))
|
||||||
|
.OrderBy(s => s.UserSubscriptionCount)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
{
|
return CallResult.Ok(connection);
|
||||||
bool lessThanBatchSubCombineTarget = connection.UserSubscriptionCount < ClientOptions.SocketSubscriptionsCombineTarget;
|
|
||||||
bool lessThanIndividualSubCombineTarget = connection.Subscriptions.Sum(x => x.IndividualSubscriptionCount) < ClientOptions.SocketIndividualSubscriptionCombineTarget;
|
|
||||||
|
|
||||||
if ((lessThanBatchSubCombineTarget && lessThanIndividualSubCombineTarget)
|
|
||||||
|| maxConnectionsReached)
|
|
||||||
{
|
|
||||||
// Use existing socket if it has less than target connections OR it has the least connections and we can't make new
|
|
||||||
// If there is a max subscriptions per connection limit also only use existing if the new subscription doesn't go over the limit
|
|
||||||
if (MaxIndividualSubscriptionsPerConnection == null)
|
|
||||||
return CallResult.Ok(connection);
|
|
||||||
|
|
||||||
var currentCount = connection.Subscriptions.Sum(x => x.IndividualSubscriptionCount);
|
|
||||||
if (currentCount + individualSubscriptionCount <= MaxIndividualSubscriptionsPerConnection)
|
|
||||||
return CallResult.Ok(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxConnectionsReached)
|
if (maxConnectionsReached)
|
||||||
return CallResult.Fail<SocketConnection>(new InvalidOperationError("Max amount of socket connections reached"));
|
return CallResult.Fail<SocketConnection>(new InvalidOperationError("Max amount of socket connections reached"));
|
||||||
@@ -784,6 +777,21 @@ namespace CryptoExchange.Net.Clients
|
|||||||
return CallResult.Ok(socketConnection);
|
return CallResult.Ok(socketConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsConnectionEligible(SocketConnection socketConnection, int individualSubscriptionCount, bool maxConnectionsReached)
|
||||||
|
{
|
||||||
|
var currentIndividualSubscriptionCount = socketConnection.Subscriptions.Sum(x => x.IndividualSubscriptionCount);
|
||||||
|
bool lessThanBatchSubCombineTarget = socketConnection.UserSubscriptionCount < ClientOptions.SocketSubscriptionsCombineTarget;
|
||||||
|
// Include the incoming batch so batched subscriptions cannot overshoot the configured socket target.
|
||||||
|
bool lessThanIndividualSubCombineTarget = currentIndividualSubscriptionCount + individualSubscriptionCount <= ClientOptions.SocketIndividualSubscriptionCombineTarget;
|
||||||
|
|
||||||
|
if ((!lessThanBatchSubCombineTarget || !lessThanIndividualSubCombineTarget)
|
||||||
|
&& !maxConnectionsReached)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return MaxIndividualSubscriptionsPerConnection == null
|
||||||
|
|| currentIndividualSubscriptionCount + individualSubscriptionCount <= MaxIndividualSubscriptionsPerConnection;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Process an unhandled message
|
/// Process an unhandled message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
if (reader.TokenType == JsonTokenType.Number)
|
if (reader.TokenType == JsonTokenType.Number)
|
||||||
{
|
{
|
||||||
var number = reader.GetInt16();
|
var number = reader.GetInt16();
|
||||||
if (number > 1)
|
if (number >= 1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -198,6 +198,9 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
return new DateTime(year, month, day, 0, 0, 0, DateTimeKind.Utc);
|
return new DateTime(year, month, day, 0, 0, 0, DateTimeKind.Utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stringValue.EndsWith("+00:00:00"))
|
||||||
|
return DateTime.Parse(stringValue.Substring(0, stringValue.Length - 9), CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
|
||||||
|
|
||||||
return DateTime.Parse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
|
return DateTime.Parse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
<PackageId>CryptoExchange.Net</PackageId>
|
<PackageId>CryptoExchange.Net</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<Authors>JKorf</Authors>
|
||||||
<Description>CryptoExchange.Net is a base library which is used to implement different cryptocurrency (exchange) API's. It provides a standardized way of implementing different API's, which results in a very similar experience for users of the API implementations.</Description>
|
<Description>CryptoExchange.Net is a base library which is used to implement different cryptocurrency (exchange) API's. It provides a standardized way of implementing different API's, which results in a very similar experience for users of the API implementations.</Description>
|
||||||
<PackageVersion>12.0.0</PackageVersion>
|
<PackageVersion>12.3.0</PackageVersion>
|
||||||
<AssemblyVersion>12.0.0</AssemblyVersion>
|
<AssemblyVersion>12.3.0</AssemblyVersion>
|
||||||
<FileVersion>12.0.0</FileVersion>
|
<FileVersion>12.3.0</FileVersion>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<PackageTags>OKX;OKX.Net;Mexc;Mexc.Net;Kucoin;Kucoin.Net;Kraken;Kraken.Net;Huobi;Huobi.Net;CoinEx;CoinEx.Net;Bybit;Bybit.Net;Bitget;Bitget.Net;Bitfinex;Bitfinex.Net;Binance;Binance.Net;CryptoCurrency;CryptoCurrency Exchange;CryptoExchange.Net</PackageTags>
|
<PackageTags>OKX;OKX.Net;Mexc;Mexc.Net;Kucoin;Kucoin.Net;Kraken;Kraken.Net;Huobi;Huobi.Net;CoinEx;CoinEx.Net;Bybit;Bybit.Net;Bitget;Bitget.Net;Bitfinex;Bitfinex.Net;Binance;Binance.Net;CryptoCurrency;CryptoCurrency Exchange;CryptoExchange.Net</PackageTags>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace CryptoExchange.Net
|
|||||||
if (keyedCache != null && DateTime.UtcNow - keyedCache.UpdateTime < TimeSpan.FromMinutes(60))
|
if (keyedCache != null && DateTime.UtcNow - keyedCache.UpdateTime < TimeSpan.FromMinutes(60))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
exchangeInfo.Set(key, new ExchangeInfo(DateTime.UtcNow, updateData.ToDictionary(x => x.Name, x => x.SharedSymbol)));
|
exchangeInfo.Set(key, new ExchangeInfo(DateTime.UtcNow, updateData.ToDictionary(x => x.Name, x => x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -118,6 +118,22 @@ namespace CryptoExchange.Net
|
|||||||
return exchangeInfo.ParseSymbol(key, symbolName);
|
return exchangeInfo.ParseSymbol(key, symbolName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a symbol catalog for a specific exchange(topic) and environment. Only available if <see cref="UpdateSymbolInfo(string, string, string?, SharedSpotSymbol[])"/> has been called previously.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exchange">Exchange name</param>
|
||||||
|
/// <param name="topicId">Id for the provided data</param>
|
||||||
|
/// <param name="environmentName">Trade environment</param>
|
||||||
|
/// <param name="key">Additional data set identification key</param>
|
||||||
|
public static SharedSymbolCatalog? GetSymbolCatalog(string exchange, string topicId, string environmentName, string? key)
|
||||||
|
{
|
||||||
|
var id = topicId + environmentName;
|
||||||
|
if (!_symbolInfos.TryGetValue(id, out var exchangeInfo))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return exchangeInfo.GetSymbolCatalog(exchange, key);
|
||||||
|
}
|
||||||
|
|
||||||
class ExchangeKeyedCache
|
class ExchangeKeyedCache
|
||||||
{
|
{
|
||||||
private ExchangeInfo? _noKeyCache;
|
private ExchangeInfo? _noKeyCache;
|
||||||
@@ -163,7 +179,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
public SharedSymbol? ParseSymbol(string? key, string symbolName)
|
public SharedSymbol? ParseSymbol(string? key, string symbolName)
|
||||||
{
|
{
|
||||||
SharedSymbol? symbolInfo = null;
|
SharedSpotSymbol? symbolInfo = null;
|
||||||
if (key == null)
|
if (key == null)
|
||||||
{
|
{
|
||||||
if (_noKeyCache != null)
|
if (_noKeyCache != null)
|
||||||
@@ -173,7 +189,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
return new SharedSymbol(symbolInfo.TradingMode, symbolInfo.BaseAsset, symbolInfo.QuoteAsset, symbolName)
|
return new SharedSymbol(symbolInfo.TradingMode, symbolInfo.BaseAsset, symbolInfo.QuoteAsset, symbolName)
|
||||||
{
|
{
|
||||||
DeliverTime = symbolInfo.DeliverTime
|
DeliverTime = (symbolInfo as SharedFuturesSymbol)?.DeliveryTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +199,7 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
return new SharedSymbol(symbolInfo.TradingMode, symbolInfo.BaseAsset, symbolInfo.QuoteAsset, symbolName)
|
return new SharedSymbol(symbolInfo.TradingMode, symbolInfo.BaseAsset, symbolInfo.QuoteAsset, symbolName)
|
||||||
{
|
{
|
||||||
DeliverTime = symbolInfo.DeliverTime
|
DeliverTime = (symbolInfo as SharedFuturesSymbol)?.DeliveryTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,7 +215,7 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
return new SharedSymbol(symbolInfo.TradingMode, symbolInfo.BaseAsset, symbolInfo.QuoteAsset, symbolName)
|
return new SharedSymbol(symbolInfo.TradingMode, symbolInfo.BaseAsset, symbolInfo.QuoteAsset, symbolName)
|
||||||
{
|
{
|
||||||
DeliverTime = symbolInfo.DeliverTime
|
DeliverTime = (symbolInfo as SharedFuturesSymbol)?.DeliveryTime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +281,7 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
return _noKeyCache.Symbols
|
return _noKeyCache.Symbols
|
||||||
.Where(x => x.Value.BaseAsset.Equals(baseAsset, StringComparison.InvariantCultureIgnoreCase))
|
.Where(x => x.Value.BaseAsset.Equals(baseAsset, StringComparison.InvariantCultureIgnoreCase))
|
||||||
.Select(x => x.Value)
|
.Select(x => x.Value.SharedSymbol)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +290,7 @@ namespace CryptoExchange.Net
|
|||||||
{
|
{
|
||||||
result.AddRange(cache.Symbols
|
result.AddRange(cache.Symbols
|
||||||
.Where(x => x.Value.BaseAsset.Equals(baseAsset, StringComparison.InvariantCultureIgnoreCase))
|
.Where(x => x.Value.BaseAsset.Equals(baseAsset, StringComparison.InvariantCultureIgnoreCase))
|
||||||
.Select(x => x.Value));
|
.Select(x => x.Value.SharedSymbol));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.ToArray();
|
return result.ToArray();
|
||||||
@@ -286,18 +302,63 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
return exchangeInfo.Symbols
|
return exchangeInfo.Symbols
|
||||||
.Where(x => x.Value.BaseAsset.Equals(baseAsset, StringComparison.InvariantCultureIgnoreCase))
|
.Where(x => x.Value.BaseAsset.Equals(baseAsset, StringComparison.InvariantCultureIgnoreCase))
|
||||||
.Select(x => x.Value)
|
.Select(x => x.Value.SharedSymbol)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal SharedSymbolCatalog? GetSymbolCatalog(string exchange, string? key)
|
||||||
|
{
|
||||||
|
IEnumerable<SharedSpotSymbol> cachedSymbols;
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
if (_noKeyCache != null)
|
||||||
|
cachedSymbols = _noKeyCache.Symbols.Values;
|
||||||
|
else
|
||||||
|
cachedSymbols = _keyedCache.Values.SelectMany(x => x.Symbols.Values);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!_keyedCache.TryGetValue(key, out var exchangeInfo) || exchangeInfo == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
cachedSymbols = exchangeInfo.Symbols.Values;
|
||||||
|
}
|
||||||
|
|
||||||
|
var assets = new Dictionary<string, SharedAssetInfo>();
|
||||||
|
var symbols = new Dictionary<string, SharedSpotSymbol>();
|
||||||
|
foreach (var symbol in cachedSymbols)
|
||||||
|
{
|
||||||
|
if (!assets.TryGetValue(symbol.BaseAsset, out var baseAssetInfo))
|
||||||
|
{
|
||||||
|
baseAssetInfo = new SharedAssetInfo(symbol.BaseAsset, symbol.BaseAssetType, symbol.BaseAssetSubType);
|
||||||
|
assets.Add(symbol.BaseAsset, baseAssetInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!assets.TryGetValue(symbol.QuoteAsset, out var quoteAssetInfo))
|
||||||
|
{
|
||||||
|
quoteAssetInfo = new SharedAssetInfo(symbol.QuoteAsset, symbol.QuoteAssetType, symbol.QuoteAssetSubType);
|
||||||
|
assets.Add(symbol.QuoteAsset, quoteAssetInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbols.Add(symbol.Name, symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SharedSymbolCatalog
|
||||||
|
{
|
||||||
|
Exchange = exchange,
|
||||||
|
Assets = assets,
|
||||||
|
Symbols = symbols
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ExchangeInfo
|
class ExchangeInfo
|
||||||
{
|
{
|
||||||
public DateTime UpdateTime { get; set; }
|
public DateTime UpdateTime { get; set; }
|
||||||
public Dictionary<string, SharedSymbol> Symbols { get; set; }
|
public Dictionary<string, SharedSpotSymbol> Symbols { get; set; }
|
||||||
|
|
||||||
public ExchangeInfo(DateTime updateTime, Dictionary<string, SharedSymbol> symbols)
|
public ExchangeInfo(DateTime updateTime, Dictionary<string, SharedSpotSymbol> symbols)
|
||||||
{
|
{
|
||||||
UpdateTime = updateTime;
|
UpdateTime = updateTime;
|
||||||
Symbols = symbols;
|
Symbols = symbols;
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ namespace CryptoExchange.Net.Interfaces
|
|||||||
/// <param name="interval">Kline interval</param>
|
/// <param name="interval">Kline interval</param>
|
||||||
/// <param name="limit">The max amount of klines to retain</param>
|
/// <param name="limit">The max amount of klines to retain</param>
|
||||||
/// <param name="period">The max period the data should be retained</param>
|
/// <param name="period">The max period the data should be retained</param>
|
||||||
|
/// <param name="exchangeParameters">Exchange parameters</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
IKlineTracker CreateKlineTracker(SharedSymbol symbol, SharedKlineInterval interval, int? limit = null, TimeSpan? period = null);
|
IKlineTracker CreateKlineTracker(SharedSymbol symbol, SharedKlineInterval interval, int? limit = null, TimeSpan? period = null, ExchangeParameters? exchangeParameters = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the factory supports creating a TradeTracker instance for this symbol
|
/// Whether the factory supports creating a TradeTracker instance for this symbol
|
||||||
@@ -39,7 +40,8 @@ namespace CryptoExchange.Net.Interfaces
|
|||||||
/// <param name="symbol">The symbol</param>
|
/// <param name="symbol">The symbol</param>
|
||||||
/// <param name="limit">The max amount of trades to retain</param>
|
/// <param name="limit">The max amount of trades to retain</param>
|
||||||
/// <param name="period">The max period the data should be retained</param>
|
/// <param name="period">The max period the data should be retained</param>
|
||||||
|
/// <param name="exchangeParameters">Exchange parameters</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ITradeTracker CreateTradeTracker(SharedSymbol symbol, int? limit = null, TimeSpan? period = null);
|
ITradeTracker CreateTradeTracker(SharedSymbol symbol, int? limit = null, TimeSpan? period = null, ExchangeParameters? exchangeParameters = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ using CryptoExchange.Net.Objects.Options;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Pipelines;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
|
||||||
@@ -14,6 +16,61 @@ namespace CryptoExchange.Net
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class LibraryHelpers
|
public static class LibraryHelpers
|
||||||
{
|
{
|
||||||
|
private static readonly HashSet<string> _stableCoins = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
// USD
|
||||||
|
"USDT", "USDC", "DAI", "FDUSD", "USDE", "TUSD", "USDP", "PYUSD", "GUSD",
|
||||||
|
"USDD", "LUSD", "USDJ", "SUSD", "ZUSD", "BUSD", "USTC", "USDX", "USDK",
|
||||||
|
"CUSD", "USD1", "USD0", "XUSD", "BFUSD", "USDS", "RLUSD", "OUSD", "USDH",
|
||||||
|
"APXUSD", "USDQ", "USDPT", "FIDD", "AUSD",
|
||||||
|
// EUR
|
||||||
|
"EURS", "EURC", "EURI", "EURT", "AGEUR", "CEUR", "AEUR", "EURQ", "EUROP",
|
||||||
|
// Other
|
||||||
|
"CNYT", // CNY
|
||||||
|
"CREAL", "BRL1", // BRL
|
||||||
|
"XSGD", // SGD
|
||||||
|
"GYEN", // JPY
|
||||||
|
"KGST", // KGS
|
||||||
|
"QCAD", // CAD
|
||||||
|
"TGBP", // GBP
|
||||||
|
"AUDX", // AUD
|
||||||
|
"MXNB", // MXN
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly HashSet<string> _commodities = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
// Metals
|
||||||
|
"XAU", "XAUT", "XAG", "XPT", "XPD", "COPPER", "PAXG", "XNI", "XCU", "XAL", "GOLD", "SILVER",
|
||||||
|
// Energy
|
||||||
|
"BZ", "NATGAS", "NGAS", "CL", "XTI", "UKOIL", "USOIL", "BRENTOIL"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly HashSet<string> _stocks = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
// Top stocks, will need to update periodically
|
||||||
|
"AAAU", "AADR", "AAPL", "ACWI", "ACWX", "AGG", "AMD", "AMLP", "AMZN", "ARKF",
|
||||||
|
"ARKG", "ARKK", "ARKQ", "ARKW", "AVGO", "BA", "BABA", "BND", "BNDX", "BOTZ",
|
||||||
|
"CIBR", "COIN", "DIA", "DIVB", "DVY", "EEM", "EFA", "EFAV", "ESGU", "EWG",
|
||||||
|
"EWJ", "EWT", "EWU", "EWW", "EWY", "EWZ", "FDN", "FEZ", "GLDM", "GOOGL",
|
||||||
|
"HDV", "HOOD", "HYG", "IAU", "IBB", "ICLN", "IEFA", "IEMG", "IGSB", "IJH",
|
||||||
|
"IJR", "INTC", "ITOT", "IUSB", "IUSG", "IUSV", "IWM", "IWO", "IWR", "IYR",
|
||||||
|
"JETS", "JPM", "LIT", "MCHI", "META", "MGK", "MSTR", "MTUM", "MU", "NET",
|
||||||
|
"NFLX", "NOBL", "NVDA", "OIH", "ORCL", "PAVE", "PBW", "PLTR", "QQQ", "QQQM",
|
||||||
|
"SCHB", "SCHD", "SCHF", "SCHG", "SCHH", "SCHV", "SCHX", "SKHY", "SPCX", "SPCXD",
|
||||||
|
"SPLG", "SPY", "SPYG", "SPYV", "SQQQ", "TSLA", "TSM", "TQQQ", "USMV", "VBR",
|
||||||
|
"VCIT", "VCSH", "VEA", "VEU", "VGIT", "VGK", "VGT", "VHT", "VIG", "VNQ",
|
||||||
|
"VOO", "VOT", "VTI", "VTV", "VUG", "VXUS", "XBI", "XLC", "XLE", "XLF",
|
||||||
|
"XLI", "XLK", "XLP", "XLU", "XLV", "XLY", "CSCO", "UBER", "MRVL", "RKLB",
|
||||||
|
"COHR", "SOXL", "HD", "DIS", "CBRS", "V", "BRKB", "FLNC", "LLY", "COST",
|
||||||
|
"ARM", "BMNR", "NBIS", "ASML", "AAOI", "GLW", "SHLD", "BE", "QNTX", "IBM",
|
||||||
|
"AMAT", "NOK", "ASTS", "BBX", "SLX", "SKHYNIX", "SAMSUNG", "HYUNDAI", "NVO",
|
||||||
|
"IREN", "ONDS", "CRM" , "VRT", "ZEST", "BTW", "HPE", "AXTI", "BX", "CRWD",
|
||||||
|
"CRDO", "NOW", "ZM", "DKNG", "RIVN", "URNM", "EBAY", "ADBE", "UVXY", "RDW",
|
||||||
|
"CIEN","PANW", "WIN", "PAYP", "HIMS", "CRWV", "QCOM", "LITE", "DRAM", "ANTHROPIC",
|
||||||
|
"OPENAI", "USAR", "BILL", "SNDK", "NASDAQ100", "SPX500", "BSB", "CRCL", "STRC",
|
||||||
|
"MSFT", "WDC"
|
||||||
|
};
|
||||||
|
|
||||||
private static ILogger? _staticLogger;
|
private static ILogger? _staticLogger;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Static logger
|
/// Static logger
|
||||||
@@ -105,6 +162,67 @@ namespace CryptoExchange.Net
|
|||||||
return _defaultClientReferences.TryGetValue(key, out var id) ? id : throw new KeyNotFoundException($"{exchange} not found in configuration");
|
return _defaultClientReferences.TryGetValue(key, out var id) ? id : throw new KeyNotFoundException($"{exchange} not found in configuration");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether an asset is a known stablecoin. Note that this is not definitive, only large known stocks are checked
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">Asset name</param>
|
||||||
|
/// <param name="additionalStableCoins">Additional stablecoin names for the specific exchange</param>
|
||||||
|
public static bool IsStableCoin(string asset, params HashSet<string> additionalStableCoins)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(asset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _stableCoins.Contains(asset) || (additionalStableCoins != null && additionalStableCoins.Contains(asset, StringComparer.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether an asset is a known commodity. Note that this is not definitive, only large known stocks are checked
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">Asset name</param>
|
||||||
|
/// <param name="additionalCommodities">Additional commodity names for the specific exchange</param>
|
||||||
|
public static bool IsCommodity(string asset, params HashSet<string> additionalCommodities)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(asset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _commodities.Contains(asset) || (additionalCommodities != null && additionalCommodities.Contains(asset, StringComparer.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether an asset is a known stock. Note that this is not definitive, only large known stocks are checked
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">Asset name</param>
|
||||||
|
/// <param name="additionalStocks">Additional stock names for the specific exchange</param>
|
||||||
|
public static bool IsEquity(string asset, params HashSet<string> additionalStocks)
|
||||||
|
=> IsEquity(asset, [], additionalStocks);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether an asset is a known stock.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">Asset name</param>
|
||||||
|
/// <param name="potentialSuffixes">Suffixes to check, for example when `X` is a potential suffix both `TSLA` and `TSLAX` will be checked</param>
|
||||||
|
/// <param name="additionalStocks">Additional stock names for the specific exchange</param>
|
||||||
|
public static bool IsEquity(string asset, string[] potentialSuffixes, params HashSet<string> additionalStocks)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(asset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_stocks.Contains(asset) || (additionalStocks != null && additionalStocks.Contains(asset, StringComparer.OrdinalIgnoreCase)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach (var suffix in potentialSuffixes)
|
||||||
|
{
|
||||||
|
if (!asset.EndsWith(suffix))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var suffixAsset = asset.Substring(0, asset.Length - suffix.Length);
|
||||||
|
if (_stocks.Contains(suffixAsset) || (additionalStocks != null && additionalStocks.Contains(suffixAsset, StringComparer.OrdinalIgnoreCase)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new HttpMessageHandler instance
|
/// Create a new HttpMessageHandler instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// Add key as comma separated values
|
/// Add key as comma separated values
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#if NET5_0_OR_GREATER
|
#if NET5_0_OR_GREATER
|
||||||
public void AddCommaSeparated<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields)] T>(string key, IEnumerable<T> values)
|
public void AddCommaSeparated<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields)] T>(string key, IEnumerable<T>? values)
|
||||||
#else
|
#else
|
||||||
public void AddCommaSeparated<T>(string key, IEnumerable<T>? values)
|
public void AddCommaSeparated<T>(string key, IEnumerable<T>? values)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Asset type
|
||||||
|
/// </summary>
|
||||||
|
public enum SharedAssetType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unknown or unspecified asset type
|
||||||
|
/// </summary>
|
||||||
|
Unspecified,
|
||||||
|
/// <summary>
|
||||||
|
/// Cryptocurrency asset type
|
||||||
|
/// </summary>
|
||||||
|
Crypto,
|
||||||
|
/// <summary>
|
||||||
|
/// Fiat currency asset type
|
||||||
|
/// </summary>
|
||||||
|
Fiat,
|
||||||
|
/// <summary>
|
||||||
|
/// Traditional finance asset type
|
||||||
|
/// </summary>
|
||||||
|
TradFi
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asset sub type
|
||||||
|
/// </summary>
|
||||||
|
public enum SharedAssetSubType
|
||||||
|
{
|
||||||
|
// --- Crypto sub types ---
|
||||||
|
/// <summary>
|
||||||
|
/// Stable coin, can be for different fiat currencies
|
||||||
|
/// </summary>
|
||||||
|
StableCoin,
|
||||||
|
|
||||||
|
// --- TradFi sub types ---
|
||||||
|
/// <summary>
|
||||||
|
/// Equity, can be stocks, ETFs, or indices
|
||||||
|
/// </summary>
|
||||||
|
Equity,
|
||||||
|
/// <summary>
|
||||||
|
/// Commodity, can be oil, gas, metals, etc.
|
||||||
|
/// </summary>
|
||||||
|
Commodity
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,11 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IFuturesSymbolRestClient : ISharedClient
|
public interface IFuturesSymbolRestClient : ISharedClient
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the futures symbol catalog. Only available if <see cref="GetFuturesSymbolsAsync(GetSymbolsRequest, CancellationToken)"/> has been called previously.
|
||||||
|
/// </summary>
|
||||||
|
SharedSymbolCatalog? FuturesSymbolCatalog { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Futures symbol request options.<br />
|
/// Futures symbol request options.<br />
|
||||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISpotSymbolRestClient : ISharedClient
|
public interface ISpotSymbolRestClient : ISharedClient
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the spot symbol catalog. Only available if <see cref="GetSpotSymbolsAsync(GetSymbolsRequest, CancellationToken)"/> has been called previously.
|
||||||
|
/// </summary>
|
||||||
|
SharedSymbolCatalog? SpotSymbolCatalog { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Spot symbols request options.<br />
|
/// Spot symbols request options.<br />
|
||||||
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||||
|
|||||||
@@ -68,9 +68,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
return ArgumentError.Invalid("TradingMode", $"TradingMode.{tradingMode} is not supported, supported types: {string.Join(", ", supportedTradingModes)}");
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{tradingMode} is not supported, supported types: {string.Join(", ", supportedTradingModes)}");
|
||||||
|
|
||||||
foreach (var param in RequiredExchangeParameters)
|
foreach (var param in RequiredExchangeParameters)
|
||||||
{
|
{
|
||||||
if (param.Names!.All(x => ExchangeParameters.HasValue(exchangeParameters, Exchange, x, param.ValueType) != true))
|
if (param.Names!.All(x => ExchangeParameters.HasValue(exchangeParameters, Exchange, x, param.ValueType) != true))
|
||||||
return ArgumentError.Invalid(string.Join("/", param.Names!), $"One of exchange parameters `{string.Join(", ", param.Names!)}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
{
|
||||||
|
if (param.Names.Length == 1)
|
||||||
|
return ArgumentError.Invalid(string.Join("/", param.Names!), $"Exchange parameter `{param.Names[0]}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
||||||
|
else
|
||||||
|
return ArgumentError.Invalid(string.Join("/", param.Names!), $"One of exchange parameters `{string.Join(", ", param.Names!)}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -149,7 +154,12 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
foreach (var param in RequiredOptionalParameters)
|
foreach (var param in RequiredOptionalParameters)
|
||||||
{
|
{
|
||||||
if (param.Names!.All(x => _requestProperties.Single(p => p.Name == x).GetValue(request, null) == null))
|
if (param.Names!.All(x => _requestProperties.Single(p => p.Name == x).GetValue(request, null) == null))
|
||||||
return ArgumentError.Invalid(string.Join("/", param.Names!), $"One of optional parameters `{string.Join(", ", param.Names!)}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
{
|
||||||
|
if (param.Names.Length == 1)
|
||||||
|
return ArgumentError.Invalid(string.Join("/", param.Names!), $"Optional parameter `{param.Names[0]}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
||||||
|
else
|
||||||
|
return ArgumentError.Invalid(string.Join("/", param.Names!), $"One of optional parameters `{string.Join(", ", param.Names!)}` for exchange `{Exchange}` should be provided. Example: {param.ExampleValue}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request is SharedSymbolRequest symbolsRequest)
|
if (request is SharedSymbolRequest symbolsRequest)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -15,5 +16,43 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
public GetFuturesSymbolsOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesSymbolRestClient.GetFuturesSymbolsAsync))
|
public GetFuturesSymbolsOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesSymbolRestClient.GetFuturesSymbolsAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(GetSymbolsRequest request, IFuturesSymbolRestClient client)
|
||||||
|
{
|
||||||
|
if (request.BaseAssetType != null && request.BaseAssetSubType != null)
|
||||||
|
{
|
||||||
|
var error = ValidateAssetTypeCombination(request.BaseAssetType.Value, request.BaseAssetSubType.Value);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.QuoteAssetType != null && request.QuoteAssetSubType != null)
|
||||||
|
{
|
||||||
|
var error = ValidateAssetTypeCombination(request.QuoteAssetType.Value, request.QuoteAssetSubType.Value);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Error? ValidateAssetTypeCombination(SharedAssetType type, SharedAssetSubType subType)
|
||||||
|
{
|
||||||
|
if (type == SharedAssetType.Crypto
|
||||||
|
&& (subType == SharedAssetSubType.Commodity
|
||||||
|
|| (subType == SharedAssetSubType.Equity)))
|
||||||
|
{
|
||||||
|
return ArgumentError.Invalid(nameof(GetSymbolsRequest.BaseAssetSubType), $"Invalid combination of asset type filters: {type} and {subType}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == SharedAssetType.TradFi && subType == SharedAssetSubType.StableCoin)
|
||||||
|
return ArgumentError.Invalid(nameof(GetSymbolsRequest.BaseAssetSubType), $"Invalid combination of asset type filters: {type} and {subType}");
|
||||||
|
|
||||||
|
if (type == SharedAssetType.Fiat)
|
||||||
|
return ArgumentError.Invalid(nameof(GetSymbolsRequest.BaseAssetSubType), $"Invalid combination of asset type filters: {type} and {subType}");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -15,5 +16,44 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
public GetSpotSymbolsOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotSymbolRestClient.GetSpotSymbolsAsync))
|
public GetSpotSymbolsOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotSymbolRestClient.GetSpotSymbolsAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(GetSymbolsRequest request, ISpotSymbolRestClient client)
|
||||||
|
{
|
||||||
|
if (request.BaseAssetType != null && request.BaseAssetSubType != null)
|
||||||
|
{
|
||||||
|
var error = ValidateAssetTypeCombination(request.BaseAssetType.Value, request.BaseAssetSubType.Value);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.QuoteAssetType != null && request.QuoteAssetSubType != null)
|
||||||
|
{
|
||||||
|
var error = ValidateAssetTypeCombination(request.QuoteAssetType.Value, request.QuoteAssetSubType.Value);
|
||||||
|
if (error != null)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Error? ValidateAssetTypeCombination(SharedAssetType type, SharedAssetSubType subType)
|
||||||
|
{
|
||||||
|
if (type == SharedAssetType.Crypto
|
||||||
|
&& (subType == SharedAssetSubType.Commodity
|
||||||
|
|| (subType == SharedAssetSubType.Equity)))
|
||||||
|
{
|
||||||
|
return ArgumentError.Invalid(nameof(GetSymbolsRequest.BaseAssetSubType), $"Invalid combination of asset type filters: {type} and {subType}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == SharedAssetType.TradFi && subType == SharedAssetSubType.StableCoin)
|
||||||
|
return ArgumentError.Invalid(nameof(GetSymbolsRequest.BaseAssetSubType), $"Invalid combination of asset type filters: {type} and {subType}");
|
||||||
|
|
||||||
|
if (type == SharedAssetType.Fiat)
|
||||||
|
return ArgumentError.Invalid(nameof(GetSymbolsRequest.BaseAssetSubType), $"Invalid combination of asset type filters: {type} and {subType}");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,44 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public record GetSymbolsRequest : SharedRequest
|
public record GetSymbolsRequest : SharedRequest
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base asset type filter
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetType? BaseAssetType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Base asset subtype filter
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetSubType? BaseAssetSubType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Quote asset type filter
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetType? QuoteAssetType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Quote asset subtype filter
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetSubType? QuoteAssetSubType { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tradingMode">Trading mode filter</param>
|
/// <param name="tradingMode">Trading mode filter</param>
|
||||||
|
/// <param name="baseAssetType">Filter by base asset type</param>
|
||||||
|
/// <param name="baseAssetSubType">Filter by base asset subtype</param>
|
||||||
|
/// <param name="quoteAssetType">Filter by quote asset type</param>
|
||||||
|
/// <param name="quoteAssetSubType">Filter by quote asset subtype</param>
|
||||||
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
/// <param name="exchangeParameters">Exchange specific parameters</param>
|
||||||
public GetSymbolsRequest(TradingMode? tradingMode = null, ExchangeParameters? exchangeParameters = null) : base(tradingMode, exchangeParameters)
|
public GetSymbolsRequest(
|
||||||
|
TradingMode? tradingMode = null,
|
||||||
|
SharedAssetType? baseAssetType = null,
|
||||||
|
SharedAssetSubType? baseAssetSubType = null,
|
||||||
|
SharedAssetType? quoteAssetType = null,
|
||||||
|
SharedAssetSubType? quoteAssetSubType = null,
|
||||||
|
ExchangeParameters? exchangeParameters = null) : base(tradingMode, exchangeParameters)
|
||||||
{
|
{
|
||||||
|
BaseAssetType = baseAssetType;
|
||||||
|
BaseAssetSubType = baseAssetSubType;
|
||||||
|
QuoteAssetType = quoteAssetType;
|
||||||
|
QuoteAssetSubType = quoteAssetSubType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Symbol and asset catalog for a shared client
|
||||||
|
/// </summary>
|
||||||
|
public class SharedSymbolCatalog
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exchange name
|
||||||
|
/// </summary>
|
||||||
|
public string Exchange { get; set; } = string.Empty;
|
||||||
|
/// <summary>
|
||||||
|
/// Assets supported
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyDictionary<string, SharedAssetInfo> Assets { get; set; } = new Dictionary<string, SharedAssetInfo>();
|
||||||
|
/// <summary>
|
||||||
|
/// Symbols supported
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyDictionary<string, SharedSpotSymbol> Symbols { get; set; } = new Dictionary<string, SharedSpotSymbol>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asset info
|
||||||
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
|
public class SharedAssetInfo
|
||||||
|
{
|
||||||
|
private string DebugView => $"{Name} - {Type}{(SubType == null ? "": $" {SubType}")}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asset name
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Asset type
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetType Type { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Asset sub type
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetSubType? SubType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetInfo(string name, SharedAssetType type, SharedAssetSubType? subType)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Type = type;
|
||||||
|
SubType = subType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Asset info
|
/// Asset info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Name,nq} - {Networks.Length} network(s)")]
|
||||||
public record SharedAsset
|
public record SharedAsset
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -32,6 +34,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Asset network info
|
/// Asset network info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Name,nq}")]
|
||||||
public record SharedAssetNetwork
|
public record SharedAssetNetwork
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Balance info
|
/// Balance info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Available} {Asset, nq}")]
|
||||||
public record SharedBalance
|
public record SharedBalance
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Book ticker
|
/// Book ticker
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Symbol,nq} - {BestBidPrice} / {BestAskPrice}")]
|
||||||
public record SharedBookTicker : SharedSymbolModel
|
public record SharedBookTicker : SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deposit info
|
/// Deposit info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("[{Timestamp}] {Quantity} {Asset,nq}")]
|
||||||
public record SharedDeposit
|
public record SharedDeposit
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deposit address info
|
/// Deposit address info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Asset,nq} - {Address,nq}")]
|
||||||
public record SharedDepositAddress
|
public record SharedDepositAddress
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Trading fee info
|
/// Trading fee info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{MakerFee} / {TakerFee}")]
|
||||||
public record SharedFee
|
public record SharedFee
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Funding rate
|
/// Funding rate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("[{Timestamp}] {FundingRate}")]
|
||||||
public record SharedFundingRate
|
public record SharedFundingRate
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Mark/index price kline
|
/// Mark/index price kline
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("[{OpenTime}] O: {OpenPrice} H: {HighPrice} L: {LowPrice} C: {ClosePrice}")]
|
||||||
public record SharedFuturesKline : SharedSymbolModel
|
public record SharedFuturesKline : SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Futures order info
|
/// Futures order info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
public record SharedFuturesOrder : SharedSymbolModel
|
public record SharedFuturesOrder : SharedSymbolModel
|
||||||
{
|
{
|
||||||
|
private string DebugView =>
|
||||||
|
$"[{CreateTime}] {OrderId} {(PositionSide != null ? $"{PositionSide} " : "")}{Symbol} - " +
|
||||||
|
$"{OrderType} {Side} {OrderQuantity}{(OrderPrice != null ? " @ " + OrderPrice : "")}, " +
|
||||||
|
$"{Status}{(QuantityFilled != null && Status != SharedOrderStatus.Canceled ? $" {QuantityFilled}" : "")}{(AveragePrice != null ? " @ " + AveragePrice : "")}";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id of the order
|
/// Id of the order
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -47,10 +54,18 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// Order price
|
/// Order price
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal? OrderPrice { get; set; }
|
public decimal? OrderPrice { get; set; }
|
||||||
|
private decimal? _averagePrice;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Average price
|
/// Average fill price
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal? AveragePrice { get; set; }
|
public decimal? AveragePrice
|
||||||
|
{
|
||||||
|
get => _averagePrice > 0 ? _averagePrice
|
||||||
|
: (QuantityFilled?.QuantityInBaseAsset > 0 && QuantityFilled?.QuantityInQuoteAsset > 0
|
||||||
|
? QuantityFilled.QuantityInQuoteAsset / QuantityFilled.QuantityInBaseAsset
|
||||||
|
: null);
|
||||||
|
set => _averagePrice = value;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Client order id
|
/// Client order id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Futures symbol info
|
/// Futures symbol info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
public record SharedFuturesSymbol : SharedSpotSymbol
|
public record SharedFuturesSymbol : SharedSpotSymbol
|
||||||
{
|
{
|
||||||
|
private string DebugView => $"{TradingMode} {(DisplayName ?? Name)} - {BaseAssetType}{(BaseAssetSubType == null ? "" : " " + BaseAssetSubType)}{(DeliveryTime != null ? $" Delivery: {DeliveryTime:yyyy-MM-dd}": "")}";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The size of a single contract
|
/// The size of a single contract
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Futures ticker info
|
/// Futures ticker info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Symbol,nq} High: {HighPrice}, Low: {LowPrice}, Last: {LastPrice}, Change: {ChangePercentage}%")]
|
||||||
public record SharedFuturesTicker: SharedSymbolModel
|
public record SharedFuturesTicker: SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Kline info
|
/// Kline info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("[{OpenTime}] O: {OpenPrice} H: {HighPrice} L: {LowPrice} C: {ClosePrice} V: {Volume}")]
|
||||||
public record SharedKline : SharedSymbolModel
|
public record SharedKline : SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Position info
|
/// Position info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Symbol,nq} {PositionSide}: {PositionSize} {AverageOpenPrice}")]
|
||||||
public record SharedPosition : SharedSymbolModel
|
public record SharedPosition : SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Position history
|
/// Position history
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("[{Timestamp}] {Symbol,nq} {PositionSide}: {RealizedPnl}")]
|
||||||
public record SharedPositionHistory : SharedSymbolModel
|
public record SharedPositionHistory : SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Spot order info
|
/// Spot order info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
public record SharedSpotOrder : SharedSymbolModel
|
public record SharedSpotOrder : SharedSymbolModel
|
||||||
{
|
{
|
||||||
|
private string DebugView =>
|
||||||
|
$"[{CreateTime}] {OrderId} {Symbol} - " +
|
||||||
|
$"{OrderType} {Side} {OrderQuantity}{(OrderPrice != null ? " @ " + OrderPrice : "")}, " +
|
||||||
|
$"{Status}{(QuantityFilled != null && Status != SharedOrderStatus.Canceled ? $" {QuantityFilled}" : "")}{(AveragePrice != null ? " @ " + AveragePrice : "")}";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The id of the order
|
/// The id of the order
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -39,10 +46,18 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// Order price
|
/// Order price
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal? OrderPrice { get; set; }
|
public decimal? OrderPrice { get; set; }
|
||||||
|
private decimal? _averagePrice;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Average fill price
|
/// Average fill price
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal? AveragePrice { get; set; }
|
public decimal? AveragePrice
|
||||||
|
{
|
||||||
|
get => _averagePrice > 0 ? _averagePrice
|
||||||
|
: (QuantityFilled?.QuantityInBaseAsset > 0 && QuantityFilled?.QuantityInQuoteAsset > 0
|
||||||
|
? QuantityFilled.QuantityInQuoteAsset / QuantityFilled.QuantityInBaseAsset
|
||||||
|
: null);
|
||||||
|
set => _averagePrice = value;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Client order id
|
/// Client order id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Symbol info
|
/// Symbol info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
public record SharedSpotSymbol
|
public record SharedSpotSymbol
|
||||||
{
|
{
|
||||||
|
private string DebugView => $"{TradingMode} {(DisplayName ?? Name)} - {BaseAssetType} {BaseAssetSubType}";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The trading mode of the symbol
|
/// The trading mode of the symbol
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -22,6 +29,10 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// The display name of the symbol
|
||||||
|
/// </summary>
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
/// <summary>
|
||||||
/// Minimal quantity of an order in the base asset
|
/// Minimal quantity of an order in the base asset
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal? MinTradeQuantity { get; set; }
|
public decimal? MinTradeQuantity { get; set; }
|
||||||
@@ -57,6 +68,22 @@
|
|||||||
/// Whether the symbol is currently available for trading
|
/// Whether the symbol is currently available for trading
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Trading { get; set; }
|
public bool Trading { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Base asset type
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetType BaseAssetType { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Base asset sub type
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetSubType? BaseAssetSubType { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Quote asset type
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetType QuoteAssetType { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Quote asset sub type
|
||||||
|
/// </summary>
|
||||||
|
public SharedAssetSubType? QuoteAssetSubType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ticker info
|
/// Ticker info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Symbol,nq} High: {HighPrice}, Low: {LowPrice}, Last: {LastPrice}, Change: {ChangePercentage}%")]
|
||||||
public record SharedSpotTicker: SharedSymbolModel
|
public record SharedSpotTicker: SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Public trade info
|
/// Public trade info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("[{Timestamp}] {Symbol,nq} {Side.ToString(),nq} {Quantity} @ {Price}")]
|
||||||
public record SharedTrade : SharedSymbolModel
|
public record SharedTrade : SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A user trade
|
/// A user trade
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("[{Timestamp}] {Id,nq} {Symbol,nq} {Side.ToString(),nq} {Quantity} @ {Price}")]
|
||||||
public record SharedUserTrade : SharedSymbolModel
|
public record SharedUserTrade : SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A withdrawal record
|
/// A withdrawal record
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("[{Timestamp}] {Quantity} {Asset,nq}")]
|
||||||
public record SharedWithdrawal
|
public record SharedWithdrawal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using CryptoExchange.Net.Converters.SystemTextJson;
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using System.Text;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
@@ -35,6 +36,33 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
QuantityInQuoteAsset = quoteAssetQuantity;
|
QuantityInQuoteAsset = quoteAssetQuantity;
|
||||||
QuantityInContracts = contractQuantity;
|
QuantityInContracts = contractQuantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder("[");
|
||||||
|
if (QuantityInBaseAsset != null)
|
||||||
|
sb.Append($"{QuantityInBaseAsset} base");
|
||||||
|
|
||||||
|
if (QuantityInQuoteAsset != null)
|
||||||
|
{
|
||||||
|
if (sb.Length > 1)
|
||||||
|
sb.Append(", ");
|
||||||
|
|
||||||
|
sb.Append($"{QuantityInQuoteAsset} quote");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QuantityInContracts != null)
|
||||||
|
{
|
||||||
|
if (sb.Length > 1)
|
||||||
|
sb.Append(", ");
|
||||||
|
|
||||||
|
sb.Append($"{QuantityInContracts} contracts");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append("]");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -53,6 +81,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedQuantity() : base(null, null, null) { }
|
public SharedQuantity() : base(null, null, null) { }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString() => base.ToString();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specify quantity in base asset
|
/// Specify quantity in base asset
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -123,5 +154,8 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
: base(baseAssetQuantity, quoteAssetQuantity, contractQuantity)
|
: base(baseAssetQuantity, quoteAssetQuantity, contractQuantity)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString() => base.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -176,5 +177,24 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
|
|
||||||
return result.ToArray();
|
return result.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply symbols request filter for asset type and trading mode
|
||||||
|
/// </summary>
|
||||||
|
public static T[] ApplySymbolFilter<T>(T[] symbols, GetSymbolsRequest request) where T : SharedSpotSymbol
|
||||||
|
{
|
||||||
|
IEnumerable<T> resultData = symbols;
|
||||||
|
if (request.TradingMode != null)
|
||||||
|
resultData = resultData.Where(x => x.TradingMode == request.TradingMode);
|
||||||
|
if (request.BaseAssetType != null)
|
||||||
|
resultData = resultData.Where(x => x.BaseAssetType == request.BaseAssetType);
|
||||||
|
if (request.QuoteAssetType != null)
|
||||||
|
resultData = resultData.Where(x => x.QuoteAssetType == request.QuoteAssetType);
|
||||||
|
if (request.BaseAssetSubType != null)
|
||||||
|
resultData = resultData.Where(x => x.BaseAssetSubType == request.BaseAssetSubType);
|
||||||
|
if (request.QuoteAssetSubType != null)
|
||||||
|
resultData = resultData.Where(x => x.QuoteAssetSubType == request.QuoteAssetSubType);
|
||||||
|
return resultData.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Text.Json;
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using CryptoExchange.Net.Converters;
|
using CryptoExchange.Net.Converters;
|
||||||
using CryptoExchange.Net.Converters.SystemTextJson;
|
using CryptoExchange.Net.Converters.SystemTextJson;
|
||||||
|
using CryptoExchange.Net.Testing.Exceptions;
|
||||||
|
|
||||||
#pragma warning disable IL2026
|
#pragma warning disable IL2026
|
||||||
#pragma warning disable IL2070
|
#pragma warning disable IL2070
|
||||||
@@ -18,7 +19,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
internal class SystemTextJsonComparer
|
internal class SystemTextJsonComparer
|
||||||
{
|
{
|
||||||
internal static void CompareData(
|
internal static List<Exception> CompareData(
|
||||||
string method,
|
string method,
|
||||||
object? resultData,
|
object? resultData,
|
||||||
string json,
|
string json,
|
||||||
@@ -26,6 +27,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
List<string>? ignoreProperties = null,
|
List<string>? ignoreProperties = null,
|
||||||
bool userSingleArrayItem = false)
|
bool userSingleArrayItem = false)
|
||||||
{
|
{
|
||||||
|
var outputExceptions = new List<Exception>();
|
||||||
var jsonObject = JsonDocument.Parse(json).RootElement;
|
var jsonObject = JsonDocument.Parse(json).RootElement;
|
||||||
if (nestedJsonProperty != null)
|
if (nestedJsonProperty != null)
|
||||||
{
|
{
|
||||||
@@ -46,10 +48,10 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
if (resultData == null)
|
if (resultData == null)
|
||||||
{
|
{
|
||||||
if (jsonObject.ValueKind == JsonValueKind.Null)
|
if (jsonObject.ValueKind == JsonValueKind.Null)
|
||||||
return;
|
return outputExceptions;
|
||||||
|
|
||||||
if (jsonObject.ValueKind == JsonValueKind.Object && jsonObject.GetPropertyCount() == 0)
|
if (jsonObject.ValueKind == JsonValueKind.Object && jsonObject.GetPropertyCount() == 0)
|
||||||
return;
|
return outputExceptions;
|
||||||
|
|
||||||
throw new Exception("ResultData null");
|
throw new Exception("ResultData null");
|
||||||
}
|
}
|
||||||
@@ -61,13 +63,16 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
foreach (var dictProp in jObj.EnumerateObject())
|
foreach (var dictProp in jObj.EnumerateObject())
|
||||||
{
|
{
|
||||||
if (!dict.Contains(dictProp.Name))
|
if (!dict.Contains(dictProp.Name))
|
||||||
throw new Exception($"{method}: Dictionary has no value for {dictProp.Name} while input json `{dictProp.Name}` has value {dictProp.Value}");
|
{
|
||||||
|
outputExceptions.Add(new Exception($"{method}: Dictionary has no value for {dictProp.Name} while input json `{dictProp.Name}` has value {dictProp.Value}"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (dictProp.Value.ValueKind == JsonValueKind.Object)
|
if (dictProp.Value.ValueKind == JsonValueKind.Object)
|
||||||
{
|
{
|
||||||
// TODO Some additional checking for objects
|
// TODO Some additional checking for objects
|
||||||
foreach (var prop in dictProp.Value.EnumerateObject())
|
foreach (var prop in dictProp.Value.EnumerateObject())
|
||||||
CheckObject(method, prop, dict[dictProp.Name]!, ignoreProperties!);
|
CheckObject(method, prop, dict[dictProp.Name]!, ignoreProperties!, outputExceptions);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -77,7 +82,8 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Property value not correct
|
// Property value not correct
|
||||||
throw new Exception($"{method}: Dictionary entry `{dictProp.Name}` has no value while input json has value {dictProp.Value}");
|
outputExceptions.Add(new Exception($"{method}: Dictionary entry `{dictProp.Name}` has no value while input json has value {dictProp.Value}"));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,7 +105,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
if (ignoreProperties?.Contains(subProp.Name) == true)
|
if (ignoreProperties?.Contains(subProp.Name) == true)
|
||||||
continue;
|
continue;
|
||||||
CheckObject(method, subProp, enumerator.Current, ignoreProperties!);
|
CheckObject(method, subProp, enumerator.Current, ignoreProperties!, outputExceptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (jObj.ValueKind == JsonValueKind.Array)
|
else if (jObj.ValueKind == JsonValueKind.Array)
|
||||||
@@ -121,7 +127,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
var arrayProp = resultProps.Where(p => p.Item2 != null).FirstOrDefault(p => p.Item2!.Index == i).p;
|
var arrayProp = resultProps.Where(p => p.Item2 != null).FirstOrDefault(p => p.Item2!.Index == i).p;
|
||||||
if (arrayProp != null)
|
if (arrayProp != null)
|
||||||
CheckPropertyValue(method, item.Value, arrayProp.GetValue(resultObj), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!);
|
CheckPropertyValue(method, item.Value, arrayProp.GetValue(resultObj), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!, outputExceptions);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +135,10 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
var value = enumerator.Current;
|
var value = enumerator.Current;
|
||||||
if (value == default && jObj.ValueKind != JsonValueKind.Null)
|
if (value == default && jObj.ValueKind != JsonValueKind.Null)
|
||||||
throw new Exception($"{method}: Array has no value while input json array has value {jObj}");
|
{
|
||||||
|
outputExceptions.Add(new Exception($"{method}: Array has no value while input json array has value {jObj}"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +150,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
var arrayProp = resultProps.Where(p => p.Item2 != null).FirstOrDefault(p => p.Item2!.Index == i).p;
|
var arrayProp = resultProps.Where(p => p.Item2 != null).FirstOrDefault(p => p.Item2!.Index == i).p;
|
||||||
if (arrayProp != null)
|
if (arrayProp != null)
|
||||||
CheckPropertyValue(method, item, arrayProp.GetValue(resultData), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!);
|
CheckPropertyValue(method, item, arrayProp.GetValue(resultData), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!, outputExceptions);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +164,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
if (ignoreProperties?.Contains(item.Name) == true)
|
if (ignoreProperties?.Contains(item.Name) == true)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CheckObject(method, item, resultData, ignoreProperties);
|
CheckObject(method, item, resultData, ignoreProperties, outputExceptions);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,9 +174,10 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
}
|
}
|
||||||
|
|
||||||
Debug.WriteLine($"Successfully validated {method}");
|
Debug.WriteLine($"Successfully validated {method}");
|
||||||
|
return outputExceptions.Distinct().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckObject(string method, JsonProperty prop, object obj, List<string>? ignoreProperties)
|
private static void CheckObject(string method, JsonProperty prop, object obj, List<string>? ignoreProperties, List<Exception> outputExceptions)
|
||||||
{
|
{
|
||||||
var publicProperties = obj.GetType().GetProperties(
|
var publicProperties = obj.GetType().GetProperties(
|
||||||
System.Reflection.BindingFlags.Public
|
System.Reflection.BindingFlags.Public
|
||||||
@@ -190,8 +200,11 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
property ??= resultProperties.SingleOrDefault(p => p.p.Name == prop.Name).p;
|
property ??= resultProperties.SingleOrDefault(p => p.p.Name == prop.Name).p;
|
||||||
|
|
||||||
if (property is null)
|
if (property is null)
|
||||||
|
{
|
||||||
// Property not found
|
// Property not found
|
||||||
throw new Exception($"{method}: Missing property `{prop.Name}` on `{obj.GetType().Name}`");
|
outputExceptions.Add(new MissingPropertyException(method, obj.GetType().Name, prop.Name, prop.Value.ValueKind == JsonValueKind.Null ? "[null]" : prop.Value.ToString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var getMethod = property.GetGetMethod();
|
var getMethod = property.GetGetMethod();
|
||||||
if (getMethod is null)
|
if (getMethod is null)
|
||||||
@@ -199,10 +212,18 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var propertyValue = property.GetValue(obj);
|
var propertyValue = property.GetValue(obj);
|
||||||
CheckPropertyValue(method, prop.Value, propertyValue, property.PropertyType, property.Name, prop.Name, ignoreProperties);
|
CheckPropertyValue(method, prop.Value, propertyValue, property.PropertyType, property.Name, prop.Name, ignoreProperties, outputExceptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckPropertyValue(string method, JsonElement propValue, object? propertyValue, Type propertyType, string? propertyName = null, string? propName = null, List<string>? ignoreProperties = null)
|
private static void CheckPropertyValue(
|
||||||
|
string method,
|
||||||
|
JsonElement propValue,
|
||||||
|
object? propertyValue,
|
||||||
|
Type propertyType,
|
||||||
|
string? propertyName,
|
||||||
|
string? propName,
|
||||||
|
List<string>? ignoreProperties,
|
||||||
|
List<Exception> outputExceptions)
|
||||||
{
|
{
|
||||||
if (propertyValue == default && propValue.ValueKind != JsonValueKind.Null && !string.IsNullOrEmpty(propValue.ToString()))
|
if (propertyValue == default && propValue.ValueKind != JsonValueKind.Null && !string.IsNullOrEmpty(propValue.ToString()))
|
||||||
{
|
{
|
||||||
@@ -211,7 +232,10 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
|
|
||||||
// Property value not correct
|
// Property value not correct
|
||||||
if (propValue.ToString() != "0")
|
if (propValue.ToString() != "0")
|
||||||
throw new Exception($"{method}: Property `{propertyName}` has no value while input json `{propName}` has value {propValue}");
|
{
|
||||||
|
outputExceptions.Add(new Exception($"{method}: Property `{propertyName}` has no value while input json `{propName}` has value {propValue}"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((propertyValue == default && (propValue.ValueKind == JsonValueKind.Null || string.IsNullOrEmpty(propValue.ToString()))) || propValue.ToString() == "0")
|
if ((propertyValue == default && (propValue.ValueKind == JsonValueKind.Null || string.IsNullOrEmpty(propValue.ToString()))) || propValue.ToString() == "0")
|
||||||
@@ -223,17 +247,23 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
foreach (var dictProp in propValue.EnumerateObject())
|
foreach (var dictProp in propValue.EnumerateObject())
|
||||||
{
|
{
|
||||||
if (!dict.Contains(dictProp.Name))
|
if (!dict.Contains(dictProp.Name))
|
||||||
throw new Exception($"{method}: Property `{propertyName}` has no value while input json `{propName}` has value {propValue}");
|
{
|
||||||
|
outputExceptions.Add(new Exception($"{method}: Property `{propertyName}` has no value while input json `{propName}` has value {propValue}"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (dictProp.Value.ValueKind == JsonValueKind.Object)
|
if (dictProp.Value.ValueKind == JsonValueKind.Object)
|
||||||
{
|
{
|
||||||
CheckPropertyValue(method, dictProp.Value, dict[dictProp.Name]!, dict[dictProp.Name]!.GetType(), null, null, ignoreProperties);
|
CheckPropertyValue(method, dictProp.Value, dict[dictProp.Name]!, dict[dictProp.Name]!.GetType(), null, null, ignoreProperties, outputExceptions);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (dict[dictProp.Name] == default && dictProp.Value.ValueKind != JsonValueKind.Null)
|
if (dict[dictProp.Name] == default && dictProp.Value.ValueKind != JsonValueKind.Null)
|
||||||
|
{
|
||||||
// Property value not correct
|
// Property value not correct
|
||||||
throw new Exception($"{method}: Dictionary entry `{dictProp.Name}` has no value while input json has value {propValue} for");
|
outputExceptions.Add(new Exception($"{method}: Dictionary entry `{dictProp.Name}` has no value while input json has value {propValue} for"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,7 +293,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
if (ignoreProperties?.Contains(subProp.Name) == true)
|
if (ignoreProperties?.Contains(subProp.Name) == true)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CheckObject(method, subProp, enumerator.Current, ignoreProperties);
|
CheckObject(method, subProp, enumerator.Current, ignoreProperties, outputExceptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (jToken.ValueKind == JsonValueKind.Array)
|
else if (jToken.ValueKind == JsonValueKind.Array)
|
||||||
@@ -281,7 +311,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
var arrayProp = resultProps.Where(p => p.Item2 != null).FirstOrDefault(p => p.Item2!.Index == i).p;
|
var arrayProp = resultProps.Where(p => p.Item2 != null).FirstOrDefault(p => p.Item2!.Index == i).p;
|
||||||
if (arrayProp != null)
|
if (arrayProp != null)
|
||||||
CheckPropertyValue(method, item, arrayProp.GetValue(resultObj), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties);
|
CheckPropertyValue(method, item, arrayProp.GetValue(resultObj), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties, outputExceptions);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -290,9 +320,12 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
var value = enumerator.Current;
|
var value = enumerator.Current;
|
||||||
if (value == default && jToken.ValueKind != JsonValueKind.Null)
|
if (value == default && jToken.ValueKind != JsonValueKind.Null)
|
||||||
throw new Exception($"{method}: Property `{propertyName}` has no value while input json `{propName}` has value {jToken}");
|
{
|
||||||
|
outputExceptions.Add(new Exception($"{method}: Property `{propertyName}` has no value while input json `{propName}` has value {jToken}"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CheckValues(method, propertyName!, propertyType, jToken, value!);
|
CheckValues(method, propertyName!, propertyType, jToken, value!, outputExceptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,7 +340,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
if (ignoreProperties?.Contains(item.Name) == true)
|
if (ignoreProperties?.Contains(item.Name) == true)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CheckObject(method, item, propertyValue, ignoreProperties);
|
CheckObject(method, item, propertyValue, ignoreProperties, outputExceptions);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,7 +361,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
if (ignoreProperties?.Contains(subProp.Name) == true)
|
if (ignoreProperties?.Contains(subProp.Name) == true)
|
||||||
continue;
|
continue;
|
||||||
CheckObject(method, subProp, enumerator.Current, ignoreProperties!);
|
CheckObject(method, subProp, enumerator.Current, ignoreProperties!, outputExceptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (jObj.ValueKind == JsonValueKind.Array)
|
else if (jObj.ValueKind == JsonValueKind.Array)
|
||||||
@@ -346,7 +379,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
var arrayProp = resultProps.SingleOrDefault(p => p.Item2!.Index == i).p;
|
var arrayProp = resultProps.SingleOrDefault(p => p.Item2!.Index == i).p;
|
||||||
if (arrayProp != null)
|
if (arrayProp != null)
|
||||||
CheckPropertyValue(method, item, arrayProp.GetValue(resultObj), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!);
|
CheckPropertyValue(method, item, arrayProp.GetValue(resultObj), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!, outputExceptions);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,7 +387,10 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
var value = enumerator.Current;
|
var value = enumerator.Current;
|
||||||
if (value == default && jObj.ValueKind != JsonValueKind.Null)
|
if (value == default && jObj.ValueKind != JsonValueKind.Null)
|
||||||
throw new Exception($"{method}: Array has no value while input json array has value {jObj}");
|
{
|
||||||
|
outputExceptions.Add(new Exception($"{method}: Array has no value while input json array has value {jObj}"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,19 +402,19 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
{
|
{
|
||||||
var arrayProp = resultProps.Where(p => p.Item2 != null).FirstOrDefault(p => p.Item2!.Index == i).p;
|
var arrayProp = resultProps.Where(p => p.Item2 != null).FirstOrDefault(p => p.Item2!.Index == i).p;
|
||||||
if (arrayProp != null)
|
if (arrayProp != null)
|
||||||
CheckPropertyValue(method, item, arrayProp.GetValue(propertyValue), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!);
|
CheckPropertyValue(method, item, arrayProp.GetValue(propertyValue), arrayProp.PropertyType, arrayProp.Name, "Array index " + i, ignoreProperties!, outputExceptions);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CheckValues(method, propertyName!, propertyType, propValue, propertyValue);
|
CheckValues(method, propertyName!, propertyType, propValue, propertyValue, outputExceptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckValues(string method, string property, Type propertyType, JsonElement jsonValue, object objectValue)
|
private static void CheckValues(string method, string property, Type propertyType, JsonElement jsonValue, object objectValue, List<Exception> outputExceptions)
|
||||||
{
|
{
|
||||||
if (jsonValue.ValueKind == JsonValueKind.String)
|
if (jsonValue.ValueKind == JsonValueKind.String)
|
||||||
{
|
{
|
||||||
@@ -386,19 +422,19 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
if (objectValue is decimal dec)
|
if (objectValue is decimal dec)
|
||||||
{
|
{
|
||||||
if (ExchangeHelpers.ParseDecimal(stringValue!) != dec)
|
if (ExchangeHelpers.ParseDecimal(stringValue!) != dec)
|
||||||
throw new Exception($"{method}: {property} not equal: {stringValue} vs {dec}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {stringValue} vs {dec}") );
|
||||||
}
|
}
|
||||||
else if (objectValue is DateTime time)
|
else if (objectValue is DateTime time)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(stringValue) && time != DateTimeConverter.ParseFromString(stringValue!, null))
|
if (!string.IsNullOrEmpty(stringValue) && time != DateTimeConverter.ParseFromString(stringValue!, null))
|
||||||
throw new Exception($"{method}: {property} not equal: {stringValue} vs {time}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {stringValue} vs {time}"));
|
||||||
}
|
}
|
||||||
else if (objectValue is bool bl)
|
else if (objectValue is bool bl)
|
||||||
{
|
{
|
||||||
if (bl && (stringValue != "1" && stringValue != "true" && stringValue != "True" && stringValue != "yes" && stringValue != "YES" && stringValue != "enabled"))
|
if (bl && (stringValue != "1" && stringValue != "true" && stringValue != "True" && stringValue != "yes" && stringValue != "YES" && stringValue != "enabled"))
|
||||||
throw new Exception($"{method}: {property} not equal: {stringValue} vs {bl}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {stringValue} vs {bl}"));
|
||||||
if (!bl && (stringValue != "0" && stringValue != "-1" && stringValue != "false" && stringValue != "False" && stringValue != "no" && stringValue != "NO" && stringValue != "disabled"))
|
if (!bl && (stringValue != "0" && stringValue != "-1" && stringValue != "false" && stringValue != "False" && stringValue != "no" && stringValue != "NO" && stringValue != "disabled"))
|
||||||
throw new Exception($"{method}: {property} not equal: {stringValue} vs {bl}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {stringValue} vs {bl}") );
|
||||||
}
|
}
|
||||||
else if (propertyType.IsEnum || Nullable.GetUnderlyingType(propertyType)?.IsEnum == true)
|
else if (propertyType.IsEnum || Nullable.GetUnderlyingType(propertyType)?.IsEnum == true)
|
||||||
{
|
{
|
||||||
@@ -406,7 +442,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
}
|
}
|
||||||
else if (!stringValue!.Equals(Convert.ToString(objectValue, CultureInfo.InvariantCulture), StringComparison.InvariantCultureIgnoreCase))
|
else if (!stringValue!.Equals(Convert.ToString(objectValue, CultureInfo.InvariantCulture), StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
throw new Exception($"{method}: {property} not equal: {stringValue} vs {objectValue}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {stringValue} vs {objectValue}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (jsonValue.ValueKind == JsonValueKind.Number)
|
else if (jsonValue.ValueKind == JsonValueKind.Number)
|
||||||
@@ -415,7 +451,7 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
if (objectValue is DateTime time)
|
if (objectValue is DateTime time)
|
||||||
{
|
{
|
||||||
if (time != DateTimeConverter.ParseFromDecimal(value))
|
if (time != DateTimeConverter.ParseFromDecimal(value))
|
||||||
throw new Exception($"{method}: {property} not equal: {DateTimeConverter.ParseFromDouble((double)value!)} vs {time}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {DateTimeConverter.ParseFromDouble((double)value!)} vs {time}"));
|
||||||
}
|
}
|
||||||
else if (propertyType.IsEnum || Nullable.GetUnderlyingType(propertyType)?.IsEnum == true)
|
else if (propertyType.IsEnum || Nullable.GetUnderlyingType(propertyType)?.IsEnum == true)
|
||||||
{
|
{
|
||||||
@@ -424,27 +460,27 @@ namespace CryptoExchange.Net.Testing.Comparers
|
|||||||
else if(objectValue is decimal dec)
|
else if(objectValue is decimal dec)
|
||||||
{
|
{
|
||||||
if (dec != value)
|
if (dec != value)
|
||||||
throw new Exception($"{method}: {property} not equal: {dec} vs {value}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {dec} vs {value}"));
|
||||||
}
|
}
|
||||||
else if (objectValue is double dbl)
|
else if (objectValue is double dbl)
|
||||||
{
|
{
|
||||||
if ((decimal)dbl != value)
|
if ((decimal)dbl != value)
|
||||||
throw new Exception($"{method}: {property} not equal: {dbl} vs {value}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {dbl} vs {value}"));
|
||||||
}
|
}
|
||||||
else if(objectValue is string objStr)
|
else if(objectValue is string objStr)
|
||||||
{
|
{
|
||||||
if (objStr != value.ToString())
|
if (objStr != value.ToString())
|
||||||
throw new Exception($"{method}: {property} not equal: {value} vs {objStr}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {value} vs {objStr}"));
|
||||||
}
|
}
|
||||||
else if (value != Convert.ToInt64(objectValue, CultureInfo.InvariantCulture))
|
else if (value != Convert.ToInt64(objectValue, CultureInfo.InvariantCulture))
|
||||||
{
|
{
|
||||||
throw new Exception($"{method}: {property} not equal: {value} vs {Convert.ToInt64(objectValue)}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {value} vs {Convert.ToInt64(objectValue)}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (jsonValue.ValueKind == JsonValueKind.True || jsonValue.ValueKind == JsonValueKind.False)
|
else if (jsonValue.ValueKind == JsonValueKind.True || jsonValue.ValueKind == JsonValueKind.False)
|
||||||
{
|
{
|
||||||
if (jsonValue.GetBoolean() != (bool)objectValue)
|
if (jsonValue.GetBoolean() != (bool)objectValue)
|
||||||
throw new Exception($"{method}: {property} not equal: {jsonValue.GetBoolean()} vs {(bool)objectValue}");
|
outputExceptions.Add(new Exception($"{method}: {property} not equal: {jsonValue.GetBoolean()} vs {(bool)objectValue}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.Testing.Exceptions
|
||||||
|
{
|
||||||
|
internal class MissingPropertyException : Exception
|
||||||
|
{
|
||||||
|
public MissingPropertyException(string method, string objName, string propName, string value)
|
||||||
|
: base($"{method}: Missing property `{propName}` on `{objName}`, value: {value.Substring(0, Math.Min(50, value.Length))}")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using CryptoExchange.Net.Interfaces;
|
using CryptoExchange.Net.Interfaces;
|
||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using CryptoExchange.Net.Testing.Comparers;
|
using CryptoExchange.Net.Testing.Comparers;
|
||||||
|
using CryptoExchange.Net.Testing.Exceptions;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -55,6 +57,26 @@ namespace CryptoExchange.Net.Testing
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute a REST endpoint call and check for any errors or warnings. Also checks for missing fields in the response mapping
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="warningExceptionsHolder">List for outputting warnings</param>
|
||||||
|
/// <param name="expression">The call expression</param>
|
||||||
|
/// <param name="authRequest">Whether this is an authenticated request</param>
|
||||||
|
/// <param name="compareNestedProperty">Nested property to use for comparing when checking for missing fields</param>
|
||||||
|
/// <param name="ignoreProperties">Properties to ignore when checking for missing fields</param>
|
||||||
|
/// <param name="useSingleArrayItem">Whether to use the single array item as compare when checking for missing fields</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task RunAndCheckResult<T>(
|
||||||
|
List<Exception> warningExceptionsHolder,
|
||||||
|
Expression<Func<TClient, Task<HttpResult<T>>>> expression,
|
||||||
|
bool authRequest,
|
||||||
|
string? compareNestedProperty = null,
|
||||||
|
List<string>? ignoreProperties = null,
|
||||||
|
bool? useSingleArrayItem = null)
|
||||||
|
=> RunAndCheckResult(expression, authRequest, true, compareNestedProperty, ignoreProperties, useSingleArrayItem, warningExceptionsHolder);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Execute a REST endpoint call and check for any errors or warnings.
|
/// Execute a REST endpoint call and check for any errors or warnings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -65,13 +87,15 @@ namespace CryptoExchange.Net.Testing
|
|||||||
/// <param name="compareNestedProperty">Nested property to use for comparing when checking for missing fields</param>
|
/// <param name="compareNestedProperty">Nested property to use for comparing when checking for missing fields</param>
|
||||||
/// <param name="ignoreProperties">Properties to ignore when checking for missing fields</param>
|
/// <param name="ignoreProperties">Properties to ignore when checking for missing fields</param>
|
||||||
/// <param name="useSingleArrayItem">Whether to use the single array item as compare when checking for missing fields</param>
|
/// <param name="useSingleArrayItem">Whether to use the single array item as compare when checking for missing fields</param>
|
||||||
|
/// <param name="warnings">List for outputting warnings</param>
|
||||||
public async Task RunAndCheckResult<T>(
|
public async Task RunAndCheckResult<T>(
|
||||||
Expression<Func<TClient, Task<HttpResult<T>>>> expression,
|
Expression<Func<TClient, Task<HttpResult<T>>>> expression,
|
||||||
bool authRequest,
|
bool authRequest,
|
||||||
bool checkMissingFields = false,
|
bool checkMissingFields = false,
|
||||||
string? compareNestedProperty = null,
|
string? compareNestedProperty = null,
|
||||||
List<string>? ignoreProperties = null,
|
List<string>? ignoreProperties = null,
|
||||||
bool? useSingleArrayItem = null)
|
bool? useSingleArrayItem = null,
|
||||||
|
List<Exception>? warnings = null)
|
||||||
{
|
{
|
||||||
if (!ShouldRun())
|
if (!ShouldRun())
|
||||||
return;
|
return;
|
||||||
@@ -112,8 +136,20 @@ namespace CryptoExchange.Net.Testing
|
|||||||
if (originalData == null)
|
if (originalData == null)
|
||||||
throw new Exception($"Original data needs to be enabled in the client options to check for missing fields");
|
throw new Exception($"Original data needs to be enabled in the client options to check for missing fields");
|
||||||
|
|
||||||
try {
|
var errors = new List<Exception>();
|
||||||
SystemTextJsonComparer.CompareData(expressionBody.Method.Name, data, originalData, compareNestedProperty, ignoreProperties, useSingleArrayItem ?? false);
|
try
|
||||||
|
{
|
||||||
|
var issues = SystemTextJsonComparer.CompareData(expressionBody.Method.Name, data, originalData, compareNestedProperty, ignoreProperties, useSingleArrayItem ?? false);
|
||||||
|
foreach(var issue in issues)
|
||||||
|
{
|
||||||
|
if (issue is MissingPropertyException && !warnings?.Any(x => x.Message == issue.Message) == true)
|
||||||
|
warnings?.Add(issue);
|
||||||
|
else
|
||||||
|
errors.Add(issue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.Count > 0)
|
||||||
|
throw new AggregateException(errors);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using CryptoExchange.Net.Clients;
|
using CryptoExchange.Net.Clients;
|
||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using CryptoExchange.Net.Testing.Comparers;
|
using CryptoExchange.Net.Testing.Comparers;
|
||||||
|
using CryptoExchange.Net.Testing.Exceptions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
@@ -184,7 +185,9 @@ namespace CryptoExchange.Net.Testing
|
|||||||
{
|
{
|
||||||
// Check response data
|
// Check response data
|
||||||
object responseData = (TActualResponse)result.Data!;
|
object responseData = (TActualResponse)result.Data!;
|
||||||
SystemTextJsonComparer.CompareData(name, responseData, response, nestedJsonProperty ?? _nestedPropertyForCompare, ignoreProperties, useSingleArrayItem);
|
var issues = SystemTextJsonComparer.CompareData(name, responseData, response, nestedJsonProperty ?? _nestedPropertyForCompare, ignoreProperties, useSingleArrayItem);
|
||||||
|
if (issues.Count > 0)
|
||||||
|
throw new AggregateException(issues);
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace.Listeners.Remove(listener);
|
Trace.Listeners.Remove(listener);
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ namespace CryptoExchange.Net.Testing
|
|||||||
else if (line.StartsWith("< "))
|
else if (line.StartsWith("< "))
|
||||||
{
|
{
|
||||||
// Expect a message from server to client
|
// Expect a message from server to client
|
||||||
foreach(var item in replaceValues)
|
foreach (var item in replaceValues)
|
||||||
line = line.Replace(item.Key, item.Value);
|
line = line.Replace(item.Key, item.Value);
|
||||||
|
|
||||||
socket.InvokeMessage(line.Substring(2));
|
socket.InvokeMessage(line.Substring(2));
|
||||||
@@ -175,7 +175,11 @@ namespace CryptoExchange.Net.Testing
|
|||||||
result = responseMapper(task.Result.Data!);
|
result = responseMapper(task.Result.Data!);
|
||||||
|
|
||||||
if (!skipResponseValidation)
|
if (!skipResponseValidation)
|
||||||
SystemTextJsonComparer.CompareData(name, result, compareData, nestedJsonProperty ?? _nestedPropertyForCompare, ignoreProperties, useSingleArrayItem);
|
{
|
||||||
|
var issues = SystemTextJsonComparer.CompareData(name, result, compareData, nestedJsonProperty ?? _nestedPropertyForCompare, ignoreProperties, useSingleArrayItem);
|
||||||
|
if (issues.Count > 0)
|
||||||
|
throw new AggregateException(issues);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -326,7 +326,11 @@ namespace CryptoExchange.Net.Testing
|
|||||||
throw new Exception($"{name} Update send to client did not trigger in update handler");
|
throw new Exception($"{name} Update send to client did not trigger in update handler");
|
||||||
|
|
||||||
if (skipUpdateValidation != true)
|
if (skipUpdateValidation != true)
|
||||||
SystemTextJsonComparer.CompareData(name, update, compareData, nestedJsonProperty ?? _nestedPropertyForCompare, ignoreProperties, useFirstUpdateItem ?? false);
|
{
|
||||||
|
var issues = SystemTextJsonComparer.CompareData(name, update, compareData, nestedJsonProperty ?? _nestedPropertyForCompare, ignoreProperties, useFirstUpdateItem ?? false);
|
||||||
|
if (issues.Count > 0)
|
||||||
|
throw new AggregateException(issues);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace CryptoExchange.Net.Trackers.Klines
|
|||||||
private readonly IKlineRestClient _restClient;
|
private readonly IKlineRestClient _restClient;
|
||||||
private SyncStatus _status;
|
private SyncStatus _status;
|
||||||
private bool _startWithSnapshot;
|
private bool _startWithSnapshot;
|
||||||
|
private ExchangeParameters? _exchangeParameters;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The internal data structure
|
/// The internal data structure
|
||||||
@@ -157,9 +158,11 @@ namespace CryptoExchange.Net.Trackers.Klines
|
|||||||
SharedSymbol symbol,
|
SharedSymbol symbol,
|
||||||
SharedKlineInterval interval,
|
SharedKlineInterval interval,
|
||||||
int? limit = null,
|
int? limit = null,
|
||||||
TimeSpan? period = null)
|
TimeSpan? period = null,
|
||||||
|
ExchangeParameters? exchangeParameters = null)
|
||||||
{
|
{
|
||||||
_logger = logger ?? new NullLogger<KlineTracker>();
|
_logger = logger ?? new NullLogger<KlineTracker>();
|
||||||
|
_exchangeParameters = exchangeParameters;
|
||||||
Symbol = symbol;
|
Symbol = symbol;
|
||||||
SymbolName = socketClient.FormatSymbol(symbol.BaseAsset, symbol.QuoteAsset, symbol.TradingMode, symbol.DeliverTime);
|
SymbolName = socketClient.FormatSymbol(symbol.BaseAsset, symbol.QuoteAsset, symbol.TradingMode, symbol.DeliverTime);
|
||||||
Exchange = restClient.Exchange;
|
Exchange = restClient.Exchange;
|
||||||
@@ -180,7 +183,7 @@ namespace CryptoExchange.Net.Trackers.Klines
|
|||||||
Status = SyncStatus.Syncing;
|
Status = SyncStatus.Syncing;
|
||||||
_logger.KlineTrackerStarting(SymbolName);
|
_logger.KlineTrackerStarting(SymbolName);
|
||||||
|
|
||||||
var subResult = await _socketClient.SubscribeToKlineUpdatesAsync(new SubscribeKlineRequest(Symbol, Interval),
|
var subResult = await _socketClient.SubscribeToKlineUpdatesAsync(new SubscribeKlineRequest(Symbol, Interval, exchangeParameters: _exchangeParameters),
|
||||||
update =>
|
update =>
|
||||||
{
|
{
|
||||||
AddOrUpdate(update.Data);
|
AddOrUpdate(update.Data);
|
||||||
@@ -237,7 +240,7 @@ namespace CryptoExchange.Net.Trackers.Klines
|
|||||||
|
|
||||||
var limit = Math.Min(_restClient.GetKlinesOptions.MaxLimit, Limit ?? 100);
|
var limit = Math.Min(_restClient.GetKlinesOptions.MaxLimit, Limit ?? 100);
|
||||||
|
|
||||||
var request = new GetKlinesRequest(Symbol, Interval, startTime, DateTime.UtcNow, limit: limit);
|
var request = new GetKlinesRequest(Symbol, Interval, startTime, DateTime.UtcNow, limit: limit, exchangeParameters: _exchangeParameters);
|
||||||
var data = new List<SharedKline>();
|
var data = new List<SharedKline>();
|
||||||
await foreach (var result in ExchangeHelpers.ExecutePages(_restClient.GetKlinesAsync, request).ConfigureAwait(false))
|
await foreach (var result in ExchangeHelpers.ExecutePages(_restClient.GetKlinesAsync, request).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace CryptoExchange.Net.Trackers.Trades
|
|||||||
private SyncStatus _status;
|
private SyncStatus _status;
|
||||||
private long _snapshotId;
|
private long _snapshotId;
|
||||||
private bool _startWithSnapshot;
|
private bool _startWithSnapshot;
|
||||||
|
private ExchangeParameters? _exchangeParameters;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The internal data structure
|
/// The internal data structure
|
||||||
@@ -154,12 +155,14 @@ namespace CryptoExchange.Net.Trackers.Trades
|
|||||||
ITradeSocketClient socketClient,
|
ITradeSocketClient socketClient,
|
||||||
SharedSymbol symbol,
|
SharedSymbol symbol,
|
||||||
int? limit = null,
|
int? limit = null,
|
||||||
TimeSpan? period = null)
|
TimeSpan? period = null,
|
||||||
|
ExchangeParameters? exchangeParameters = null)
|
||||||
{
|
{
|
||||||
_logger = logger ?? new NullLogger<TradeTracker>();
|
_logger = logger ?? new NullLogger<TradeTracker>();
|
||||||
_recentRestClient = recentRestClient;
|
_recentRestClient = recentRestClient;
|
||||||
_historyRestClient = historyRestClient;
|
_historyRestClient = historyRestClient;
|
||||||
_socketClient = socketClient;
|
_socketClient = socketClient;
|
||||||
|
_exchangeParameters = exchangeParameters;
|
||||||
Exchange = socketClient.Exchange;
|
Exchange = socketClient.Exchange;
|
||||||
Symbol = symbol;
|
Symbol = symbol;
|
||||||
SymbolName = socketClient.FormatSymbol(symbol.BaseAsset, symbol.QuoteAsset, symbol.TradingMode, symbol.DeliverTime);
|
SymbolName = socketClient.FormatSymbol(symbol.BaseAsset, symbol.QuoteAsset, symbol.TradingMode, symbol.DeliverTime);
|
||||||
@@ -203,7 +206,7 @@ namespace CryptoExchange.Net.Trackers.Trades
|
|||||||
_startWithSnapshot = startWithSnapshot;
|
_startWithSnapshot = startWithSnapshot;
|
||||||
Status = SyncStatus.Syncing;
|
Status = SyncStatus.Syncing;
|
||||||
_logger.TradeTrackerStarting(SymbolName);
|
_logger.TradeTrackerStarting(SymbolName);
|
||||||
var subResult = await _socketClient.SubscribeToTradeUpdatesAsync(new SubscribeTradeRequest(Symbol),
|
var subResult = await _socketClient.SubscribeToTradeUpdatesAsync(new SubscribeTradeRequest(Symbol, exchangeParameters: _exchangeParameters),
|
||||||
update =>
|
update =>
|
||||||
{
|
{
|
||||||
AddData(update.Data);
|
AddData(update.Data);
|
||||||
@@ -257,7 +260,7 @@ namespace CryptoExchange.Net.Trackers.Trades
|
|||||||
if (_historyRestClient != null)
|
if (_historyRestClient != null)
|
||||||
{
|
{
|
||||||
var startTime = Period == null ? DateTime.UtcNow.AddMinutes(-5) : DateTime.UtcNow.Add(-Period.Value);
|
var startTime = Period == null ? DateTime.UtcNow.AddMinutes(-5) : DateTime.UtcNow.Add(-Period.Value);
|
||||||
var request = new GetTradeHistoryRequest(Symbol, startTime, DateTime.UtcNow);
|
var request = new GetTradeHistoryRequest(Symbol, startTime, DateTime.UtcNow, exchangeParameters: _exchangeParameters);
|
||||||
var data = new List<SharedTrade>();
|
var data = new List<SharedTrade>();
|
||||||
await foreach (var result in ExchangeHelpers.ExecutePages(_historyRestClient.GetTradeHistoryAsync, request).ConfigureAwait(false))
|
await foreach (var result in ExchangeHelpers.ExecutePages(_historyRestClient.GetTradeHistoryAsync, request).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
@@ -278,7 +281,7 @@ namespace CryptoExchange.Net.Trackers.Trades
|
|||||||
if (Limit.HasValue)
|
if (Limit.HasValue)
|
||||||
limit = Math.Min(_recentRestClient.GetRecentTradesOptions.MaxLimit, Limit.Value);
|
limit = Math.Min(_recentRestClient.GetRecentTradesOptions.MaxLimit, Limit.Value);
|
||||||
|
|
||||||
var snapshot = await _recentRestClient.GetRecentTradesAsync(new GetRecentTradesRequest(Symbol, limit)).ConfigureAwait(false);
|
var snapshot = await _recentRestClient.GetRecentTradesAsync(new GetRecentTradesRequest(Symbol, limit, exchangeParameters: _exchangeParameters)).ConfigureAwait(false);
|
||||||
if (!snapshot.Success)
|
if (!snapshot.Success)
|
||||||
{
|
{
|
||||||
return CallResult.Fail(snapshot.Error);
|
return CallResult.Fail(snapshot.Error);
|
||||||
|
|||||||
@@ -5,33 +5,34 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Binance.Net" Version="12.13.0" />
|
<PackageReference Include="Binance.Net" Version="13.0.0" />
|
||||||
<PackageReference Include="Bitfinex.Net" Version="10.12.0" />
|
<PackageReference Include="Bitfinex.Net" Version="11.0.0" />
|
||||||
<PackageReference Include="BitMart.Net" Version="3.11.2" />
|
<PackageReference Include="BitMart.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="BloFin.Net" Version="2.11.0" />
|
<PackageReference Include="BloFin.Net" Version="3.0.0" />
|
||||||
<PackageReference Include="Bybit.Net" Version="6.13.0" />
|
<PackageReference Include="Bybit.Net" Version="7.0.0" />
|
||||||
<PackageReference Include="CoinEx.Net" Version="10.11.0" />
|
<PackageReference Include="CoinEx.Net" Version="11.0.0" />
|
||||||
<PackageReference Include="CoinW.Net" Version="2.10.0" />
|
<PackageReference Include="CoinW.Net" Version="3.0.0" />
|
||||||
<PackageReference Include="CryptoCom.Net" Version="3.11.0" />
|
<PackageReference Include="CryptoCom.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="DeepCoin.Net" Version="3.10.0" />
|
<PackageReference Include="DeepCoin.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="GateIo.Net" Version="3.11.0" />
|
<PackageReference Include="GateIo.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="HyperLiquid.Net" Version="4.7.1" />
|
<PackageReference Include="HyperLiquid.Net" Version="5.0.0" />
|
||||||
<PackageReference Include="JK.BingX.Net" Version="3.11.1" />
|
<PackageReference Include="JK.BingX.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="JK.Bitget.Net" Version="3.12.1" />
|
<PackageReference Include="JK.Bitget.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="JK.Mexc.Net" Version="5.2.0" />
|
<PackageReference Include="JK.Mexc.Net" Version="6.0.0" />
|
||||||
<PackageReference Include="JK.OKX.Net" Version="4.14.0" />
|
<PackageReference Include="JK.OKX.Net" Version="5.0.1" />
|
||||||
<PackageReference Include="Jkorf.Aster.Net" Version="3.3.0" />
|
<PackageReference Include="Jkorf.Aster.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="JKorf.BitMEX.Net" Version="3.10.0" />
|
<PackageReference Include="JKorf.BitMEX.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="JKorf.Coinbase.Net" Version="3.10.1" />
|
<PackageReference Include="JKorf.Coinbase.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="JKorf.HTX.Net" Version="8.10.1" />
|
<PackageReference Include="JKorf.HTX.Net" Version="9.0.0" />
|
||||||
<PackageReference Include="JKorf.Upbit.Net" Version="2.10.1" />
|
<PackageReference Include="JKorf.Lighter.Net" Version="1.0.0" />
|
||||||
<PackageReference Include="KrakenExchange.Net" Version="7.11.0" />
|
<PackageReference Include="JKorf.Upbit.Net" Version="3.0.0" />
|
||||||
<PackageReference Include="Kucoin.Net" Version="8.13.0" />
|
<PackageReference Include="KrakenExchange.Net" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Kucoin.Net" Version="9.0.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||||
<PackageReference Include="Toobit.Net" Version="3.10.0" />
|
<PackageReference Include="Toobit.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="Weex.Net" Version="1.1.1" />
|
<PackageReference Include="Weex.Net" Version="2.0.0" />
|
||||||
<PackageReference Include="WhiteBit.Net" Version="3.11.1" />
|
<PackageReference Include="WhiteBit.Net" Version="4.0.0" />
|
||||||
<PackageReference Include="XT.Net" Version="3.10.0" />
|
<PackageReference Include="XT.Net" Version="4.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
@inject IHyperLiquidRestClient hyperLiquidClient
|
@inject IHyperLiquidRestClient hyperLiquidClient
|
||||||
@inject IKrakenRestClient krakenClient
|
@inject IKrakenRestClient krakenClient
|
||||||
@inject IKucoinRestClient kucoinClient
|
@inject IKucoinRestClient kucoinClient
|
||||||
|
@inject ILighterRestClient lighterClient
|
||||||
@inject IMexcRestClient mexcClient
|
@inject IMexcRestClient mexcClient
|
||||||
@inject IOKXRestClient okxClient
|
@inject IOKXRestClient okxClient
|
||||||
@inject IToobitRestClient toobitClient
|
@inject IToobitRestClient toobitClient
|
||||||
@@ -40,7 +41,7 @@
|
|||||||
var asterTask = asterClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
var asterTask = asterClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
||||||
var binanceTask = binanceClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
var binanceTask = binanceClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
||||||
var bingXTask = bingXClient.SpotApi.ExchangeData.GetTickersAsync("BTC-USDT");
|
var bingXTask = bingXClient.SpotApi.ExchangeData.GetTickersAsync("BTC-USDT");
|
||||||
var bitfinexTask = bitfinexClient.SpotApi.ExchangeData.GetTickerAsync("tBTCUSD");
|
var bitfinexTask = bitfinexClient.ExchangeApi.ExchangeData.GetTickerAsync("tBTCUSD");
|
||||||
var bitgetTask = bitgetClient.SpotApiV2.ExchangeData.GetTickersAsync("BTCUSDT");
|
var bitgetTask = bitgetClient.SpotApiV2.ExchangeData.GetTickersAsync("BTCUSDT");
|
||||||
var bitmartTask = bitmartClient.SpotApi.ExchangeData.GetTickerAsync("BTC_USDT");
|
var bitmartTask = bitmartClient.SpotApi.ExchangeData.GetTickerAsync("BTC_USDT");
|
||||||
var bitmexTask = bitmexClient.ExchangeApi.ExchangeData.GetSymbolsAsync("XBT_USDT");
|
var bitmexTask = bitmexClient.ExchangeApi.ExchangeData.GetSymbolsAsync("XBT_USDT");
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
var hyperLiquidTask = hyperLiquidClient.FuturesApi.ExchangeData.GetExchangeInfoAndTickersAsync();
|
var hyperLiquidTask = hyperLiquidClient.FuturesApi.ExchangeData.GetExchangeInfoAndTickersAsync();
|
||||||
var krakenTask = krakenClient.SpotApi.ExchangeData.GetTickerAsync("XBTUSD");
|
var krakenTask = krakenClient.SpotApi.ExchangeData.GetTickerAsync("XBTUSD");
|
||||||
var kucoinTask = kucoinClient.SpotApi.ExchangeData.GetTickerAsync("BTC-USDT");
|
var kucoinTask = kucoinClient.SpotApi.ExchangeData.GetTickerAsync("BTC-USDT");
|
||||||
|
var lighterTask = lighterClient.ExchangeApi.ExchangeData.GetSymbolDetailsAsync("BTC");
|
||||||
var mexcTask = mexcClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
var mexcTask = mexcClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
|
||||||
var okxTask = okxClient.UnifiedApi.ExchangeData.GetTickerAsync("BTC-USDT");
|
var okxTask = okxClient.UnifiedApi.ExchangeData.GetTickerAsync("BTC-USDT");
|
||||||
var toobitTask = toobitClient.SpotApi.ExchangeData.GetTickersAsync("BTCUSDT");
|
var toobitTask = toobitClient.SpotApi.ExchangeData.GetTickersAsync("BTCUSDT");
|
||||||
@@ -131,6 +133,9 @@
|
|||||||
if (kucoinTask.Result.Success)
|
if (kucoinTask.Result.Success)
|
||||||
_prices.Add("Kucoin", kucoinTask.Result.Data.LastPrice ?? 0);
|
_prices.Add("Kucoin", kucoinTask.Result.Data.LastPrice ?? 0);
|
||||||
|
|
||||||
|
if (lighterTask.Result.Success)
|
||||||
|
_prices.Add("Lighter", lighterTask.Result.Data.PerpSymbols[0].LastPrice);
|
||||||
|
|
||||||
if (mexcTask.Result.Success)
|
if (mexcTask.Result.Success)
|
||||||
_prices.Add("Mexc", mexcTask.Result.Data.LastPrice);
|
_prices.Add("Mexc", mexcTask.Result.Data.LastPrice);
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
@inject IHyperLiquidSocketClient hyperLiquidSocketClient
|
@inject IHyperLiquidSocketClient hyperLiquidSocketClient
|
||||||
@inject IKrakenSocketClient krakenSocketClient
|
@inject IKrakenSocketClient krakenSocketClient
|
||||||
@inject IKucoinSocketClient kucoinSocketClient
|
@inject IKucoinSocketClient kucoinSocketClient
|
||||||
|
@inject ILighterSocketClient lighterSocketClient
|
||||||
@inject IMexcSocketClient mexcSocketClient
|
@inject IMexcSocketClient mexcSocketClient
|
||||||
@inject IOKXSocketClient okxSocketClient
|
@inject IOKXSocketClient okxSocketClient
|
||||||
@inject IToobitSocketClient toobitSocketClient
|
@inject IToobitSocketClient toobitSocketClient
|
||||||
@@ -44,13 +45,13 @@
|
|||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
var tasks = new Task<CallResult<UpdateSubscription>>[]
|
var tasks = new Task<WebSocketResult<UpdateSubscription>>[]
|
||||||
{
|
{
|
||||||
// Aster doesn't support the ETH/BTC pair
|
// Aster doesn't support the ETH/BTC pair
|
||||||
//asterSocketClient.SpotApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Aster", data.Data.LastPrice)),
|
//asterSocketClient.SpotApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Aster", data.Data.LastPrice)),
|
||||||
binanceSocketClient.SpotApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Binance", data.Data.LastPrice)),
|
binanceSocketClient.SpotApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Binance", data.Data.LastPrice)),
|
||||||
bingXSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH-BTC", data => UpdateData("BingX", data.Data.LastPrice)),
|
bingXSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH-BTC", data => UpdateData("BingX", data.Data.LastPrice)),
|
||||||
bitfinexSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("tETHBTC", data => UpdateData("Bitfinex", data.Data.LastPrice)),
|
bitfinexSocketClient.ExchangeApi.SubscribeToTickerUpdatesAsync("tETHBTC", data => UpdateData("Bitfinex", data.Data.LastPrice)),
|
||||||
bitgetSocketClient.SpotApiV2.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Bitget", data.Data.First().LastPrice)),
|
bitgetSocketClient.SpotApiV2.SubscribeToTickerUpdatesAsync("ETHBTC", data => UpdateData("Bitget", data.Data.First().LastPrice)),
|
||||||
bitmartSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("BitMart", data.Data.LastPrice)),
|
bitmartSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("BitMart", data.Data.LastPrice)),
|
||||||
bitmexSocketClient.ExchangeApi.SubscribeToSymbolUpdatesAsync("ETH_XBT", data => UpdateData("BitMEX", data.Data.LastPrice ?? 0)),
|
bitmexSocketClient.ExchangeApi.SubscribeToSymbolUpdatesAsync("ETH_XBT", data => UpdateData("BitMEX", data.Data.LastPrice ?? 0)),
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
@using Kucoin.Net
|
@using Kucoin.Net
|
||||||
@using Kucoin.Net.Clients
|
@using Kucoin.Net.Clients
|
||||||
@using Kucoin.Net.Interfaces
|
@using Kucoin.Net.Interfaces
|
||||||
|
@using Lighter.Net.Interfaces
|
||||||
@using Mexc.Net.Interfaces
|
@using Mexc.Net.Interfaces
|
||||||
@using OKX.Net.Interfaces;
|
@using OKX.Net.Interfaces;
|
||||||
@using Upbit.Net.Interfaces;
|
@using Upbit.Net.Interfaces;
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
@inject IHyperLiquidOrderBookFactory hyperLiquidFactory
|
@inject IHyperLiquidOrderBookFactory hyperLiquidFactory
|
||||||
@inject IKrakenOrderBookFactory krakenFactory
|
@inject IKrakenOrderBookFactory krakenFactory
|
||||||
@inject IKucoinOrderBookFactory kucoinFactory
|
@inject IKucoinOrderBookFactory kucoinFactory
|
||||||
|
@inject ILighterOrderBookFactory lighterFactory
|
||||||
@inject IMexcOrderBookFactory mexcFactory
|
@inject IMexcOrderBookFactory mexcFactory
|
||||||
@inject IOKXOrderBookFactory okxFactory
|
@inject IOKXOrderBookFactory okxFactory
|
||||||
@inject IToobitOrderBookFactory toobitFactory
|
@inject IToobitOrderBookFactory toobitFactory
|
||||||
@@ -110,6 +112,7 @@
|
|||||||
{ "HyperLiquid", hyperLiquidFactory.Create("UETH/USDC") },
|
{ "HyperLiquid", hyperLiquidFactory.Create("UETH/USDC") },
|
||||||
{ "Kraken", krakenFactory.CreateSpot("ETH/BTC") },
|
{ "Kraken", krakenFactory.CreateSpot("ETH/BTC") },
|
||||||
{ "Kucoin", kucoinFactory.CreateSpot("ETH-BTC") },
|
{ "Kucoin", kucoinFactory.CreateSpot("ETH-BTC") },
|
||||||
|
{ "Lighter", lighterFactory.Create("ETH/USDC") },
|
||||||
{ "Mexc", mexcFactory.CreateSpot("ETHBTC") },
|
{ "Mexc", mexcFactory.CreateSpot("ETHBTC") },
|
||||||
{ "OKX", okxFactory.Create("ETH-BTC") },
|
{ "OKX", okxFactory.Create("ETH-BTC") },
|
||||||
{ "Toobit", toobitFactory.CreateSpot("ETHUSDT") },
|
{ "Toobit", toobitFactory.CreateSpot("ETHUSDT") },
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
@using Kraken.Net.Interfaces
|
@using Kraken.Net.Interfaces
|
||||||
@using Kucoin.Net.Clients
|
@using Kucoin.Net.Clients
|
||||||
@using Kucoin.Net.Interfaces
|
@using Kucoin.Net.Interfaces
|
||||||
|
@using Lighter.Net.Interfaces
|
||||||
@using Mexc.Net.Interfaces
|
@using Mexc.Net.Interfaces
|
||||||
@using OKX.Net.Interfaces;
|
@using OKX.Net.Interfaces;
|
||||||
@using Upbit.Net.Interfaces;
|
@using Upbit.Net.Interfaces;
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
@inject IHyperLiquidTrackerFactory hyperLiquidFactory
|
@inject IHyperLiquidTrackerFactory hyperLiquidFactory
|
||||||
@inject IKrakenTrackerFactory krakenFactory
|
@inject IKrakenTrackerFactory krakenFactory
|
||||||
@inject IKucoinTrackerFactory kucoinFactory
|
@inject IKucoinTrackerFactory kucoinFactory
|
||||||
|
@inject ILighterTrackerFactory lighterFactory
|
||||||
@inject IMexcTrackerFactory mexcFactory
|
@inject IMexcTrackerFactory mexcFactory
|
||||||
@inject IOKXTrackerFactory okxFactory
|
@inject IOKXTrackerFactory okxFactory
|
||||||
@inject IToobitTrackerFactory toobitFactory
|
@inject IToobitTrackerFactory toobitFactory
|
||||||
@@ -103,6 +105,7 @@
|
|||||||
{ hyperLiquidFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
{ hyperLiquidFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ krakenFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
{ krakenFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ kucoinFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
{ kucoinFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
|
{ lighterFactory.CreateTradeTracker(futuresSymbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ mexcFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
{ mexcFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ okxFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
{ okxFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
{ toobitFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
{ toobitFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) },
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ namespace BlazorClient
|
|||||||
services.AddHTX();
|
services.AddHTX();
|
||||||
services.AddKraken();
|
services.AddKraken();
|
||||||
services.AddKucoin();
|
services.AddKucoin();
|
||||||
|
services.AddLighter();
|
||||||
services.AddMexc();
|
services.AddMexc();
|
||||||
services.AddOKX();
|
services.AddOKX();
|
||||||
services.AddToobit();
|
services.AddToobit();
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
@using HyperLiquid.Net.Interfaces.Clients;
|
@using HyperLiquid.Net.Interfaces.Clients;
|
||||||
@using Kraken.Net.Interfaces.Clients;
|
@using Kraken.Net.Interfaces.Clients;
|
||||||
@using Kucoin.Net.Interfaces.Clients;
|
@using Kucoin.Net.Interfaces.Clients;
|
||||||
|
@using Lighter.Net.Interfaces.Clients
|
||||||
@using Mexc.Net.Interfaces.Clients;
|
@using Mexc.Net.Interfaces.Clients;
|
||||||
@using OKX.Net.Interfaces.Clients;
|
@using OKX.Net.Interfaces.Clients;
|
||||||
@using Upbit.Net.Interfaces.Clients;
|
@using Upbit.Net.Interfaces.Clients;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2018 Jan Korf
|
Copyright (c) 2026 JKorf
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ This library and the entire CryptoExchange.Net ecosystem provide first-class sup
|
|||||||
|
|
||||||
For single-exchange code, see also the AI files in each exchange's repository (Binance.Net, Bybit.Net, OKX.Net, ...) — they cover exchange-specific patterns.
|
For single-exchange code, see also the AI files in each exchange's repository (Binance.Net, Bybit.Net, OKX.Net, ...) — they cover exchange-specific patterns.
|
||||||
|
|
||||||
|
See [cryptoexchange-skills-hub](https://github.com/JKorf/cryptoexchange-skills-hub) for installable skills.
|
||||||
|
|
||||||
**Quick prompt to verify your assistant is using these:**
|
**Quick prompt to verify your assistant is using these:**
|
||||||
> "Show me how to fetch BTC/USDT spot tickers from Binance and OKX concurrently in C# using the SharedApis pattern."
|
> "Show me how to fetch BTC/USDT spot tickers from Binance and OKX concurrently in C# using the SharedApis pattern."
|
||||||
|
|
||||||
@@ -51,6 +53,7 @@ Full list of all libraries part of the CryptoExchange.Net ecosystem. Consider us
|
|||||||
||HyperLiquid|DEX|[JKorf/HyperLiquid.Net](https://github.com/JKorf/HyperLiquid.Net)|[](https://www.nuget.org/packages/HyperLiquid.Net)|[Link](https://app.hyperliquid.xyz/join/JKORF)|4%|
|
||HyperLiquid|DEX|[JKorf/HyperLiquid.Net](https://github.com/JKorf/HyperLiquid.Net)|[](https://www.nuget.org/packages/HyperLiquid.Net)|[Link](https://app.hyperliquid.xyz/join/JKORF)|4%|
|
||||||
||Kraken|CEX|[JKorf/Kraken.Net](https://github.com/JKorf/Kraken.Net)|[](https://www.nuget.org/packages/KrakenExchange.Net)|-|-|
|
||Kraken|CEX|[JKorf/Kraken.Net](https://github.com/JKorf/Kraken.Net)|[](https://www.nuget.org/packages/KrakenExchange.Net)|-|-|
|
||||||
||Kucoin|CEX|[JKorf/Kucoin.Net](https://github.com/JKorf/Kucoin.Net)|[](https://www.nuget.org/packages/Kucoin.Net)|[Link](https://www.kucoin.com/r/rf/QBS4FPED)|-|
|
||Kucoin|CEX|[JKorf/Kucoin.Net](https://github.com/JKorf/Kucoin.Net)|[](https://www.nuget.org/packages/Kucoin.Net)|[Link](https://www.kucoin.com/r/rf/QBS4FPED)|-|
|
||||||
|
||Lighter|DEX|[JKorf/Lighter.Net](https://github.com/JKorf/Lighter.Net)|[](https://www.nuget.org/packages/JKorf.Lighter.Net)|-|-|
|
||||||
||Mexc|CEX|[JKorf/Mexc.Net](https://github.com/JKorf/Mexc.Net)|[](https://www.nuget.org/packages/JK.Mexc.Net)|-|-|
|
||Mexc|CEX|[JKorf/Mexc.Net](https://github.com/JKorf/Mexc.Net)|[](https://www.nuget.org/packages/JK.Mexc.Net)|-|-|
|
||||||
||OKX|CEX|[JKorf/OKX.Net](https://github.com/JKorf/OKX.Net)|[](https://www.nuget.org/packages/JK.OKX.Net)|[Link](https://www.okx.com/join/14592495)|20%|
|
||OKX|CEX|[JKorf/OKX.Net](https://github.com/JKorf/OKX.Net)|[](https://www.nuget.org/packages/JK.OKX.Net)|[Link](https://www.okx.com/join/14592495)|20%|
|
||||||
||Polymarket|DEX|[JKorf/Polymarket.Net](https://github.com/JKorf/Polymarket.Net)|[](https://www.nuget.org/packages/Polymarket.Net)|-|-|
|
||Polymarket|DEX|[JKorf/Polymarket.Net](https://github.com/JKorf/Polymarket.Net)|[](https://www.nuget.org/packages/Polymarket.Net)|-|-|
|
||||||
@@ -124,6 +127,36 @@ Various:
|
|||||||
* PlatformInfo now required support environment names in the constructor
|
* PlatformInfo now required support environment names in the constructor
|
||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
* Version 12.3.0 - 23 Jul 2026
|
||||||
|
* Added calculation of AveragePrice on Shared order models if data is available and AveragePrice is not set
|
||||||
|
* Extracted ConnectionCanBeUsedFor method in SocketApiClient for easier custom logic implementation
|
||||||
|
* Updated some Shared APIs error messages
|
||||||
|
* Remove duplicate warnings from testing output
|
||||||
|
|
||||||
|
* Version 12.2.0 - 20 Jul 2026
|
||||||
|
* Added SpotSymbolCatalog to Shared ISpotSymbolRestClient interface
|
||||||
|
* Added FuturesSymbolCatalog to Shared IFuturesSymbolRestClient interface
|
||||||
|
* Added BaseAssetType, BaseAssetSubType, QuoteAssetType and QuoteAssetSubType to GetSymbolsRequest model
|
||||||
|
* Added DisplayName to SharedSpotSymbol and SharedFuturesSymbol models
|
||||||
|
* Added BaseAssetType, BaseAssetSubType, QuoteAssetType and QuoteAssetSubType to SharedSpotSymbol and SharedFuturesSymbol models
|
||||||
|
* Added IsStableCoin, IsCommodity and IsEquity helper methods to LibraryHelpers
|
||||||
|
* Added DebuggerDisplay attributes to Shared models
|
||||||
|
* Fixed socket connection combine calculations
|
||||||
|
|
||||||
|
* Version 12.1.1 - 11 Jul 2026
|
||||||
|
* Added timestamp deserialization support for yyyy-MM-dd HH:mm:ss.ffffff+00:00:00
|
||||||
|
|
||||||
|
* Version 12.1.0 - 09 Jul 2026
|
||||||
|
* Added ExchangeParameters parameter to KlineTracker, TradeTracker and ITrackerFactory methods
|
||||||
|
* Updated some testing logic
|
||||||
|
* Fixed nullability operator on Parameters.AddCommaSeperated
|
||||||
|
|
||||||
|
* Version 12.0.2 - 01 Jul 2026
|
||||||
|
* Updated test validation to output a list of issues instead of throwing on the first
|
||||||
|
|
||||||
|
* Version 12.0.1 - 29 Jun 2026
|
||||||
|
* Fixed bug in bool converter
|
||||||
|
|
||||||
* Version 12.0.0 - 29 Jun 2026
|
* Version 12.0.0 - 29 Jun 2026
|
||||||
* Result types:
|
* Result types:
|
||||||
* (Web)CallResult types are replaced by HttpResult, WebSocketResult and QueryResult with the same logic
|
* (Web)CallResult types are replaced by HttpResult, WebSocketResult and QueryResult with the same logic
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
Source for https://jkorf.github.io/CryptoExchange.Net
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
remote_theme: pmarsceill/just-the-docs
|
|
||||||
markdown: GFM
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*============================
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,162 +0,0 @@
|
|||||||
/*
|
|
||||||
================================================================
|
|
||||||
* 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($('<i />').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: '<div class="preloader"><div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div></div>',
|
|
||||||
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)
|
|
||||||
@@ -1,537 +0,0 @@
|
|||||||
/* =================================== */
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,448 +0,0 @@
|
|||||||
/* =================================== */
|
|
||||||
/* 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;}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
/* =================================== */
|
|
||||||
/* 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;}
|
|
||||||
}
|
|
||||||
@@ -1,554 +0,0 @@
|
|||||||
/* =================================== */
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,301 +0,0 @@
|
|||||||
/* =================================== */
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,171 +0,0 @@
|
|||||||
/* =================================== */
|
|
||||||
/* 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;}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
//---------- @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);
|
|
||||||
}
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
/* =================================== */
|
|
||||||
/* 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;}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*===========================================================
|
|
||||||
|
|
||||||
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;
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
//
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||