decred.org/dcrdex@v1.0.5/client/mm/libxc/binance_live_test.go (about) 1 //go:build bnclive 2 3 package libxc 4 5 import ( 6 "context" 7 "encoding/json" 8 "fmt" 9 "os" 10 "os/user" 11 "strings" 12 "sync" 13 "testing" 14 "time" 15 16 "decred.org/dcrdex/client/asset" 17 _ "decred.org/dcrdex/client/asset/importall" 18 "decred.org/dcrdex/client/mm/libxc/bntypes" 19 "decred.org/dcrdex/dex" 20 ) 21 22 var ( 23 log = dex.StdOutLogger("T", dex.LevelTrace) 24 u, _ = user.Current() 25 apiKey = "" 26 apiSecret = "" 27 ) 28 29 func TestMain(m *testing.M) { 30 if s := os.Getenv("SECRET"); s != "" { 31 apiSecret = s 32 } 33 if k := os.Getenv("KEY"); k != "" { 34 apiKey = k 35 } 36 37 m.Run() 38 } 39 40 func tNewBinance(t *testing.T, net dex.Network) *binance { 41 cfg := &CEXConfig{ 42 Net: net, 43 APIKey: apiKey, 44 SecretKey: apiSecret, 45 Logger: log, 46 Notify: func(n interface{}) { 47 log.Infof("Notification sent: %+v", n) 48 }, 49 } 50 const binanceUS = true 51 return newBinance(cfg, binanceUS) 52 } 53 54 type spoofDriver struct { 55 cFactor uint64 56 } 57 58 func (drv *spoofDriver) Open(*asset.WalletConfig, dex.Logger, dex.Network) (asset.Wallet, error) { 59 return nil, nil 60 } 61 62 func (drv *spoofDriver) DecodeCoinID(coinID []byte) (string, error) { 63 return "", nil 64 } 65 66 func (drv *spoofDriver) Info() *asset.WalletInfo { 67 return &asset.WalletInfo{ 68 UnitInfo: dex.UnitInfo{ 69 Conventional: dex.Denomination{ 70 ConversionFactor: drv.cFactor, 71 }, 72 }, 73 } 74 } 75 76 func TestConnect(t *testing.T) { 77 bnc := tNewBinance(t, dex.Simnet) 78 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 79 defer cancel() 80 81 _, err := bnc.Connect(ctx) 82 if err != nil { 83 t.Fatalf("Connect error: %v", err) 84 } 85 86 balance, err := bnc.Balance(60) 87 if err != nil { 88 t.Fatalf("Balance error: %v", err) 89 } 90 t.Logf("usdc balance: %v", balance) 91 92 balance, err = bnc.Balance(0) 93 if err != nil { 94 t.Fatalf("Balance error: %v", err) 95 } 96 t.Logf("btc balance: %v", balance) 97 } 98 99 // This may fail due to balance being to low. You can try switching the side 100 // of the trade or the qty. 101 func TestTrade(t *testing.T) { 102 bnc := tNewBinance(t, dex.Testnet) 103 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 104 defer cancel() 105 _, err := bnc.Connect(ctx) 106 if err != nil { 107 t.Fatalf("Connect error: %v", err) 108 } 109 110 wg := sync.WaitGroup{} 111 wg.Add(1) 112 updates, unsubscribe, updaterID := bnc.SubscribeTradeUpdates() 113 defer unsubscribe() 114 115 go func() { 116 defer wg.Done() 117 for { 118 select { 119 case tradeUpdate := <-updates: 120 t.Logf("Trade Update: %+v", tradeUpdate) 121 if tradeUpdate.Complete { 122 // Sleep because context might get cancelled before 123 // Trade returns. 124 time.Sleep(1 * time.Second) 125 cancel() 126 return 127 } 128 case <-ctx.Done(): 129 return 130 } 131 } 132 }() 133 134 trade, err := bnc.Trade(ctx, 60, 60001, false, 3600e5, 1e7, updaterID) 135 if err != nil { 136 t.Fatalf("trade error: %v", err) 137 } 138 139 if false { // Cancel the trade 140 time.Sleep(1 * time.Second) 141 err = bnc.CancelTrade(ctx, 60, 0, trade.ID) 142 if err != nil { 143 t.Fatalf("error cancelling trade: %v", err) 144 } 145 } 146 147 wg.Wait() 148 } 149 150 func TestCancelTrade(t *testing.T) { 151 tradeID := "42641326270691d752e000000001" 152 153 bnc := tNewBinance(t, dex.Testnet) 154 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 155 defer cancel() 156 _, err := bnc.Connect(ctx) 157 if err != nil { 158 t.Fatalf("Connect error: %v", err) 159 } 160 161 err = bnc.CancelTrade(ctx, 60, 0, tradeID) 162 if err != nil { 163 t.Fatalf("error cancelling trade: %v", err) 164 } 165 } 166 167 func TestMatchedMarkets(t *testing.T) { 168 bnc := tNewBinance(t, dex.Mainnet) 169 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 170 defer cancel() 171 172 _, err := bnc.Connect(ctx) 173 if err != nil { 174 t.Fatalf("Connect error: %v", err) 175 } 176 177 markets, err := bnc.Markets(ctx) 178 if err != nil { 179 t.Fatalf("failed to load markets") 180 } 181 182 for _, market := range markets { 183 fmt.Printf("%s_%s %d %d\n", dex.BipIDSymbol(market.BaseID), dex.BipIDSymbol(market.QuoteID), market.BaseMinWithdraw, market.QuoteMinWithdraw) 184 } 185 } 186 187 func TestVWAP(t *testing.T) { 188 bnc := tNewBinance(t, dex.Mainnet) 189 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 190 defer cancel() 191 _, err := bnc.Connect(ctx) 192 if err != nil { 193 t.Fatalf("Connect error: %v", err) 194 } 195 196 err = bnc.SubscribeMarket(ctx, 60, 60001) 197 if err != nil { 198 t.Fatalf("failed to subscribe to market: %v", err) 199 } 200 201 err = bnc.SubscribeMarket(ctx, 60, 0) 202 if err != nil { 203 t.Fatalf("failed to subscribe to market: %v", err) 204 } 205 206 time.Sleep(30 * time.Second) 207 208 avg, extrema, filled, err := bnc.VWAP(60, 0, true, 2e9) 209 if err != nil { 210 t.Fatalf("VWAP failed: %v", err) 211 } 212 t.Logf("ethbtc - avg: %v, extrema: %v, filled: %v", avg, extrema, filled) 213 214 avg, extrema, filled, err = bnc.VWAP(60, 60001, true, 2e9) 215 if err != nil { 216 t.Fatalf("VWAP failed: %v", err) 217 } 218 t.Logf("ethusdc - avg: %v, extrema: %v, filled: %v", avg, extrema, filled) 219 220 err = bnc.SubscribeMarket(ctx, 60, 0) 221 if err != nil { 222 t.Fatalf("failed to subscribe to market: %v", err) 223 } 224 225 avg, extrema, filled, err = bnc.VWAP(60, 0, true, 2e9) 226 if err != nil { 227 t.Fatalf("VWAP failed: %v", err) 228 } 229 230 t.Logf("ethbtc - avg: %v, extrema: %v, filled: %v", avg, extrema, filled) 231 232 bnc.UnsubscribeMarket(60, 0) 233 234 avg, extrema, filled, err = bnc.VWAP(60, 0, true, 2e9) 235 if err != nil { 236 t.Fatalf("VWAP failed: %v", err) 237 } 238 239 t.Logf("avg: %v, extrema: %v, filled: %v", avg, extrema, filled) 240 241 err = bnc.UnsubscribeMarket(60, 0) 242 if err != nil { 243 t.Fatalf("error unsubscribing market") 244 } 245 246 _, _, _, err = bnc.VWAP(60, 0, true, 2e9) 247 if err == nil { 248 t.Fatalf("error should be returned since all subscribers have unsubscribed") 249 } 250 } 251 252 func TestSubscribeMarket(t *testing.T) { 253 bnc := tNewBinance(t, dex.Testnet) 254 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 255 defer cancel() 256 wg, err := bnc.Connect(ctx) 257 if err != nil { 258 t.Fatalf("Connect error: %v", err) 259 } 260 261 err = bnc.SubscribeMarket(ctx, 60, 0) 262 if err != nil { 263 t.Fatalf("failed to subscribe to market: %v", err) 264 } 265 266 wg.Wait() 267 } 268 269 func TestWithdrawal(t *testing.T) { 270 bnc := tNewBinance(t, dex.Mainnet) 271 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 272 defer cancel() 273 274 _, err := bnc.Connect(ctx) 275 if err != nil { 276 t.Fatalf("Connect error: %v", err) 277 } 278 279 withdrawalID, err := bnc.Withdraw(ctx, 966, 2e10, "") 280 if err != nil { 281 fmt.Printf("withdrawal error: %v", err) 282 return 283 } 284 285 t.Logf("withdrawalID: %v", withdrawalID) 286 } 287 288 func TestConfirmDeposit(t *testing.T) { 289 bnc := tNewBinance(t, dex.Mainnet) 290 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 291 defer cancel() 292 293 _, err := bnc.Connect(ctx) 294 if err != nil { 295 t.Fatalf("Connect error: %v", err) 296 } 297 298 confirmed, amt := bnc.ConfirmDeposit(ctx, &DepositData{}) 299 t.Logf("confirmed: %v, amt: %v", confirmed, amt) 300 } 301 302 func TestGetDepositAddress(t *testing.T) { 303 bnc := tNewBinance(t, dex.Mainnet) 304 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 305 defer cancel() 306 307 _, err := bnc.Connect(ctx) 308 if err != nil { 309 t.Fatalf("Connect error: %v", err) 310 } 311 312 addr, err := bnc.GetDepositAddress(ctx, 966) 313 if err != nil { 314 t.Fatalf("getDepositAddress error: %v", err) 315 } 316 317 t.Logf("deposit address: %v", addr) 318 } 319 320 func TestBalances(t *testing.T) { 321 bnc := tNewBinance(t, dex.Testnet) 322 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 323 defer cancel() 324 325 _, err := bnc.Connect(ctx) 326 if err != nil { 327 t.Fatalf("Connect error: %v", err) 328 } 329 330 balance, err := bnc.Balance(0) 331 if err != nil { 332 t.Fatalf("balances error: %v", err) 333 } 334 335 t.Logf("%+v", balance) 336 } 337 338 func TestGetCoinInfo(t *testing.T) { 339 bnc := tNewBinance(t, dex.Mainnet) 340 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 341 defer cancel() 342 343 coins := make([]*bntypes.CoinInfo, 0) 344 err := bnc.getAPI(ctx, "/sapi/v1/capital/config/getall", nil, true, true, &coins) 345 if err != nil { 346 t.Fatalf("error getting binance coin info: %v", err) 347 } 348 349 coinLookup := make(map[string]bool) 350 for _, a := range asset.Assets() { 351 coinLookup[a.Info.UnitInfo.Conventional.Unit] = true 352 for _, tkn := range a.Tokens { 353 coinLookup[tkn.UnitInfo.Conventional.Unit] = true 354 } 355 } 356 357 for _, c := range coins { 358 if !coinLookup[c.Coin] { 359 continue 360 } 361 networkMins := make([]string, 0) 362 for _, n := range c.NetworkList { 363 if !n.DepositEnable || !n.WithdrawEnable { 364 fmt.Printf("%s on network %s not withdrawing and/or depositing. withdraw = %t, deposit = %t\n", 365 c.Coin, n.Network, n.WithdrawEnable, n.DepositEnable) 366 } 367 networkMins = append(networkMins, fmt.Sprintf("{net: %s, min_withdraw: %.8f, withdraw_fee: %.8f}", n.Network, n.WithdrawMin, n.WithdrawFee)) 368 } 369 fmt.Printf("%q network mins: %+v \n", c.Coin, strings.Join(networkMins, ", ")) 370 } 371 } 372 373 func TestTradeStatus(t *testing.T) { 374 bnc := tNewBinance(t, dex.Testnet) 375 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 376 defer cancel() 377 378 _, err := bnc.Connect(ctx) 379 if err != nil { 380 t.Fatalf("Connect error: %v", err) 381 } 382 383 trade, err := bnc.TradeStatus(ctx, "eb6b6e1177213643142700000001", 60, 60001) 384 if err != nil { 385 t.Fatalf("trade status error: %v", err) 386 } 387 388 t.Logf("trade status: %+v", trade) 389 } 390 391 func TestMarkets(t *testing.T) { 392 // Need keys for getCoinInfo 393 bnc := tNewBinance(t, dex.Testnet) 394 ctx, cancel := context.WithTimeout(context.Background(), time.Hour*23) 395 defer cancel() 396 397 err := bnc.getCoinInfo(ctx) 398 if err != nil { 399 t.Fatalf("error getting coin info: %v", err) 400 } 401 402 mkts, err := bnc.Markets(ctx) 403 if err != nil { 404 t.Fatalf("error getting markets: %v", err) 405 } 406 407 b, _ := json.MarshalIndent(mkts, "", " ") 408 fmt.Println("##### Market Data:", string(b)) 409 }