Skip to content

Commit b8554b3

Browse files
author
callmedenchick
committed
implement new client
1 parent bdf3812 commit b8554b3

11 files changed

Lines changed: 3964 additions & 7 deletions

File tree

go.mod

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
module github.com/tonkeeper/tongo
22

3-
go 1.19
3+
go 1.24.0
4+
5+
toolchain go1.24.10
46

57
require (
68
github.com/alecthomas/participle/v2 v2.0.0-beta.5
79
github.com/oasisprotocol/curve25519-voi v0.0.0-20220328075252-7dd334e3daae
810
github.com/snksoft/crc v1.1.0
9-
golang.org/x/crypto v0.17.0
11+
golang.org/x/crypto v0.40.0
1012
golang.org/x/exp v0.0.0-20230116083435-1de6713980de
13+
google.golang.org/grpc v1.76.0
14+
google.golang.org/protobuf v1.36.10
1115
)
1216

1317
require (
1418
github.com/alecthomas/repr v0.1.1 // indirect
15-
golang.org/x/sys v0.15.0 // indirect
19+
golang.org/x/net v0.42.0 // indirect
20+
golang.org/x/sys v0.34.0 // indirect
21+
golang.org/x/text v0.27.0 // indirect
22+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect
1623
)

go.sum

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,52 @@
11
github.com/alecthomas/assert/v2 v2.0.3 h1:WKqJODfOiQG0nEJKFKzDIG3E29CN2/4zR9XGJzKIkbg=
2+
github.com/alecthomas/assert/v2 v2.0.3/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA=
23
github.com/alecthomas/participle/v2 v2.0.0-beta.5 h1:y6dsSYVb1G5eK6mgmy+BgI3Mw35a3WghArZ/Hbebrjo=
34
github.com/alecthomas/participle/v2 v2.0.0-beta.5/go.mod h1:RC764t6n4L8D8ITAJv0qdokritYSNR3wV5cVwmIEaMM=
45
github.com/alecthomas/repr v0.1.1 h1:87P60cSmareLAxMc4Hro0r2RBY4ROm0dYwkJNpS4pPs=
56
github.com/alecthomas/repr v0.1.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
7+
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
8+
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
9+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
10+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
11+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
12+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
13+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
14+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
15+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
16+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
617
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
18+
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
719
github.com/oasisprotocol/curve25519-voi v0.0.0-20220328075252-7dd334e3daae h1:7smdlrfdcZic4VfsGKD2ulWL804a4GVphr4s7WZxGiY=
820
github.com/oasisprotocol/curve25519-voi v0.0.0-20220328075252-7dd334e3daae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s=
921
github.com/snksoft/crc v1.1.0 h1:HkLdI4taFlgGGG1KvsWMpz78PkOC9TkPVpTV/cuWn48=
1022
github.com/snksoft/crc v1.1.0/go.mod h1:5/gUOsgAm7OmIhb6WJzw7w5g2zfJi4FrHYgGPdshE+A=
11-
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
12-
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
23+
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
24+
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
25+
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
26+
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
27+
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
28+
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
29+
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
30+
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
31+
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
32+
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
33+
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
34+
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
35+
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
36+
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
1337
golang.org/x/exp v0.0.0-20230116083435-1de6713980de h1:DBWn//IJw30uYCgERoxCg84hWtA97F4wMiKOIh00Uf0=
1438
golang.org/x/exp v0.0.0-20230116083435-1de6713980de/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
15-
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
16-
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
39+
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
40+
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
41+
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
42+
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
43+
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
44+
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
45+
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
46+
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
47+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b h1:zPKJod4w6F1+nRGDI9ubnXYhU9NSWoFAijkHkUXeTK8=
48+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
49+
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
50+
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
51+
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
52+
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=

