From b2599993b7691ce50d24c96f69b78010d9b4d48d Mon Sep 17 00:00:00 2001 From: hirokisan Date: Sat, 15 Apr 2023 10:39:41 +0900 Subject: [PATCH] feat: v5 get transaction log (#120) * feat: implement * test: integration * test: unit * docs: update --- README.md | 1 + integrationtest/v5/account/account_test.go | 14 +++ .../v5-account-get-transaction-log.json | 26 +++++ v5_account_service.go | 70 ++++++++++++ v5_account_service_test.go | 104 ++++++++++++++++++ v5_enum.go | 17 +++ 6 files changed, 232 insertions(+) create mode 100644 integrationtest/v5/account/testdata/v5-account-get-transaction-log.json diff --git a/README.md b/README.md index a524013..ee2691a 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ The following API endpoints have been implemented - [`/v5/account/wallet-balance` Get Wallet Balance](https://bybit-exchange.github.io/docs/v5/account/wallet-balance) - [`/v5/account/account-info` Get Account Info](https://bybit-exchange.github.io/docs/v5/account/account-info) +- [`/v5/account/transaction-log` Get Transaction Log](https://bybit-exchange.github.io/docs/v5/account/transaction-log) #### Asset diff --git a/integrationtest/v5/account/account_test.go b/integrationtest/v5/account/account_test.go index d92e4cb..11556e8 100644 --- a/integrationtest/v5/account/account_test.go +++ b/integrationtest/v5/account/account_test.go @@ -31,3 +31,17 @@ func TestGetAccountInfo(t *testing.T) { testhelper.UpdateFile(t, goldenFilename, testhelper.ConvertToJSON(res.Result)) } } + +func TestGetTransactionLog(t *testing.T) { + client := bybit.NewTestClient().WithAuthFromEnv() + limit := 1 + res, err := client.V5().Account().GetTransactionLog(bybit.V5GetTransactionLogParam{ + Limit: &limit, + }) + require.NoError(t, err) + { + goldenFilename := "./testdata/v5-account-get-transaction-log.json" + testhelper.Compare(t, goldenFilename, testhelper.ConvertToJSON(res.Result)) + testhelper.UpdateFile(t, goldenFilename, testhelper.ConvertToJSON(res.Result)) + } +} diff --git a/integrationtest/v5/account/testdata/v5-account-get-transaction-log.json b/integrationtest/v5/account/testdata/v5-account-get-transaction-log.json new file mode 100644 index 0000000..73ed45c --- /dev/null +++ b/integrationtest/v5/account/testdata/v5-account-get-transaction-log.json @@ -0,0 +1,26 @@ +{ + "nextPageCursor": "133%3A1%2C133%3A1", + "list": [ + { + "symbol": "BTCUSDT", + "category": "linear", + "side": "Sell", + "transactionTime": "1680525485078", + "type": "TRADE", + "qty": "0.01", + "size": "0", + "currency": "USDT", + "tradePrice": "28149.9", + "funding": "", + "fee": "0.16889940", + "cashFlow": "0.052", + "change": "-0.1168994", + "cashBalance": "1149.11399896", + "feeRate": "0.0006", + "bonusChange": "0", + "tradeId": "259f8703-26ff-5e31-b9c6-edf3f2869f9a", + "orderId": "bb9020dc-92e2-4216-becf-cf4be4dcc81a", + "orderLinkId": "" + } + ] +} \ No newline at end of file diff --git a/v5_account_service.go b/v5_account_service.go index 9af1c7c..b20d36f 100644 --- a/v5_account_service.go +++ b/v5_account_service.go @@ -3,12 +3,15 @@ package bybit import ( "net/url" "strings" + + "github.com/google/go-querystring/query" ) // V5AccountServiceI : type V5AccountServiceI interface { GetWalletBalance(AccountType, []Coin) (*V5GetWalletBalanceResponse, error) GetAccountInfo() (*V5GetAccountInfoResponse, error) + GetTransactionLog(V5GetTransactionLogParam) (*V5GetTransactionLogResponse, error) } // V5AccountService : @@ -114,3 +117,70 @@ func (s *V5AccountService) GetAccountInfo() (*V5GetAccountInfoResponse, error) { return &res, nil } + +// V5GetTransactionLogParam : +type V5GetTransactionLogParam struct { + AccountType *AccountTypeV5 `url:"accountType,omitempty"` + Category *CategoryV5 `url:"category,omitempty"` + Currency *string `url:"currency,omitempty"` + BaseCoin *Coin `url:"baseCoin,omitempty"` + Type *TransactionLogTypeV5 `url:"type,omitempty"` + StartTime *int64 `url:"startTime,omitempty"` // The start timestamp (ms) + EndTime *int64 `url:"endTime,omitempty"` // The start timestamp (ms) + Limit *int `url:"limit,omitempty"` // Limit for data size per page. [1, 50]. Default: 20 + Cursor *string `url:"cursor,omitempty"` +} + +// V5GetTransactionLogResponse : +type V5GetTransactionLogResponse struct { + CommonV5Response `json:",inline"` + Result V5GetTransactionLogResult `json:"result"` +} + +// V5GetTransactionLogResult : +type V5GetTransactionLogResult struct { + NextPageCursor string `json:"nextPageCursor"` + List V5GetTransactionLogList `json:"list"` +} + +// V5GetTransactionLogList : +type V5GetTransactionLogList []V5GetTransactionLogItem + +// V5GetTransactionLogItem : +type V5GetTransactionLogItem struct { + Symbol SymbolV5 `json:"symbol"` + Category CategoryV5 `json:"category"` + Side Side `json:"side"` + TransactionTime string `json:"transactionTime"` + Type TransactionLogTypeV5 `json:"type"` + Qty string `json:"qty"` + Size string `json:"size"` + Currency string `json:"currency"` + TradePrice string `json:"tradePrice"` + Funding string `json:"funding"` + Fee string `json:"fee"` + CashFlow string `json:"cashFlow"` + Change string `json:"change"` + CashBalance string `json:"cashBalance"` + FeeRate string `json:"feeRate"` + BonusChange string `json:"bonusChange"` + TradeID string `json:"tradeId"` + OrderID string `json:"orderId"` + OrderLinkID string `json:"orderLinkId"` +} + +// GetTransactionLog : +func (s *V5AccountService) GetTransactionLog(param V5GetTransactionLogParam) (*V5GetTransactionLogResponse, error) { + var res V5GetTransactionLogResponse + + queryString, err := query.Values(param) + if err != nil { + return nil, err + } + + if err := s.client.getV5Privately("/v5/account/transaction-log", queryString, &res); err != nil { + return nil, err + } + + return &res, nil +} diff --git a/v5_account_service_test.go b/v5_account_service_test.go index 9e81d0c..f196584 100644 --- a/v5_account_service_test.go +++ b/v5_account_service_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/hirokisan/bybit/v2/testhelper" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -102,3 +103,106 @@ func TestV5Account_GetAccountInfo(t *testing.T) { testhelper.Compare(t, respBody["result"], resp.Result) }) } + +func TestV5Account_GetTransactionLog(t *testing.T) { + t.Run("success", func(t *testing.T) { + param := V5GetTransactionLogParam{} + + path := "/v5/account/transaction-log" + method := http.MethodGet + status := http.StatusOK + respBody := map[string]interface{}{ + "result": map[string]interface{}{ + "nextPageCursor": "133%3A1%2C133%3A1", + "list": []map[string]interface{}{ + { + "symbol": "BTCUSDT", + "category": "linear", + "side": "Sell", + "transactionTime": "1680525485078", + "type": "TRADE", + "qty": "0.01", + "size": "0", + "currency": "USDT", + "tradePrice": "28149.9", + "funding": "", + "fee": "0.16889940", + "cashFlow": "0.052", + "change": "-0.1168994", + "cashBalance": "1149.11399896", + "feeRate": "0.0006", + "bonusChange": "0", + "tradeId": "259f8703-26ff-5e31-b9c6-edf3f2869f9a", + "orderId": "bb9020dc-92e2-4216-becf-cf4be4dcc81a", + "orderLinkId": "", + }, + }, + }, + } + bytesBody, err := json.Marshal(respBody) + require.NoError(t, err) + + server, teardown := testhelper.NewServer( + testhelper.WithHandlerOption(path, method, status, bytesBody), + ) + defer teardown() + + client := NewTestClient(). + WithBaseURL(server.URL). + WithAuth("test", "test") + + resp, err := client.V5().Account().GetTransactionLog(param) + require.NoError(t, err) + + require.NotNil(t, resp) + testhelper.Compare(t, respBody["result"], resp.Result) + }) + t.Run("authentication required", func(t *testing.T) { + param := V5GetTransactionLogParam{} + + path := "/v5/account/transaction-log" + method := http.MethodGet + status := http.StatusOK + respBody := map[string]interface{}{ + "result": map[string]interface{}{ + "nextPageCursor": "133%3A1%2C133%3A1", + "list": []map[string]interface{}{ + { + "symbol": "BTCUSDT", + "category": "linear", + "side": "Sell", + "transactionTime": "1680525485078", + "type": "TRADE", + "qty": "0.01", + "size": "0", + "currency": "USDT", + "tradePrice": "28149.9", + "funding": "", + "fee": "0.16889940", + "cashFlow": "0.052", + "change": "-0.1168994", + "cashBalance": "1149.11399896", + "feeRate": "0.0006", + "bonusChange": "0", + "tradeId": "259f8703-26ff-5e31-b9c6-edf3f2869f9a", + "orderId": "bb9020dc-92e2-4216-becf-cf4be4dcc81a", + "orderLinkId": "", + }, + }, + }, + } + bytesBody, err := json.Marshal(respBody) + require.NoError(t, err) + + server, teardown := testhelper.NewServer( + testhelper.WithHandlerOption(path, method, status, bytesBody), + ) + defer teardown() + + client := NewTestClient(). + WithBaseURL(server.URL) + + _, err = client.V5().Account().GetTransactionLog(param) + assert.Error(t, err) + }) +} diff --git a/v5_enum.go b/v5_enum.go index 0bafa28..6ae01cf 100644 --- a/v5_enum.go +++ b/v5_enum.go @@ -227,3 +227,20 @@ const ( // UnifiedMarginStatusUnifiedTrade : Unified trade account, it can trade linear perpetual, options and spot UnifiedMarginStatusUnifiedTrade = UnifiedMarginStatus(3) ) + +// TransactionLogTypeV5 : +type TransactionLogTypeV5 string + +const ( + TransactionLogTypeV5TRANSFERIN = TransactionLogTypeV5("TRANSFER_IN") + TransactionLogTypeV5TRANSFEROUT = TransactionLogTypeV5("TRANSFER_OUT") + TransactionLogTypeV5TRADE = TransactionLogTypeV5("TRADE") + TransactionLogTypeV5SETTLEMENT = TransactionLogTypeV5("SETTLEMENT") + TransactionLogTypeV5DELIVERY = TransactionLogTypeV5("DELIVERY") + TransactionLogTypeV5LIQUIDATION = TransactionLogTypeV5("LIQUIDATION") + TransactionLogTypeV5BONUS = TransactionLogTypeV5("BONUS") + TransactionLogTypeV5FEEREFUND = TransactionLogTypeV5("FEE_REFUND") + TransactionLogTypeV5INTEREST = TransactionLogTypeV5("INTEREST") + TransactionLogTypeV5CURRENCYBUY = TransactionLogTypeV5("CURRENCY_BUY") + TransactionLogTypeV5CURRENCYSELL = TransactionLogTypeV5("CURRENCY_SELL") +)