Skip to content

Commit edbd4ca

Browse files
committed
feat: add getLastAcceptedEpoch to repository and jsonrpc
1 parent 0495479 commit edbd4ca

4 files changed

Lines changed: 119 additions & 0 deletions

File tree

internal/jsonrpc/jsonrpc-discover.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,27 @@
138138
}
139139
}
140140
},
141+
{
142+
"name": "cartesi_getLastAcceptedEpoch",
143+
"summary": "Get the last accepted epoch",
144+
"description": "Fetches the latest accepted epoch by application.",
145+
"params": [
146+
{
147+
"name": "application",
148+
"description": "The application's name or hex encoded address.",
149+
"schema": {
150+
"type": "string"
151+
},
152+
"required": true
153+
}
154+
],
155+
"result": {
156+
"name": "result",
157+
"schema": {
158+
"$ref": "#/components/schemas/EpochGetResult"
159+
}
160+
}
161+
},
141162
{
142163
"name": "cartesi_listInputs",
143164
"summary": "Retrieve a List of Inputs",

internal/jsonrpc/jsonrpc.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ func (s *Service) handleRPC(w http.ResponseWriter, r *http.Request) {
6969
s.handleListEpochs(w, r, req)
7070
case "cartesi_getEpoch":
7171
s.handleGetEpoch(w, r, req)
72+
case "cartesi_getLastAcceptedEpoch":
73+
s.handleGetLastAcceptedEpoch(w, r, req)
7274
case "cartesi_listInputs":
7375
s.handleListInputs(w, r, req)
7476
case "cartesi_getInput":
@@ -320,6 +322,40 @@ func (s *Service) handleGetEpoch(w http.ResponseWriter, r *http.Request, req RPC
320322
writeRPCResult(w, req.ID, result)
321323
}
322324

325+
func (s *Service) handleGetLastAcceptedEpoch(w http.ResponseWriter, r *http.Request, req RPCRequest) {
326+
var params GetEpochParams
327+
if err := json.Unmarshal(req.Params, &params); err != nil {
328+
writeRPCError(w, req.ID, JSONRPC_INVALID_PARAMS, "Invalid params", nil)
329+
return
330+
}
331+
332+
// Validate application parameter
333+
if err := validateNameOrAddress(params.Application); err != nil {
334+
writeRPCError(w, req.ID, JSONRPC_INVALID_PARAMS, fmt.Sprintf("Invalid application identifier: %v", err), nil)
335+
return
336+
}
337+
338+
epoch, err := s.repository.GetLastAcceptedEpoch(r.Context(), params.Application)
339+
if err != nil {
340+
s.Logger.Error("Unable to retrieve epoch from repository", "err", err)
341+
writeRPCError(w, req.ID, JSONRPC_INTERNAL_ERROR, "Internal server error", nil)
342+
return
343+
}
344+
if epoch == nil {
345+
writeRPCError(w, req.ID, JSONRPC_RESOURCE_NOT_FOUND, "Epoch not found", nil)
346+
return
347+
}
348+
349+
// Format response according to spec
350+
result := struct {
351+
Data *model.Epoch `json:"data"`
352+
}{
353+
Data: epoch,
354+
}
355+
356+
writeRPCResult(w, req.ID, result)
357+
}
358+
323359
func (s *Service) handleListInputs(w http.ResponseWriter, r *http.Request, req RPCRequest) {
324360
var params ListInputsParams
325361
if err := json.Unmarshal(req.Params, &params); err != nil {

internal/repository/postgres/epoch.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,67 @@ func (r *PostgresRepository) GetEpoch(
280280
return &ep, nil
281281
}
282282

283+
func (r *PostgresRepository) GetLastAcceptedEpoch(
284+
ctx context.Context,
285+
nameOrAddress string,
286+
) (*model.Epoch, error) {
287+
288+
whereClause, err := getWhereClauseFromNameOrAddress(nameOrAddress)
289+
if err != nil {
290+
return nil, err
291+
}
292+
293+
stmt := table.Epoch.
294+
SELECT(
295+
table.Epoch.ApplicationID,
296+
table.Epoch.Index,
297+
table.Epoch.FirstBlock,
298+
table.Epoch.LastBlock,
299+
table.Epoch.ClaimHash,
300+
table.Epoch.ClaimTransactionHash,
301+
table.Epoch.Status,
302+
table.Epoch.VirtualIndex,
303+
table.Epoch.CreatedAt,
304+
table.Epoch.UpdatedAt,
305+
).
306+
FROM(
307+
table.Epoch.
308+
INNER_JOIN(table.Application,
309+
table.Epoch.ApplicationID.EQ(table.Application.ID),
310+
),
311+
).
312+
WHERE(
313+
whereClause.
314+
AND(table.Epoch.Status.EQ(postgres.NewEnumValue(model.EpochStatus_ClaimAccepted.String()))),
315+
).
316+
ORDER_BY(table.Epoch.Index.DESC()).
317+
LIMIT(1)
318+
319+
sqlStr, args := stmt.Sql()
320+
row := r.db.QueryRow(ctx, sqlStr, args...)
321+
322+
var ep model.Epoch
323+
err = row.Scan(
324+
&ep.ApplicationID,
325+
&ep.Index,
326+
&ep.FirstBlock,
327+
&ep.LastBlock,
328+
&ep.ClaimHash,
329+
&ep.ClaimTransactionHash,
330+
&ep.Status,
331+
&ep.VirtualIndex,
332+
&ep.CreatedAt,
333+
&ep.UpdatedAt,
334+
)
335+
if errors.Is(err, sql.ErrNoRows) {
336+
return nil, nil
337+
}
338+
if err != nil {
339+
return nil, err
340+
}
341+
return &ep, nil
342+
}
343+
283344
func (r *PostgresRepository) GetEpochByVirtualIndex(
284345
ctx context.Context,
285346
nameOrAddress string,

internal/repository/repository.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type EpochRepository interface {
7474
CreateEpochsAndInputs(ctx context.Context, nameOrAddress string, epochInputMap map[*Epoch][]*Input, blockNumber uint64) error
7575

7676
GetEpoch(ctx context.Context, nameOrAddress string, index uint64) (*Epoch, error)
77+
GetLastAcceptedEpoch(ctx context.Context, nameOrAddress string) (*Epoch, error)
7778
GetEpochByVirtualIndex(ctx context.Context, nameOrAddress string, index uint64) (*Epoch, error)
7879

7980
UpdateEpoch(ctx context.Context, nameOrAddress string, e *Epoch) error

0 commit comments

Comments
 (0)