tychoclient/client.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package tychoclient
2+
3+
import (
4+
"context"
5+
"crypto/tls"
6+
"fmt"
7+
"time"
8+
9+
"google.golang.org/grpc"
10+
"google.golang.org/grpc/credentials"
11+
12+
"github.com/tonkeeper/tongo/tychoclient/proto"
13+
)
14+
15+
const (
16+
// DefaultEndpoint is the testnet endpoint provided by the team
17+
DefaultEndpoint = "tonapi-testnet.tychoprotocol.com:443"
18+
19+
// DefaultTimeout for gRPC calls
20+
DefaultTimeout = 30 * time.Second
21+
)
22+
23+
// Client provides access to Tycho blockchain data via gRPC
24+
type Client struct {
25+
conn *grpc.ClientConn
26+
client proto.TychoIndexerClient
27+
}
28+
29+
// NewClient creates a new Tycho client with default settings
30+
func NewClient() (*Client, error) {
31+
return NewClientWithEndpoint(DefaultEndpoint)
32+
}
33+
34+
// NewClientWithEndpoint creates a new Tycho client with custom endpoint
35+
func NewClientWithEndpoint(endpoint string) (*Client, error) {
36+
// Use TLS for secure connection
37+
creds := credentials.NewTLS(&tls.Config{})
38+
39+
conn, err := grpc.Dial(endpoint, grpc.WithTransportCredentials(creds))
40+
if err != nil {
41+
return nil, fmt.Errorf("failed to connect to %s: %w", endpoint, err)
42+
}
43+
44+
return &Client{
45+
conn: conn,
46+
client: proto.NewTychoIndexerClient(conn),
47+
}, nil
48+
}
49+
50+
// Close closes the gRPC connection
51+
func (c *Client) Close() error {
52+
return c.conn.Close()
53+
}
54+
55+
// GetStatus returns the current status of the Tycho node
56+
func (c *Client) GetStatus(ctx context.Context) (*proto.GetStatusResponse, error) {
57+
ctx, cancel := context.WithTimeout(ctx, DefaultTimeout)
58+
defer cancel()
59+
60+
return c.client.GetStatus(ctx, &proto.GetStatusRequest{})
61+
}
62+
63+
// GetLibraryCell fetches a library cell by hash
64+
func (c *Client) GetLibraryCell(ctx context.Context, hash []byte) ([]byte, error) {
65+
ctx, cancel := context.WithTimeout(ctx, DefaultTimeout)
66+
defer cancel()
67+
68+
req := &proto.GetLibraryCellRequest{
69+
Hash: hash,
70+
}
71+
72+
resp, err := c.client.GetLibraryCell(ctx, req)
73+
if err != nil {
74+
return nil, fmt.Errorf("failed to get library cell: %w", err)
75+
}
76+
77+
switch result := resp.Library.(type) {
78+
case *proto.GetLibraryCellResponse_NotFound:
79+
return nil, fmt.Errorf("library cell not found")
80+
case *proto.GetLibraryCellResponse_Found:
81+
return result.Found.Cell, nil
82+
default:
83+
return nil, fmt.Errorf("unexpected response type")
84+
}
85+
}
86+
87+
// GetRawBlockData fetches raw BOC data for debugging purposes
88+
func (c *Client) GetRawBlockData(ctx context.Context, workchain int32, shard uint64, seqno uint32) ([]byte, error) {
89+
ctx, cancel := context.WithTimeout(ctx, DefaultTimeout)
90+
defer cancel()
91+
92+
req := &proto.GetBlockRequest{
93+
Query: &proto.GetBlockRequest_BySeqno{
94+
BySeqno: &proto.BlockBySeqno{
95+
Workchain: workchain,
96+
Shard: shard,
97+
Seqno: seqno,
98+
},
99+
},
100+
}
101+
102+
stream, err := c.client.GetBlock(ctx, req)
103+
if err != nil {
104+
return nil, fmt.Errorf("failed to start block stream: %w", err)
105+
}
106+
107+
return c.readBlockFromStream(stream)
108+
}
109+
110+
// readBlockFromStream reads block data from the gRPC stream
111+
func (c *Client) readBlockFromStream(stream proto.TychoIndexer_GetBlockClient) ([]byte, error) {
112+
var totalData []byte
113+
114+
for {
115+
resp, err := stream.Recv()
116+
if err != nil {
117+
if err.Error() == "EOF" {
118+
break
119+
}
120+
return nil, fmt.Errorf("stream error: %w", err)
121+
}
122+
123+
switch msg := resp.Msg.(type) {
124+
case *proto.GetBlockResponse_NotFound:
125+
return nil, fmt.Errorf("block not found")
126+
case *proto.GetBlockResponse_Found:
127+
// First chunk with metadata
128+
if msg.Found.FirstChunk != nil {
129+
totalData = append(totalData, msg.Found.FirstChunk.Data...)
130+
}
131+
case *proto.GetBlockResponse_Chunk:
132+
// Subsequent chunks
133+
totalData = append(totalData, msg.Chunk.Data...)
134+
default:
135+
return nil, fmt.Errorf("unexpected response type: %T", msg)
136+
}
137+
}
138+
139+
if len(totalData) == 0 {
140+
return nil, fmt.Errorf("no block data received")
141+
}
142+
143+
return totalData, nil
144+
}

0 commit comments

Comments
 (0)