add get symbol repository
This commit is contained in:
parent
d587e95442
commit
436996d25d
|
@ -14,10 +14,16 @@ import (
|
|||
)
|
||||
|
||||
type (
|
||||
NoneReq = app_cloudep_blockchain.NoneReq
|
||||
OKResp = app_cloudep_blockchain.OKResp
|
||||
ListSymbolsRequest = app_cloudep_blockchain.ListSymbolsRequest
|
||||
ListSymbolsResponse = app_cloudep_blockchain.ListSymbolsResponse
|
||||
NoneReq = app_cloudep_blockchain.NoneReq
|
||||
OKResp = app_cloudep_blockchain.OKResp
|
||||
Symbol = app_cloudep_blockchain.Symbol
|
||||
|
||||
BlockchainService interface {
|
||||
// ListSymbols retrieves all available trading symbols.
|
||||
ListSymbols(ctx context.Context, in *ListSymbolsRequest, opts ...grpc.CallOption) (*ListSymbolsResponse, error)
|
||||
// Ping is a health-check endpoint.
|
||||
Ping(ctx context.Context, in *NoneReq, opts ...grpc.CallOption) (*OKResp, error)
|
||||
}
|
||||
|
||||
|
@ -32,6 +38,13 @@ func NewBlockchainService(cli zrpc.Client) BlockchainService {
|
|||
}
|
||||
}
|
||||
|
||||
// ListSymbols retrieves all available trading symbols.
|
||||
func (m *defaultBlockchainService) ListSymbols(ctx context.Context, in *ListSymbolsRequest, opts ...grpc.CallOption) (*ListSymbolsResponse, error) {
|
||||
client := app_cloudep_blockchain.NewBlockchainServiceClient(m.cli.Conn())
|
||||
return client.ListSymbols(ctx, in, opts...)
|
||||
}
|
||||
|
||||
// Ping is a health-check endpoint.
|
||||
func (m *defaultBlockchainService) Ping(ctx context.Context, in *NoneReq, opts ...grpc.CallOption) (*OKResp, error) {
|
||||
client := app_cloudep_blockchain.NewBlockchainServiceClient(m.cli.Conn())
|
||||
return client.Ping(ctx, in, opts...)
|
||||
|
|
|
@ -2,9 +2,13 @@ Name: blockchain.rpc
|
|||
ListenOn: 0.0.0.0:8888
|
||||
Etcd:
|
||||
Hosts:
|
||||
- 127.0.0.1:2379
|
||||
- 10.0.0.19:2379
|
||||
Key: blockchain.rpc
|
||||
Binance:
|
||||
Key: ""
|
||||
Secret: ""
|
||||
TestMode: true
|
||||
TestMode: true
|
||||
|
||||
RedisCluster:
|
||||
Host: 127.0.0.1:6379
|
||||
Type: node
|
|
@ -95,6 +95,174 @@ func (*NoneReq) Descriptor() ([]byte, []int) {
|
|||
return file_generate_rpc_blockchain_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
// ListSymbolsRequest is the request for the ListSymbols RPC.
|
||||
// It is currently empty but can be extended with filtering or pagination fields in the future.
|
||||
type ListSymbolsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListSymbolsRequest) Reset() {
|
||||
*x = ListSymbolsRequest{}
|
||||
mi := &file_generate_rpc_blockchain_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListSymbolsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListSymbolsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListSymbolsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_generate_rpc_blockchain_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListSymbolsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListSymbolsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_generate_rpc_blockchain_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
// ListSymbolsResponse contains a list of symbols.
|
||||
type ListSymbolsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Symbols []*Symbol `protobuf:"bytes,1,rep,name=symbols,proto3" json:"symbols,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListSymbolsResponse) Reset() {
|
||||
*x = ListSymbolsResponse{}
|
||||
mi := &file_generate_rpc_blockchain_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListSymbolsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListSymbolsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListSymbolsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_generate_rpc_blockchain_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListSymbolsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListSymbolsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_generate_rpc_blockchain_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ListSymbolsResponse) GetSymbols() []*Symbol {
|
||||
if x != nil {
|
||||
return x.Symbols
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Symbol represents information about a trading pair.
|
||||
type Symbol struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Symbol string `protobuf:"bytes,1,opt,name=symbol,proto3" json:"symbol,omitempty"` // 交易對名稱 (BTCUSDT)
|
||||
Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` // 狀態(如 "TRADING" 表示可交易)
|
||||
BaseAsset string `protobuf:"bytes,3,opt,name=base_asset,json=baseAsset,proto3" json:"base_asset,omitempty"` // 主幣種(如 BTCUSDT 的 BTC)
|
||||
BaseAssetPrecision int32 `protobuf:"varint,4,opt,name=base_asset_precision,json=baseAssetPrecision,proto3" json:"base_asset_precision,omitempty"` // 主幣的小數點精度
|
||||
QuoteAsset string `protobuf:"bytes,5,opt,name=quote_asset,json=quoteAsset,proto3" json:"quote_asset,omitempty"` // 報價幣種(如 BTCUSDT 的 USDT)
|
||||
QuoteAssetPrecision int32 `protobuf:"varint,6,opt,name=quote_asset_precision,json=quoteAssetPrecision,proto3" json:"quote_asset_precision,omitempty"` // 報價資產顯示的小數位數
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Symbol) Reset() {
|
||||
*x = Symbol{}
|
||||
mi := &file_generate_rpc_blockchain_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Symbol) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Symbol) ProtoMessage() {}
|
||||
|
||||
func (x *Symbol) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_generate_rpc_blockchain_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Symbol.ProtoReflect.Descriptor instead.
|
||||
func (*Symbol) Descriptor() ([]byte, []int) {
|
||||
return file_generate_rpc_blockchain_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *Symbol) GetSymbol() string {
|
||||
if x != nil {
|
||||
return x.Symbol
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Symbol) GetStatus() string {
|
||||
if x != nil {
|
||||
return x.Status
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Symbol) GetBaseAsset() string {
|
||||
if x != nil {
|
||||
return x.BaseAsset
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Symbol) GetBaseAssetPrecision() int32 {
|
||||
if x != nil {
|
||||
return x.BaseAssetPrecision
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Symbol) GetQuoteAsset() string {
|
||||
if x != nil {
|
||||
return x.QuoteAsset
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Symbol) GetQuoteAssetPrecision() int32 {
|
||||
if x != nil {
|
||||
return x.QuoteAssetPrecision
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_generate_rpc_blockchain_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_generate_rpc_blockchain_proto_rawDesc = "" +
|
||||
|
@ -102,8 +270,21 @@ const file_generate_rpc_blockchain_proto_rawDesc = "" +
|
|||
"\x1dgenerate/rpc/blockchain.proto\x12\n" +
|
||||
"blockchain\"\b\n" +
|
||||
"\x06OKResp\"\t\n" +
|
||||
"\aNoneReq2D\n" +
|
||||
"\x11BlockchainService\x12/\n" +
|
||||
"\aNoneReq\"\x14\n" +
|
||||
"\x12ListSymbolsRequest\"C\n" +
|
||||
"\x13ListSymbolsResponse\x12,\n" +
|
||||
"\asymbols\x18\x01 \x03(\v2\x12.blockchain.SymbolR\asymbols\"\xde\x01\n" +
|
||||
"\x06Symbol\x12\x16\n" +
|
||||
"\x06symbol\x18\x01 \x01(\tR\x06symbol\x12\x16\n" +
|
||||
"\x06status\x18\x02 \x01(\tR\x06status\x12\x1d\n" +
|
||||
"\n" +
|
||||
"base_asset\x18\x03 \x01(\tR\tbaseAsset\x120\n" +
|
||||
"\x14base_asset_precision\x18\x04 \x01(\x05R\x12baseAssetPrecision\x12\x1f\n" +
|
||||
"\vquote_asset\x18\x05 \x01(\tR\n" +
|
||||
"quoteAsset\x122\n" +
|
||||
"\x15quote_asset_precision\x18\x06 \x01(\x05R\x13quoteAssetPrecision2\x94\x01\n" +
|
||||
"\x11BlockchainService\x12N\n" +
|
||||
"\vListSymbols\x12\x1e.blockchain.ListSymbolsRequest\x1a\x1f.blockchain.ListSymbolsResponse\x12/\n" +
|
||||
"\x04Ping\x12\x13.blockchain.NoneReq\x1a\x12.blockchain.OKRespB.Z,code.30cm.net/digimon/app-cloudep-blockchainb\x06proto3"
|
||||
|
||||
var (
|
||||
|
@ -118,19 +299,25 @@ func file_generate_rpc_blockchain_proto_rawDescGZIP() []byte {
|
|||
return file_generate_rpc_blockchain_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_generate_rpc_blockchain_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_generate_rpc_blockchain_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||
var file_generate_rpc_blockchain_proto_goTypes = []any{
|
||||
(*OKResp)(nil), // 0: blockchain.OKResp
|
||||
(*NoneReq)(nil), // 1: blockchain.NoneReq
|
||||
(*OKResp)(nil), // 0: blockchain.OKResp
|
||||
(*NoneReq)(nil), // 1: blockchain.NoneReq
|
||||
(*ListSymbolsRequest)(nil), // 2: blockchain.ListSymbolsRequest
|
||||
(*ListSymbolsResponse)(nil), // 3: blockchain.ListSymbolsResponse
|
||||
(*Symbol)(nil), // 4: blockchain.Symbol
|
||||
}
|
||||
var file_generate_rpc_blockchain_proto_depIdxs = []int32{
|
||||
1, // 0: blockchain.BlockchainService.Ping:input_type -> blockchain.NoneReq
|
||||
0, // 1: blockchain.BlockchainService.Ping:output_type -> blockchain.OKResp
|
||||
1, // [1:2] is the sub-list for method output_type
|
||||
0, // [0:1] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
4, // 0: blockchain.ListSymbolsResponse.symbols:type_name -> blockchain.Symbol
|
||||
2, // 1: blockchain.BlockchainService.ListSymbols:input_type -> blockchain.ListSymbolsRequest
|
||||
1, // 2: blockchain.BlockchainService.Ping:input_type -> blockchain.NoneReq
|
||||
3, // 3: blockchain.BlockchainService.ListSymbols:output_type -> blockchain.ListSymbolsResponse
|
||||
0, // 4: blockchain.BlockchainService.Ping:output_type -> blockchain.OKResp
|
||||
3, // [3:5] is the sub-list for method output_type
|
||||
1, // [1:3] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_generate_rpc_blockchain_proto_init() }
|
||||
|
@ -144,7 +331,7 @@ func file_generate_rpc_blockchain_proto_init() {
|
|||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_generate_rpc_blockchain_proto_rawDesc), len(file_generate_rpc_blockchain_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumMessages: 5,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
|
|
@ -19,13 +19,17 @@ import (
|
|||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
BlockchainService_Ping_FullMethodName = "/blockchain.BlockchainService/Ping"
|
||||
BlockchainService_ListSymbols_FullMethodName = "/blockchain.BlockchainService/ListSymbols"
|
||||
BlockchainService_Ping_FullMethodName = "/blockchain.BlockchainService/Ping"
|
||||
)
|
||||
|
||||
// BlockchainServiceClient is the client API for BlockchainService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type BlockchainServiceClient interface {
|
||||
// ListSymbols retrieves all available trading symbols.
|
||||
ListSymbols(ctx context.Context, in *ListSymbolsRequest, opts ...grpc.CallOption) (*ListSymbolsResponse, error)
|
||||
// Ping is a health-check endpoint.
|
||||
Ping(ctx context.Context, in *NoneReq, opts ...grpc.CallOption) (*OKResp, error)
|
||||
}
|
||||
|
||||
|
@ -37,6 +41,16 @@ func NewBlockchainServiceClient(cc grpc.ClientConnInterface) BlockchainServiceCl
|
|||
return &blockchainServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *blockchainServiceClient) ListSymbols(ctx context.Context, in *ListSymbolsRequest, opts ...grpc.CallOption) (*ListSymbolsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListSymbolsResponse)
|
||||
err := c.cc.Invoke(ctx, BlockchainService_ListSymbols_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *blockchainServiceClient) Ping(ctx context.Context, in *NoneReq, opts ...grpc.CallOption) (*OKResp, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(OKResp)
|
||||
|
@ -51,6 +65,9 @@ func (c *blockchainServiceClient) Ping(ctx context.Context, in *NoneReq, opts ..
|
|||
// All implementations must embed UnimplementedBlockchainServiceServer
|
||||
// for forward compatibility.
|
||||
type BlockchainServiceServer interface {
|
||||
// ListSymbols retrieves all available trading symbols.
|
||||
ListSymbols(context.Context, *ListSymbolsRequest) (*ListSymbolsResponse, error)
|
||||
// Ping is a health-check endpoint.
|
||||
Ping(context.Context, *NoneReq) (*OKResp, error)
|
||||
mustEmbedUnimplementedBlockchainServiceServer()
|
||||
}
|
||||
|
@ -62,6 +79,9 @@ type BlockchainServiceServer interface {
|
|||
// pointer dereference when methods are called.
|
||||
type UnimplementedBlockchainServiceServer struct{}
|
||||
|
||||
func (UnimplementedBlockchainServiceServer) ListSymbols(context.Context, *ListSymbolsRequest) (*ListSymbolsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListSymbols not implemented")
|
||||
}
|
||||
func (UnimplementedBlockchainServiceServer) Ping(context.Context, *NoneReq) (*OKResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented")
|
||||
}
|
||||
|
@ -86,6 +106,24 @@ func RegisterBlockchainServiceServer(s grpc.ServiceRegistrar, srv BlockchainServ
|
|||
s.RegisterService(&BlockchainService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _BlockchainService_ListSymbols_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListSymbolsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(BlockchainServiceServer).ListSymbols(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: BlockchainService_ListSymbols_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(BlockchainServiceServer).ListSymbols(ctx, req.(*ListSymbolsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _BlockchainService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(NoneReq)
|
||||
if err := dec(in); err != nil {
|
||||
|
@ -111,6 +149,10 @@ var BlockchainService_ServiceDesc = grpc.ServiceDesc{
|
|||
ServiceName: "blockchain.BlockchainService",
|
||||
HandlerType: (*BlockchainServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "ListSymbols",
|
||||
Handler: _BlockchainService_ListSymbols_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Ping",
|
||||
Handler: _BlockchainService_Ping_Handler,
|
||||
|
|
|
@ -8,6 +8,27 @@ message OKResp {}
|
|||
// NoneReq
|
||||
message NoneReq {}
|
||||
|
||||
// ListSymbolsRequest is the request for the ListSymbols RPC.
|
||||
// It is currently empty but can be extended with filtering or pagination fields in the future.
|
||||
message ListSymbolsRequest {}
|
||||
|
||||
// ListSymbolsResponse contains a list of symbols.
|
||||
message ListSymbolsResponse {
|
||||
repeated Symbol symbols = 1;
|
||||
}
|
||||
// Symbol represents information about a trading pair.
|
||||
message Symbol {
|
||||
string symbol = 1; // 交易對名稱 (BTCUSDT)
|
||||
string status = 2; // 狀態(如 "TRADING" 表示可交易)
|
||||
string base_asset = 3; // 主幣種(如 BTCUSDT 的 BTC)
|
||||
int32 base_asset_precision = 4; // 主幣的小數點精度
|
||||
string quote_asset = 5; // 報價幣種(如 BTCUSDT 的 USDT)
|
||||
int32 quote_asset_precision = 6; // 報價資產顯示的小數位數
|
||||
}
|
||||
|
||||
service BlockchainService{
|
||||
// ListSymbols retrieves all available trading symbols.
|
||||
rpc ListSymbols(ListSymbolsRequest) returns(ListSymbolsResponse);
|
||||
// Ping is a health-check endpoint.
|
||||
rpc Ping(NoneReq) returns(OKResp);
|
||||
}
|
||||
}
|
||||
|
|
1
go.mod
1
go.mod
|
@ -18,6 +18,7 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
code.30cm.net/digimon/library-go/errs v1.2.14
|
||||
github.com/adshao/go-binance/v2 v2.8.3
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1,3 +1,5 @@
|
|||
code.30cm.net/digimon/library-go/errs v1.2.14 h1:Un9wcIIjjJW8D2i0ISf8ibzp9oNT4OqLsaSKW0T4RJU=
|
||||
code.30cm.net/digimon/library-go/errs v1.2.14/go.mod h1:Hs4v7SbXNggDVBGXSYsFMjkii1qLF+rugrIpWePN4/o=
|
||||
github.com/adshao/go-binance/v2 v2.8.3 h1:jwPRcX2u7FIO1pPoXgocyXpXhBI81A41kcmSDzS6uzo=
|
||||
github.com/adshao/go-binance/v2 v2.8.3/go.mod h1:XkkuecSyJKPolaCGf/q4ovJYB3t0P+7RUYTbGr+LMGM=
|
||||
github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI=
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
package config
|
||||
|
||||
import "github.com/zeromicro/go-zero/zrpc"
|
||||
import (
|
||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||
"github.com/zeromicro/go-zero/zrpc"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
zrpc.RpcServerConf
|
||||
Binance
|
||||
Binance Binance
|
||||
// Redis Cluster
|
||||
RedisCluster redis.RedisConf
|
||||
}
|
||||
|
||||
type Binance struct {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package blockchain
|
||||
|
||||
import "code.30cm.net/digimon/library-go/errs"
|
||||
|
||||
const CodeBlockchain uint32 = 10
|
||||
|
||||
const FailedToGetSymbolFormBinanceErrorCode errs.ErrorCode = 1
|
|
@ -6,5 +6,5 @@ import (
|
|||
)
|
||||
|
||||
type DataSourceRepository interface {
|
||||
GetSymbols(ctx context.Context) ([]entity.Symbol, error)
|
||||
GetSymbols(ctx context.Context) ([]*entity.Symbol, error)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type DataSourceUseCase interface {
|
||||
GetSymbols(ctx context.Context) ([]*Symbol, error)
|
||||
}
|
||||
|
||||
// Symbol 代表交易對資訊
|
||||
type Symbol struct {
|
||||
Symbol string `json:"symbol"` // 交易對名稱 (BTCUSDT)
|
||||
Status string `json:"status"` // 狀態(如 "TRADING" 表示可交易)
|
||||
BaseAsset string `json:"base_asset"` // 主幣種(如 BTCUSDT 的 BTC)
|
||||
BaseAssetPrecision int `json:"base_asset_precision"` // 主幣的小數點精度
|
||||
QuoteAsset string `json:"quote_asset"` // 報價幣種(如 BTCUSDT 的 USDT)
|
||||
QuoteAssetPrecision int `json:"quote_asset_precision"` // 報價資產顯示的小數位數
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package blockchainservicelogic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
app_cloudep_blockchain "blockchain/gen_result/pb/code.30cm.net/digimon/app-cloudep-blockchain"
|
||||
"blockchain/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ListSymbolsLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewListSymbolsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListSymbolsLogic {
|
||||
return &ListSymbolsLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// ListSymbols retrieves all available trading symbols.
|
||||
func (l *ListSymbolsLogic) ListSymbols(in *app_cloudep_blockchain.ListSymbolsRequest) (*app_cloudep_blockchain.ListSymbolsResponse, error) {
|
||||
result, err := l.svcCtx.BinanceDataSource.GetSymbols(l.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rpy := make([]*app_cloudep_blockchain.Symbol, 0, len(result))
|
||||
|
||||
for _, item := range result {
|
||||
rpy = append(rpy, &app_cloudep_blockchain.Symbol{
|
||||
Symbol: item.Symbol,
|
||||
Status: item.Status,
|
||||
BaseAsset: item.BaseAsset,
|
||||
BaseAssetPrecision: int32(item.BaseAssetPrecision),
|
||||
QuoteAsset: item.QuoteAsset,
|
||||
QuoteAssetPrecision: int32(item.QuoteAssetPrecision),
|
||||
})
|
||||
}
|
||||
|
||||
return &app_cloudep_blockchain.ListSymbolsResponse{
|
||||
Symbols: rpy,
|
||||
}, nil
|
||||
}
|
|
@ -41,16 +41,16 @@ func MustBinanceRepository(param BinanceRepositoryParam) repository.DataSourceRe
|
|||
}
|
||||
}
|
||||
|
||||
func (repo *BinanceRepository) GetSymbols(ctx context.Context) ([]entity.Symbol, error) {
|
||||
func (repo *BinanceRepository) GetSymbols(ctx context.Context) ([]*entity.Symbol, error) {
|
||||
// 優先從 redis hash 拿
|
||||
cached, err := repo.rds.Hgetall(blockchain.RedisKeySymbolList)
|
||||
if err == nil && len(cached) > 0 {
|
||||
symbols := make([]entity.Symbol, 0, len(cached))
|
||||
symbols := make([]*entity.Symbol, 0, len(cached))
|
||||
canUseCache := true
|
||||
for _, v := range cached {
|
||||
var symbol entity.Symbol
|
||||
if err := json.Unmarshal([]byte(v), &symbol); err == nil {
|
||||
symbols = append(symbols, symbol)
|
||||
symbols = append(symbols, &symbol)
|
||||
} else {
|
||||
// 如果任何一個反序列化失敗,代表快取可能已損壞,最好是回源重新拉取
|
||||
canUseCache = false
|
||||
|
@ -68,11 +68,11 @@ func (repo *BinanceRepository) GetSymbols(ctx context.Context) ([]entity.Symbol,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]entity.Symbol, 0, len(srcSymbols))
|
||||
result := make([]*entity.Symbol, 0, len(srcSymbols))
|
||||
hashData := make(map[string]string, len(srcSymbols))
|
||||
for _, s := range srcSymbols {
|
||||
// 只挑目前需要的欄位
|
||||
symbolEntity := entity.Symbol{
|
||||
symbolEntity := &entity.Symbol{
|
||||
Symbol: s.Symbol,
|
||||
Status: s.Status,
|
||||
BaseAsset: s.BaseAsset,
|
||||
|
@ -106,7 +106,7 @@ func (repo *BinanceRepository) GetSymbols(ctx context.Context) ([]entity.Symbol,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return val.([]entity.Symbol), nil
|
||||
return val.([]*entity.Symbol), nil
|
||||
}
|
||||
|
||||
func (repo *BinanceRepository) getSymbolsFromSource(ctx context.Context) ([]binance.Symbol, error) {
|
||||
|
|
|
@ -23,6 +23,13 @@ func NewBlockchainServiceServer(svcCtx *svc.ServiceContext) *BlockchainServiceSe
|
|||
}
|
||||
}
|
||||
|
||||
// ListSymbols retrieves all available trading symbols.
|
||||
func (s *BlockchainServiceServer) ListSymbols(ctx context.Context, in *app_cloudep_blockchain.ListSymbolsRequest) (*app_cloudep_blockchain.ListSymbolsResponse, error) {
|
||||
l := blockchainservicelogic.NewListSymbolsLogic(ctx, s.svcCtx)
|
||||
return l.ListSymbols(in)
|
||||
}
|
||||
|
||||
// Ping is a health-check endpoint.
|
||||
func (s *BlockchainServiceServer) Ping(ctx context.Context, in *app_cloudep_blockchain.NoneReq) (*app_cloudep_blockchain.OKResp, error) {
|
||||
l := blockchainservicelogic.NewPingLogic(ctx, s.svcCtx)
|
||||
return l.Ping(in)
|
||||
|
|
|
@ -1,13 +1,37 @@
|
|||
package svc
|
||||
|
||||
import "blockchain/internal/config"
|
||||
import (
|
||||
"blockchain/internal/config"
|
||||
"blockchain/internal/domain/repository"
|
||||
"blockchain/internal/domain/usecase"
|
||||
repo "blockchain/internal/repository"
|
||||
uc "blockchain/internal/usecase"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||
)
|
||||
|
||||
type ServiceContext struct {
|
||||
Config config.Config
|
||||
Config config.Config
|
||||
BinanceDataSource usecase.DataSourceUseCase
|
||||
BinanceRepo repository.DataSourceRepository
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
|
||||
newRedis, err := redis.NewRedis(c.RedisCluster)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
binanceRepo := repo.MustBinanceRepository(repo.BinanceRepositoryParam{
|
||||
Conf: &c.Binance,
|
||||
Redis: newRedis,
|
||||
})
|
||||
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
Config: c,
|
||||
BinanceRepo: binanceRepo,
|
||||
BinanceDataSource: uc.MustBinanceUseCase(uc.BinanceUseCaseParam{
|
||||
BinanceRepo: binanceRepo,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package usecase
|
||||
|
||||
import (
|
||||
"blockchain/internal/domain/blockchain"
|
||||
"blockchain/internal/domain/repository"
|
||||
"blockchain/internal/domain/usecase"
|
||||
"context"
|
||||
|
||||
"code.30cm.net/digimon/library-go/errs"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type BinanceUseCaseParam struct {
|
||||
BinanceRepo repository.DataSourceRepository
|
||||
}
|
||||
|
||||
type BinanceUseCase struct {
|
||||
BinanceUseCaseParam
|
||||
}
|
||||
|
||||
func MustBinanceUseCase(param BinanceUseCaseParam) usecase.DataSourceUseCase {
|
||||
return &BinanceUseCase{
|
||||
BinanceUseCaseParam: param,
|
||||
}
|
||||
}
|
||||
|
||||
// GetSymbols implements usecase.DataSourceUseCase.
|
||||
func (use *BinanceUseCase) GetSymbols(ctx context.Context) ([]*usecase.Symbol, error) {
|
||||
result, err := use.BinanceRepo.GetSymbols(ctx)
|
||||
if err != nil {
|
||||
// 錯誤代碼 20-201-04
|
||||
e := errs.ThirdPartyErrorL(
|
||||
blockchain.CodeBlockchain,
|
||||
blockchain.FailedToGetSymbolFormBinanceErrorCode,
|
||||
logx.WithContext(ctx),
|
||||
[]logx.LogField{
|
||||
{Key: "func", Value: "BinanceUseCase.ThirdPartyErrorL"},
|
||||
{Key: "err", Value: err.Error()},
|
||||
},
|
||||
"failed to get symbols from binance").Wrap(err)
|
||||
|
||||
return nil, e
|
||||
}
|
||||
|
||||
rpy := make([]*usecase.Symbol, len(result))
|
||||
for _, item := range result {
|
||||
rpy = append(rpy, &usecase.Symbol{
|
||||
Symbol: item.Symbol,
|
||||
Status: item.Status,
|
||||
BaseAsset: item.BaseAsset,
|
||||
BaseAssetPrecision: item.BaseAssetPrecision,
|
||||
QuoteAsset: item.QuoteAsset,
|
||||
QuoteAssetPrecision: item.QuoteAssetPrecision,
|
||||
})
|
||||
}
|
||||
|
||||
return rpy, nil
|
||||
|
||||
}
|
Loading…
Reference in New Issue