Skip to content

Commit 3c8b802

Browse files
committed
wip explorer
1 parent 1311785 commit 3c8b802

File tree

2 files changed

+296
-41
lines changed

2 files changed

+296
-41
lines changed

server/internal/core/application/indexer.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,10 @@ func (i *indexerService) GetVirtualTxs(ctx context.Context, req VirtualTxsReq) (
323323
}
324324

325325
func (i *indexerService) GetSweptCommitmentTx(ctx context.Context, txid string) (SweptCommitmentTxResp, error) {
326-
round, err := i.repoManager.Rounds().GetRoundWithTxid(ctx, txid)
327-
if err != nil {
328-
return SweptCommitmentTxResp{}, err
329-
}
326+
// TODO currently not possible to find swept commitment tx, we need either to scan explorer which would be inefficient
327+
// or to store sweep txs it in the database
330328

331-
return SweptCommitmentTxResp{
332-
SweptBy: round.Swept,
333-
}, nil
329+
return SweptCommitmentTxResp{}, nil
334330
}
335331

336332
func paginate[T any](items []T, params PageReq) ([]T, PageResp, error) {

server/internal/interface/grpc/handlers/explorer.go

Lines changed: 293 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ package handlers
22

33
import (
44
"context"
5+
"fmt"
6+
57
arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1"
68
"github.com/ark-network/ark/server/internal/core/application"
9+
"google.golang.org/grpc/codes"
10+
"google.golang.org/grpc/status"
711
)
812

913
type explorerService struct {
@@ -16,50 +20,305 @@ func NewExplorerServiceServer(indexerSvc application.IndexerService) arkv1.Explo
1620
}
1721
}
1822

