diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43fe890 --- /dev/null +++ b/.gitignore @@ -0,0 +1,398 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea \ No newline at end of file diff --git a/Src/Common/ApiServiceImp/BybitAssetService.cs b/Src/Common/ApiServiceImp/BybitAssetService.cs index 20083bf..38c78b7 100644 --- a/Src/Common/ApiServiceImp/BybitAssetService.cs +++ b/Src/Common/ApiServiceImp/BybitAssetService.cs @@ -1,566 +1,566 @@ -using bybit.net.api.Models; -using bybit.net.api.Models.Account; -using bybit.net.api.Models.Asset; -using bybit.net.api.Models.Position; -using bybit.net.api.Services; - -namespace bybit.net.api.ApiServiceImp -{ - public class BybitAssetService : BybitApiService - { - public BybitAssetService(string apiKey, string apiSecret, string? url = null, string recvWindow = BybitConstants.DEFAULT_REC_WINDOW, bool debugMode = false) - : this(httpClient: new HttpClient(), apiKey: apiKey, apiSecret: apiSecret, url: url, recvWindow: recvWindow, debugMode: debugMode) - { - } - - public BybitAssetService(HttpClient httpClient, string apiKey, string apiSecret, string? url = null, string recvWindow = BybitConstants.DEFAULT_REC_WINDOW, bool debugMode = false) - : base(httpClient: httpClient, apiKey: apiKey, apiSecret: apiSecret, url: url, recvWindow: recvWindow, debugMode: debugMode) - { - } - - private const string COIN_EXCHANGE_RECORDS = "/v5/asset/exchange/order-record"; - /// - /// Query the coin exchange records. - /// This endpoint currently is not available to get data after 12 Mar 2023. We will make it fully available later. - /// CAUTION : You may have a long delay of this endpoint. - /// - /// - /// - /// - /// - /// Coin Exchange Records - public async Task GetCoinExchangeRecords(string? fromCoin = null, string? toCoin = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary(); - - BybitParametersUtils.AddOptionalParameters(query, - ("fromCoin", fromCoin), - ("toCoin", toCoin), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(COIN_EXCHANGE_RECORDS, HttpMethod.Get, query: query); - return result; - } - - private const string ASSET_DELIVERY_RECORDS = "/v5/asset/exchange/order-record"; - /// - /// Query delivery records of USDC futures and Options, sorted by deliveryTime in descending order - /// Unified account covers: USDC futures / Option - /// - /// - /// - /// - /// - /// - /// Delivery Records - public async Task GetAssetDeliveryRecords(Category category, string? symbol = null, string? expDate = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { { "category", category.Value } }; - - BybitParametersUtils.AddOptionalParameters(query, - ("symbol", symbol), - ("expDate", expDate), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(ASSET_DELIVERY_RECORDS, HttpMethod.Get, query: query); - return result; - } - - private const string USDC_SETTLEMENT = "/v5/asset/settlement-record"; - /// - /// Query session settlement records of USDC perpetual and futures - /// Unified account covers: USDC perpetual / USDC futures - /// - /// - /// - /// - /// - /// Usdc Settlements - public async Task GetAssetUsdcSettlement(Category category, string? symbol = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { { "category", category.Value } }; - - BybitParametersUtils.AddOptionalParameters(query, - ("symbol", symbol), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(USDC_SETTLEMENT, HttpMethod.Get, query: query); - return result; - } - - private const string ASSET_INFO = "/v5/asset/transfer/query-asset-info"; - /// - /// For now, it can query SPOT only. - /// - /// - /// - /// Asset Info - public async Task GetAssetInfo(AccountType accountType, string? coin = null) - { - var query = new Dictionary { { "accountType", accountType.Value } }; - - BybitParametersUtils.AddOptionalParameters(query, - ("coin", coin) - ); - var result = await this.SendSignedAsync(ASSET_INFO, HttpMethod.Get, query: query); - return result; - } - - private const string ALL_ASSETS_INFO = "/v5/asset/transfer/query-account-coins-balance"; - /// - /// You could get all coin balance of all account types under the master account, and sub account. - /// It is not allowed to get master account coin balance via sub account api key. - /// - /// - /// - /// - /// - /// All assets info - public async Task GetAllAssetBalance(AccountType accountType, string? coin = null, string? memberId = null, WithBonus? withBonus = null) - { - var query = new Dictionary { { "accountType", accountType.Value } }; - - BybitParametersUtils.AddOptionalParameters(query, - ("coin", coin), - ("memberId", memberId), - ("withBonus", withBonus?.Value) - ); - var result = await this.SendSignedAsync(ALL_ASSETS_INFO, HttpMethod.Get, query: query); - return result; - } - - private const string SINGLE_ASSET_INFO = "/v5/asset/transfer/query-account-coin-balance"; - /// - /// Query the balance of a specific coin in a specific account type. Supports querying sub UID's balance. Also, you can check the transferable amount from master to sub account, sub to master account or sub to sub account, especially for user who has INS loan. - /// Sub account cannot query master account balance - /// Sub account can only check its own balance - /// Master account can check its own and its sub UIDs balance - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Single Coin Balance - public async Task GetSingleAssetBalance(AccountType accountType, string coin, AccountType? toAccountType = null, string? memberId = null, string? toMemberId = null, WithBonus? withBonus = null, WithBonus? withTransferSafeAmount = null, WithBonus? withLtvTransferSafeAmount = null) - { - var query = new Dictionary { { "accountType", accountType.Value }, { "coin", coin } }; - - BybitParametersUtils.AddOptionalParameters(query, - ("toAccountType", toAccountType?.Value), - ("toMemberId", toMemberId), - ("coin", coin), - ("memberId", memberId), - ("withBonus", withBonus?.Value), - ("withTransferSafeAmount", withTransferSafeAmount?.Value), - ("withLtvTransferSafeAmount", withLtvTransferSafeAmount?.Value) - ); - var result = await this.SendSignedAsync(SINGLE_ASSET_INFO, HttpMethod.Get, query: query); - return result; - } - - private const string TRANSABLE_COIN = "/v5/asset/transfer/query-transfer-coin-list"; - /// - /// Query the transferable coin list between each account type - /// - /// - /// - /// List of coin - public async Task GetAllAssetBalance(AccountType accountType, AccountType toAccountType) - { - var query = new Dictionary { { "accountType", accountType.Value }, { "toAccountType", toAccountType.Value } }; - var result = await this.SendSignedAsync(TRANSABLE_COIN, HttpMethod.Get, query: query); - return result; - } - - private const string INTERNAL_TRANSFER = "/v5/asset/transfer/inter-transfer"; - /// - /// Create the internal transfer between different account types under the same UID. - /// Each account type has its own acceptable coins, e.g, you cannot transfer USDC from SPOT to CONTRACT.Please refer to transferable coin list API to find out more. - /// - /// - /// - /// - /// - /// - /// transferId - public async Task CreateInternalTransfer(AccountType accountType, AccountType toAccountType, string coin, string amount, string? transferId = null) - { - var query = new Dictionary { { "accountType", accountType.Value }, { "toAccountType", toAccountType.Value }, { "coin", coin }, { "amount", amount } }; - if (string.IsNullOrEmpty(transferId)) transferId = BybitParametersUtils.GenerateTransferId(); - query.Add("transferId", transferId); - var result = await this.SendSignedAsync(INTERNAL_TRANSFER, HttpMethod.Post, query: query); - return result; - } - - private const string UNIVERSAL_TRANSFER = "/v5/asset/transfer/universal-transfer"; - /// - /// Transfer between sub-sub or main-sub. - /// Can use master or sub acct api key to request - /// To use sub acct api key, it must have "SubMemberTransferList" permission - /// When use sub acct api key, it can only transfer to main account - /// If you encounter errorCode: 131228 and msg: your balance is not enough, please go to Get Single Coin Balance to check transfer safe amount. - /// You can not transfer between the same UID - /// - /// - /// - /// - /// - /// - /// - /// transferId - public async Task CreateUniversalTransfer(AccountType accountType, AccountType toAccountType, string fromMemberId, string toMemberId, string coin, string amount, string? transferId = null) - { - var query = new Dictionary { { "accountType", accountType.Value }, { "toAccountType", toAccountType.Value }, { "fromMemberId", fromMemberId }, { "toMemberId", toMemberId }, { "coin", coin }, { "amount", amount } }; - if (string.IsNullOrEmpty(transferId)) transferId = BybitParametersUtils.GenerateTransferId(); - query.Add("transferId", transferId); - var result = await this.SendSignedAsync(UNIVERSAL_TRANSFER, HttpMethod.Post, query: query); - return result; - } - - private const string INTERNAL_TRANSFER_RECORDS = "/v5/asset/transfer/query-inter-transfer-list"; - /// - /// Query the internal transfer records between different account types under the same UID. - /// - /// - /// - /// - /// - /// - /// - /// - /// Internal Transfers - public async Task GetInternalTransferRecords(string? transferId = null, string? coin = null, TransferStatus? transferStatus = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { }; - - BybitParametersUtils.AddOptionalParameters(query, - ("transferId", transferId), - ("coin", coin), - ("transferStatus", transferStatus?.Value), - ("startTime", startTime), - ("endTime", endTime), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(INTERNAL_TRANSFER_RECORDS, HttpMethod.Get, query: query); - return result; - } - - private const string UNIVERSAL_TRANSFER_RECORDS = "/v5/asset/transfer/query-universal-transfer-list"; - /// - /// Query universal transfer records - /// Main acct api key or Sub acct api key are both supported - /// Main acct api key needs "SubMemberTransfer" permission - /// Sub acct api key needs "SubMemberTransferList" permission - /// - /// - /// - /// - /// - /// - /// - /// - /// Universal Transfers - public async Task GetUniversalTransferRecords(string? transferId = null, string? coin = null, TransferStatus? transferStatus = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { }; - - BybitParametersUtils.AddOptionalParameters(query, - ("transferId", transferId), - ("coin", coin), - ("transferStatus", transferStatus?.Value), - ("startTime", startTime), - ("endTime", endTime), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(UNIVERSAL_TRANSFER_RECORDS, HttpMethod.Get, query: query); - return result; - } - - private const string SUB_UIDS = "/v5/asset/transfer/query-sub-member-list"; - /// - /// Query the sub UIDs under a main UID - /// Can query by the master UID's api key only - /// - /// List Sub uid - public async Task GetAssetSubMembers() - { - var query = new Dictionary { }; - var result = await this.SendSignedAsync(SUB_UIDS, HttpMethod.Get, query: query); - return result; - } - - private const string ALLOW_DEPOSIT_COINS = "/v5/asset/deposit/query-allowed-list"; - /// - /// Query allowed deposit coin information. To find out paired chain of coin, please refer coin info api. - /// This is an endpoint that does not need authentication - /// - /// - /// - /// - /// - /// Deposited Coin Info - public async Task GetAssetAllowedDepositInfo(string? chain = null, string? coin = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { }; - - BybitParametersUtils.AddOptionalParameters(query, - ("chain", chain), - ("coin", coin), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(ALLOW_DEPOSIT_COINS, HttpMethod.Get, query: query); - return result; - } - - private const string SET_DEPOSIT_ACCOUNT = "/v5/asset/deposit/deposit-to-account"; - /// - /// Set auto transfer account after deposit. The same function as the setting for Deposit on web GUI - /// Your funds will be deposited into FUND wallet by default. You can set the wallet for auto-transfer after deposit by this API. - /// Only main UID can access. - /// Unified trading account has FUND, UNIFIED, CONTRACT(for inverse derivatives) - /// Unified margin account has FUND, UNIFIED, CONTRACT(for inverse derivatives), SPOT - /// Classic account has FUND, OPTION(USDC account), CONTRACT(for inverse derivatives and derivatives), SPOT - /// - /// - /// status - public async Task SetAssetDepositAccount(AccountType accountType) - { - var query = new Dictionary { { "accountType", accountType.Value } }; - var result = await this.SendSignedAsync(SET_DEPOSIT_ACCOUNT, HttpMethod.Post, query: query); - return result; - } - - private const string DEPOSIT_RECORDS = "/v5/asset/deposit/deposit-to-account"; - /// - /// endTime - startTime should be less than 30 days. Query last 30 days records by default. - /// Can use main or sub UID api key to query deposit records respectively. - /// - /// - /// - /// - /// - /// - /// deposit records - public async Task GetAssetDepositRecords(string? coin = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { }; - - BybitParametersUtils.AddOptionalParameters(query, - ("coin", coin), - ("startTime", startTime), - ("endTime", endTime), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(DEPOSIT_RECORDS, HttpMethod.Get, query: query); - return result; - } - - private const string SUB_DEPOSIT_RECORDS = "/v5/asset/deposit/query-sub-member-record"; - /// - /// endTime - startTime should be less than 30 days. Queries for the last 30 days worth of records by default. - /// - /// - /// - /// - /// - /// - /// - /// Query subaccount's deposit records by main UID's API key. - public async Task GetAssetSubDepositRecords(string subMemberId, string? coin = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { { "subMemberId", subMemberId } }; - - BybitParametersUtils.AddOptionalParameters(query, - ("coin", coin), - ("startTime", startTime), - ("endTime", endTime), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(SUB_DEPOSIT_RECORDS, HttpMethod.Get, query: query); - return result; - } - - private const string INTERNAL_DEPOSIT_RECORDS = "/v5/asset/deposit/query-sub-member-record"; - /// - /// The maximum difference between the start time and the end time is 30 days. - /// Support to get deposit records by Master or Sub Member Api Key - /// - /// - /// - /// - /// - /// - /// Query deposit records within the Bybit platform. These transactions are not on the blockchain. - public async Task GetAssetInternalDepositRecords(string? coin = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { }; - - BybitParametersUtils.AddOptionalParameters(query, - ("coin", coin), - ("startTime", startTime), - ("endTime", endTime), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(INTERNAL_DEPOSIT_RECORDS, HttpMethod.Get, query: query); - return result; - } - - private const string MASTER_DEPOSIT_ADDRESS = "/v5/asset/deposit/query-address"; - /// - /// Query the deposit address information of MASTER account. - /// - /// - /// - /// Master Deposit Address - public async Task GetAssetMasterDepositAddress(string coin, string? chainType = null) - { - var query = new Dictionary { { "coin", coin } }; - - BybitParametersUtils.AddOptionalParameters(query, - ("chainType", chainType) - ); - var result = await this.SendSignedAsync(MASTER_DEPOSIT_ADDRESS, HttpMethod.Get, query: query); - return result; - } - - private const string SUB_DEPOSIT_ADDRESS = "/v5/asset/deposit/query-sub-member-address"; - /// - /// Query the deposit address information of SUB account. - /// Can use master UID's api key only - /// - /// - /// - /// - /// Sub Deposit Address - public async Task GetAssetSubDepositAddress(string coin, string chainType, string subMemberId) - { - var query = new Dictionary { { "coin", coin }, { "chainType", chainType }, { "subMemberId", subMemberId } }; - var result = await this.SendSignedAsync(SUB_DEPOSIT_ADDRESS, HttpMethod.Get, query: query); - return result; - } - - private const string COIN_INFO = "/v5/asset/coin/query-info"; - /// - /// Query coin information, including chain information, withdraw and deposit status. - /// - /// - /// Coin Info - public async Task GetAssetCoinInfo(string? coin = null) - { - var query = new Dictionary { }; - BybitParametersUtils.AddOptionalParameters(query, - ("coin", coin) - ); - var result = await this.SendSignedAsync(COIN_INFO, HttpMethod.Get, query: query); - return result; - } - - private const string WITHDRAW_RECORDS = "/v5/asset/withdraw/query-record"; - /// - /// endTime - startTime should be less than 30 days. Query last 30 days records by default. - /// Can query by the master UID's api key only - /// - /// - /// - /// - /// - /// - /// - /// - /// Get Withdrawal Records - public async Task GetAssetWithdrawRecords(string? coin = null, string? withdrawID = null, WithdrawType? withdrawType = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) - { - var query = new Dictionary { }; - BybitParametersUtils.AddOptionalParameters(query, - ("withdrawID", withdrawID), - ("coin", coin), - ("withdrawType", withdrawType?.Value), - ("startTime", startTime), - ("endTime", endTime), - ("limit", limit), - ("cursor", cursor) - ); - var result = await this.SendSignedAsync(WITHDRAW_RECORDS, HttpMethod.Get, query: query); - return result; - } - - private const string WITHDRAWABLE_AMOUNT = "/v5/asset/withdraw/withdrawable-amount"; - /// - /// How can partial funds be subject to delayed withdrawal requests? - /// On-chain deposit: If the number of on-chain confirmations has not reached a risk-controlled level, a portion of the funds will be frozen for a period of time until they are unfrozen. - /// Buying crypto: If there is a risk, the funds will be frozen for a certain period of time and cannot be withdrawn. - /// - /// - /// Get Withdrawable Amount - public async Task GetAssetWithdrawableAmount(string coin) - { - var query = new Dictionary { { "coin", coin } }; - var result = await this.SendSignedAsync(WITHDRAWABLE_AMOUNT, HttpMethod.Get, query: query); - return result; - } - - private const string ASSET_WITHDRAW = "/v5/asset/withdraw/create"; - /// - /// Withdraw assets from your Bybit account. You can make an off-chain transfer if the target wallet address is from Bybit. This means that no blockchain fee will be charged. - /// UTA does not have SPOT account - /// How do I know if my account is a UTA account? Call this endpoint, and if uta=1, then it is a UTA account. - /// Make sure you have whitelisted your wallet address here - /// Can query by the master UID's api key only - /// feeType = 0: - /// withdrawPercentageFee != 0: handlingFee = inputAmount / (1 - withdrawPercentageFee) * withdrawPercentageFee + withdrawFee - /// withdrawPercentageFee = 0: handlingFee = withdrawFee - /// feeType = 1: - /// withdrawPercentageFee != 0: handlingFee = withdrawFee + (inputAmount - withdrawFee) * withdrawPercentageFee - /// withdrawPercentageFee = 0: handlingFee = withdrawFee - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// id - public async Task PlaceAssetWithdraw(string coin, string chain, string address, string amount, long timestamp, string? tag = null, int? forceChain = null, AccountType? accountType = null, FeeType? feeType = null) - { - var query = new Dictionary { { "coin", coin }, { "chain", chain }, { "address", address }, { "amount", amount }, { "timestamp", timestamp } }; - BybitParametersUtils.AddOptionalParameters(query, - ("tag", tag), - ("forceChain", forceChain), - ("accountType", accountType?.Value), - ("feeType", feeType?.Value) - ); - var result = await this.SendSignedAsync(ASSET_WITHDRAW, HttpMethod.Post, query: query); - return result; - } - - private const string CANCEL_WITHDRAW = "/v5/asset/withdraw/cancel"; - /// - /// Cancel the withdrawal - /// Can query by the master UID's api key only - /// - /// - /// status - public async Task CancelAssetWithdrawal(string id) - { - var query = new Dictionary { { "id", id } }; - var result = await this.SendSignedAsync(CANCEL_WITHDRAW, HttpMethod.Post, query: query); - return result; - } - } -} +using bybit.net.api.Models; +using bybit.net.api.Models.Account; +using bybit.net.api.Models.Asset; +using bybit.net.api.Models.Position; +using bybit.net.api.Services; + +namespace bybit.net.api.ApiServiceImp +{ + public class BybitAssetService : BybitApiService + { + public BybitAssetService(string apiKey, string apiSecret, string? url = null, string recvWindow = BybitConstants.DEFAULT_REC_WINDOW, bool debugMode = false) + : this(httpClient: new HttpClient(), apiKey: apiKey, apiSecret: apiSecret, url: url, recvWindow: recvWindow, debugMode: debugMode) + { + } + + public BybitAssetService(HttpClient httpClient, string apiKey, string apiSecret, string? url = null, string recvWindow = BybitConstants.DEFAULT_REC_WINDOW, bool debugMode = false) + : base(httpClient: httpClient, apiKey: apiKey, apiSecret: apiSecret, url: url, recvWindow: recvWindow, debugMode: debugMode) + { + } + + private const string COIN_EXCHANGE_RECORDS = "/v5/asset/exchange/order-record"; + /// + /// Query the coin exchange records. + /// This endpoint currently is not available to get data after 12 Mar 2023. We will make it fully available later. + /// CAUTION : You may have a long delay of this endpoint. + /// + /// + /// + /// + /// + /// Coin Exchange Records + public async Task GetCoinExchangeRecords(string? fromCoin = null, string? toCoin = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary(); + + BybitParametersUtils.AddOptionalParameters(query, + ("fromCoin", fromCoin), + ("toCoin", toCoin), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(COIN_EXCHANGE_RECORDS, HttpMethod.Get, query: query); + return result; + } + + private const string ASSET_DELIVERY_RECORDS = "/v5/asset/exchange/order-record"; + /// + /// Query delivery records of USDC futures and Options, sorted by deliveryTime in descending order + /// Unified account covers: USDC futures / Option + /// + /// + /// + /// + /// + /// + /// Delivery Records + public async Task GetAssetDeliveryRecords(Category category, string? symbol = null, string? expDate = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { { "category", category.Value } }; + + BybitParametersUtils.AddOptionalParameters(query, + ("symbol", symbol), + ("expDate", expDate), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(ASSET_DELIVERY_RECORDS, HttpMethod.Get, query: query); + return result; + } + + private const string USDC_SETTLEMENT = "/v5/asset/settlement-record"; + /// + /// Query session settlement records of USDC perpetual and futures + /// Unified account covers: USDC perpetual / USDC futures + /// + /// + /// + /// + /// + /// Usdc Settlements + public async Task GetAssetUsdcSettlement(Category category, string? symbol = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { { "category", category.Value } }; + + BybitParametersUtils.AddOptionalParameters(query, + ("symbol", symbol), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(USDC_SETTLEMENT, HttpMethod.Get, query: query); + return result; + } + + private const string ASSET_INFO = "/v5/asset/transfer/query-asset-info"; + /// + /// For now, it can query SPOT only. + /// + /// + /// + /// Asset Info + public async Task GetAssetInfo(AccountType accountType, string? coin = null) + { + var query = new Dictionary { { "accountType", accountType.Value } }; + + BybitParametersUtils.AddOptionalParameters(query, + ("coin", coin) + ); + var result = await this.SendSignedAsync(ASSET_INFO, HttpMethod.Get, query: query); + return result; + } + + private const string ALL_ASSETS_INFO = "/v5/asset/transfer/query-account-coins-balance"; + /// + /// You could get all coin balance of all account types under the master account, and sub account. + /// It is not allowed to get master account coin balance via sub account api key. + /// + /// + /// + /// + /// + /// All assets info + public async Task GetAllAssetBalance(AccountType accountType, string? coin = null, string? memberId = null, WithBonus? withBonus = null) + { + var query = new Dictionary { { "accountType", accountType.Value } }; + + BybitParametersUtils.AddOptionalParameters(query, + ("coin", coin), + ("memberId", memberId), + ("withBonus", withBonus?.Value) + ); + var result = await this.SendSignedAsync(ALL_ASSETS_INFO, HttpMethod.Get, query: query); + return result; + } + + private const string SINGLE_ASSET_INFO = "/v5/asset/transfer/query-account-coin-balance"; + /// + /// Query the balance of a specific coin in a specific account type. Supports querying sub UID's balance. Also, you can check the transferable amount from master to sub account, sub to master account or sub to sub account, especially for user who has INS loan. + /// Sub account cannot query master account balance + /// Sub account can only check its own balance + /// Master account can check its own and its sub UIDs balance + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Single Coin Balance + public async Task GetSingleAssetBalance(AccountType accountType, string coin, AccountType? toAccountType = null, string? memberId = null, string? toMemberId = null, WithBonus? withBonus = null, WithBonus? withTransferSafeAmount = null, WithBonus? withLtvTransferSafeAmount = null) + { + var query = new Dictionary { { "accountType", accountType.Value }, { "coin", coin } }; + + BybitParametersUtils.AddOptionalParameters(query, + ("toAccountType", toAccountType?.Value), + ("toMemberId", toMemberId), + ("coin", coin), + ("memberId", memberId), + ("withBonus", withBonus?.Value), + ("withTransferSafeAmount", withTransferSafeAmount?.Value), + ("withLtvTransferSafeAmount", withLtvTransferSafeAmount?.Value) + ); + var result = await this.SendSignedAsync(SINGLE_ASSET_INFO, HttpMethod.Get, query: query); + return result; + } + + private const string TRANSABLE_COIN = "/v5/asset/transfer/query-transfer-coin-list"; + /// + /// Query the transferable coin list between each account type + /// + /// + /// + /// List of coin + public async Task GetInternalTransferableCoins(AccountType accountType, AccountType toAccountType) + { + var query = new Dictionary { { "fromAccountType", accountType.Value }, { "toAccountType", toAccountType.Value } }; + var result = await this.SendSignedAsync(TRANSABLE_COIN, HttpMethod.Get, query: query); + return result; + } + + private const string INTERNAL_TRANSFER = "/v5/asset/transfer/inter-transfer"; + /// + /// Create the internal transfer between different account types under the same UID. + /// Each account type has its own acceptable coins, e.g, you cannot transfer USDC from SPOT to CONTRACT.Please refer to transferable coin list API to find out more. + /// + /// + /// + /// + /// + /// + /// transferId + public async Task CreateInternalTransfer(AccountType accountType, AccountType toAccountType, string coin, string amount, string? transferId = null) + { + var query = new Dictionary { { "fromAccountType", accountType.Value }, { "toAccountType", toAccountType.Value }, { "coin", coin }, { "amount", amount } }; + if (string.IsNullOrEmpty(transferId)) transferId = BybitParametersUtils.GenerateTransferId(); + query.Add("transferId", transferId); + var result = await this.SendSignedAsync(INTERNAL_TRANSFER, HttpMethod.Post, query: query); + return result; + } + + private const string UNIVERSAL_TRANSFER = "/v5/asset/transfer/universal-transfer"; + /// + /// Transfer between sub-sub or main-sub. + /// Can use master or sub acct api key to request + /// To use sub acct api key, it must have "SubMemberTransferList" permission + /// When use sub acct api key, it can only transfer to main account + /// If you encounter errorCode: 131228 and msg: your balance is not enough, please go to Get Single Coin Balance to check transfer safe amount. + /// You can not transfer between the same UID + /// + /// + /// + /// + /// + /// + /// + /// transferId + public async Task CreateUniversalTransfer(AccountType accountType, AccountType toAccountType, string fromMemberId, string toMemberId, string coin, string amount, string? transferId = null) + { + var query = new Dictionary { { "accountType", accountType.Value }, { "toAccountType", toAccountType.Value }, { "fromMemberId", fromMemberId }, { "toMemberId", toMemberId }, { "coin", coin }, { "amount", amount } }; + if (string.IsNullOrEmpty(transferId)) transferId = BybitParametersUtils.GenerateTransferId(); + query.Add("transferId", transferId); + var result = await this.SendSignedAsync(UNIVERSAL_TRANSFER, HttpMethod.Post, query: query); + return result; + } + + private const string INTERNAL_TRANSFER_RECORDS = "/v5/asset/transfer/query-inter-transfer-list"; + /// + /// Query the internal transfer records between different account types under the same UID. + /// + /// + /// + /// + /// + /// + /// + /// + /// Internal Transfers + public async Task GetInternalTransferRecords(string? transferId = null, string? coin = null, TransferStatus? transferStatus = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { }; + + BybitParametersUtils.AddOptionalParameters(query, + ("transferId", transferId), + ("coin", coin), + ("transferStatus", transferStatus?.Value), + ("startTime", startTime), + ("endTime", endTime), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(INTERNAL_TRANSFER_RECORDS, HttpMethod.Get, query: query); + return result; + } + + private const string UNIVERSAL_TRANSFER_RECORDS = "/v5/asset/transfer/query-universal-transfer-list"; + /// + /// Query universal transfer records + /// Main acct api key or Sub acct api key are both supported + /// Main acct api key needs "SubMemberTransfer" permission + /// Sub acct api key needs "SubMemberTransferList" permission + /// + /// + /// + /// + /// + /// + /// + /// + /// Universal Transfers + public async Task GetUniversalTransferRecords(string? transferId = null, string? coin = null, TransferStatus? transferStatus = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { }; + + BybitParametersUtils.AddOptionalParameters(query, + ("transferId", transferId), + ("coin", coin), + ("transferStatus", transferStatus?.Value), + ("startTime", startTime), + ("endTime", endTime), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(UNIVERSAL_TRANSFER_RECORDS, HttpMethod.Get, query: query); + return result; + } + + private const string SUB_UIDS = "/v5/asset/transfer/query-sub-member-list"; + /// + /// Query the sub UIDs under a main UID + /// Can query by the master UID's api key only + /// + /// List Sub uid + public async Task GetAssetSubMembers() + { + var query = new Dictionary { }; + var result = await this.SendSignedAsync(SUB_UIDS, HttpMethod.Get, query: query); + return result; + } + + private const string ALLOW_DEPOSIT_COINS = "/v5/asset/deposit/query-allowed-list"; + /// + /// Query allowed deposit coin information. To find out paired chain of coin, please refer coin info api. + /// This is an endpoint that does not need authentication + /// + /// + /// + /// + /// + /// Deposited Coin Info + public async Task GetAssetAllowedDepositInfo(string? chain = null, string? coin = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { }; + + BybitParametersUtils.AddOptionalParameters(query, + ("chain", chain), + ("coin", coin), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(ALLOW_DEPOSIT_COINS, HttpMethod.Get, query: query); + return result; + } + + private const string SET_DEPOSIT_ACCOUNT = "/v5/asset/deposit/deposit-to-account"; + /// + /// Set auto transfer account after deposit. The same function as the setting for Deposit on web GUI + /// Your funds will be deposited into FUND wallet by default. You can set the wallet for auto-transfer after deposit by this API. + /// Only main UID can access. + /// Unified trading account has FUND, UNIFIED, CONTRACT(for inverse derivatives) + /// Unified margin account has FUND, UNIFIED, CONTRACT(for inverse derivatives), SPOT + /// Classic account has FUND, OPTION(USDC account), CONTRACT(for inverse derivatives and derivatives), SPOT + /// + /// + /// status + public async Task SetAssetDepositAccount(AccountType accountType) + { + var query = new Dictionary { { "accountType", accountType.Value } }; + var result = await this.SendSignedAsync(SET_DEPOSIT_ACCOUNT, HttpMethod.Post, query: query); + return result; + } + + private const string DEPOSIT_RECORDS = "/v5/asset/deposit/deposit-to-account"; + /// + /// endTime - startTime should be less than 30 days. Query last 30 days records by default. + /// Can use main or sub UID api key to query deposit records respectively. + /// + /// + /// + /// + /// + /// + /// deposit records + public async Task GetAssetDepositRecords(string? coin = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { }; + + BybitParametersUtils.AddOptionalParameters(query, + ("coin", coin), + ("startTime", startTime), + ("endTime", endTime), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(DEPOSIT_RECORDS, HttpMethod.Get, query: query); + return result; + } + + private const string SUB_DEPOSIT_RECORDS = "/v5/asset/deposit/query-sub-member-record"; + /// + /// endTime - startTime should be less than 30 days. Queries for the last 30 days worth of records by default. + /// + /// + /// + /// + /// + /// + /// + /// Query subaccount's deposit records by main UID's API key. + public async Task GetAssetSubDepositRecords(string subMemberId, string? coin = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { { "subMemberId", subMemberId } }; + + BybitParametersUtils.AddOptionalParameters(query, + ("coin", coin), + ("startTime", startTime), + ("endTime", endTime), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(SUB_DEPOSIT_RECORDS, HttpMethod.Get, query: query); + return result; + } + + private const string INTERNAL_DEPOSIT_RECORDS = "/v5/asset/deposit/query-sub-member-record"; + /// + /// The maximum difference between the start time and the end time is 30 days. + /// Support to get deposit records by Master or Sub Member Api Key + /// + /// + /// + /// + /// + /// + /// Query deposit records within the Bybit platform. These transactions are not on the blockchain. + public async Task GetAssetInternalDepositRecords(string? coin = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { }; + + BybitParametersUtils.AddOptionalParameters(query, + ("coin", coin), + ("startTime", startTime), + ("endTime", endTime), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(INTERNAL_DEPOSIT_RECORDS, HttpMethod.Get, query: query); + return result; + } + + private const string MASTER_DEPOSIT_ADDRESS = "/v5/asset/deposit/query-address"; + /// + /// Query the deposit address information of MASTER account. + /// + /// + /// + /// Master Deposit Address + public async Task GetAssetMasterDepositAddress(string coin, string? chainType = null) + { + var query = new Dictionary { { "coin", coin } }; + + BybitParametersUtils.AddOptionalParameters(query, + ("chainType", chainType) + ); + var result = await this.SendSignedAsync(MASTER_DEPOSIT_ADDRESS, HttpMethod.Get, query: query); + return result; + } + + private const string SUB_DEPOSIT_ADDRESS = "/v5/asset/deposit/query-sub-member-address"; + /// + /// Query the deposit address information of SUB account. + /// Can use master UID's api key only + /// + /// + /// + /// + /// Sub Deposit Address + public async Task GetAssetSubDepositAddress(string coin, string chainType, string subMemberId) + { + var query = new Dictionary { { "coin", coin }, { "chainType", chainType }, { "subMemberId", subMemberId } }; + var result = await this.SendSignedAsync(SUB_DEPOSIT_ADDRESS, HttpMethod.Get, query: query); + return result; + } + + private const string COIN_INFO = "/v5/asset/coin/query-info"; + /// + /// Query coin information, including chain information, withdraw and deposit status. + /// + /// + /// Coin Info + public async Task GetAssetCoinInfo(string? coin = null) + { + var query = new Dictionary { }; + BybitParametersUtils.AddOptionalParameters(query, + ("coin", coin) + ); + var result = await this.SendSignedAsync(COIN_INFO, HttpMethod.Get, query: query); + return result; + } + + private const string WITHDRAW_RECORDS = "/v5/asset/withdraw/query-record"; + /// + /// endTime - startTime should be less than 30 days. Query last 30 days records by default. + /// Can query by the master UID's api key only + /// + /// + /// + /// + /// + /// + /// + /// + /// Get Withdrawal Records + public async Task GetAssetWithdrawRecords(string? coin = null, string? withdrawID = null, WithdrawType? withdrawType = null, long? startTime = null, long? endTime = null, int? limit = null, string? cursor = null) + { + var query = new Dictionary { }; + BybitParametersUtils.AddOptionalParameters(query, + ("withdrawID", withdrawID), + ("coin", coin), + ("withdrawType", withdrawType?.Value), + ("startTime", startTime), + ("endTime", endTime), + ("limit", limit), + ("cursor", cursor) + ); + var result = await this.SendSignedAsync(WITHDRAW_RECORDS, HttpMethod.Get, query: query); + return result; + } + + private const string WITHDRAWABLE_AMOUNT = "/v5/asset/withdraw/withdrawable-amount"; + /// + /// How can partial funds be subject to delayed withdrawal requests? + /// On-chain deposit: If the number of on-chain confirmations has not reached a risk-controlled level, a portion of the funds will be frozen for a period of time until they are unfrozen. + /// Buying crypto: If there is a risk, the funds will be frozen for a certain period of time and cannot be withdrawn. + /// + /// + /// Get Withdrawable Amount + public async Task GetAssetWithdrawableAmount(string coin) + { + var query = new Dictionary { { "coin", coin } }; + var result = await this.SendSignedAsync(WITHDRAWABLE_AMOUNT, HttpMethod.Get, query: query); + return result; + } + + private const string ASSET_WITHDRAW = "/v5/asset/withdraw/create"; + /// + /// Withdraw assets from your Bybit account. You can make an off-chain transfer if the target wallet address is from Bybit. This means that no blockchain fee will be charged. + /// UTA does not have SPOT account + /// How do I know if my account is a UTA account? Call this endpoint, and if uta=1, then it is a UTA account. + /// Make sure you have whitelisted your wallet address here + /// Can query by the master UID's api key only + /// feeType = 0: + /// withdrawPercentageFee != 0: handlingFee = inputAmount / (1 - withdrawPercentageFee) * withdrawPercentageFee + withdrawFee + /// withdrawPercentageFee = 0: handlingFee = withdrawFee + /// feeType = 1: + /// withdrawPercentageFee != 0: handlingFee = withdrawFee + (inputAmount - withdrawFee) * withdrawPercentageFee + /// withdrawPercentageFee = 0: handlingFee = withdrawFee + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// id + public async Task PlaceAssetWithdraw(string coin, string chain, string address, string amount, long timestamp, string? tag = null, int? forceChain = null, AccountType? accountType = null, FeeType? feeType = null) + { + var query = new Dictionary { { "coin", coin }, { "chain", chain }, { "address", address }, { "amount", amount }, { "timestamp", timestamp } }; + BybitParametersUtils.AddOptionalParameters(query, + ("tag", tag), + ("forceChain", forceChain), + ("accountType", accountType?.Value), + ("feeType", feeType?.Value) + ); + var result = await this.SendSignedAsync(ASSET_WITHDRAW, HttpMethod.Post, query: query); + return result; + } + + private const string CANCEL_WITHDRAW = "/v5/asset/withdraw/cancel"; + /// + /// Cancel the withdrawal + /// Can query by the master UID's api key only + /// + /// + /// status + public async Task CancelAssetWithdrawal(string id) + { + var query = new Dictionary { { "id", id } }; + var result = await this.SendSignedAsync(CANCEL_WITHDRAW, HttpMethod.Post, query: query); + return result; + } + } +} diff --git a/Src/Common/Services/BybitService.cs b/Src/Common/Services/BybitService.cs index 4228459..b7d7092 100644 --- a/Src/Common/Services/BybitService.cs +++ b/Src/Common/Services/BybitService.cs @@ -11,7 +11,7 @@ namespace bybit.net.api public abstract class BybitService { private static readonly string UserAgent = "bybit.net.api/" + VersionInfo.GetVersion; - private static readonly string CurrentTimeStamp = BybitParametersUtils.GetCurrentTimeStamp(); + private static string CurrentTimeStamp => BybitParametersUtils.GetCurrentTimeStamp(); private readonly string? apiKey; private readonly string? apiSecret; private readonly string? url;