diff --git a/api-spec/openapi/swagger/ark/v1/service.swagger.json b/api-spec/openapi/swagger/ark/v1/service.swagger.json index 59488c0..66e5504 100644 --- a/api-spec/openapi/swagger/ark/v1/service.swagger.json +++ b/api-spec/openapi/swagger/ark/v1/service.swagger.json @@ -415,6 +415,37 @@ ] } }, + "/v1/transactions": { + "get": { + "operationId": "ArkService_GetTransactionsStream", + "responses": { + "200": { + "description": "A successful response.(streaming responses)", + "schema": { + "type": "object", + "properties": { + "result": { + "$ref": "#/definitions/v1GetTransactionsStreamResponse" + }, + "error": { + "$ref": "#/definitions/rpcStatus" + } + }, + "title": "Stream result of v1GetTransactionsStreamResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "ArkService" + ] + } + }, "/v1/vtxos/{address}": { "get": { "operationId": "ArkService_ListVtxos", @@ -620,6 +651,17 @@ } } }, + "v1GetTransactionsStreamResponse": { + "type": "object", + "properties": { + "round": { + "$ref": "#/definitions/v1RoundTransaction" + }, + "redeem": { + "$ref": "#/definitions/v1RedeemTransaction" + } + } + }, "v1Input": { "type": "object", "properties": { @@ -727,6 +769,28 @@ } } }, + "v1RedeemTransaction": { + "type": "object", + "properties": { + "txid": { + "type": "string" + }, + "spentVtxos": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Outpoint" + } + }, + "spendableVtxos": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Vtxo" + } + } + } + }, "v1RegisterInputsForNextRoundRequest": { "type": "object", "properties": { @@ -896,6 +960,35 @@ ], "default": "ROUND_STAGE_UNSPECIFIED" }, + "v1RoundTransaction": { + "type": "object", + "properties": { + "txid": { + "type": "string" + }, + "spentVtxos": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Outpoint" + } + }, + "spendableVtxos": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Vtxo" + } + }, + "claimedBoardingUtxos": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Outpoint" + } + } + } + }, "v1SubmitSignedForfeitTxsRequest": { "type": "object", "properties": { diff --git a/api-spec/protobuf/ark/v1/service.proto b/api-spec/protobuf/ark/v1/service.proto index 92ed368..2481ec4 100755 --- a/api-spec/protobuf/ark/v1/service.proto +++ b/api-spec/protobuf/ark/v1/service.proto @@ -92,6 +92,11 @@ service ArkService { get: "/v1/vtxos/{address}" }; } + rpc GetTransactionsStream(GetTransactionsStreamRequest) returns (stream GetTransactionsStreamResponse) { + option (google.api.http) = { + get: "/v1/transactions" + }; + } } message GetInfoRequest {} @@ -321,3 +326,24 @@ message PendingPayment { string redeem_tx = 1; repeated string unconditional_forfeit_txs =2; } + +message GetTransactionsStreamRequest {} +message GetTransactionsStreamResponse { + oneof tx { + RoundTransaction round = 1; + RedeemTransaction redeem = 2; + } +} + +message RoundTransaction { + string txid = 1; + repeated Outpoint spent_vtxos = 2; + repeated Vtxo spendable_vtxos = 3; + repeated Outpoint claimed_boarding_utxos = 4; +} + +message RedeemTransaction { + string txid = 1; + repeated Outpoint spent_vtxos = 2; + repeated Vtxo spendable_vtxos = 3; +} \ No newline at end of file diff --git a/api-spec/protobuf/gen/ark/v1/service.pb.go b/api-spec/protobuf/gen/ark/v1/service.pb.go index b34b62f..e160681 100644 --- a/api-spec/protobuf/gen/ark/v1/service.pb.go +++ b/api-spec/protobuf/gen/ark/v1/service.pb.go @@ -2568,6 +2568,259 @@ func (x *PendingPayment) GetUnconditionalForfeitTxs() []string { return nil } +type GetTransactionsStreamRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetTransactionsStreamRequest) Reset() { + *x = GetTransactionsStreamRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ark_v1_service_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTransactionsStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTransactionsStreamRequest) ProtoMessage() {} + +func (x *GetTransactionsStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_ark_v1_service_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTransactionsStreamRequest.ProtoReflect.Descriptor instead. +func (*GetTransactionsStreamRequest) Descriptor() ([]byte, []int) { + return file_ark_v1_service_proto_rawDescGZIP(), []int{42} +} + +type GetTransactionsStreamResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Tx: + // + // *GetTransactionsStreamResponse_Round + // *GetTransactionsStreamResponse_Redeem + Tx isGetTransactionsStreamResponse_Tx `protobuf_oneof:"tx"` +} + +func (x *GetTransactionsStreamResponse) Reset() { + *x = GetTransactionsStreamResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ark_v1_service_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTransactionsStreamResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTransactionsStreamResponse) ProtoMessage() {} + +func (x *GetTransactionsStreamResponse) ProtoReflect() protoreflect.Message { + mi := &file_ark_v1_service_proto_msgTypes[43] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTransactionsStreamResponse.ProtoReflect.Descriptor instead. +func (*GetTransactionsStreamResponse) Descriptor() ([]byte, []int) { + return file_ark_v1_service_proto_rawDescGZIP(), []int{43} +} + +func (m *GetTransactionsStreamResponse) GetTx() isGetTransactionsStreamResponse_Tx { + if m != nil { + return m.Tx + } + return nil +} + +func (x *GetTransactionsStreamResponse) GetRound() *RoundTransaction { + if x, ok := x.GetTx().(*GetTransactionsStreamResponse_Round); ok { + return x.Round + } + return nil +} + +func (x *GetTransactionsStreamResponse) GetRedeem() *RedeemTransaction { + if x, ok := x.GetTx().(*GetTransactionsStreamResponse_Redeem); ok { + return x.Redeem + } + return nil +} + +type isGetTransactionsStreamResponse_Tx interface { + isGetTransactionsStreamResponse_Tx() +} + +type GetTransactionsStreamResponse_Round struct { + Round *RoundTransaction `protobuf:"bytes,1,opt,name=round,proto3,oneof"` +} + +type GetTransactionsStreamResponse_Redeem struct { + Redeem *RedeemTransaction `protobuf:"bytes,2,opt,name=redeem,proto3,oneof"` +} + +func (*GetTransactionsStreamResponse_Round) isGetTransactionsStreamResponse_Tx() {} + +func (*GetTransactionsStreamResponse_Redeem) isGetTransactionsStreamResponse_Tx() {} + +type RoundTransaction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Txid string `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` + SpentVtxos []*Outpoint `protobuf:"bytes,2,rep,name=spent_vtxos,json=spentVtxos,proto3" json:"spent_vtxos,omitempty"` + SpendableVtxos []*Vtxo `protobuf:"bytes,3,rep,name=spendable_vtxos,json=spendableVtxos,proto3" json:"spendable_vtxos,omitempty"` + ClaimedBoardingUtxos []*Outpoint `protobuf:"bytes,4,rep,name=claimed_boarding_utxos,json=claimedBoardingUtxos,proto3" json:"claimed_boarding_utxos,omitempty"` +} + +func (x *RoundTransaction) Reset() { + *x = RoundTransaction{} + if protoimpl.UnsafeEnabled { + mi := &file_ark_v1_service_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RoundTransaction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoundTransaction) ProtoMessage() {} + +func (x *RoundTransaction) ProtoReflect() protoreflect.Message { + mi := &file_ark_v1_service_proto_msgTypes[44] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RoundTransaction.ProtoReflect.Descriptor instead. +func (*RoundTransaction) Descriptor() ([]byte, []int) { + return file_ark_v1_service_proto_rawDescGZIP(), []int{44} +} + +func (x *RoundTransaction) GetTxid() string { + if x != nil { + return x.Txid + } + return "" +} + +func (x *RoundTransaction) GetSpentVtxos() []*Outpoint { + if x != nil { + return x.SpentVtxos + } + return nil +} + +func (x *RoundTransaction) GetSpendableVtxos() []*Vtxo { + if x != nil { + return x.SpendableVtxos + } + return nil +} + +func (x *RoundTransaction) GetClaimedBoardingUtxos() []*Outpoint { + if x != nil { + return x.ClaimedBoardingUtxos + } + return nil +} + +type RedeemTransaction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Txid string `protobuf:"bytes,1,opt,name=txid,proto3" json:"txid,omitempty"` + SpentVtxos []*Outpoint `protobuf:"bytes,2,rep,name=spent_vtxos,json=spentVtxos,proto3" json:"spent_vtxos,omitempty"` + SpendableVtxos []*Vtxo `protobuf:"bytes,3,rep,name=spendable_vtxos,json=spendableVtxos,proto3" json:"spendable_vtxos,omitempty"` +} + +func (x *RedeemTransaction) Reset() { + *x = RedeemTransaction{} + if protoimpl.UnsafeEnabled { + mi := &file_ark_v1_service_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RedeemTransaction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RedeemTransaction) ProtoMessage() {} + +func (x *RedeemTransaction) ProtoReflect() protoreflect.Message { + mi := &file_ark_v1_service_proto_msgTypes[45] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RedeemTransaction.ProtoReflect.Descriptor instead. +func (*RedeemTransaction) Descriptor() ([]byte, []int) { + return file_ark_v1_service_proto_rawDescGZIP(), []int{45} +} + +func (x *RedeemTransaction) GetTxid() string { + if x != nil { + return x.Txid + } + return "" +} + +func (x *RedeemTransaction) GetSpentVtxos() []*Outpoint { + if x != nil { + return x.SpentVtxos + } + return nil +} + +func (x *RedeemTransaction) GetSpendableVtxos() []*Vtxo { + if x != nil { + return x.SpendableVtxos + } + return nil +} + var File_ark_v1_service_proto protoreflect.FileDescriptor var file_ark_v1_service_proto_rawDesc = []byte{ @@ -2869,129 +3122,172 @@ var file_ark_v1_service_proto_rawDesc = []byte{ 0x78, 0x12, 0x3a, 0x0a, 0x19, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x61, 0x6c, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x2a, 0x98, 0x01, - 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x17, - 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, - 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x52, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, - 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, - 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x03, - 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, - 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x32, 0xe8, 0x0c, 0x0a, 0x0a, 0x41, 0x72, 0x6b, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, - 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, - 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, - 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, - 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, - 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, - 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, - 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, - 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, - 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, + 0x6e, 0x61, 0x6c, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x22, 0x1e, 0x0a, + 0x1c, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, + 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x30, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, + 0x64, 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, + 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, + 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, + 0x10, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, + 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, + 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, + 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, + 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, + 0x46, 0x0a, 0x16, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x14, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, + 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, + 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, + 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, + 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, + 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x2a, 0x98, 0x01, 0x0a, 0x0a, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, + 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, + 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, + 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, + 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, + 0x0a, 0x12, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x41, + 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x32, 0xeb, 0x0d, 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, + 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, + 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, + 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, + 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, + 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, - 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, - 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, - 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, - 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, - 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, - 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, - 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, - 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, - 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, - 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, - 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x6b, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, - 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x30, 0x01, 0x12, 0x56, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x14, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, - 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x70, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0d, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, - 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x73, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, - 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x12, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, - 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, + 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, + 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, + 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, + 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, + 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, + 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, + 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, + 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, + 0x54, 0x78, 0x73, 0x12, 0x6b, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, - 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, - 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, - 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, - 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, - 0x73, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, - 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, - 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x7d, 0x42, 0x92, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, - 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, - 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, - 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, - 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, - 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, + 0x12, 0x56, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, + 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x70, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, + 0x2a, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x73, + 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, + 0x76, 0x31, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, + 0x65, 0x74, 0x65, 0x12, 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, + 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, + 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, + 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x12, 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, + 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, + 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, + 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, + 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x30, 0x01, 0x42, 0x92, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, + 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, + 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, + 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, + 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, + 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -3007,7 +3303,7 @@ func file_ark_v1_service_proto_rawDescGZIP() []byte { } var file_ark_v1_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ark_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 42) +var file_ark_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 46) var file_ark_v1_service_proto_goTypes = []interface{}{ (RoundStage)(0), // 0: ark.v1.RoundStage (*GetInfoRequest)(nil), // 1: ark.v1.GetInfoRequest @@ -3052,6 +3348,10 @@ var file_ark_v1_service_proto_goTypes = []interface{}{ (*Node)(nil), // 40: ark.v1.Node (*Vtxo)(nil), // 41: ark.v1.Vtxo (*PendingPayment)(nil), // 42: ark.v1.PendingPayment + (*GetTransactionsStreamRequest)(nil), // 43: ark.v1.GetTransactionsStreamRequest + (*GetTransactionsStreamResponse)(nil), // 44: ark.v1.GetTransactionsStreamResponse + (*RoundTransaction)(nil), // 45: ark.v1.RoundTransaction + (*RedeemTransaction)(nil), // 46: ark.v1.RedeemTransaction } var file_ark_v1_service_proto_depIdxs = []int32{ 36, // 0: ark.v1.RegisterInputsForNextRoundRequest.inputs:type_name -> ark.v1.Input @@ -3081,39 +3381,48 @@ var file_ark_v1_service_proto_depIdxs = []int32{ 40, // 24: ark.v1.TreeLevel.nodes:type_name -> ark.v1.Node 35, // 25: ark.v1.Vtxo.outpoint:type_name -> ark.v1.Outpoint 42, // 26: ark.v1.Vtxo.pending_data:type_name -> ark.v1.PendingPayment - 1, // 27: ark.v1.ArkService.GetInfo:input_type -> ark.v1.GetInfoRequest - 3, // 28: ark.v1.ArkService.GetBoardingAddress:input_type -> ark.v1.GetBoardingAddressRequest - 5, // 29: ark.v1.ArkService.RegisterInputsForNextRound:input_type -> ark.v1.RegisterInputsForNextRoundRequest - 7, // 30: ark.v1.ArkService.RegisterOutputsForNextRound:input_type -> ark.v1.RegisterOutputsForNextRoundRequest - 9, // 31: ark.v1.ArkService.SubmitTreeNonces:input_type -> ark.v1.SubmitTreeNoncesRequest - 11, // 32: ark.v1.ArkService.SubmitTreeSignatures:input_type -> ark.v1.SubmitTreeSignaturesRequest - 13, // 33: ark.v1.ArkService.SubmitSignedForfeitTxs:input_type -> ark.v1.SubmitSignedForfeitTxsRequest - 15, // 34: ark.v1.ArkService.GetEventStream:input_type -> ark.v1.GetEventStreamRequest - 17, // 35: ark.v1.ArkService.Ping:input_type -> ark.v1.PingRequest - 19, // 36: ark.v1.ArkService.CreatePayment:input_type -> ark.v1.CreatePaymentRequest - 21, // 37: ark.v1.ArkService.CompletePayment:input_type -> ark.v1.CompletePaymentRequest - 23, // 38: ark.v1.ArkService.GetRound:input_type -> ark.v1.GetRoundRequest - 25, // 39: ark.v1.ArkService.GetRoundById:input_type -> ark.v1.GetRoundByIdRequest - 27, // 40: ark.v1.ArkService.ListVtxos:input_type -> ark.v1.ListVtxosRequest - 2, // 41: ark.v1.ArkService.GetInfo:output_type -> ark.v1.GetInfoResponse - 4, // 42: ark.v1.ArkService.GetBoardingAddress:output_type -> ark.v1.GetBoardingAddressResponse - 6, // 43: ark.v1.ArkService.RegisterInputsForNextRound:output_type -> ark.v1.RegisterInputsForNextRoundResponse - 8, // 44: ark.v1.ArkService.RegisterOutputsForNextRound:output_type -> ark.v1.RegisterOutputsForNextRoundResponse - 10, // 45: ark.v1.ArkService.SubmitTreeNonces:output_type -> ark.v1.SubmitTreeNoncesResponse - 12, // 46: ark.v1.ArkService.SubmitTreeSignatures:output_type -> ark.v1.SubmitTreeSignaturesResponse - 14, // 47: ark.v1.ArkService.SubmitSignedForfeitTxs:output_type -> ark.v1.SubmitSignedForfeitTxsResponse - 16, // 48: ark.v1.ArkService.GetEventStream:output_type -> ark.v1.GetEventStreamResponse - 18, // 49: ark.v1.ArkService.Ping:output_type -> ark.v1.PingResponse - 20, // 50: ark.v1.ArkService.CreatePayment:output_type -> ark.v1.CreatePaymentResponse - 22, // 51: ark.v1.ArkService.CompletePayment:output_type -> ark.v1.CompletePaymentResponse - 24, // 52: ark.v1.ArkService.GetRound:output_type -> ark.v1.GetRoundResponse - 26, // 53: ark.v1.ArkService.GetRoundById:output_type -> ark.v1.GetRoundByIdResponse - 28, // 54: ark.v1.ArkService.ListVtxos:output_type -> ark.v1.ListVtxosResponse - 41, // [41:55] is the sub-list for method output_type - 27, // [27:41] is the sub-list for method input_type - 27, // [27:27] is the sub-list for extension type_name - 27, // [27:27] is the sub-list for extension extendee - 0, // [0:27] is the sub-list for field type_name + 45, // 27: ark.v1.GetTransactionsStreamResponse.round:type_name -> ark.v1.RoundTransaction + 46, // 28: ark.v1.GetTransactionsStreamResponse.redeem:type_name -> ark.v1.RedeemTransaction + 35, // 29: ark.v1.RoundTransaction.spent_vtxos:type_name -> ark.v1.Outpoint + 41, // 30: ark.v1.RoundTransaction.spendable_vtxos:type_name -> ark.v1.Vtxo + 35, // 31: ark.v1.RoundTransaction.claimed_boarding_utxos:type_name -> ark.v1.Outpoint + 35, // 32: ark.v1.RedeemTransaction.spent_vtxos:type_name -> ark.v1.Outpoint + 41, // 33: ark.v1.RedeemTransaction.spendable_vtxos:type_name -> ark.v1.Vtxo + 1, // 34: ark.v1.ArkService.GetInfo:input_type -> ark.v1.GetInfoRequest + 3, // 35: ark.v1.ArkService.GetBoardingAddress:input_type -> ark.v1.GetBoardingAddressRequest + 5, // 36: ark.v1.ArkService.RegisterInputsForNextRound:input_type -> ark.v1.RegisterInputsForNextRoundRequest + 7, // 37: ark.v1.ArkService.RegisterOutputsForNextRound:input_type -> ark.v1.RegisterOutputsForNextRoundRequest + 9, // 38: ark.v1.ArkService.SubmitTreeNonces:input_type -> ark.v1.SubmitTreeNoncesRequest + 11, // 39: ark.v1.ArkService.SubmitTreeSignatures:input_type -> ark.v1.SubmitTreeSignaturesRequest + 13, // 40: ark.v1.ArkService.SubmitSignedForfeitTxs:input_type -> ark.v1.SubmitSignedForfeitTxsRequest + 15, // 41: ark.v1.ArkService.GetEventStream:input_type -> ark.v1.GetEventStreamRequest + 17, // 42: ark.v1.ArkService.Ping:input_type -> ark.v1.PingRequest + 19, // 43: ark.v1.ArkService.CreatePayment:input_type -> ark.v1.CreatePaymentRequest + 21, // 44: ark.v1.ArkService.CompletePayment:input_type -> ark.v1.CompletePaymentRequest + 23, // 45: ark.v1.ArkService.GetRound:input_type -> ark.v1.GetRoundRequest + 25, // 46: ark.v1.ArkService.GetRoundById:input_type -> ark.v1.GetRoundByIdRequest + 27, // 47: ark.v1.ArkService.ListVtxos:input_type -> ark.v1.ListVtxosRequest + 43, // 48: ark.v1.ArkService.GetTransactionsStream:input_type -> ark.v1.GetTransactionsStreamRequest + 2, // 49: ark.v1.ArkService.GetInfo:output_type -> ark.v1.GetInfoResponse + 4, // 50: ark.v1.ArkService.GetBoardingAddress:output_type -> ark.v1.GetBoardingAddressResponse + 6, // 51: ark.v1.ArkService.RegisterInputsForNextRound:output_type -> ark.v1.RegisterInputsForNextRoundResponse + 8, // 52: ark.v1.ArkService.RegisterOutputsForNextRound:output_type -> ark.v1.RegisterOutputsForNextRoundResponse + 10, // 53: ark.v1.ArkService.SubmitTreeNonces:output_type -> ark.v1.SubmitTreeNoncesResponse + 12, // 54: ark.v1.ArkService.SubmitTreeSignatures:output_type -> ark.v1.SubmitTreeSignaturesResponse + 14, // 55: ark.v1.ArkService.SubmitSignedForfeitTxs:output_type -> ark.v1.SubmitSignedForfeitTxsResponse + 16, // 56: ark.v1.ArkService.GetEventStream:output_type -> ark.v1.GetEventStreamResponse + 18, // 57: ark.v1.ArkService.Ping:output_type -> ark.v1.PingResponse + 20, // 58: ark.v1.ArkService.CreatePayment:output_type -> ark.v1.CreatePaymentResponse + 22, // 59: ark.v1.ArkService.CompletePayment:output_type -> ark.v1.CompletePaymentResponse + 24, // 60: ark.v1.ArkService.GetRound:output_type -> ark.v1.GetRoundResponse + 26, // 61: ark.v1.ArkService.GetRoundById:output_type -> ark.v1.GetRoundByIdResponse + 28, // 62: ark.v1.ArkService.ListVtxos:output_type -> ark.v1.ListVtxosResponse + 44, // 63: ark.v1.ArkService.GetTransactionsStream:output_type -> ark.v1.GetTransactionsStreamResponse + 49, // [49:64] is the sub-list for method output_type + 34, // [34:49] is the sub-list for method input_type + 34, // [34:34] is the sub-list for extension type_name + 34, // [34:34] is the sub-list for extension extendee + 0, // [0:34] is the sub-list for field type_name } func init() { file_ark_v1_service_proto_init() } @@ -3626,6 +3935,54 @@ func file_ark_v1_service_proto_init() { return nil } } + file_ark_v1_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTransactionsStreamRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ark_v1_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTransactionsStreamResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ark_v1_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RoundTransaction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ark_v1_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RedeemTransaction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_ark_v1_service_proto_msgTypes[4].OneofWrappers = []interface{}{} file_ark_v1_service_proto_msgTypes[12].OneofWrappers = []interface{}{} @@ -3643,13 +4000,17 @@ func file_ark_v1_service_proto_init() { (*PingResponse_RoundSigning)(nil), (*PingResponse_RoundSigningNoncesGenerated)(nil), } + file_ark_v1_service_proto_msgTypes[43].OneofWrappers = []interface{}{ + (*GetTransactionsStreamResponse_Round)(nil), + (*GetTransactionsStreamResponse_Redeem)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ark_v1_service_proto_rawDesc, NumEnums: 1, - NumMessages: 42, + NumMessages: 46, NumExtensions: 0, NumServices: 1, }, diff --git a/api-spec/protobuf/gen/ark/v1/service.pb.gw.go b/api-spec/protobuf/gen/ark/v1/service.pb.gw.go index 2aae451..6304976 100644 --- a/api-spec/protobuf/gen/ark/v1/service.pb.gw.go +++ b/api-spec/protobuf/gen/ark/v1/service.pb.gw.go @@ -482,6 +482,23 @@ func local_request_ArkService_ListVtxos_0(ctx context.Context, marshaler runtime } +func request_ArkService_GetTransactionsStream_0(ctx context.Context, marshaler runtime.Marshaler, client ArkServiceClient, req *http.Request, pathParams map[string]string) (ArkService_GetTransactionsStreamClient, runtime.ServerMetadata, error) { + var protoReq GetTransactionsStreamRequest + var metadata runtime.ServerMetadata + + stream, err := client.GetTransactionsStream(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 + +} + // 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. @@ -821,6 +838,13 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, }) + mux.Handle("GET", pattern_ArkService_GetTransactionsStream_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 + }) + return nil } @@ -1170,6 +1194,28 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, }) + mux.Handle("GET", pattern_ArkService_GetTransactionsStream_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) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/GetTransactionsStream", runtime.WithHTTPPathPattern("/v1/transactions")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_ArkService_GetTransactionsStream_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_ArkService_GetTransactionsStream_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1201,6 +1247,8 @@ var ( pattern_ArkService_GetRoundById_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 2}, []string{"v1", "round", "id"}, "")) pattern_ArkService_ListVtxos_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "vtxos", "address"}, "")) + + pattern_ArkService_GetTransactionsStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "transactions"}, "")) ) var ( @@ -1231,4 +1279,6 @@ var ( forward_ArkService_GetRoundById_0 = runtime.ForwardResponseMessage forward_ArkService_ListVtxos_0 = runtime.ForwardResponseMessage + + forward_ArkService_GetTransactionsStream_0 = runtime.ForwardResponseStream ) diff --git a/api-spec/protobuf/gen/ark/v1/service_grpc.pb.go b/api-spec/protobuf/gen/ark/v1/service_grpc.pb.go index 98c7404..6d4400e 100644 --- a/api-spec/protobuf/gen/ark/v1/service_grpc.pb.go +++ b/api-spec/protobuf/gen/ark/v1/service_grpc.pb.go @@ -32,6 +32,7 @@ type ArkServiceClient interface { GetRound(ctx context.Context, in *GetRoundRequest, opts ...grpc.CallOption) (*GetRoundResponse, error) GetRoundById(ctx context.Context, in *GetRoundByIdRequest, opts ...grpc.CallOption) (*GetRoundByIdResponse, error) ListVtxos(ctx context.Context, in *ListVtxosRequest, opts ...grpc.CallOption) (*ListVtxosResponse, error) + GetTransactionsStream(ctx context.Context, in *GetTransactionsStreamRequest, opts ...grpc.CallOption) (ArkService_GetTransactionsStreamClient, error) } type arkServiceClient struct { @@ -191,6 +192,38 @@ func (c *arkServiceClient) ListVtxos(ctx context.Context, in *ListVtxosRequest, return out, nil } +func (c *arkServiceClient) GetTransactionsStream(ctx context.Context, in *GetTransactionsStreamRequest, opts ...grpc.CallOption) (ArkService_GetTransactionsStreamClient, error) { + stream, err := c.cc.NewStream(ctx, &ArkService_ServiceDesc.Streams[1], "/ark.v1.ArkService/GetTransactionsStream", opts...) + if err != nil { + return nil, err + } + x := &arkServiceGetTransactionsStreamClient{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_GetTransactionsStreamClient interface { + Recv() (*GetTransactionsStreamResponse, error) + grpc.ClientStream +} + +type arkServiceGetTransactionsStreamClient struct { + grpc.ClientStream +} + +func (x *arkServiceGetTransactionsStreamClient) Recv() (*GetTransactionsStreamResponse, error) { + m := new(GetTransactionsStreamResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // ArkServiceServer is the server API for ArkService service. // All implementations should embed UnimplementedArkServiceServer // for forward compatibility @@ -209,6 +242,7 @@ type ArkServiceServer interface { GetRound(context.Context, *GetRoundRequest) (*GetRoundResponse, error) GetRoundById(context.Context, *GetRoundByIdRequest) (*GetRoundByIdResponse, error) ListVtxos(context.Context, *ListVtxosRequest) (*ListVtxosResponse, error) + GetTransactionsStream(*GetTransactionsStreamRequest, ArkService_GetTransactionsStreamServer) error } // UnimplementedArkServiceServer should be embedded to have forward compatible implementations. @@ -257,6 +291,9 @@ func (UnimplementedArkServiceServer) GetRoundById(context.Context, *GetRoundById func (UnimplementedArkServiceServer) ListVtxos(context.Context, *ListVtxosRequest) (*ListVtxosResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListVtxos not implemented") } +func (UnimplementedArkServiceServer) GetTransactionsStream(*GetTransactionsStreamRequest, ArkService_GetTransactionsStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetTransactionsStream 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 @@ -524,6 +561,27 @@ func _ArkService_ListVtxos_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _ArkService_GetTransactionsStream_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetTransactionsStreamRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ArkServiceServer).GetTransactionsStream(m, &arkServiceGetTransactionsStreamServer{stream}) +} + +type ArkService_GetTransactionsStreamServer interface { + Send(*GetTransactionsStreamResponse) error + grpc.ServerStream +} + +type arkServiceGetTransactionsStreamServer struct { + grpc.ServerStream +} + +func (x *arkServiceGetTransactionsStreamServer) Send(m *GetTransactionsStreamResponse) error { + return x.ServerStream.SendMsg(m) +} + // 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) @@ -590,6 +648,11 @@ var ArkService_ServiceDesc = grpc.ServiceDesc{ Handler: _ArkService_GetEventStream_Handler, ServerStreams: true, }, + { + StreamName: "GetTransactionsStream", + Handler: _ArkService_GetTransactionsStream_Handler, + ServerStreams: true, + }, }, Metadata: "ark/v1/service.proto", } diff --git a/server/internal/core/application/covenant.go b/server/internal/core/application/covenant.go index 0cbc140..3f4b153 100644 --- a/server/internal/core/application/covenant.go +++ b/server/internal/core/application/covenant.go @@ -45,7 +45,8 @@ type covenantService struct { paymentRequests *paymentsMap forfeitTxs *forfeitTxsMap - eventsCh chan domain.RoundEvent + eventsCh chan domain.RoundEvent + transactionEventsCh chan TransactionEvent currentRoundLock sync.Mutex currentRound *domain.Round @@ -59,23 +60,30 @@ func NewCovenantService( builder ports.TxBuilder, scanner ports.BlockchainScanner, scheduler ports.SchedulerService, ) (Service, error) { - eventsCh := make(chan domain.RoundEvent) - paymentRequests := newPaymentsMap() - - forfeitTxs := newForfeitTxsMap(builder) pubkey, err := walletSvc.GetPubkey(context.Background()) if err != nil { return nil, fmt.Errorf("failed to fetch pubkey: %s", err) } - sweeper := newSweeper(walletSvc, repoManager, builder, scheduler) - svc := &covenantService{ - network, pubkey, - roundLifetime, roundInterval, unilateralExitDelay, boardingExitDelay, - walletSvc, repoManager, builder, scanner, sweeper, - paymentRequests, forfeitTxs, eventsCh, sync.Mutex{}, nil, nil, + network: network, + pubkey: pubkey, + roundLifetime: roundLifetime, + roundInterval: roundInterval, + unilateralExitDelay: unilateralExitDelay, + boardingExitDelay: boardingExitDelay, + wallet: walletSvc, + repoManager: repoManager, + builder: builder, + scanner: scanner, + sweeper: newSweeper(walletSvc, repoManager, builder, scheduler), + paymentRequests: newPaymentsMap(), + forfeitTxs: newForfeitTxsMap(builder), + eventsCh: make(chan domain.RoundEvent), + transactionEventsCh: make(chan TransactionEvent), + currentRoundLock: sync.Mutex{}, } + repoManager.RegisterEventsHandler( func(round *domain.Round) { go svc.propagateEvents(round) @@ -346,6 +354,10 @@ func (s *covenantService) GetEventsChannel(ctx context.Context) <-chan domain.Ro return s.eventsCh } +func (s *covenantService) GetTransactionEventsChannel(ctx context.Context) <-chan TransactionEvent { + return s.transactionEventsCh +} + func (s *covenantService) GetRoundByTxid(ctx context.Context, poolTxid string) (*domain.Round, error) { return s.repoManager.Rounds().GetRoundWithTxid(ctx, poolTxid) } @@ -851,6 +863,26 @@ func (s *covenantService) updateVtxoSet(round *domain.Round) { } }() } + + go func() { + // nolint:all + tx, _ := psetv2.NewPsetFromBase64(round.UnsignedTx) + boardingInputs := make([]domain.VtxoKey, 0) + for _, in := range tx.Inputs { + if len(in.TapLeafScript) > 0 { + boardingInputs = append(boardingInputs, domain.VtxoKey{ + Txid: elementsutil.TxIDFromBytes(in.PreviousTxid), + VOut: in.PreviousTxIndex, + }) + } + } + s.transactionEventsCh <- RoundTransactionEvent{ + RoundTxID: round.Txid, + SpentVtxos: getSpentVtxos(round.Payments), + SpendableVtxos: s.getNewVtxos(round), + ClaimedBoardingInputs: boardingInputs, + } + }() } func (s *covenantService) propagateEvents(round *domain.Round) { diff --git a/server/internal/core/application/covenantless.go b/server/internal/core/application/covenantless.go index 384d414..f7dde6f 100644 --- a/server/internal/core/application/covenantless.go +++ b/server/internal/core/application/covenantless.go @@ -42,7 +42,8 @@ type covenantlessService struct { paymentRequests *paymentsMap forfeitTxs *forfeitTxsMap - eventsCh chan domain.RoundEvent + eventsCh chan domain.RoundEvent + transactionEventsCh chan TransactionEvent // cached data for the current round lastEvent domain.RoundEvent @@ -62,16 +63,11 @@ func NewCovenantlessService( builder ports.TxBuilder, scanner ports.BlockchainScanner, scheduler ports.SchedulerService, ) (Service, error) { - eventsCh := make(chan domain.RoundEvent) - paymentRequests := newPaymentsMap() - - forfeitTxs := newForfeitTxsMap(builder) pubkey, err := walletSvc.GetPubkey(context.Background()) if err != nil { return nil, fmt.Errorf("failed to fetch pubkey: %s", err) } - sweeper := newSweeper(walletSvc, repoManager, builder, scheduler) asyncPaymentsCache := make(map[string]struct { receivers []domain.Receiver expireAt int64 @@ -87,10 +83,11 @@ func NewCovenantlessService( repoManager: repoManager, builder: builder, scanner: scanner, - sweeper: sweeper, - paymentRequests: paymentRequests, - forfeitTxs: forfeitTxs, - eventsCh: eventsCh, + sweeper: newSweeper(walletSvc, repoManager, builder, scheduler), + paymentRequests: newPaymentsMap(), + forfeitTxs: newForfeitTxsMap(builder), + eventsCh: make(chan domain.RoundEvent), + transactionEventsCh: make(chan TransactionEvent), currentRoundLock: sync.Mutex{}, asyncPaymentsCache: asyncPaymentsCache, treeSigningSessions: make(map[string]*musigSigningSession), @@ -303,6 +300,14 @@ func (s *covenantlessService) CompleteAsyncPayment( delete(s.asyncPaymentsCache, redeemTxid) + go func() { + s.transactionEventsCh <- RedeemTransactionEvent{ + AsyncTxID: redeemTxid, + SpentVtxos: spentVtxos, + SpendableVtxos: vtxos, + } + }() + return nil } @@ -579,6 +584,10 @@ func (s *covenantlessService) GetEventsChannel(ctx context.Context) <-chan domai return s.eventsCh } +func (s *covenantlessService) GetTransactionEventsChannel(ctx context.Context) <-chan TransactionEvent { + return s.transactionEventsCh +} + func (s *covenantlessService) GetRoundByTxid(ctx context.Context, roundTxid string) (*domain.Round, error) { return s.repoManager.Rounds().GetRoundWithTxid(ctx, roundTxid) } @@ -1262,7 +1271,27 @@ func (s *covenantlessService) updateVtxoSet(round *domain.Round) { return } }() + } + go func() { + // nolint:all + tx, _ := psbt.NewFromRawBytes(strings.NewReader(round.UnsignedTx), true) + boardingInputs := make([]domain.VtxoKey, 0) + for i, in := range tx.Inputs { + if len(in.TaprootLeafScript) > 0 { + boardingInputs = append(boardingInputs, domain.VtxoKey{ + Txid: tx.UnsignedTx.TxIn[i].PreviousOutPoint.Hash.String(), + VOut: tx.UnsignedTx.TxIn[i].PreviousOutPoint.Index, + }) + } + } + s.transactionEventsCh <- RoundTransactionEvent{ + RoundTxID: round.Txid, + SpentVtxos: getSpentVtxos(round.Payments), + SpendableVtxos: s.getNewVtxos(round), + ClaimedBoardingInputs: boardingInputs, + } + }() } func (s *covenantlessService) propagateEvents(round *domain.Round) { diff --git a/server/internal/core/application/types.go b/server/internal/core/application/types.go index 81ece8e..ea1440b 100644 --- a/server/internal/core/application/types.go +++ b/server/internal/core/application/types.go @@ -50,6 +50,7 @@ type Service interface { ctx context.Context, roundID string, pubkey *secp256k1.PublicKey, signatures string, ) error + GetTransactionEventsChannel(ctx context.Context) <-chan TransactionEvent } type ServiceInfo struct { @@ -81,3 +82,35 @@ func (outpoint txOutpoint) GetTxid() string { func (outpoint txOutpoint) GetIndex() uint32 { return outpoint.vout } + +const ( + RoundTransaction TransactionEventType = "round_tx" + RedeemTransaction TransactionEventType = "redeem_tx" +) + +type TransactionEventType string + +type TransactionEvent interface { + Type() TransactionEventType +} + +type RoundTransactionEvent struct { + RoundTxID string + SpentVtxos []domain.VtxoKey + SpendableVtxos []domain.Vtxo + ClaimedBoardingInputs []domain.VtxoKey +} + +func (r RoundTransactionEvent) Type() TransactionEventType { + return RoundTransaction +} + +type RedeemTransactionEvent struct { + AsyncTxID string + SpentVtxos []domain.VtxoKey + SpendableVtxos []domain.Vtxo +} + +func (a RedeemTransactionEvent) Type() TransactionEventType { + return RedeemTransaction +} diff --git a/server/internal/interface/grpc/handlers/arkservice.go b/server/internal/interface/grpc/handlers/arkservice.go index a3ae1a4..e8c52c9 100644 --- a/server/internal/interface/grpc/handlers/arkservice.go +++ b/server/internal/interface/grpc/handlers/arkservice.go @@ -15,27 +15,22 @@ import ( "google.golang.org/grpc/status" ) -type listener struct { - id string - done chan struct{} - ch chan *arkv1.GetEventStreamResponse -} - type handler struct { svc application.Service - listenersLock *sync.Mutex - listeners []*listener + eventsListenerHandler *listenerHanlder[*arkv1.GetEventStreamResponse] + transactionsListenerHandler *listenerHanlder[*arkv1.GetTransactionsStreamResponse] } func NewHandler(service application.Service) arkv1.ArkServiceServer { h := &handler{ - svc: service, - listenersLock: &sync.Mutex{}, - listeners: make([]*listener, 0), + svc: service, + eventsListenerHandler: newListenerHandler[*arkv1.GetEventStreamResponse](), + transactionsListenerHandler: newListenerHandler[*arkv1.GetTransactionsStreamResponse](), } go h.listenToEvents() + go h.listenToPaymentEvents() return h } @@ -234,14 +229,14 @@ func (h *handler) GetEventStream( ) error { doneCh := make(chan struct{}) - listener := &listener{ + listener := &listener[*arkv1.GetEventStreamResponse]{ id: uuid.NewString(), done: doneCh, ch: make(chan *arkv1.GetEventStreamResponse), } - h.pushListener(listener) - defer h.removeListener(listener.id) + h.eventsListenerHandler.pushListener(listener) + defer h.eventsListenerHandler.removeListener(listener.id) defer close(listener.ch) defer close(doneCh) @@ -488,21 +483,31 @@ func (h *handler) ListVtxos( }, nil } -func (h *handler) pushListener(l *listener) { - h.listenersLock.Lock() - defer h.listenersLock.Unlock() +func (h *handler) GetTransactionsStream( + _ *arkv1.GetTransactionsStreamRequest, + stream arkv1.ArkService_GetTransactionsStreamServer, +) error { + listener := &listener[*arkv1.GetTransactionsStreamResponse]{ + id: uuid.NewString(), + done: make(chan struct{}), + ch: make(chan *arkv1.GetTransactionsStreamResponse), + } - h.listeners = append(h.listeners, l) -} + h.transactionsListenerHandler.pushListener(listener) -func (h *handler) removeListener(id string) { - h.listenersLock.Lock() - defer h.listenersLock.Unlock() + defer func() { + h.transactionsListenerHandler.removeListener(listener.id) + close(listener.ch) + }() - for i, listener := range h.listeners { - if listener.id == id { - h.listeners = append(h.listeners[:i], h.listeners[i+1:]...) - return + for { + select { + case <-stream.Context().Done(): + return nil + case ev := <-listener.ch: + if err := stream.Send(ev); err != nil { + return err + } } } } @@ -582,9 +587,9 @@ func (h *handler) listenToEvents() { } if ev != nil { - logrus.Debugf("forwarding event to %d listeners", len(h.listeners)) - for _, l := range h.listeners { - go func(l *listener) { + logrus.Debugf("forwarding event to %d listeners", len(h.eventsListenerHandler.listeners)) + for _, l := range h.eventsListenerHandler.listeners { + go func(l *listener[*arkv1.GetEventStreamResponse]) { l.ch <- ev if shouldClose { l.done <- struct{}{} @@ -594,3 +599,88 @@ func (h *handler) listenToEvents() { } } } + +func (h *handler) listenToPaymentEvents() { + paymentEventsCh := h.svc.GetTransactionEventsChannel(context.Background()) + for event := range paymentEventsCh { + var paymentEvent *arkv1.GetTransactionsStreamResponse + + switch event.Type() { + case application.RoundTransaction: + paymentEvent = &arkv1.GetTransactionsStreamResponse{ + Tx: &arkv1.GetTransactionsStreamResponse_Round{ + Round: convertRoundPaymentEvent(event.(application.RoundTransactionEvent)), + }, + } + case application.RedeemTransaction: + paymentEvent = &arkv1.GetTransactionsStreamResponse{ + Tx: &arkv1.GetTransactionsStreamResponse_Redeem{ + Redeem: convertAsyncPaymentEvent(event.(application.RedeemTransactionEvent)), + }, + } + } + + if paymentEvent != nil { + logrus.Debugf("forwarding event to %d listeners", len(h.transactionsListenerHandler.listeners)) + for _, l := range h.transactionsListenerHandler.listeners { + go func(l *listener[*arkv1.GetTransactionsStreamResponse]) { + l.ch <- paymentEvent + }(l) + } + } + } +} + +func convertRoundPaymentEvent(e application.RoundTransactionEvent) *arkv1.RoundTransaction { + return &arkv1.RoundTransaction{ + Txid: e.RoundTxID, + SpentVtxos: vtxoKeyList(e.SpentVtxos).toProto(), + SpendableVtxos: vtxoList(e.SpendableVtxos).toProto(), + ClaimedBoardingUtxos: vtxoKeyList(e.ClaimedBoardingInputs).toProto(), + } +} + +func convertAsyncPaymentEvent(e application.RedeemTransactionEvent) *arkv1.RedeemTransaction { + return &arkv1.RedeemTransaction{ + Txid: e.AsyncTxID, + SpentVtxos: vtxoKeyList(e.SpentVtxos).toProto(), + SpendableVtxos: vtxoList(e.SpendableVtxos).toProto(), + } +} + +type listener[T any] struct { + id string + done chan struct{} + ch chan T +} + +type listenerHanlder[T any] struct { + lock *sync.Mutex + listeners []*listener[T] +} + +func newListenerHandler[T any]() *listenerHanlder[T] { + return &listenerHanlder[T]{ + lock: &sync.Mutex{}, + listeners: make([]*listener[T], 0), + } +} + +func (h *listenerHanlder[T]) pushListener(l *listener[T]) { + h.lock.Lock() + defer h.lock.Unlock() + + h.listeners = append(h.listeners, l) +} + +func (h *listenerHanlder[T]) removeListener(id string) { + h.lock.Lock() + defer h.lock.Unlock() + + for i, listener := range h.listeners { + if listener.id == id { + h.listeners = append(h.listeners[:i], h.listeners[i+1:]...) + return + } + } +} diff --git a/server/internal/interface/grpc/handlers/parser.go b/server/internal/interface/grpc/handlers/parser.go index 8ea1f5a..c858577 100644 --- a/server/internal/interface/grpc/handlers/parser.go +++ b/server/internal/interface/grpc/handlers/parser.go @@ -92,6 +92,19 @@ func (v vtxoList) toProto() []*arkv1.Vtxo { return list } +type vtxoKeyList []domain.VtxoKey + +func (v vtxoKeyList) toProto() []*arkv1.Outpoint { + list := make([]*arkv1.Outpoint, 0, len(v)) + for _, vtxoKey := range v { + list = append(list, &arkv1.Outpoint{ + Txid: vtxoKey.Txid, + Vout: vtxoKey.VOut, + }) + } + return list +} + type congestionTree tree.CongestionTree func (t congestionTree) toProto() *arkv1.Tree {