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:
Louis Singer
2023-12-01 17:13:28 +01:00
committed by GitHub
parent 7c2a70db91
commit c8d9db89c5
13 changed files with 1519 additions and 516 deletions

0
asp/internal/interface/grpc/handlers/.gitkeep → .gitignore vendored Executable file → Normal file
View File

View File

@@ -16,6 +16,37 @@
"application/json" "application/json"
], ],
"paths": { "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": { "/v1/payment/claim": {
"post": { "post": {
"operationId": "ArkService_ClaimPayment", "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}": { "/v1/round/{txid}": {
"get": { "get": {
"operationId": "ArkService_GetRound", "operationId": "ArkService_GetRound",
@@ -141,38 +202,6 @@
"ArkService" "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": { "definitions": {
@@ -225,15 +254,32 @@
"v1FinalizePaymentRequest": { "v1FinalizePaymentRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
"signedVtx": { "signedForfeits": {
"type": "string", "type": "array",
"description": "Forfeit tx signed also by the user." "items": {
"type": "string"
},
"description": "Forfeit txs signed by the user."
} }
} }
}, },
"v1FinalizePaymentResponse": { "v1FinalizePaymentResponse": {
"type": "object" "type": "object"
}, },
"v1GetEventStreamResponse": {
"type": "object",
"properties": {
"roundFinalization": {
"$ref": "#/definitions/v1RoundFinalizationEvent"
},
"roundFinalized": {
"$ref": "#/definitions/v1RoundFinalizedEvent"
},
"roundFailed": {
"$ref": "#/definitions/v1RoundFailed"
}
}
},
"v1GetRoundResponse": { "v1GetRoundResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -242,30 +288,18 @@
} }
} }
}, },
"v1ListRoundsRequest": { "v1Input": {
"type": "object", "type": "object",
"properties": { "properties": {
"start": { "txid": {
"type": "string", "type": "string"
"format": "int64"
}, },
"end": { "vout": {
"type": "string", "type": "integer",
"format": "int64" "format": "int64"
} }
} }
}, },
"v1ListRoundsResponse": {
"type": "object",
"properties": {
"rounds": {
"type": "array",
"items": {
"$ref": "#/definitions/v1Round"
}
}
}
},
"v1Output": { "v1Output": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -278,12 +312,17 @@
} }
} }
}, },
"v1PingResponse": {
"type": "object"
},
"v1RegisterPaymentRequest": { "v1RegisterPaymentRequest": {
"type": "object", "type": "object",
"properties": { "properties": {
"vtx": { "inputs": {
"type": "string", "type": "array",
"description": "Unsigned forfeit tx sending all funds back to the ASP." "items": {
"$ref": "#/definitions/v1Input"
}
} }
} }
}, },
@@ -293,16 +332,15 @@
"id": { "id": {
"type": "string", "type": "string",
"description": "Mocks wabisabi's credentials." "description": "Mocks wabisabi's credentials."
},
"signedVtx": {
"type": "string",
"description": "Forfeit tx signed by the ASP."
} }
} }
}, },
"v1Round": { "v1Round": {
"type": "object", "type": "object",
"properties": { "properties": {
"id": {
"type": "string"
},
"start": { "start": {
"type": "string", "type": "string",
"format": "int64" "format": "int64"
@@ -314,13 +352,58 @@
"txid": { "txid": {
"type": "string" "type": "string"
}, },
"outputs": { "congestionTree": {
"type": "array", "type": "array",
"items": { "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"
}
}
} }
} }
} }

View File

@@ -23,28 +23,29 @@ service ArkService {
body: "*" body: "*"
}; };
}; };
rpc ListRounds(ListRoundsRequest) returns (ListRoundsResponse) {
option (google.api.http) = {
post: "/v1/rounds"
body: "*"
};
};
rpc GetRound(GetRoundRequest) returns (GetRoundResponse) { rpc GetRound(GetRoundRequest) returns (GetRoundResponse) {
option (google.api.http) = { option (google.api.http) = {
get: "/v1/round/{txid}" 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 { message RegisterPaymentRequest {
// Unsigned forfeit tx sending all funds back to the ASP. repeated Input inputs = 1;
string vtx = 1;
} }
message RegisterPaymentResponse { message RegisterPaymentResponse {
// Mocks wabisabi's credentials. // Mocks wabisabi's credentials.
string id = 1; string id = 1;
// Forfeit tx signed by the ASP.
string signed_vtx = 2;
} }
message ClaimPaymentRequest { message ClaimPaymentRequest {
@@ -56,19 +57,11 @@ message ClaimPaymentRequest {
message ClaimPaymentResponse {} message ClaimPaymentResponse {}
message FinalizePaymentRequest { message FinalizePaymentRequest {
// Forfeit tx signed also by the user. // Forfeit txs signed by the user.
string signed_vtx = 1; repeated string signed_forfeits = 1;
} }
message FinalizePaymentResponse {} message FinalizePaymentResponse {}
message ListRoundsRequest {
int64 start = 1;
int64 end = 2;
}
message ListRoundsResponse {
repeated Round rounds = 1;
}
message GetRoundRequest { message GetRoundRequest {
string txid = 1; string txid = 1;
} }
@@ -77,13 +70,53 @@ message GetRoundResponse {
} }
message Round { message Round {
int64 start = 1; string id = 1;
int64 end = 2; int64 start = 2;
string txid = 3; int64 end = 3;
repeated Output outputs = 4; string txid = 4;
repeated string congestion_tree = 5;
}
message Input {
string txid = 1;
uint32 vout = 2;
} }
message Output { message Output {
string pubkey = 1; string pubkey = 1;
uint64 amount = 2; 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

View File

@@ -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) { 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 protoReq GetRoundRequest
var metadata runtime.ServerMetadata 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". // RegisterArkServiceHandlerServer registers the http handlers for service ArkService to "mux".
// UnaryRPC :call ArkServiceServer directly. // UnaryRPC :call ArkServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // 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) { mux.Handle("GET", pattern_ArkService_GetRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() 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 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) { mux.Handle("GET", pattern_ArkService_GetRound_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() 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 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_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_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 ( var (
@@ -503,7 +567,9 @@ var (
forward_ArkService_FinalizePayment_0 = runtime.ForwardResponseMessage forward_ArkService_FinalizePayment_0 = runtime.ForwardResponseMessage
forward_ArkService_ListRounds_0 = runtime.ForwardResponseMessage
forward_ArkService_GetRound_0 = runtime.ForwardResponseMessage forward_ArkService_GetRound_0 = runtime.ForwardResponseMessage
forward_ArkService_GetEventStream_0 = runtime.ForwardResponseStream
forward_ArkService_Ping_0 = runtime.ForwardResponseMessage
) )

View File

@@ -21,8 +21,9 @@ type ArkServiceClient interface {
RegisterPayment(ctx context.Context, in *RegisterPaymentRequest, opts ...grpc.CallOption) (*RegisterPaymentResponse, error) RegisterPayment(ctx context.Context, in *RegisterPaymentRequest, opts ...grpc.CallOption) (*RegisterPaymentResponse, error)
ClaimPayment(ctx context.Context, in *ClaimPaymentRequest, opts ...grpc.CallOption) (*ClaimPaymentResponse, error) ClaimPayment(ctx context.Context, in *ClaimPaymentRequest, opts ...grpc.CallOption) (*ClaimPaymentResponse, error)
FinalizePayment(ctx context.Context, in *FinalizePaymentRequest, opts ...grpc.CallOption) (*FinalizePaymentResponse, 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) 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 { type arkServiceClient struct {
@@ -60,18 +61,50 @@ func (c *arkServiceClient) FinalizePayment(ctx context.Context, in *FinalizePaym
return out, nil return out, nil
} }
func (c *arkServiceClient) ListRounds(ctx context.Context, in *ListRoundsRequest, opts ...grpc.CallOption) (*ListRoundsResponse, error) { func (c *arkServiceClient) GetRound(ctx context.Context, in *GetRoundRequest, opts ...grpc.CallOption) (*GetRoundResponse, error) {
out := new(ListRoundsResponse) out := new(GetRoundResponse)
err := c.cc.Invoke(ctx, "/ark.v1.ArkService/ListRounds", in, out, opts...) err := c.cc.Invoke(ctx, "/ark.v1.ArkService/GetRound", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return out, nil return out, nil
} }
func (c *arkServiceClient) GetRound(ctx context.Context, in *GetRoundRequest, opts ...grpc.CallOption) (*GetRoundResponse, error) { func (c *arkServiceClient) GetEventStream(ctx context.Context, in *GetEventStreamRequest, opts ...grpc.CallOption) (ArkService_GetEventStreamClient, error) {
out := new(GetRoundResponse) stream, err := c.cc.NewStream(ctx, &ArkService_ServiceDesc.Streams[0], "/ark.v1.ArkService/GetEventStream", opts...)
err := c.cc.Invoke(ctx, "/ark.v1.ArkService/GetRound", in, out, 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 { if err != nil {
return nil, err return nil, err
} }
@@ -85,8 +118,9 @@ type ArkServiceServer interface {
RegisterPayment(context.Context, *RegisterPaymentRequest) (*RegisterPaymentResponse, error) RegisterPayment(context.Context, *RegisterPaymentRequest) (*RegisterPaymentResponse, error)
ClaimPayment(context.Context, *ClaimPaymentRequest) (*ClaimPaymentResponse, error) ClaimPayment(context.Context, *ClaimPaymentRequest) (*ClaimPaymentResponse, error)
FinalizePayment(context.Context, *FinalizePaymentRequest) (*FinalizePaymentResponse, error) FinalizePayment(context.Context, *FinalizePaymentRequest) (*FinalizePaymentResponse, error)
ListRounds(context.Context, *ListRoundsRequest) (*ListRoundsResponse, error)
GetRound(context.Context, *GetRoundRequest) (*GetRoundResponse, 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. // 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) { func (UnimplementedArkServiceServer) FinalizePayment(context.Context, *FinalizePaymentRequest) (*FinalizePaymentResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method FinalizePayment not implemented") 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) { func (UnimplementedArkServiceServer) GetRound(context.Context, *GetRoundRequest) (*GetRoundResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRound not implemented") 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. // 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 // 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) 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) { func _ArkService_GetRound_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetRoundRequest) in := new(GetRoundRequest)
if err := dec(in); err != nil { 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) 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. // ArkService_ServiceDesc is the grpc.ServiceDesc for ArkService service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@@ -229,15 +287,21 @@ var ArkService_ServiceDesc = grpc.ServiceDesc{
MethodName: "FinalizePayment", MethodName: "FinalizePayment",
Handler: _ArkService_FinalizePayment_Handler, Handler: _ArkService_FinalizePayment_Handler,
}, },
{
MethodName: "ListRounds",
Handler: _ArkService_ListRounds_Handler,
},
{ {
MethodName: "GetRound", MethodName: "GetRound",
Handler: _ArkService_GetRound_Handler, 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", Metadata: "ark/v1/service.proto",
} }

View File

@@ -4,9 +4,9 @@ import (
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
log "github.com/sirupsen/logrus"
service_interface "github.com/ark-network/ark/internal/interface" service_interface "github.com/ark-network/ark/internal/interface"
log "github.com/sirupsen/logrus"
) )
//nolint:all //nolint:all
@@ -16,15 +16,14 @@ var (
date = "unknown" date = "unknown"
) )
// TODO: Edit this file to something more meaningful for your application.
func main() { func main() {
svc, err := service_interface.NewService() svc, err := service_interface.NewService(service_interface.Options{}) // TODO populate options
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
log.RegisterExitHandler(svc.Stop) log.RegisterExitHandler(svc.Stop)
log.Info("starting service...") log.Info("starting service...")
if err := svc.Start(); err != nil { if err := svc.Start(); err != nil {
log.Fatal(err) log.Fatal(err)
@@ -37,4 +36,3 @@ func main() {
log.Info("shutting down service...") log.Info("shutting down service...")
log.Exit(0) log.Exit(0)
} }

View File

@@ -17,7 +17,6 @@ require (
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/timshannon/badgerhold/v4 v4.0.3 github.com/timshannon/badgerhold/v4 v4.0.3
github.com/vulpemventures/go-elements v0.4.7 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/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17
google.golang.org/grpc v1.59.0 google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.31.0 google.golang.org/protobuf v1.31.0
@@ -36,7 +35,9 @@ require (
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect
go.opencensus.io v0.24.0 // 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/genproto v0.0.0-20231030173426-d783a09b4405 // indirect
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 // indirect
) )
require ( require (

View File

@@ -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.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 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= 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-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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

View File

@@ -21,6 +21,15 @@ import (
const paymentsThreshold = 128 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 { type service struct {
roundInterval int64 roundInterval int64
network common.Network network common.Network
@@ -32,20 +41,28 @@ type service struct {
builder ports.TxBuilder builder ports.TxBuilder
paymentRequests *paymentsMap paymentRequests *paymentsMap
forfeitTxs *forfeitTxsMap forfeitTxs *forfeitTxsMap
eventsCh chan domain.RoundEvent
} }
func NewService( func NewService(
interval int64, network common.Network, onchainNetwork network.Network, interval int64, network common.Network, onchainNetwork network.Network,
walletSvc ports.WalletService, schedulerSvc ports.SchedulerService, walletSvc ports.WalletService, schedulerSvc ports.SchedulerService,
repoManager ports.RepoManager, builder ports.TxBuilder, repoManager ports.RepoManager, builder ports.TxBuilder,
) *service { ) Service {
paymentRequests := newPaymentsMap(nil) paymentRequests := newPaymentsMap(nil)
forfeitTxs := newForfeitTxsMap() forfeitTxs := newForfeitTxsMap()
svc := &service{ svc := &service{
interval, network, onchainNetwork, interval, network, onchainNetwork,
walletSvc, schedulerSvc, repoManager, builder, paymentRequests, forfeitTxs, 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 return svc
} }
@@ -100,6 +117,14 @@ func (s *service) SignVtxos(ctx context.Context, forfeitTxs map[string]string) e
return nil 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 { func (s *service) start() error {
startImmediately := true startImmediately := true
finalizationInterval := int64(s.roundInterval / 2) 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 { func getNewVtxos(net network.Network, round *domain.Round) []domain.Vtxo {
treeDepth := math.Log2(float64(len(round.CongestionTree) + 1)) treeDepth := math.Log2(float64(len(round.CongestionTree) + 1))
leaves := round.CongestionTree[int(math.Pow(2, treeDepth)-1):] leaves := round.CongestionTree[int(math.Pow(2, treeDepth)-1):]

View 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
}
}
}
}

View File

@@ -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")
}

View File

@@ -1,7 +1,12 @@
package service_interface package interfaces
import ( 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. // TODO: Edit this file to something more meaningful for your application.
@@ -10,7 +15,35 @@ type Service interface {
Stop() Stop()
} }
func NewService() (Service, error) { type service struct {
return grpc_interface.NewService() 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()
} }