19-
func (e explorerService) GetCommitmentTxInfo(
20-
ctx context.Context, request *arkv1.GetCommitmentTxInfoRequest,
21-
) (*arkv1.GetCommitmentTxInfoResponse, error) {
22-
//TODO implement me
23-
panic("implement me")
23+
func (e explorerService) GetCommitmentTx(
24+
ctx context.Context, request *arkv1.GetCommitmentTxRequest,
25+
) (*arkv1.GetCommitmentTxResponse, error) {
26+
resp, err := e.indexerSvc.GetCommitmentTxInfo(ctx, request.Txid)
27+
if err != nil {
28+
return nil, status.Errorf(codes.Internal, "failed to get commitment tx info: %v", err)
29+
}
30+
31+
batches := make(map[uint32]*arkv1.Batch)
32+
for vout, batch := range resp.Batches {
33+
batches[uint32(vout)] = &arkv1.Batch{
34+
TotalBatchAmount: batch.TotalBatchAmount,
35+
TotalForfeitAmount: batch.TotalForfeitAmount,
36+
TotalInputVtxos: batch.TotalInputVtxos,
37+
TotalOutputVtxos: batch.TotalOutputVtxos,
38+
ExpiresAt: batch.ExpiresAt,
39+
Swept: batch.Swept,
40+
}
41+
}
42+
43+
return &arkv1.GetCommitmentTxResponse{
44+
StartedAt: resp.StartedAt,
45+
EndedAt: resp.EndAt,
46+
Batches: batches,
47+
}, nil
48+
}
49+
50+
func (e explorerService) GetVtxoTree(ctx context.Context, request *arkv1.GetVtxoTreeRequest) (*arkv1.GetVtxoTreeResponse, error) {
51+
req := application.VtxoTreeReq{
52+
BatchOutpoint: application.Outpoint{
53+
Txid: request.BatchOutpoint.Txid,
54+
Vout: request.BatchOutpoint.Vout,
55+
},
56+
Page: application.PageReq{
57+
PageSize: int(request.Page.Size),
58+
PageNum: int(request.Page.Index),
59+
},
60+
}
61+
62+
resp, err := e.indexerSvc.GetVtxoTree(ctx, req)
63+
if err != nil {
64+
return nil, status.Errorf(codes.Internal, "failed to get vtxo tree: %v", err)
65+
}
66+
67+
nodes := make([]*arkv1.Node, len(resp.Nodes))
68+
for i, node := range resp.Nodes {
69+
nodes[i] = &arkv1.Node{
70+
Txid: node.Txid,
71+
Tx: node.Tx,
72+
ParentTxid: node.ParentTxid,
73+
Level: node.Level,
74+
LevelIndex: node.LevelIndex,
75+
}
76+
}
77+
78+
return &arkv1.GetVtxoTreeResponse{
79+
VtxoTree: nodes,
80+
Page: &arkv1.PageResponse{
81+
Current: int32(resp.Page.Current),
82+
Next: int32(resp.Page.Next),
83+
Total: int32(resp.Page.Total),
84+
},
85+
}, nil
86+
}
87+
88+
func (e explorerService) GetForfeitTxs(ctx context.Context, request *arkv1.GetForfeitTxsRequest) (*arkv1.GetForfeitTxsResponse, error) {
89+
req := application.ForfeitTxsReq{
90+
BatchOutpoint: application.Outpoint{
91+
Txid: request.BatchOutpoint.Txid,
92+
Vout: request.BatchOutpoint.Vout,
93+
},
94+
Page: application.PageReq{
95+
PageSize: int(request.Page.Size),
96+
PageNum: int(request.Page.Index),
97+
},
98+
}
99+
100+
resp, err := e.indexerSvc.GetForfeitTxs(ctx, req)
101+
if err != nil {
102+
return nil, status.Errorf(codes.Internal, "failed to get forfeit txs: %v", err)
103+
}
104+
105+
return &arkv1.GetForfeitTxsResponse{
106+
Txs: resp.Txs,
107+
Page: &arkv1.PageResponse{
108+
Current: int32(resp.Page.Current),
109+
Next: int32(resp.Page.Next),
110+
Total: int32(resp.Page.Total),
111+
},
112+
}, nil
113+
}
114+
115+
func (e explorerService) GetConnectors(ctx context.Context, request *arkv1.GetConnectorsRequest) (*arkv1.GetConnectorsResponse, error) {
116+
req := application.ConnectorsReq{
117+
BatchOutpoint: application.Outpoint{
118+
Txid: request.BatchOutpoint.Txid,
119+
Vout: request.BatchOutpoint.Vout,
120+
},
121+
Page: application.PageReq{
122+
PageSize: int(request.Page.Size),
123+
PageNum: int(request.Page.Index),
124+
},
125+
}
126+
127+
resp, err := e.indexerSvc.GetConnectors(ctx, req)
128+
if err != nil {
129+
return nil, status.Errorf(codes.Internal, "failed to get connectors: %v", err)
130+
}
131+
132+
connectors := make([]*arkv1.Node, len(resp.Connectors))
133+
for i, connector := range resp.Connectors {
134+
connectors[i] = &arkv1.Node{
135+
Txid: connector.Txid,
136+
Tx: connector.Tx,
137+
ParentTxid: connector.ParentTxid,
138+
Level: connector.Level,
139+
LevelIndex: connector.LevelIndex,
140+
}
141+
}
142+
143+
return &arkv1.GetConnectorsResponse{
144+
Connectors: connectors,
145+
Page: &arkv1.PageResponse{
146+
Current: int32(resp.Page.Current),
147+
Next: int32(resp.Page.Next),
148+
Total: int32(resp.Page.Total),
149+
},
150+
}, nil
24151
}
25152

26-
func (e explorerService) GetVtxoTree(
27-
ctx context.Context, request *arkv1.GetVtxoTreeRequest,
28-
) (*arkv1.GetVtxoTreeResponse, error) {
29-
//TODO implement me
30-
panic("implement me")
153+
func (e explorerService) GetSpendableVtxos(ctx context.Context, request *arkv1.GetSpendableVtxosRequest) (*arkv1.GetSpendableVtxosResponse, error) {
154+
req := application.SpendableVtxosReq{
155+
Address: request.Address,
156+
Page: application.PageReq{
157+
PageSize: int(request.Page.Size),
158+
PageNum: int(request.Page.Index),
159+
},
160+
}
161+
162+
resp, err := e.indexerSvc.GetSpendableVtxos(ctx, req)
163+
if err != nil {
164+
return nil, status.Errorf(codes.Internal, "failed to get spendable vtxos: %v", err)
165+
}
166+
167+
vtxos := make([]*arkv1.Vtxo, len(resp.Vtxos))
168+
for i, vtxo := range resp.Vtxos {
169+
vtxos[i] = &arkv1.Vtxo{
170+
Outpoint: &arkv1.Outpoint{
171+
Txid: vtxo.Txid,
172+
Vout: vtxo.VOut,
173+
},
174+
CreatedAt: vtxo.CreatedAt,
175+
ExpiresAt: vtxo.ExpireAt,
176+
Amount: vtxo.Amount,
177+
Script: vtxo.PubKey,
178+
IsLeaf: vtxo.RoundTxid == "",
179+
IsSwept: vtxo.Swept,
180+
IsSpent: vtxo.Spent,
181+
SpentBy: vtxo.SpentBy,
182+
}
183+
}
184+
185+
return &arkv1.GetSpendableVtxosResponse{
186+
Vtxos: vtxos,
187+
Page: &arkv1.PageResponse{
188+
Current: int32(resp.Page.Current),
189+
Next: int32(resp.Page.Next),
190+
Total: int32(resp.Page.Total),
191+
},
192+
}, nil
31193
}
32194

33-
func (e explorerService) GetForfeitTxs(
34-
ctx context.Context, request *arkv1.GetForfeitTxsRequest) (*arkv1.GetForfeitTxsResponse, error) {
35-
//TODO implement me
36-
panic("implement me")
195+
func (e explorerService) GetTransactionHistory(ctx context.Context, request *arkv1.GetTransactionHistoryRequest) (*arkv1.GetTransactionHistoryResponse, error) {
196+
req := application.TxHistoryReq{
197+
Address: request.Address,
198+
StartTime: request.StartTime,
199+
EndTime: request.EndTime,
200+
Page: application.PageReq{
201+
PageSize: int(request.Page.Size),
202+
PageNum: int(request.Page.Index),
203+
},
204+
}
205+
206+
resp, err := e.indexerSvc.GetTransactionHistory(ctx, req)
207+
if err != nil {
208+
return nil, status.Errorf(codes.Internal, "failed to get transaction history: %v", err)
209+
}
210+
211+
history := make([]*arkv1.TxHistoryRecord, len(resp.Records))
212+
for i, record := range resp.Records {
213+
history[i] = &arkv1.TxHistoryRecord{
214+
Type: arkv1.TxType(record.Type),
215+
Amount: record.Amount,
216+
CreatedAt: record.CreatedAt,
217+
ConfirmedAt: record.ConfirmedAt,
218+
IsSettled: record.IsSettled,
219+
}
220+
221+
// Set the appropriate key based on the record type
222+
switch record.Type {
223+
case application.TxTypeReceived:
224+
history[i].Key = &arkv1.TxHistoryRecord_BoardingTxid{
225+
BoardingTxid: record.Txid,
226+
}
227+
case application.TxTypeSent:
228+
history[i].Key = &arkv1.TxHistoryRecord_CommitmentTxid{
229+
CommitmentTxid: record.Txid,
230+
}
231+
case application.TxTypeSweep:
232+
history[i].Key = &arkv1.TxHistoryRecord_SweepTxid{
233+
SweepTxid: record.Txid,
234+
}
235+
default:
236+
history[i].Key = &arkv1.TxHistoryRecord_ArkTxid{
237+
ArkTxid: record.Txid,
238+
}
239+
}
240+
}
241+
242+
return &arkv1.GetTransactionHistoryResponse{
243+
History: history,
244+
Page: &arkv1.PageResponse{
245+
Current: int32(resp.Pagination.Current),
246+
Next: int32(resp.Pagination.Next),
247+
Total: int32(resp.Pagination.Total),
248+
},
249+
}, nil
37250
}
38251

39-
func (e explorerService) GetConnectors(
40-
ctx context.Context, request *arkv1.GetConnectorsRequest,
41-
) (*arkv1.GetConnectorsResponse, error) {
42-
//TODO implement me
43-
panic("implement me")
252+
func (e explorerService) GetVtxoChain(ctx context.Context, request *arkv1.GetVtxoChainRequest) (*arkv1.GetVtxoChainResponse, error) {
253+
req := application.VtxoChainReq{
254+
VtxoKey: application.Outpoint{
255+
Txid: request.Outpoint.Txid,
256+
Vout: request.Outpoint.Vout,
257+
},
258+
Page: application.PageReq{
259+
PageSize: int(request.Page.Size),
260+
PageNum: int(request.Page.Index),
261+
},
262+
}
263+
264+
resp, err := e.indexerSvc.GetVtxoChain(ctx, req)
265+
if err != nil {
266+
return nil, status.Errorf(codes.Internal, "failed to get vtxo chain: %v", err)
267+
}
268+
269+
graph := make(map[string]*arkv1.Transactions)
270+
for outpoint, tx := range resp.Transactions {
271+
graph[fmt.Sprintf("%s:%d", outpoint.Txid, outpoint.Vout)] = &arkv1.Transactions{
272+
Txs: []string{tx},
273+
}
274+
}
275+
276+
return &arkv1.GetVtxoChainResponse{
277+
Graph: graph,
278+
Page: &arkv1.PageResponse{
279+
Current: int32(resp.Page.Current),
280+
Next: int32(resp.Page.Next),
281+
Total: int32(resp.Page.Total),
282+
},
283+
}, nil
44284
}
45285

46-
func (e explorerService) GetSpendableVtxos(
47-
ctx context.Context, request *arkv1.GetSpendableVtxosRequest,
48-
) (*arkv1.GetSpendableVtxosResponse, error) {
49-
//TODO implement me
50-
panic("implement me")
286+
func (e explorerService) GetVirtualTxs(ctx context.Context, request *arkv1.GetVirtualTxsRequest) (*arkv1.GetVirtualTxsResponse, error) {
287+
req := application.VirtualTxsReq{
288+
TxIDs: request.Txids,
289+
Page: application.PageReq{
290+
PageSize: int(request.Page.Size),
291+
PageNum: int(request.Page.Index),
292+
},
293+
}
294+
295+
resp, err := e.indexerSvc.GetVirtualTxs(ctx, req)
296+
if err != nil {
297+
return nil, status.Errorf(codes.Internal, "failed to get virtual txs: %v", err)
298+
}
299+
300+
return &arkv1.GetVirtualTxsResponse{
301+
Txs: resp.Transactions,
302+
Page: &arkv1.PageResponse{
303+
Current: int32(resp.Page.Current),
304+
Next: int32(resp.Page.Next),
305+
Total: int32(resp.Page.Total),
306+
},
307+
}, nil
51308
}
52309

53-
func (e explorerService) GetTransactionHistory(
54-
ctx context.Context, request *arkv1.GetTransactionHistoryRequest,
55-
) (*arkv1.GetTransactionHistoryResponse, error) {
56-
//TODO implement me
57-
panic("implement me")
310+
func (e explorerService) GetSweptCommitmentTx(ctx context.Context, request *arkv1.GetSweptCommitmentTxRequest) (*arkv1.GetSweptCommitmentTxResponse, error) {
311+
resp, err := e.indexerSvc.GetSweptCommitmentTx(ctx, request.Txid)
312+
if err != nil {
313+
return nil, status.Errorf(codes.Internal, "failed to get swept commitment tx: %v", err)
314+
}
315+
316+
return &arkv1.GetSweptCommitmentTxResponse{
317+
SweptBy: resp.SweptBy,
318+
}, nil
58319
}
59320

60-
func (e explorerService) GetTransactionChain(
61-
ctx context.Context, request *arkv1.GetTransactionChainRequest,
62-
) (*arkv1.GetTransactionChainResponse, error) {
63-
//TODO implement me
64-
panic("implement me")
321+
func (e explorerService) SubscribeForAddresses(request *arkv1.SubscribeForAddressesRequest, server arkv1.ExplorerService_SubscribeForAddressesServer) error {
322+
// TODO: Implement address subscription
323+
return status.Error(codes.Unimplemented, "method SubscribeForAddresses not implemented")
65324
}

0 commit comments

Comments
 (0)