diff options
-rw-r--r-- | Gopkg.lock | 24 | ||||
-rw-r--r-- | api/market_config.go | 19 | ||||
-rw-r--r-- | cmd/web/js/poloniex.jsx | 12 | ||||
-rw-r--r-- | markets/balance.go | 15 | ||||
-rw-r--r-- | markets/poloniex.go | 61 |
5 files changed, 96 insertions, 35 deletions
@@ -10,8 +10,8 @@ | |||
10 | [[projects]] | 10 | [[projects]] |
11 | name = "github.com/Sirupsen/logrus" | 11 | name = "github.com/Sirupsen/logrus" |
12 | packages = ["."] | 12 | packages = ["."] |
13 | revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" | 13 | revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" |
14 | version = "v1.0.4" | 14 | version = "v1.0.5" |
15 | 15 | ||
16 | [[projects]] | 16 | [[projects]] |
17 | name = "github.com/boombuler/barcode" | 17 | name = "github.com/boombuler/barcode" |
@@ -26,8 +26,8 @@ | |||
26 | [[projects]] | 26 | [[projects]] |
27 | name = "github.com/dgrijalva/jwt-go" | 27 | name = "github.com/dgrijalva/jwt-go" |
28 | packages = ["."] | 28 | packages = ["."] |
29 | revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29" | 29 | revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" |
30 | version = "v3.1.0" | 30 | version = "v3.2.0" |
31 | 31 | ||
32 | [[projects]] | 32 | [[projects]] |
33 | name = "github.com/gin-contrib/cors" | 33 | name = "github.com/gin-contrib/cors" |
@@ -61,8 +61,8 @@ | |||
61 | "orm", | 61 | "orm", |
62 | "types" | 62 | "types" |
63 | ] | 63 | ] |
64 | revision = "62ce1a18dd39eab82c8a3fc1a5b076e59c0a284f" | 64 | revision = "24dfe0572921e42ffe1035f7afbd40f9d97cb8c8" |
65 | version = "v6.9.6" | 65 | version = "v6.10.0" |
66 | 66 | ||
67 | [[projects]] | 67 | [[projects]] |
68 | name = "github.com/golang/protobuf" | 68 | name = "github.com/golang/protobuf" |
@@ -74,13 +74,13 @@ | |||
74 | branch = "master" | 74 | branch = "master" |
75 | name = "github.com/jinzhu/inflection" | 75 | name = "github.com/jinzhu/inflection" |
76 | packages = ["."] | 76 | packages = ["."] |
77 | revision = "1c35d901db3da928c72a72d8458480cc9ade058f" | 77 | revision = "04140366298a54a039076d798123ffa108fff46c" |
78 | 78 | ||
79 | [[projects]] | 79 | [[projects]] |
80 | branch = "master" | 80 | branch = "master" |
81 | name = "github.com/jloup/poloniex" | 81 | name = "github.com/jloup/poloniex" |
82 | packages = ["."] | 82 | packages = ["."] |
83 | revision = "e75e6fd7991c1d71576ad97de73fc922f24a5fd2" | 83 | revision = "72d53259a0b28f1778281d7a9f7b20469d8c0171" |
84 | 84 | ||
85 | [[projects]] | 85 | [[projects]] |
86 | branch = "master" | 86 | branch = "master" |
@@ -108,7 +108,7 @@ | |||
108 | branch = "master" | 108 | branch = "master" |
109 | name = "github.com/shopspring/decimal" | 109 | name = "github.com/shopspring/decimal" |
110 | packages = ["."] | 110 | packages = ["."] |
111 | revision = "e3482495ff4cba75613e4177ed79825c890058a9" | 111 | revision = "2df3e6ddaf6e9531dd02d7b6337f2d310f5e4f22" |
112 | 112 | ||
113 | [[projects]] | 113 | [[projects]] |
114 | name = "github.com/ugorji/go" | 114 | name = "github.com/ugorji/go" |
@@ -124,13 +124,13 @@ | |||
124 | "blowfish", | 124 | "blowfish", |
125 | "ssh/terminal" | 125 | "ssh/terminal" |
126 | ] | 126 | ] |
127 | revision = "91a49db82a88618983a78a06c1cbd4e00ab749ab" | 127 | revision = "88942b9c40a4c9d203b82b3731787b672d6e809b" |
128 | 128 | ||
129 | [[projects]] | 129 | [[projects]] |
130 | branch = "master" | 130 | branch = "master" |
131 | name = "golang.org/x/net" | 131 | name = "golang.org/x/net" |
132 | packages = ["websocket"] | 132 | packages = ["websocket"] |
133 | revision = "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb" | 133 | revision = "6078986fec03a1dcc236c34816c71b0e05018fda" |
134 | 134 | ||
135 | [[projects]] | 135 | [[projects]] |
136 | branch = "master" | 136 | branch = "master" |
@@ -139,7 +139,7 @@ | |||
139 | "unix", | 139 | "unix", |
140 | "windows" | 140 | "windows" |
141 | ] | 141 | ] |
142 | revision = "f6cff0780e542efa0c8e864dc8fa522808f6a598" | 142 | revision = "91ee8cde435411ca3f1cd365e8f20131aed4d0a1" |
143 | 143 | ||
144 | [[projects]] | 144 | [[projects]] |
145 | name = "gopkg.in/go-playground/validator.v8" | 145 | name = "gopkg.in/go-playground/validator.v8" |
diff --git a/api/market_config.go b/api/market_config.go index d85af4d..25e390d 100644 --- a/api/market_config.go +++ b/api/market_config.go | |||
@@ -82,7 +82,7 @@ func (q MarketBalanceQuery) Run() (interface{}, *Error) { | |||
82 | result := struct { | 82 | result := struct { |
83 | Value decimal.Decimal `json:"value"` | 83 | Value decimal.Decimal `json:"value"` |
84 | ValueCurrency string `json:"valueCurrency"` | 84 | ValueCurrency string `json:"valueCurrency"` |
85 | Balance map[string]decimal.Decimal `json:"balance"` | 85 | Balance map[string]markets.Balance `json:"balance"` |
86 | }{} | 86 | }{} |
87 | 87 | ||
88 | resultErr := CallExternalService(fmt.Sprintf("'%s' GetBalanceValue", q.In.Market), EXTERNAL_SERVICE_TIMEOUT_SECONDS*time.Second, func() *Error { | 88 | resultErr := CallExternalService(fmt.Sprintf("'%s' GetBalanceValue", q.In.Market), EXTERNAL_SERVICE_TIMEOUT_SECONDS*time.Second, func() *Error { |
@@ -92,18 +92,23 @@ func (q MarketBalanceQuery) Run() (interface{}, *Error) { | |||
92 | return &Error{InvalidMarketCredentials, "wrong market credentials", fmt.Errorf("wrong '%v' market credentials", q.In.Market)} | 92 | return &Error{InvalidMarketCredentials, "wrong market credentials", fmt.Errorf("wrong '%v' market credentials", q.In.Market)} |
93 | } | 93 | } |
94 | 94 | ||
95 | if err != nil { | 95 | if utils.ErrIs(err, markets.IPRestricted) { |
96 | return NewInternalError(err) | 96 | return &Error{IPRestrictedApiKey, "ip restricted api key", fmt.Errorf("'%v' ip restricted", q.In.Market)} |
97 | } | 97 | } |
98 | 98 | ||
99 | value, err := Poloniex.ComputeAccountBalanceValue(balance, q.In.Currency) | ||
100 | if err != nil { | 99 | if err != nil { |
101 | return NewInternalError(err) | 100 | return NewInternalError(err) |
102 | } | 101 | } |
103 | 102 | ||
104 | result.Balance = balance | 103 | for currency, value := range balance.Balances { |
105 | result.ValueCurrency = q.In.Currency | 104 | if value.BTCValue.Abs().LessThan(decimal.NewFromFloat(0.0001)) { |
106 | result.Value = value.Round(8) | 105 | delete(balance.Balances, currency) |
106 | } | ||
107 | } | ||
108 | |||
109 | result.Balance = balance.Balances | ||
110 | result.ValueCurrency = "BTC" | ||
111 | result.Value = balance.BTCValue.Round(8) | ||
107 | 112 | ||
108 | return nil | 113 | return nil |
109 | }) | 114 | }) |
diff --git a/cmd/web/js/poloniex.jsx b/cmd/web/js/poloniex.jsx index 813a506..db6b1c4 100644 --- a/cmd/web/js/poloniex.jsx +++ b/cmd/web/js/poloniex.jsx | |||
@@ -113,6 +113,10 @@ class PoloniexBalance extends React.Component { | |||
113 | this.state = {'hideMsg': true, 'msg': '', 'msgOk': false}; | 113 | this.state = {'hideMsg': true, 'msg': '', 'msgOk': false}; |
114 | } | 114 | } |
115 | 115 | ||
116 | computeCurrencyRatio = (currency) => { | ||
117 | return (parseFloat(this.props.balance[currency].btcValue) / parseFloat(this.props.balanceValue) * 100.0).toFixed(1); | ||
118 | } | ||
119 | |||
116 | render = () => { | 120 | render = () => { |
117 | var dashboard = null; | 121 | var dashboard = null; |
118 | 122 | ||
@@ -120,16 +124,18 @@ class PoloniexBalance extends React.Component { | |||
120 | 124 | ||
121 | var balance = Object.keys(this.props.balance).map(function(currency) { | 125 | var balance = Object.keys(this.props.balance).map(function(currency) { |
122 | return <div key={currency}> | 126 | return <div key={currency}> |
123 | <CurrencyLogo currency={currency} /> {this.props.balance[currency]} | 127 | <div> |
128 | <CurrencyLogo currency={currency} /> {this.props.balance[currency].amount} {currency} ({this.computeCurrencyRatio(currency)}%) | ||
129 | </div> | ||
124 | </div>; | 130 | </div>; |
125 | }.bind(this)); | 131 | }.bind(this)); |
126 | 132 | ||
127 | dashboard = | 133 | dashboard = |
128 | <div className="row"> | 134 | <div className="row"> |
129 | <div className="col-4 align-self-center h-100 balances"> | 135 | <div className="col-6 align-self-center h-100 balances"> |
130 | {balance} | 136 | {balance} |
131 | </div> | 137 | </div> |
132 | <div className="offset-1 col-7 h-100 align-self-center"> | 138 | <div className="offset-1 col-5 h-100 align-self-center"> |
133 | <div className="text-center"> | 139 | <div className="text-center"> |
134 | Balance ({this.props.balanceCurrency}): <span>{this.props.balanceValue}</span><CurrencyLogo currency={this.props.balanceCurrency} /> | 140 | Balance ({this.props.balanceCurrency}): <span>{this.props.balanceValue}</span><CurrencyLogo currency={this.props.balanceCurrency} /> |
135 | </div> | 141 | </div> |
diff --git a/markets/balance.go b/markets/balance.go new file mode 100644 index 0000000..cd46ac9 --- /dev/null +++ b/markets/balance.go | |||
@@ -0,0 +1,15 @@ | |||
1 | package markets | ||
2 | |||
3 | import ( | ||
4 | "github.com/shopspring/decimal" | ||
5 | ) | ||
6 | |||
7 | type Balance struct { | ||
8 | Amount decimal.Decimal `json:"amount"` | ||
9 | BTCValue decimal.Decimal `json:"btcValue"` | ||
10 | } | ||
11 | |||
12 | type Summary struct { | ||
13 | Balances map[string]Balance | ||
14 | BTCValue decimal.Decimal | ||
15 | } | ||
diff --git a/markets/poloniex.go b/markets/poloniex.go index 34ebb7e..9aaeafb 100644 --- a/markets/poloniex.go +++ b/markets/poloniex.go | |||
@@ -52,40 +52,75 @@ func NewPoloniex() *Poloniex { | |||
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | func (p *Poloniex) GetBalance(apiKey, apiSecret string) (map[string]decimal.Decimal, error) { | 55 | func (p *Poloniex) GetBalance(apiKey, apiSecret string) (Summary, error) { |
56 | client, _ := poloniex.NewClient(apiKey, apiSecret) | 56 | client, _ := poloniex.NewClient(apiKey, apiSecret) |
57 | var summary Summary | ||
57 | 58 | ||
58 | accounts, err := client.TradeReturnAvailableAccountBalances() | 59 | accounts, err := client.TradeReturnAvailableAccountBalances() |
59 | if poloniexInvalidCredentialsError(err) { | 60 | if poloniexInvalidCredentialsError(err) { |
60 | return nil, utils.Error{InvalidCredentials, "invalid poloniex credentials"} | 61 | return Summary{}, utils.Error{InvalidCredentials, "invalid poloniex credentials"} |
61 | } | 62 | } |
62 | 63 | ||
64 | if poloniexRestrictedIPError(err) { | ||
65 | return Summary{}, utils.Error{IPRestricted, "IP restricted api key"} | ||
66 | } | ||
67 | |||
68 | if err != nil { | ||
69 | return Summary{}, err | ||
70 | } | ||
71 | |||
72 | positions, err := client.TradeGetMarginPosition() | ||
63 | if err != nil { | 73 | if err != nil { |
64 | return nil, err | 74 | return Summary{}, err |
65 | } | 75 | } |
66 | 76 | ||
67 | balances := make(map[string]decimal.Decimal) | 77 | marginAccount, err := client.TradeReturnMarginAccountSummary() |
68 | for currency, balance := range accounts.Margin { | 78 | if err != nil { |
69 | balances[currency] = balances[currency].Add(balance) | 79 | return Summary{}, err |
70 | } | 80 | } |
71 | 81 | ||
72 | for currency, balance := range accounts.Exchange { | 82 | summary.Balances = make(map[string]Balance) |
73 | balances[currency] = balances[currency].Add(balance) | 83 | for currency, amount := range accounts.Exchange { |
84 | balance := summary.Balances[currency] | ||
85 | balance.Amount = balance.Amount.Add(amount) | ||
86 | |||
87 | summary.Balances[currency] = balance | ||
74 | } | 88 | } |
75 | 89 | ||
76 | return balances, nil | 90 | summary.BTCValue, err = p.ComputeAccountBalanceValue(summary.Balances) |
91 | if err != nil { | ||
92 | return Summary{}, err | ||
93 | } | ||
94 | |||
95 | for currencyPair, position := range positions { | ||
96 | if position.Type == "none" { | ||
97 | continue | ||
98 | } | ||
99 | currency := currencyPair[4:] | ||
100 | balance := summary.Balances[currency] | ||
101 | balance.Amount = balance.Amount.Add(position.Amount) | ||
102 | balance.BTCValue = balance.BTCValue.Add(position.Total.Add(position.PlusValue)) | ||
103 | |||
104 | summary.Balances[currency] = balance | ||
105 | } | ||
106 | |||
107 | summary.BTCValue = summary.BTCValue.Add(marginAccount.NetValue) | ||
108 | |||
109 | return summary, nil | ||
77 | } | 110 | } |
78 | 111 | ||
79 | func (p *Poloniex) ComputeAccountBalanceValue(account map[string]decimal.Decimal, baseCurrency string) (decimal.Decimal, error) { | 112 | func (p *Poloniex) ComputeAccountBalanceValue(account map[string]Balance) (decimal.Decimal, error) { |
80 | var total decimal.Decimal | 113 | var total decimal.Decimal |
81 | 114 | ||
82 | for currency, amount := range account { | 115 | for currency, balance := range account { |
83 | pair, err := p.GetCurrencyPair(baseCurrency, currency) | 116 | pair, err := p.GetCurrencyPair("BTC", currency) |
84 | if err != nil { | 117 | if err != nil { |
85 | return decimal.Zero, err | 118 | return decimal.Zero, err |
86 | } | 119 | } |
87 | 120 | ||
88 | total = total.Add(amount.Mul(pair.Rate)) | 121 | total = total.Add(balance.Amount.Mul(pair.Rate)) |
122 | balance.BTCValue = balance.BTCValue.Add(balance.Amount.Mul(pair.Rate)) | ||
123 | account[currency] = balance | ||
89 | } | 124 | } |
90 | 125 | ||
91 | return total, nil | 126 | return total, nil |