Skip to content

Commit

Permalink
feat: add inverse wallet endpoint implementation (#28)
Browse files Browse the repository at this point in the history
* add wallet endpoints

* add tests for inverse wallet endpoints

* update readme

* fix github actions
  • Loading branch information
cksidharthan authored Sep 16, 2022
1 parent 670ecec commit b5d1324
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 12 deletions.
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
with:
go-version: '^1.18'
- run: go test ./... -coverpkg=./... -coverprofile=coverage.out
- run: go test ./... -json > test.out
- run: go vet ./... 2> govet.out || true # Ignore go vet status code

lint-check:
Expand Down
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.0.4
v0.0.6
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ go get -u github.com/cksidharthan/go-bybit
| USDT Perpetual | [Wallet Data](https://bybit-exchange.github.io/docs/futuresV2/linear/#t-wallet) | :heavy_check_mark: | :heavy_check_mark: |
| Inverse Perpetual | [Market Data](https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-marketdata) | :heavy_check_mark: | :heavy_check_mark: |
| Inverse Perpetual | [Account Data](https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-accountdata) | :construction: | :construction: |
| Inverse Perpetual | [Wallet Data](https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-wallet) | :construction: | :construction: |
| Inverse Perpetual | [Wallet Data](https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-wallet) | :heavy_check_mark: | :heavy_check_mark: |

### Contributing

Expand Down
5 changes: 5 additions & 0 deletions bybit/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,9 @@ const (
PublicInversePerpetualOpenInterestPath = "/v2/public/open-interest"
PublicInversePerpetualLatestBigDealPath = "/v2/public/big-deal"
PublicInversePerpetualLongShortRatioPath = "/v2/public/account-ratio"

PrivateInversePerpetualWalletBalancePath = "/v2/private/wallet/balance"
PrivateInversePerpetualWalletFundRecordsPath = "/v2/private/wallet/fund/records"
PrivateInversePerpetualWithdrawRecordsPath = "/v2/private/wallet/withdraw/list"
PrivateInversePerpetualAssetExchangeRecords = "/v2/private/exchange-order/list"
)
6 changes: 6 additions & 0 deletions rest/domain/inverse_perpetual/wallet_methods.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
package inverseperp

import "context"

type WalletInterface interface {
GetWalletBalance(ctx context.Context, params *WalletBalanceParams) (*WalletBalanceResponse, error)
GetWalletFundRecords(ctx context.Context, params *WalletFundRecordsParams) (*WalletFundRecordsResponse, error)
GetWithdrawRecords(ctx context.Context, params *WithdrawRecordsParams) (*WithdrawRecordsResponse, error)
GetAssetExchangeRecords(ctx context.Context, params *AssetExchangeRecordsParams) (*AssetExchangeRecordsResponse, error)
}
114 changes: 114 additions & 0 deletions rest/domain/inverse_perpetual/wallet_types.go
Original file line number Diff line number Diff line change
@@ -1 +1,115 @@
package inverseperp

import "github.com/cksidharthan/go-bybit/rest/domain"

type WalletBalanceParams struct {
Coin string `url:"coin" json:"coin,omitempty" description:"currency alias. Returns all wallet balances if not passed."`
}

type WalletBalanceResponse struct {
domain.BaseResponse `json:",inline"`
Result map[string]WalletBalanceResult `json:"result"`
}

type WalletBalanceResult struct {
Equity float64 `url:"equity" json:"equity"`
AvailableBalance float64 `url:"available_balance" json:"available_balance"`
UsedMargin float64 `url:"used_margin" json:"used_margin"`
OrderMargin float64 `url:"order_margin" json:"order_margin"`
PositionMargin float64 `url:"position_margin" json:"position_margin"`
OccClosingFee float64 `url:"occ_closing_fee" json:"occ_closing_fee"`
OccFundingFee float64 `url:"occ_funding_fee" json:"occ_funding_fee"`
WalletBalance float64 `url:"wallet_balance" json:"wallet_balance"`
RealisedPnl float64 `url:"realised_pnl" json:"realised_pnl"`
UnrealisedPnl float64 `url:"unrealised_pnl" json:"unrealised_pnl"`
CumRealisedPnl float64 `url:"cum_realised_pnl" json:"cum_realised_pnl"`
GivenCash float64 `url:"given_cash" json:"given_cash"`
ServiceCash float64 `url:"service_cash" json:"service_cash"`
}

type WalletFundRecordsParams struct {
StartDate string `url:"start_date" json:"start_date,omitempty" description:"start date of the query"`
EndDate string `url:"end_date" json:"end_date,omitempty" description:"end date of the query"`
Currency string `url:"currency" json:"currency,omitempty" description:"currency alias"`
Coin string `url:"coin" json:"coin,omitempty" description:"currency alias"`
WalletFundType string `url:"wallet_fund_type" json:"wallet_fund_type,omitempty" description:"wallet fund type"`
Limit int64 `url:"limit" json:"limit,omitempty" description:"number of records to return"`
Page int64 `url:"page" json:"page,omitempty" description:"page number"`
}

type WalletFundRecordsResponse struct {
domain.BaseResponse `json:",inline"`
Result WalletFundRecordsResult `json:"result"`
}

type WalletFundRecordsResult struct {
Data []WalletFundRecordsData `json:"data"`
}

type WalletFundRecordsData struct {
UserID int64 `url:"user_id" json:"user_id"`
ID int64 `url:"id" json:"id"`
Coin string `url:"coin" json:"coin"`
WalletID int64 `url:"wallet_id" json:"wallet_id"`
Type string `url:"type" json:"type"`
Amount float64 `url:"amount" json:"amount"`
TxID string `url:"tx_id" json:"tx_id"`
Address string `url:"address" json:"address"`
WalletBalance string `url:"wallet_balance" json:"wallet_balance"`
ExecTime string `url:"exec_time" json:"exec_time"`
CrossSeq int64 `url:"cross_seq" json:"cross_seq"`
}

type WithdrawRecordsParams struct {
StartDate string `url:"start_date" json:"start_date,omitempty" description:"start date of the query"`
EndDate string `url:"end_date" json:"end_date,omitempty" description:"end date of the query"`
Coin string `url:"coin" json:"coin,omitempty" description:"currency alias"`
Status string `url:"status" json:"status,omitempty" description:"status of the withdrawal"`
Limit int64 `url:"limit" json:"limit,omitempty" description:"number of records to return"`
Page int64 `url:"page" json:"page,omitempty" description:"page number"`
}

type WithdrawRecordsResponse struct {
domain.BaseResponse `json:",inline"`
Result WithdrawRecordsResult `json:"result"`
}

type WithdrawRecordsResult struct {
Data []WithdrawRecordsData `json:"data"`
CurrentPage int64 `json:"current_page"`
LastPage int64 `json:"last_page"`
}

type WithdrawRecordsData struct {
ID int64 `url:"id" json:"id"`
UserID int64 `url:"user_id" json:"user_id"`
Coin string `url:"coin" json:"coin"`
Status string `url:"status" json:"status"`
Amount string `url:"amount" json:"amount"`
Fee string `url:"fee" json:"fee"`
Address string `url:"address" json:"address"`
TxID string `url:"tx_id" json:"tx_id"`
SubmittedAt string `url:"submitted_at" json:"submitted_at"`
UpdatedAt string `url:"updated_at" json:"updated_at"`
}

type AssetExchangeRecordsParams struct {
Limit int64 `url:"limit" json:"limit,omitempty" description:"number of records to return"`
From int64 `url:"from" json:"from,omitempty" description:"from id"`
Direction string `url:"direction" json:"direction,omitempty" description:"direction of the query"`
}

type AssetExchangeRecordsResponse struct {
domain.BaseResponse `json:",inline"`
Result []AssetExchangeRecordsResult `json:"result"`
}

type AssetExchangeRecordsResult struct {
FromCoin string `url:"from_coin" json:"from_coin"`
FromAmount float64 `url:"from_amount" json:"from_amount"`
ToCoin string `url:"to_coin" json:"to_coin"`
ToAmount float64 `url:"to_amount" json:"to_amount"`
ExchangeRate float64 `url:"exchange_rate" json:"exchange_rate"`
FromFee float64 `url:"from_fee" json:"from_fee"`
CreatedAt string `url:"created_at" json:"created_at"`
}
6 changes: 3 additions & 3 deletions rest/domain/linear/account_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,9 +500,9 @@ type AddReduceMarginResult struct {
}

type SetLeverageParams struct {
Symbol string `url:"symbol" json:"symbol"`
BuyLeverage int `url:"buy_leverage" json:"buy_leverage"`
SellLeverage int `url:"sell_leverage" json:"sell_leverage"`
Symbol string `url:"symbol" json:"symbol"`
BuyLeverage float64 `url:"buy_leverage" json:"buy_leverage"`
SellLeverage float64 `url:"sell_leverage" json:"sell_leverage"`
}

type SetLeverageResponse struct {
Expand Down
2 changes: 1 addition & 1 deletion rest/inverse_perpetual/market/market.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (c *InversePerpetualMarketClient) QueryPremiumIndexKline(ctx context.Contex
//
// docs - https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-marketopeninterest
func (c *InversePerpetualMarketClient) OpenInterest(ctx context.Context, params *inverseperp.OpenInterestParams) (response *inverseperp.OpenInterestResponse, err error) {
err = c.Transporter.UnsignedRequest(ctx, http.MethodGet, bybit.PublicInversePerpetualOrderBookPath, params, &response)
err = c.Transporter.UnsignedRequest(ctx, http.MethodGet, bybit.PublicInversePerpetualOpenInterestPath, params, &response)
if err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion rest/inverse_perpetual/market/market_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func TestClient_InversePerpetual_Market(t *testing.T) {
t.Parallel()
response, err := bybitClient.Market().OpenInterest(context.Background(), &domain.OpenInterestParams{
Symbol: "BTCUSD",
Limit: 50,
Period: "5min",
})
assert.NoError(t, err)
assert.Equal(t, 0, response.RetCode)
Expand Down
4 changes: 2 additions & 2 deletions rest/inverse_perpetual/wallet/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import (
)

type InversePerpetualWalletClient struct {
transporter transport.Transporter
Transporter transport.Transporter
}

func NewInversePerpetualWalletClient(url, apiKey, apiSecret string) *InversePerpetualWalletClient {
transporter := httpTransport.New(url, apiKey, apiSecret)
return &InversePerpetualWalletClient{
transporter: transporter,
Transporter: transporter,
}
}
79 changes: 79 additions & 0 deletions rest/inverse_perpetual/wallet/wallet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package wallet

import (
"context"
"net/http"

"github.com/cksidharthan/go-bybit/bybit"
inverseperp "github.com/cksidharthan/go-bybit/rest/domain/inverse_perpetual"
)

/*
GetWalletBalance - get wallet balance. [ /v2/private/wallet/balance - GET ]
# Get wallet balance info
docs - https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-balance
*/
func (c *InversePerpetualWalletClient) GetWalletBalance(ctx context.Context, params *inverseperp.WalletBalanceParams) (response *inverseperp.WalletBalanceResponse, err error) {
err = c.Transporter.SignedRequest(ctx, http.MethodGet, bybit.PrivateInversePerpetualWalletBalancePath, params, &response)
if err != nil {
return
}
return
}

/*
GetWalletFundRecords - get wallet fund records. [ /v2/private/wallet/fund/records - GET ]
Get wallet fund records. This endpoint also shows exchanges from the Asset Exchange, where the types for the exchange are ExchangeOrderWithdraw and ExchangeOrderDeposit.
This endpoint returns incomplete information for transfers involving the derivatives wallet. Use the account asset API for creating and querying internal transfers.
docs - https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-walletrecords
*/
func (c *InversePerpetualWalletClient) GetWalletFundRecords(ctx context.Context, params *inverseperp.WalletFundRecordsParams) (response *inverseperp.WalletFundRecordsResponse, err error) {
err = c.Transporter.SignedRequest(ctx, http.MethodGet, bybit.PrivateInversePerpetualWalletFundRecordsPath, params, &response)
if err != nil {
return
}
return
}

/*
GetWithdrawRecords - get wallet withdraw records. [ /v2/private/wallet/withdraw/list - GET ]
Get withdrawal records.
The difference between data returned by this endpoint and data of type Withdraw in the Wallet Fund Records endpoint:
This endpoint provides one withdrawal operation per record, and you can check the current withdrawal state with the status field.
Once you have submitted a withdrawal application, there will be a record with type Withdraw, and if the application is CancelByUser, Reject or Expire in the Wallet Fund Records endpoint, with a corresponding record with type Refund.
docs - https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-withdrawrecords
*/
func (c *InversePerpetualWalletClient) GetWithdrawRecords(ctx context.Context, params *inverseperp.WithdrawRecordsParams) (response *inverseperp.WithdrawRecordsResponse, err error) {
err = c.Transporter.SignedRequest(ctx, http.MethodGet, bybit.PrivateInversePerpetualWithdrawRecordsPath, params, &response)
if err != nil {
return
}
return
}

/*
GetAssetExchangeRecords - get asset exchange records. [ /v2/private/asset/records - GET ]
Get asset exchange records.
This endpoint returns the records of asset exchanges, including the exchanges from the Wallet Fund Records endpoint.
docs - https://bybit-exchange.github.io/docs/futuresV2/inverse/#t-assetexchangerecords
*/
func (c *InversePerpetualWalletClient) GetAssetExchangeRecords(ctx context.Context, params *inverseperp.AssetExchangeRecordsParams) (response *inverseperp.AssetExchangeRecordsResponse, err error) {
err = c.Transporter.SignedRequest(ctx, http.MethodGet, bybit.PrivateInversePerpetualAssetExchangeRecords, params, &response)
if err != nil {
return
}
return
}
55 changes: 55 additions & 0 deletions rest/inverse_perpetual/wallet/wallet_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package wallet_test

import (
"context"
"os"
"testing"

"github.com/cksidharthan/go-bybit/bybit"
domain "github.com/cksidharthan/go-bybit/rest/domain/inverse_perpetual"
inverseperp "github.com/cksidharthan/go-bybit/rest/inverse_perpetual"
"github.com/stretchr/testify/assert"
)

func TestClient_InversePerpetualWallet(t *testing.T) {
t.Parallel()
inversePerpClient := inverseperp.NewInversePerpetualClient(bybit.BybitTestnetBaseURL, os.Getenv("BYBIT_API_KEY"), os.Getenv("BYBIT_API_SECRET"))

t.Run("Get Wallet Balance - INVERSE PERPETUAL", func(t *testing.T) {
t.Parallel()
response, err := inversePerpClient.Wallet().GetWalletBalance(context.Background(), &domain.WalletBalanceParams{
Coin: "BTC",
})
assert.NoError(t, err)
assert.Equal(t, 0, response.RetCode)
assert.NotEmpty(t, response)
assert.NotNil(t, response)
})

t.Run("Get Wallet Fund Records - INVERSE PERPETUAL", func(t *testing.T) {
t.Parallel()
response, err := inversePerpClient.Wallet().GetWalletFundRecords(context.Background(), &domain.WalletFundRecordsParams{})
assert.NoError(t, err)
assert.Equal(t, 0, response.RetCode)
assert.NotEmpty(t, response)
assert.NotNil(t, response)
})

t.Run("Get Withdraw Records - INVERSE PERPETUAL", func(t *testing.T) {
t.Parallel()
response, err := inversePerpClient.Wallet().GetWithdrawRecords(context.Background(), &domain.WithdrawRecordsParams{})
assert.NoError(t, err)
assert.Equal(t, 0, response.RetCode)
assert.NotEmpty(t, response)
assert.NotNil(t, response)
})

t.Run("Get Asset Exchange Records - INVERSE PERPETUAL", func(t *testing.T) {
t.Parallel()
response, err := inversePerpClient.Wallet().GetAssetExchangeRecords(context.Background(), &domain.AssetExchangeRecordsParams{})
assert.NoError(t, err)
assert.Equal(t, 0, response.RetCode)
assert.NotEmpty(t, response)
assert.NotNil(t, response)
})
}
10 changes: 8 additions & 2 deletions rest/linear/wallet/wallet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ func TestClient_Linear_Wallet(t *testing.T) {

t.Run("Get Wallet Balance - LINEAR", func(t *testing.T) {
t.Parallel()
response, err := bybitClient.Wallet().GetWalletBalance(context.Background(), &linear.GetWalletBalanceParams{})
response, err := bybitClient.Wallet().GetWalletBalance(context.Background(), &linear.GetWalletBalanceParams{
Coin: "BTC",
})
assert.NoError(t, err)
assert.Equal(t, 0, response.RetCode)
assert.NotEmpty(t, response)
Expand Down Expand Up @@ -45,7 +47,11 @@ func TestClient_Linear_Wallet(t *testing.T) {

t.Run("Get Asset Exchange Records - LINEAR", func(t *testing.T) {
t.Parallel()
response, err := bybitClient.Wallet().GetAssetExchangeRecords(context.Background(), &linear.GetAssetExchangeRecordsParams{})
response, err := bybitClient.Wallet().GetAssetExchangeRecords(context.Background(), &linear.GetAssetExchangeRecordsParams{
Limit: 5,
From: 0,
Direction: "",
})
assert.NoError(t, err)
assert.Equal(t, 0, response.RetCode)
assert.NotEmpty(t, response)
Expand Down

0 comments on commit b5d1324

Please sign in to comment.