Compare commits
2
Commits
248d3153e7
...
87e69ec8d0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87e69ec8d0 | ||
|
|
440fa3bacd |
@@ -9,21 +9,21 @@ require (
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/rs/zerolog v1.32.0
|
||||
github.com/samber/lo v1.39.0
|
||||
golang.org/x/text v0.16.0
|
||||
golang.org/x/text v0.21.0
|
||||
gopkg.in/telebot.v3 v3.2.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
)
|
||||
|
||||
@@ -58,8 +58,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/adshao/go-binance/v2 v2.5.0 h1:mk8ylSjIzDYVBF9Wf2KXu6GWD/Ws4LLzD9q2R2mqZB0=
|
||||
github.com/adshao/go-binance/v2 v2.5.0/go.mod h1:41Up2dG4NfMXpCldrDPETEtiOq+pHoGsFZ73xGgaumo=
|
||||
github.com/adshao/go-binance/v2 v2.8.5 h1:2i8uVFrt1HbZPggnfdL1A1g/PS9MeD1FnoBoIXNhbow=
|
||||
github.com/adshao/go-binance/v2 v2.8.5/go.mod h1:XkkuecSyJKPolaCGf/q4ovJYB3t0P+7RUYTbGr+LMGM=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -135,8 +135,8 @@ github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvSc
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8=
|
||||
github.com/go-resty/resty/v2 v2.15.3/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
|
||||
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
||||
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@@ -155,6 +155,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -212,6 +213,8 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
@@ -220,8 +223,8 @@ github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/Oth
|
||||
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
|
||||
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
|
||||
@@ -258,12 +261,12 @@ github.com/jedib0t/go-pretty/v6 v6.5.5 h1:PpIU8lOjxvVYGGKule0QxxJfNysUSbC9lggQU2
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.5/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
@@ -316,11 +319,9 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
@@ -368,6 +369,8 @@ github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5A
|
||||
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
|
||||
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
@@ -509,8 +512,8 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -624,8 +627,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -637,8 +640,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package data
|
||||
|
||||
import "me.thuanle/bbot/internal/data/market"
|
||||
|
||||
type IMarket interface {
|
||||
GetFuturePrice(symbol string) (float64, float64, int64, bool)
|
||||
GetAllFundRate() (map[string]float64, map[string]int64)
|
||||
|
||||
GetSpotPrice(symbol string) (float64, bool)
|
||||
GetMarginInterestRates() map[string]float64
|
||||
|
||||
// Alpha token methods
|
||||
IsAlphaToken(symbol string) bool
|
||||
GetAlphaToken(symbol string) (market.AlphaTokenInfo, bool)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
package market
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// AlphaTokenInfo represents the response from Binance Alpha token API
|
||||
type AlphaTokenInfo struct {
|
||||
TokenID string `json:"tokenId"`
|
||||
ChainID string `json:"chainId"`
|
||||
ChainIconURL string `json:"chainIconUrl"`
|
||||
ChainName string `json:"chainName"`
|
||||
ContractAddress string `json:"contractAddress"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
IconURL string `json:"iconUrl"`
|
||||
Price string `json:"price"`
|
||||
PercentChange24h string `json:"percentChange24h"`
|
||||
Volume24h string `json:"volume24h"`
|
||||
MarketCap string `json:"marketCap"`
|
||||
FDV string `json:"fdv"`
|
||||
Liquidity string `json:"liquidity"`
|
||||
TotalSupply string `json:"totalSupply"`
|
||||
CirculatingSupply string `json:"circulatingSupply"`
|
||||
Holders string `json:"holders"`
|
||||
Decimals int `json:"decimals"`
|
||||
ListingCex bool `json:"listingCex"`
|
||||
HotTag bool `json:"hotTag"`
|
||||
CexCoinName string `json:"cexCoinName"`
|
||||
CanTransfer bool `json:"canTransfer"`
|
||||
Denomination int `json:"denomination"`
|
||||
Offline bool `json:"offline"`
|
||||
TradeDecimal int `json:"tradeDecimal"`
|
||||
AlphaID string `json:"alphaId"`
|
||||
Offsell bool `json:"offsell"`
|
||||
PriceHigh24h string `json:"priceHigh24h"`
|
||||
PriceLow24h string `json:"priceLow24h"`
|
||||
Count24h string `json:"count24h"`
|
||||
OnlineTge bool `json:"onlineTge"`
|
||||
OnlineAirdrop bool `json:"onlineAirdrop"`
|
||||
Score int `json:"score"`
|
||||
CexOffDisplay bool `json:"cexOffDisplay"`
|
||||
StockState bool `json:"stockState"`
|
||||
ListingTime int64 `json:"listingTime"`
|
||||
MulPoint int `json:"mulPoint"`
|
||||
BnExclusiveState bool `json:"bnExclusiveState"`
|
||||
}
|
||||
|
||||
// AlphaTokenResponse represents the API response structure
|
||||
type AlphaTokenResponse struct {
|
||||
Code string `json:"code"`
|
||||
Message *string `json:"message"`
|
||||
MessageDetail *string `json:"messageDetail"`
|
||||
Data []AlphaTokenInfo `json:"data"`
|
||||
}
|
||||
|
||||
// GetPrice returns the price as float64
|
||||
func (a *AlphaTokenInfo) GetPrice() float64 {
|
||||
price, err := strconv.ParseFloat(a.Price, 64)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("symbol", a.Symbol).Msg("Failed to parse Alpha token price")
|
||||
return 0
|
||||
}
|
||||
return price
|
||||
}
|
||||
|
||||
// GetPercentChange24h returns the 24h percentage change as float64
|
||||
func (a *AlphaTokenInfo) GetPercentChange24h() float64 {
|
||||
change, err := strconv.ParseFloat(a.PercentChange24h, 64)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("symbol", a.Symbol).Msg("Failed to parse Alpha token 24h change")
|
||||
return 0
|
||||
}
|
||||
return change
|
||||
}
|
||||
|
||||
// fetchAlphaTokens fetches Alpha tokens from Binance API
|
||||
func (ms *MarketData) fetchAlphaTokens() ([]AlphaTokenInfo, error) {
|
||||
const alphaTokenURL = "https://www.binance.com/bapi/defi/v1/public/wallet-direct/buw/wallet/cex/alpha/all/token/list"
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
resp, err := client.Get(alphaTokenURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch Alpha tokens: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("Alpha token API returned status: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var tokenResponse AlphaTokenResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&tokenResponse); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode Alpha token response: %w", err)
|
||||
}
|
||||
|
||||
if tokenResponse.Code != "000000" {
|
||||
return nil, fmt.Errorf("Alpha token API returned error code: %s", tokenResponse.Code)
|
||||
}
|
||||
|
||||
return tokenResponse.Data, nil
|
||||
}
|
||||
|
||||
// refreshAlphaTokenCache refreshes the Alpha token cache
|
||||
func (ms *MarketData) refreshAlphaTokenCache() {
|
||||
ms.alphaCacheMutex.Lock()
|
||||
defer ms.alphaCacheMutex.Unlock()
|
||||
|
||||
log.Info().Msg("Refreshing Alpha token cache")
|
||||
|
||||
tokens, err := ms.fetchAlphaTokens()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to refresh Alpha token cache")
|
||||
return
|
||||
}
|
||||
|
||||
// Clear existing cache
|
||||
ms.alphaTokens = make(map[string]AlphaTokenInfo)
|
||||
|
||||
// Populate cache with new data
|
||||
for _, token := range tokens {
|
||||
symbol := token.Symbol // Already uppercase from API
|
||||
ms.alphaTokens[symbol] = token
|
||||
}
|
||||
|
||||
ms.lastAlphaCacheUpdate = time.Now()
|
||||
log.Info().Int("count", len(tokens)).Msg("Alpha token cache refreshed successfully")
|
||||
}
|
||||
|
||||
// GetAlphaToken returns Alpha token info by symbol
|
||||
func (ms *MarketData) GetAlphaToken(symbol string) (AlphaTokenInfo, bool) {
|
||||
ms.alphaCacheMutex.RLock()
|
||||
defer ms.alphaCacheMutex.RUnlock()
|
||||
|
||||
token, exists := ms.alphaTokens[symbol]
|
||||
return token, exists
|
||||
}
|
||||
|
||||
// IsAlphaToken checks if a symbol is an Alpha token
|
||||
func (ms *MarketData) IsAlphaToken(symbol string) bool {
|
||||
_, exists := ms.GetAlphaToken(symbol)
|
||||
return exists
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func (ms *MarketData) GetFuturePrice(symbol string) (float64, float64, int64, bool) {
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
p, ok := ms.futureMarkPrice[symbol]
|
||||
if !ok {
|
||||
return 0, 0, 0, false
|
||||
@@ -23,6 +25,8 @@ func (ms *MarketData) StartFutureWsMarkPrice() error {
|
||||
}
|
||||
|
||||
func (ms *MarketData) futureWsMarkPriceHandler(event futures.WsAllMarkPriceEvent) {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
for _, priceEvent := range event {
|
||||
price, err := strconv.ParseFloat(priceEvent.MarkPrice, 64)
|
||||
if err != nil {
|
||||
@@ -46,5 +50,15 @@ func (ms *MarketData) futureWsErrHandler(err error) {
|
||||
}
|
||||
|
||||
func (ms *MarketData) GetAllFundRate() (map[string]float64, map[string]int64) {
|
||||
return ms.futureFundingRate, ms.futureNextFundingTime
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
rates := make(map[string]float64, len(ms.futureFundingRate))
|
||||
for k, v := range ms.futureFundingRate {
|
||||
rates[k] = v
|
||||
}
|
||||
times := make(map[string]int64, len(ms.futureNextFundingTime))
|
||||
for k, v := range ms.futureNextFundingTime {
|
||||
times[k] = v
|
||||
}
|
||||
return rates, times
|
||||
}
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
package market
|
||||
|
||||
import "github.com/rs/zerolog/log"
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type MarketData struct {
|
||||
mu sync.RWMutex
|
||||
futureMarkPrice map[string]float64
|
||||
futureFundingRate map[string]float64
|
||||
futureNextFundingTime map[string]int64
|
||||
|
||||
spotPrice map[string]float64
|
||||
|
||||
// Alpha token cache
|
||||
alphaTokens map[string]AlphaTokenInfo
|
||||
alphaCacheMutex sync.RWMutex
|
||||
lastAlphaCacheUpdate time.Time
|
||||
}
|
||||
|
||||
func NewMarketData() *MarketData {
|
||||
@@ -17,9 +28,14 @@ func NewMarketData() *MarketData {
|
||||
futureFundingRate: make(map[string]float64),
|
||||
futureNextFundingTime: make(map[string]int64),
|
||||
|
||||
spotPrice: make(map[string]float64),
|
||||
spotPrice: make(map[string]float64),
|
||||
alphaTokens: make(map[string]AlphaTokenInfo),
|
||||
}
|
||||
_ = ms.StartFutureWsMarkPrice()
|
||||
_ = ms.StartSpotWsMarkPrice()
|
||||
|
||||
// Initialize Alpha token cache
|
||||
go ms.refreshAlphaTokenCache()
|
||||
|
||||
return ms
|
||||
}
|
||||
|
||||
@@ -1,14 +1,30 @@
|
||||
package market
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/adshao/go-binance/v2"
|
||||
"github.com/rs/zerolog/log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (ms *MarketData) GetSpotPrice(symbol string) (float64, bool) {
|
||||
ms.mu.RLock()
|
||||
p, ok := ms.spotPrice[symbol]
|
||||
return p, ok
|
||||
ms.mu.RUnlock()
|
||||
if ok {
|
||||
return p, true
|
||||
}
|
||||
|
||||
// If not found, check if it's an Alpha token
|
||||
if ms.IsAlphaToken(symbol) {
|
||||
if alphaToken, exists := ms.GetAlphaToken(symbol); exists {
|
||||
if price := alphaToken.GetPrice(); price > 0 {
|
||||
return price, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (ms *MarketData) StartSpotWsMarkPrice() error {
|
||||
@@ -21,6 +37,8 @@ func (ms *MarketData) StartSpotWsMarkPrice() error {
|
||||
}
|
||||
|
||||
func (ms *MarketData) spotWsAllMarketsStatHandler(event binance.WsAllMarketsStatEvent) {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
for _, priceEvent := range event {
|
||||
price, err := strconv.ParseFloat(priceEvent.LastPrice, 64)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package binancex
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"me.thuanle/bbot/internal/configs/binance"
|
||||
"me.thuanle/bbot/internal/data"
|
||||
"me.thuanle/bbot/internal/utils/stringx"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Symbol2Token(sym string) string {
|
||||
@@ -74,7 +75,14 @@ func Token2Symbols(token string) []string {
|
||||
}
|
||||
|
||||
func IsToken(s string) bool {
|
||||
return len(Token2Symbols(s)) > 0
|
||||
// First check regular symbols
|
||||
if len(Token2Symbols(s)) > 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
// Then check Alpha tokens
|
||||
s = strings.ToUpper(s)
|
||||
return data.Market.IsAlphaToken(s)
|
||||
}
|
||||
|
||||
// Future2SpotSymbol convert future symbol to spot symbol
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
"gopkg.in/telebot.v3"
|
||||
@@ -9,7 +11,6 @@ import (
|
||||
"me.thuanle/bbot/internal/helper/binancex"
|
||||
"me.thuanle/bbot/internal/services/tele/chat"
|
||||
"me.thuanle/bbot/internal/services/tele/view"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var lastEthPrice float64
|
||||
@@ -27,6 +28,22 @@ func showStickerMode(context telebot.Context, token string) {
|
||||
}
|
||||
|
||||
func OnTokenInfoByToken(context telebot.Context, token string) error {
|
||||
token = strings.ToUpper(token)
|
||||
|
||||
// Check if it's an Alpha token first
|
||||
if data.Market.IsAlphaToken(token) {
|
||||
showStickerMode(context, token)
|
||||
|
||||
if alphaToken, exists := data.Market.GetAlphaToken(token); exists {
|
||||
sp := alphaToken.GetPrice()
|
||||
// For Alpha tokens, we don't have future price, funding rate, etc.
|
||||
// Use spot price for both spot and future in the display
|
||||
_ = chat.ReplyMessage(context, view.RenderOnPriceMessage(token, sp, sp, 0, 0, 0))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Regular token handling
|
||||
symbols := binancex.Token2Symbols(token)
|
||||
if len(symbols) == 0 {
|
||||
return nil
|
||||
@@ -36,7 +53,7 @@ func OnTokenInfoByToken(context telebot.Context, token string) error {
|
||||
|
||||
fp, fundRate, fundTime, ok := data.Market.GetFuturePrice(symbols[0])
|
||||
marginRates := data.Market.GetMarginInterestRates()
|
||||
tokenInterestRate := marginRates[strings.ToUpper(token)]
|
||||
tokenInterestRate := marginRates[token]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user