-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommands.go
More file actions
163 lines (146 loc) · 4.51 KB
/
commands.go
File metadata and controls
163 lines (146 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package main
import (
"context"
"fmt"
"strconv"
exchanges "github.com/QuantProcessing/exchanges"
"github.com/shopspring/decimal"
)
// dispatch routes the CLI command to the appropriate handler.
func dispatch(ctx context.Context, adp exchanges.Exchange, exchName, cmd string, args []string, jsonOut bool) error {
switch cmd {
// Market data
case "ticker", "t":
return cmdTicker(ctx, adp, args, jsonOut)
case "orderbook", "ob":
return cmdOrderBook(ctx, adp, args, jsonOut)
case "details":
return cmdSymbolDetails(ctx, adp, args, jsonOut)
case "fee":
return cmdFeeRate(ctx, adp, args, jsonOut)
case "funding":
return cmdFundingRate(ctx, adp, args, jsonOut)
case "trades":
return cmdTrades(ctx, adp, args, jsonOut)
case "klines", "kl":
return cmdKlines(ctx, adp, args, jsonOut)
// Trading
case "buy":
return cmdPlaceOrder(ctx, adp, exchanges.OrderSideBuy, args, jsonOut)
case "sell":
return cmdPlaceOrder(ctx, adp, exchanges.OrderSideSell, args, jsonOut)
case "cancel":
return cmdCancelOrder(ctx, adp, args, jsonOut)
case "cancel-all":
return cmdCancelAllOrders(ctx, adp, args, jsonOut)
case "modify":
return cmdModifyOrder(ctx, adp, args, jsonOut)
case "order":
return cmdFetchOrder(ctx, adp, args, jsonOut)
// Account (common)
case "orders", "o":
return cmdOpenOrders(ctx, adp, args, jsonOut)
case "balance", "bal", "b":
return cmdBalance(ctx, adp, jsonOut)
case "account", "acc":
return cmdAccount(ctx, adp, jsonOut)
// Perp-specific
case "positions", "pos", "p":
return cmdPositions(ctx, adp, args, jsonOut)
case "leverage", "lev":
return cmdSetLeverage(ctx, adp, args, jsonOut)
case "funding-all":
return cmdAllFundingRates(ctx, adp, jsonOut)
// Spot-specific
case "spot-balances", "sb":
return cmdSpotBalances(ctx, adp, jsonOut)
case "transfer":
return cmdTransfer(ctx, adp, args, jsonOut)
// WSS streaming
case "watch-ticker", "wt":
return cmdWatchTicker(ctx, adp, args, jsonOut)
case "watch-ob", "wob":
return cmdWatchOrderBook(ctx, adp, args, jsonOut)
case "watch-orders", "wo":
return cmdWatchOrders(ctx, adp, args, jsonOut)
case "watch-trades", "wtr":
return cmdWatchTrades(ctx, adp, args, jsonOut)
case "watch-positions", "wp":
return cmdWatchPositions(ctx, adp, args, jsonOut)
case "watch-klines", "wkl":
return cmdWatchKlines(ctx, adp, args, jsonOut)
default:
return fmt.Errorf("unknown command: %s. Run 'tctl --help' for usage", cmd)
}
}
// requireArgs checks that enough arguments were provided.
func requireArgs(args []string, min int, usage string) error {
if len(args) < min {
return fmt.Errorf("not enough arguments. Usage: %s", usage)
}
return nil
}
// parsePrice extracts --price from args.
func parsePrice(args []string) (decimal.Decimal, []string) {
for i, a := range args {
if a == "--price" && i+1 < len(args) {
p, err := decimal.NewFromString(args[i+1])
if err == nil {
// Remove --price and value from args
remaining := make([]string, 0, len(args)-2)
remaining = append(remaining, args[:i]...)
remaining = append(remaining, args[i+2:]...)
return p, remaining
}
}
}
return decimal.Zero, args
}
// parseBool extracts a boolean flag from args.
func parseBool(args []string, flag string) (bool, []string) {
for i, a := range args {
if a == flag {
remaining := make([]string, 0, len(args)-1)
remaining = append(remaining, args[:i]...)
remaining = append(remaining, args[i+1:]...)
return true, remaining
}
}
return false, args
}
// parseDecimal parses a decimal from string.
func parseDecimal(s string) (decimal.Decimal, error) {
return decimal.NewFromString(s)
}
// parseInt parses an int from string.
func parseInt(s string) (int, error) {
return strconv.Atoi(s)
}
// parseQty extracts --qty from args.
func parseQty(args []string) (decimal.Decimal, []string) {
for i, a := range args {
if a == "--qty" && i+1 < len(args) {
q, err := decimal.NewFromString(args[i+1])
if err == nil {
remaining := make([]string, 0, len(args)-2)
remaining = append(remaining, args[:i]...)
remaining = append(remaining, args[i+2:]...)
return q, remaining
}
}
}
return decimal.Zero, args
}
// parseStringFlag extracts a string flag value from args (e.g., --from SPOT).
func parseStringFlag(args []string, flag string) (string, []string) {
for i, a := range args {
if a == flag && i+1 < len(args) {
val := args[i+1]
remaining := make([]string, 0, len(args)-2)
remaining = append(remaining, args[:i]...)
remaining = append(remaining, args[i+2:]...)
return val, remaining
}
}
return "", args
}