mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-18 20:54:20 +01:00
Add interface layer (#23)
* implement grpc interface * rework GetEventStream rpc * implement Ping & GetEventStream * remove dev_portal * Compile protos * Empty gitignore --------- Co-authored-by: altafan <18440657+altafan@users.noreply.github.com>
This commit is contained in:
0
asp/internal/interface/grpc/handlers/.gitkeep → .gitignore
vendored
Executable file → Normal file
0
asp/internal/interface/grpc/handlers/.gitkeep → .gitignore
vendored
Executable file → Normal file
@@ -16,6 +16,37 @@
|
||||
"application/json"
|
||||
],
|
||||
"paths": {
|
||||
"/v1/events": {
|
||||
"get": {
|
||||
"operationId": "ArkService_GetEventStream",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.(streaming responses)",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/v1GetEventStreamResponse"
|
||||
},
|
||||
"error": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
},
|
||||
"title": "Stream result of v1GetEventStreamResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"ArkService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/payment/claim": {
|
||||
"post": {
|
||||
"operationId": "ArkService_ClaimPayment",
|
||||
@@ -112,6 +143,36 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/ping/{paymentId}": {
|
||||
"get": {
|
||||
"operationId": "ArkService_Ping",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1PingResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "paymentId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"ArkService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/round/{txid}": {
|
||||
"get": {
|
||||
"operationId": "ArkService_GetRound",
|
||||
@@ -141,38 +202,6 @@
|
||||
"ArkService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/rounds": {
|
||||
"post": {
|
||||
"operationId": "ArkService_ListRounds",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1ListRoundsResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/rpcStatus"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/v1ListRoundsRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"ArkService"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@@ -225,15 +254,32 @@
|
||||
"v1FinalizePaymentRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"signedVtx": {
|
||||
"type": "string",
|
||||
"description": "Forfeit tx signed also by the user."
|
||||
"signedForfeits": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Forfeit txs signed by the user."
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1FinalizePaymentResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"v1GetEventStreamResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"roundFinalization": {
|
||||
"$ref": "#/definitions/v1RoundFinalizationEvent"
|
||||
},
|
||||
"roundFinalized": {
|
||||
"$ref": "#/definitions/v1RoundFinalizedEvent"
|
||||
},
|
||||
"roundFailed": {
|
||||
"$ref": "#/definitions/v1RoundFailed"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1GetRoundResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -242,30 +288,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1ListRoundsRequest": {
|
||||
"v1Input": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"start": {
|
||||
"type": "string",
|
||||
"format": "int64"
|
||||
"txid": {
|
||||
"type": "string"
|
||||
},
|
||||
"end": {
|
||||
"type": "string",
|
||||
"vout": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1ListRoundsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"rounds": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/v1Round"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1Output": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -278,12 +312,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1PingResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"v1RegisterPaymentRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vtx": {
|
||||
"type": "string",
|
||||
"description": "Unsigned forfeit tx sending all funds back to the ASP."
|
||||
"inputs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/v1Input"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -293,16 +332,15 @@
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Mocks wabisabi's credentials."
|
||||
},
|
||||
"signedVtx": {
|
||||
"type": "string",
|
||||
"description": "Forfeit tx signed by the ASP."
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1Round": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"start": {
|
||||
"type": "string",
|
||||
"format": "int64"
|
||||
@@ -314,13 +352,58 @@
|
||||
"txid": {
|
||||
"type": "string"
|
||||
},
|
||||
"outputs": {
|
||||
"congestionTree": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/v1Output"
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1RoundFailed": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1RoundFinalizationEvent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"poolPartialTx": {
|
||||
"type": "string"
|
||||
},
|
||||
"forfeitTxs": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"congestionTree": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1RoundFinalizedEvent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"poolTxid": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,28 +23,29 @@ service ArkService {
|
||||
body: "*"
|
||||
};
|
||||
};
|
||||
rpc ListRounds(ListRoundsRequest) returns (ListRoundsResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/rounds"
|
||||
body: "*"
|
||||
};
|
||||
};
|
||||
rpc GetRound(GetRoundRequest) returns (GetRoundResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/round/{txid}"
|
||||
};
|
||||
};
|
||||
rpc GetEventStream(GetEventStreamRequest) returns (stream GetEventStreamResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/events"
|
||||
};
|
||||
};
|
||||
rpc Ping(PingRequest) returns (PingResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/ping/{payment_id}"
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
message RegisterPaymentRequest {
|
||||
// Unsigned forfeit tx sending all funds back to the ASP.
|
||||
string vtx = 1;
|
||||
repeated Input inputs = 1;
|
||||
}
|
||||
message RegisterPaymentResponse {
|
||||
// Mocks wabisabi's credentials.
|
||||
string id = 1;
|
||||
// Forfeit tx signed by the ASP.
|
||||
string signed_vtx = 2;
|
||||
}
|
||||
|
||||
message ClaimPaymentRequest {
|
||||
@@ -56,19 +57,11 @@ message ClaimPaymentRequest {
|
||||
message ClaimPaymentResponse {}
|
||||
|
||||
message FinalizePaymentRequest {
|
||||
// Forfeit tx signed also by the user.
|
||||
string signed_vtx = 1;
|
||||
// Forfeit txs signed by the user.
|
||||
repeated string signed_forfeits = 1;
|
||||
}
|
||||
message FinalizePaymentResponse {}
|
||||
|
||||
message ListRoundsRequest {
|
||||
int64 start = 1;
|
||||
int64 end = 2;
|
||||
}
|
||||
message ListRoundsResponse {
|
||||
repeated Round rounds = 1;
|
||||
}
|
||||
|
||||
message GetRoundRequest {
|
||||
string txid = 1;
|
||||
}
|
||||
@@ -77,13 +70,53 @@ message GetRoundResponse {
|
||||
}
|
||||
|
||||
message Round {
|
||||
int64 start = 1;
|
||||
int64 end = 2;
|
||||
string txid = 3;
|
||||
repeated Output outputs = 4;
|
||||
string id = 1;
|
||||
int64 start = 2;
|
||||
int64 end = 3;
|
||||
string txid = 4;
|
||||
repeated string congestion_tree = 5;
|
||||
}
|
||||
|
||||
message Input {
|
||||
string txid = 1;
|
||||
uint32 vout = 2;
|
||||
}
|
||||
|
||||
message Output {
|
||||
string pubkey = 1;
|
||||
uint64 amount = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message RoundFinalizationEvent {
|
||||
string id = 1;
|
||||
string pool_partial_tx = 2;
|
||||
map<string, string> forfeit_txs = 3;
|
||||
repeated string congestion_tree = 4;
|
||||
}
|
||||
|
||||
message RoundFinalizedEvent {
|
||||
string id = 1;
|
||||
string pool_txid = 2;
|
||||
}
|
||||
|
||||
message RoundFailed {
|
||||
string id = 1;
|
||||
string reason = 2;
|
||||
}
|
||||
|
||||
message GetEventStreamRequest {}
|
||||
|
||||
message GetEventStreamResponse {
|
||||
oneof event {
|
||||
RoundFinalizationEvent round_finalization = 1;
|
||||
RoundFinalizedEvent round_finalized = 2;
|
||||
RoundFailed round_failed = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message PingRequest {
|
||||
string payment_id = 1;
|
||||
}
|
||||
|
||||
message PingResponse {}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -133,40 +133,6 @@ func local_request_ArkService_FinalizePayment_0(ctx context.Context, marshaler r
|
||||
|
||||
}
|
||||
|
||||
func request_ArkService_ListRounds_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListRoundsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.ListRounds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_ArkService_ListRounds_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListRoundsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.ListRounds(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_ArkService_GetRound_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetRoundRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
@@ -219,6 +185,75 @@ func local_request_ArkService_GetRound_0(ctx context.Context, marshaler runtime.
|
||||
|
||||
}
|
||||
|
||||
func request_ArkService_GetEventStream_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (ArkService_GetEventStreamClient, runtime.ServerMetadata, error) {
|
||||
var protoReq GetEventStreamRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
stream, err := client.GetEventStream(ctx, &protoReq)
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
header, err := stream.Header()
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
metadata.HeaderMD = header
|
||||
return stream, metadata, nil
|
||||
|
||||
}
|
||||
|
||||
func request_ArkService_Ping_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq PingRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["payment_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "payment_id")
|
||||
}
|
||||
|
||||
protoReq.PaymentId, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "payment_id", err)
|
||||
}
|
||||
|
||||
msg, err := client.Ping(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_ArkService_Ping_0(ctx context.Context, marshaler runtime.Marshaler, server ArkServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq PingRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["payment_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "payment_id")
|
||||
}
|
||||
|
||||
protoReq.PaymentId, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "payment_id", err)
|
||||
}
|
||||
|
||||
msg, err := server.Ping(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterArkServiceHandlerServer registers the http handlers for service ArkService to "mux".
|
||||
// UnaryRPC :call ArkServiceServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
@@ -294,29 +329,6 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_ArkService_ListRounds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/ListRounds", runtime.WithHTTPPathPattern("/v1/rounds"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_ArkService_ListRounds_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_ArkService_ListRounds_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_ArkService_GetRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -340,6 +352,36 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_ArkService_GetEventStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
|
||||
_, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_ArkService_Ping_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/ping/{payment_id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_ArkService_Ping_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_ArkService_Ping_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -441,26 +483,6 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_ArkService_ListRounds_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/ListRounds", runtime.WithHTTPPathPattern("/v1/rounds"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_ArkService_ListRounds_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_ArkService_ListRounds_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_ArkService_GetRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
@@ -481,6 +503,46 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_ArkService_GetEventStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetEventStream", runtime.WithHTTPPathPattern("/v1/events"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_ArkService_GetEventStream_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_ArkService_GetEventStream_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_ArkService_Ping_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/ping/{payment_id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_ArkService_Ping_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_ArkService_Ping_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -491,9 +553,11 @@ var (
|
||||
|
||||
pattern_ArkService_FinalizePayment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "payment", "finalize"}, ""))
|
||||
|
||||
pattern_ArkService_ListRounds_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "rounds"}, ""))
|
||||
|
||||
pattern_ArkService_GetRound_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "round", "txid"}, ""))
|
||||
|
||||
pattern_ArkService_GetEventStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "events"}, ""))
|
||||
|
||||
pattern_ArkService_Ping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "ping", "payment_id"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -503,7 +567,9 @@ var (
|
||||
|
||||
forward_ArkService_FinalizePayment_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ArkService_ListRounds_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ArkService_GetRound_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_ArkService_GetEventStream_0 = runtime.ForwardResponseStream
|
||||
|
||||
forward_ArkService_Ping_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
||||
@@ -21,8 +21,9 @@ type ArkServiceClient interface {
|
||||
RegisterPayment(ctx context.Context, in *RegisterPaymentRequest, opts ...grpc.CallOption) (*RegisterPaymentResponse, error)
|
||||
ClaimPayment(ctx context.Context, in *ClaimPaymentRequest, opts ...grpc.CallOption) (*ClaimPaymentResponse, error)
|
||||
FinalizePayment(ctx context.Context, in *FinalizePaymentRequest, opts ...grpc.CallOption) (*FinalizePaymentResponse, error)
|
||||
ListRounds(ctx context.Context, in *ListRoundsRequest, opts ...grpc.CallOption) (*ListRoundsResponse, error)
|
||||
GetRound(ctx context.Context, in *GetRoundRequest, opts ...grpc.CallOption) (*GetRoundResponse, error)
|
||||
GetEventStream(ctx context.Context, in *GetEventStreamRequest, opts ...grpc.CallOption) (ArkService_GetEventStreamClient, error)
|
||||
Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error)
|
||||
}
|
||||
|
||||
type arkServiceClient struct {
|
||||
@@ -60,18 +61,50 @@ func (c *arkServiceClient) FinalizePayment(ctx context.Context, in *FinalizePaym
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *arkServiceClient) ListRounds(ctx context.Context, in *ListRoundsRequest, opts ...grpc.CallOption) (*ListRoundsResponse, error) {
|
||||
out := new(ListRoundsResponse)
|
||||
err := c.cc.Invoke(ctx, "/ark.v1.ArkService/ListRounds", in, out, opts...)
|
||||
func (c *arkServiceClient) GetRound(ctx context.Context, in *GetRoundRequest, opts ...grpc.CallOption) (*GetRoundResponse, error) {
|
||||
out := new(GetRoundResponse)
|
||||
err := c.cc.Invoke(ctx, "/ark.v1.ArkService/GetRound", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *arkServiceClient) GetRound(ctx context.Context, in *GetRoundRequest, opts ...grpc.CallOption) (*GetRoundResponse, error) {
|
||||
out := new(GetRoundResponse)
|
||||
err := c.cc.Invoke(ctx, "/ark.v1.ArkService/GetRound", in, out, opts...)
|
||||
func (c *arkServiceClient) GetEventStream(ctx context.Context, in *GetEventStreamRequest, opts ...grpc.CallOption) (ArkService_GetEventStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &ArkService_ServiceDesc.Streams[0], "/ark.v1.ArkService/GetEventStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &arkServiceGetEventStreamClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type ArkService_GetEventStreamClient interface {
|
||||
Recv() (*GetEventStreamResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type arkServiceGetEventStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *arkServiceGetEventStreamClient) Recv() (*GetEventStreamResponse, error) {
|
||||
m := new(GetEventStreamResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *arkServiceClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) {
|
||||
out := new(PingResponse)
|
||||
err := c.cc.Invoke(ctx, "/ark.v1.ArkService/Ping", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -85,8 +118,9 @@ type ArkServiceServer interface {
|
||||
RegisterPayment(context.Context, *RegisterPaymentRequest) (*RegisterPaymentResponse, error)
|
||||
ClaimPayment(context.Context, *ClaimPaymentRequest) (*ClaimPaymentResponse, error)
|
||||
FinalizePayment(context.Context, *FinalizePaymentRequest) (*FinalizePaymentResponse, error)
|
||||
ListRounds(context.Context, *ListRoundsRequest) (*ListRoundsResponse, error)
|
||||
GetRound(context.Context, *GetRoundRequest) (*GetRoundResponse, error)
|
||||
GetEventStream(*GetEventStreamRequest, ArkService_GetEventStreamServer) error
|
||||
Ping(context.Context, *PingRequest) (*PingResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedArkServiceServer should be embedded to have forward compatible implementations.
|
||||
@@ -102,12 +136,15 @@ func (UnimplementedArkServiceServer) ClaimPayment(context.Context, *ClaimPayment
|
||||
func (UnimplementedArkServiceServer) FinalizePayment(context.Context, *FinalizePaymentRequest) (*FinalizePaymentResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method FinalizePayment not implemented")
|
||||
}
|
||||
func (UnimplementedArkServiceServer) ListRounds(context.Context, *ListRoundsRequest) (*ListRoundsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListRounds not implemented")
|
||||
}
|
||||
func (UnimplementedArkServiceServer) GetRound(context.Context, *GetRoundRequest) (*GetRoundResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRound not implemented")
|
||||
}
|
||||
func (UnimplementedArkServiceServer) GetEventStream(*GetEventStreamRequest, ArkService_GetEventStreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method GetEventStream not implemented")
|
||||
}
|
||||
func (UnimplementedArkServiceServer) Ping(context.Context, *PingRequest) (*PingResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented")
|
||||
}
|
||||
|
||||
// UnsafeArkServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ArkServiceServer will
|
||||
@@ -174,24 +211,6 @@ func _ArkService_FinalizePayment_Handler(srv interface{}, ctx context.Context, d
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ArkService_ListRounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListRoundsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ArkServiceServer).ListRounds(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/ark.v1.ArkService/ListRounds",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ArkServiceServer).ListRounds(ctx, req.(*ListRoundsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ArkService_GetRound_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetRoundRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -210,6 +229,45 @@ func _ArkService_GetRound_Handler(srv interface{}, ctx context.Context, dec func
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ArkService_GetEventStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(GetEventStreamRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(ArkServiceServer).GetEventStream(m, &arkServiceGetEventStreamServer{stream})
|
||||
}
|
||||
|
||||
type ArkService_GetEventStreamServer interface {
|
||||
Send(*GetEventStreamResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type arkServiceGetEventStreamServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *arkServiceGetEventStreamServer) Send(m *GetEventStreamResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _ArkService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(PingRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ArkServiceServer).Ping(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/ark.v1.ArkService/Ping",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ArkServiceServer).Ping(ctx, req.(*PingRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ArkService_ServiceDesc is the grpc.ServiceDesc for ArkService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -229,15 +287,21 @@ var ArkService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "FinalizePayment",
|
||||
Handler: _ArkService_FinalizePayment_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListRounds",
|
||||
Handler: _ArkService_ListRounds_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetRound",
|
||||
Handler: _ArkService_GetRound_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Ping",
|
||||
Handler: _ArkService_Ping_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "GetEventStream",
|
||||
Handler: _ArkService_GetEventStream_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "ark/v1/service.proto",
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
service_interface "github.com/ark-network/ark/internal/interface"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//nolint:all
|
||||
@@ -16,15 +16,14 @@ var (
|
||||
date = "unknown"
|
||||
)
|
||||
|
||||
// TODO: Edit this file to something more meaningful for your application.
|
||||
func main() {
|
||||
svc, err := service_interface.NewService()
|
||||
svc, err := service_interface.NewService(service_interface.Options{}) // TODO populate options
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.RegisterExitHandler(svc.Stop)
|
||||
|
||||
|
||||
log.Info("starting service...")
|
||||
if err := svc.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -37,4 +36,3 @@ func main() {
|
||||
log.Info("shutting down service...")
|
||||
log.Exit(0)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ require (
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/timshannon/badgerhold/v4 v4.0.3
|
||||
github.com/vulpemventures/go-elements v0.4.7
|
||||
golang.org/x/crypto v0.14.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
@@ -36,7 +35,9 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
@@ -656,6 +656,8 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
||||
@@ -21,6 +21,15 @@ import (
|
||||
|
||||
const paymentsThreshold = 128
|
||||
|
||||
type Service interface {
|
||||
SpendVtxos(ctx context.Context, inputs []domain.VtxoKey) (string, error)
|
||||
ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error
|
||||
SignVtxos(ctx context.Context, forfeitTxs map[string]string) error
|
||||
GetRoundByTxid(ctx context.Context, poolTxid string) (*domain.Round, error)
|
||||
GetEventsChannel(ctx context.Context) <-chan domain.RoundEvent
|
||||
UpdatePaymenStatus(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
type service struct {
|
||||
roundInterval int64
|
||||
network common.Network
|
||||
@@ -32,20 +41,28 @@ type service struct {
|
||||
builder ports.TxBuilder
|
||||
paymentRequests *paymentsMap
|
||||
forfeitTxs *forfeitTxsMap
|
||||
|
||||
eventsCh chan domain.RoundEvent
|
||||
}
|
||||
|
||||
func NewService(
|
||||
interval int64, network common.Network, onchainNetwork network.Network,
|
||||
walletSvc ports.WalletService, schedulerSvc ports.SchedulerService,
|
||||
repoManager ports.RepoManager, builder ports.TxBuilder,
|
||||
) *service {
|
||||
) Service {
|
||||
paymentRequests := newPaymentsMap(nil)
|
||||
forfeitTxs := newForfeitTxsMap()
|
||||
svc := &service{
|
||||
interval, network, onchainNetwork,
|
||||
walletSvc, schedulerSvc, repoManager, builder, paymentRequests, forfeitTxs,
|
||||
make(chan domain.RoundEvent),
|
||||
}
|
||||
repoManager.RegisterEventsHandler(svc.updateProjectionStore)
|
||||
repoManager.RegisterEventsHandler(
|
||||
func(round *domain.Round) {
|
||||
svc.updateProjectionStore(round)
|
||||
svc.propagateEvents(round)
|
||||
},
|
||||
)
|
||||
return svc
|
||||
}
|
||||
|
||||
@@ -100,6 +117,14 @@ func (s *service) SignVtxos(ctx context.Context, forfeitTxs map[string]string) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *service) GetEventsChannel(ctx context.Context) <-chan domain.RoundEvent {
|
||||
return s.eventsCh
|
||||
}
|
||||
|
||||
func (s *service) GetRoundByTxid(ctx context.Context, poolTxid string) (*domain.Round, error) {
|
||||
return s.repoManager.Rounds().GetRoundWithTxid(ctx, poolTxid)
|
||||
}
|
||||
|
||||
func (s *service) start() error {
|
||||
startImmediately := true
|
||||
finalizationInterval := int64(s.roundInterval / 2)
|
||||
@@ -264,6 +289,14 @@ func (s *service) updateProjectionStore(round *domain.Round) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) propagateEvents(round *domain.Round) {
|
||||
lastEvent := round.Events()[len(round.Events())-1]
|
||||
switch e := lastEvent.(type) {
|
||||
case domain.RoundFinalizationStarted, domain.RoundFinalized:
|
||||
s.eventsCh <- e
|
||||
}
|
||||
}
|
||||
|
||||
func getNewVtxos(net network.Network, round *domain.Round) []domain.Vtxo {
|
||||
treeDepth := math.Log2(float64(len(round.CongestionTree) + 1))
|
||||
leaves := round.CongestionTree[int(math.Pow(2, treeDepth)-1):]
|
||||
|
||||
227
asp/internal/interface/grpc/handlers/arkservice.go
Normal file
227
asp/internal/interface/grpc/handlers/arkservice.go
Normal file
@@ -0,0 +1,227 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1"
|
||||
"github.com/ark-network/ark/internal/core/application"
|
||||
"github.com/ark-network/ark/internal/core/domain"
|
||||
"github.com/ark-network/ark/internal/core/ports"
|
||||
"github.com/google/uuid"
|
||||
"github.com/vulpemventures/go-elements/psetv2"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type listener struct {
|
||||
id string
|
||||
ch chan *arkv1.GetEventStreamResponse
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
svc application.Service
|
||||
|
||||
listenersLock *sync.Mutex
|
||||
listeners []*listener
|
||||
}
|
||||
|
||||
func NewHandler(service application.Service, repoManager ports.RepoManager) arkv1.ArkServiceServer {
|
||||
h := &handler{
|
||||
svc: service,
|
||||
listenersLock: &sync.Mutex{},
|
||||
listeners: make([]*listener, 0),
|
||||
}
|
||||
|
||||
go h.listenToEvents()
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *handler) Ping(ctx context.Context, req *arkv1.PingRequest) (*arkv1.PingResponse, error) {
|
||||
if req.GetPaymentId() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "missing payment id")
|
||||
}
|
||||
|
||||
if err := h.svc.UpdatePaymenStatus(ctx, req.GetPaymentId()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &arkv1.PingResponse{}, nil
|
||||
}
|
||||
|
||||
func (h *handler) RegisterPayment(ctx context.Context, req *arkv1.RegisterPaymentRequest) (*arkv1.RegisterPaymentResponse, error) {
|
||||
vtxosKeys := make([]domain.VtxoKey, 0, len(req.GetInputs()))
|
||||
for _, input := range req.GetInputs() {
|
||||
vtxosKeys = append(vtxosKeys, domain.VtxoKey{
|
||||
Txid: input.GetTxid(),
|
||||
VOut: input.GetVout(),
|
||||
})
|
||||
}
|
||||
|
||||
id, err := h.svc.SpendVtxos(ctx, vtxosKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &arkv1.RegisterPaymentResponse{
|
||||
Id: id,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *handler) ClaimPayment(ctx context.Context, req *arkv1.ClaimPaymentRequest) (*arkv1.ClaimPaymentResponse, error) {
|
||||
receivers := make([]domain.Receiver, 0, len(req.GetOutputs()))
|
||||
for _, output := range req.GetOutputs() {
|
||||
receivers = append(receivers, domain.Receiver{
|
||||
Pubkey: output.GetPubkey(),
|
||||
Amount: output.GetAmount(),
|
||||
})
|
||||
}
|
||||
|
||||
err := h.svc.ClaimVtxos(ctx, req.GetId(), receivers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &arkv1.ClaimPaymentResponse{}, nil
|
||||
}
|
||||
|
||||
func (h *handler) FinalizePayment(ctx context.Context, req *arkv1.FinalizePaymentRequest) (*arkv1.FinalizePaymentResponse, error) {
|
||||
forfeits := make(map[string]string)
|
||||
|
||||
for _, b64 := range req.GetSignedForfeits() {
|
||||
pset, err := psetv2.NewPsetFromBase64(b64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
unsignedTx, err := pset.UnsignedTx()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
forfeits[unsignedTx.TxHash().String()] = b64
|
||||
}
|
||||
|
||||
err := h.svc.SignVtxos(ctx, forfeits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &arkv1.FinalizePaymentResponse{}, nil
|
||||
}
|
||||
|
||||
func (h *handler) GetRound(ctx context.Context, req *arkv1.GetRoundRequest) (*arkv1.GetRoundResponse, error) {
|
||||
if req.GetTxid() != "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "missing pool txid")
|
||||
}
|
||||
|
||||
round, err := h.svc.GetRoundByTxid(ctx, req.GetTxid())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &arkv1.GetRoundResponse{
|
||||
Round: &arkv1.Round{
|
||||
Id: round.Id,
|
||||
Start: round.StartingTimestamp,
|
||||
End: round.EndingTimestamp,
|
||||
Txid: round.Txid,
|
||||
CongestionTree: round.CongestionTree,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *handler) GetEventStream(_ *arkv1.GetEventStreamRequest, stream arkv1.ArkService_GetEventStreamServer) error {
|
||||
listener := &listener{
|
||||
id: uuid.NewString(),
|
||||
ch: make(chan *arkv1.GetEventStreamResponse),
|
||||
}
|
||||
|
||||
defer h.removeListener(listener.id)
|
||||
defer close(listener.ch)
|
||||
|
||||
h.pushListener(listener)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-stream.Context().Done():
|
||||
return nil
|
||||
|
||||
case ev := <-listener.ch:
|
||||
if err := stream.Send(ev); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch ev.Event.(type) {
|
||||
case *arkv1.GetEventStreamResponse_RoundFinalized, *arkv1.GetEventStreamResponse_RoundFailed:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) pushListener(l *listener) {
|
||||
h.listenersLock.Lock()
|
||||
defer h.listenersLock.Unlock()
|
||||
|
||||
h.listeners = append(h.listeners, l)
|
||||
}
|
||||
|
||||
func (h *handler) removeListener(id string) {
|
||||
h.listenersLock.Lock()
|
||||
defer h.listenersLock.Unlock()
|
||||
|
||||
for i, listener := range h.listeners {
|
||||
if listener.id == id {
|
||||
h.listeners = append(h.listeners[:i], h.listeners[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// listenToEvents forwards events from the application layer to the set of listeners
|
||||
func (h *handler) listenToEvents() {
|
||||
channel := h.svc.GetEventsChannel(context.Background())
|
||||
for event := range channel {
|
||||
var ev *arkv1.GetEventStreamResponse
|
||||
|
||||
switch e := event.(type) {
|
||||
case domain.RoundFinalizationStarted:
|
||||
ev = &arkv1.GetEventStreamResponse{
|
||||
Event: &arkv1.GetEventStreamResponse_RoundFinalization{
|
||||
RoundFinalization: &arkv1.RoundFinalizationEvent{
|
||||
Id: e.Id,
|
||||
PoolPartialTx: e.PoolTx,
|
||||
CongestionTree: e.CongestionTree,
|
||||
ForfeitTxs: nil, // TODO: add forfeit txs
|
||||
},
|
||||
},
|
||||
}
|
||||
case domain.RoundFinalized:
|
||||
ev = &arkv1.GetEventStreamResponse{
|
||||
Event: &arkv1.GetEventStreamResponse_RoundFinalized{
|
||||
RoundFinalized: &arkv1.RoundFinalizedEvent{
|
||||
Id: e.Id,
|
||||
PoolTxid: e.Txid,
|
||||
},
|
||||
},
|
||||
}
|
||||
case domain.RoundFailed:
|
||||
ev = &arkv1.GetEventStreamResponse{
|
||||
Event: &arkv1.GetEventStreamResponse_RoundFailed{
|
||||
RoundFailed: &arkv1.RoundFailed{
|
||||
Id: e.Id,
|
||||
Reason: e.Err.Error(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if ev != nil {
|
||||
for _, listener := range h.listeners {
|
||||
listener.ch <- ev
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package grpc_interface
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// TODO: Edit this file to something more meaningful for your application.
|
||||
type service struct {}
|
||||
|
||||
func NewService() (*service, error) {
|
||||
return &service{}, nil
|
||||
}
|
||||
|
||||
func (s *service) Start() error {
|
||||
log.Debug("service is listening")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *service) Stop() {
|
||||
log.Debug("service stopped")
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package service_interface
|
||||
package interfaces
|
||||
|
||||
import (
|
||||
grpc_interface "github.com/ark-network/ark/internal/interface/grpc"
|
||||
arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1"
|
||||
"github.com/ark-network/ark/internal/core/application"
|
||||
"github.com/ark-network/ark/internal/core/ports"
|
||||
"github.com/ark-network/ark/internal/interface/grpc/handlers"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
// TODO: Edit this file to something more meaningful for your application.
|
||||
@@ -10,7 +15,35 @@ type Service interface {
|
||||
Stop()
|
||||
}
|
||||
|
||||
func NewService() (Service, error) {
|
||||
return grpc_interface.NewService()
|
||||
type service struct {
|
||||
grpcService arkv1.ArkServiceServer
|
||||
grpcServer *grpc.Server
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
applicationService application.Service
|
||||
repositoryManager ports.RepoManager
|
||||
}
|
||||
|
||||
func NewService(opts Options) (Service, error) {
|
||||
return &service{
|
||||
grpcService: handlers.NewHandler(opts.applicationService, opts.repositoryManager),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start implements Service.
|
||||
func (s *service) Start() error {
|
||||
creds := insecure.NewCredentials()
|
||||
serverOpts := grpc.Creds(creds)
|
||||
server := grpc.NewServer(serverOpts)
|
||||
|
||||
arkv1.RegisterArkServiceServer(server, s.grpcService)
|
||||
|
||||
s.grpcServer = server
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop implements Service.
|
||||
func (s *service) Stop() {
|
||||
s.grpcServer.Stop()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user