diff --git a/components/restapi/core/component.go b/components/restapi/core/component.go index fb4085c48..9d4d6a8c6 100644 --- a/components/restapi/core/component.go +++ b/components/restapi/core/component.go @@ -21,100 +21,118 @@ import ( const ( // RouteInfo is the route for getting the node info. // GET returns the node info. + // MIMEApplicationJSON => json. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteInfo = "/info" // RouteBlockIssuance is the route for getting all needed information for block creation. // GET returns the data needed toa attach block. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteBlockIssuance = "/blocks/issuance" // RouteBlock is the route for getting a block by its blockID. // GET returns the block based on the given type in the request "Accept" header. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteBlock = "/blocks/:" + restapipkg.ParameterBlockID // RouteBlockMetadata is the route for getting block metadata by its blockID. // GET returns block metadata. + // MIMEApplicationJSON => json. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteBlockMetadata = "/blocks/:" + restapipkg.ParameterBlockID + "/metadata" // RouteBlocks is the route for sending new blocks. // POST creates a single new block and returns the new block ID. // The block is parsed based on the given type in the request "Content-Type" header. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteBlocks = "/blocks" - // RouteOutput is the route for getting an output by its outputID (transactionHash + outputIndex). + // RouteOutput is the route for getting an output by its outputID (transactionHash + outputIndex). This includes the proof, that the output corresponds to the requested outputID. // GET returns the output based on the given type in the request "Accept" header. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteOutput = "/outputs/:" + restapipkg.ParameterOutputID - // RouteOutputMetadata is the route for getting output metadata by its outputID (transactionHash + outputIndex) without getting the data again. + // RouteOutputMetadata is the route for getting output metadata by its outputID (transactionHash + outputIndex) without getting the output itself again. // GET returns the output metadata. + // MIMEApplicationJSON => json. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteOutputMetadata = "/outputs/:" + restapipkg.ParameterOutputID + "/metadata" + // RouteOutputWithMetadata is the route for getting output, together with its metadata by its outputID (transactionHash + outputIndex). + // GET returns the output metadata. + // MIMEApplicationJSON => json. + // MIMEApplicationVendorIOTASerializerV2 => bytes. + RouteOutputWithMetadata = "/outputs/:" + restapipkg.ParameterOutputID + "/full" + // RouteTransactionsIncludedBlock is the route for getting the block that was first confirmed for a given transaction ID. // GET returns the block based on the given type in the request "Accept" header. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteTransactionsIncludedBlock = "/transactions/:" + restapipkg.ParameterTransactionID + "/included-block" // RouteTransactionsIncludedBlockMetadata is the route for getting the block metadata that was first confirmed in the ledger for a given transaction ID. // GET returns block metadata (including info about "promotion/reattachment needed"). // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteTransactionsIncludedBlockMetadata = "/transactions/:" + restapipkg.ParameterTransactionID + "/included-block/metadata" // RouteCommitmentByID is the route for getting a slot commitment by its ID. // GET returns the commitment. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteCommitmentByID = "/commitments/:" + restapipkg.ParameterCommitmentID // RouteCommitmentByIDUTXOChanges is the route for getting all UTXO changes of a commitment by its ID. // GET returns the output IDs of all UTXO changes. + // MIMEApplicationJSON => json. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteCommitmentByIDUTXOChanges = "/commitments/:" + restapipkg.ParameterCommitmentID + "/utxo-changes" // RouteCommitmentByIndex is the route for getting a commitment by its Slot. // GET returns the commitment. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteCommitmentByIndex = "/commitments/by-index/:" + restapipkg.ParameterSlotIndex // RouteCommitmentByIndexUTXOChanges is the route for getting all UTXO changes of a commitment by its Slot. // GET returns the output IDs of all UTXO changes. + // MIMEApplicationJSON => json. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteCommitmentByIndexUTXOChanges = "/commitments/by-index/:" + restapipkg.ParameterSlotIndex + "/utxo-changes" // RouteCongestion is the route for getting the current congestion state and all account related useful details as block issuance credits. // GET returns the congestion state related to the specified account. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteCongestion = "/accounts/:" + restapipkg.ParameterAccountID + "/congestion" // RouteValidators is the route for getting informations about the current validators. // GET returns the paginated response with the list of validators. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteValidators = "/validators" // RouteValidatorsAccount is the route for getting details about the validator by its accountID. // GET returns the validator details. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteValidatorsAccount = "/validators/:" + restapipkg.ParameterAccountID // RouteRewards is the route for getting the rewards for staking or delegation based on staking account or delegation output. // Rewards are decayed up to returned epochEnd index. // GET returns the rewards. + // MIMEApplicationJSON => json. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteRewards = "/rewards/:" + restapipkg.ParameterOutputID // RouteCommittee is the route for getting the current committee. // GET returns the committee. // MIMEApplicationJSON => json. - // MIMEVendorIOTASerializer => bytes. + // MIMEApplicationVendorIOTASerializerV2 => bytes. RouteCommittee = "/committee" ) @@ -255,12 +273,12 @@ func configure() error { }) routeGroup.GET(RouteOutput, func(c echo.Context) error { - output, err := getOutput(c) + resp, err := getOutput(c) if err != nil { return err } - return responseByHeader(c, output.Output()) + return responseByHeader(c, resp) }) routeGroup.GET(RouteOutputMetadata, func(c echo.Context) error { @@ -272,6 +290,15 @@ func configure() error { return responseByHeader(c, resp) }) + routeGroup.GET(RouteOutputWithMetadata, func(c echo.Context) error { + resp, err := getOutputWithMetadata(c) + if err != nil { + return err + } + + return responseByHeader(c, resp) + }) + routeGroup.GET(RouteTransactionsIncludedBlock, func(c echo.Context) error { block, err := blockByTransactionID(c) if err != nil { diff --git a/components/restapi/core/utxo.go b/components/restapi/core/utxo.go index c62280f3b..aaf0168ff 100644 --- a/components/restapi/core/utxo.go +++ b/components/restapi/core/utxo.go @@ -10,7 +10,7 @@ import ( "github.com/iotaledger/iota.go/v4/nodeclient/apimodels" ) -func getOutput(c echo.Context) (*utxoledger.Output, error) { +func getOutput(c echo.Context) (*apimodels.OutputResponse, error) { outputID, err := httpserver.ParseOutputIDParam(c, restapipkg.ParameterOutputID) if err != nil { return nil, ierrors.Wrapf(err, "failed to parse output ID param: %s", c.Param(restapipkg.ParameterOutputID)) @@ -21,10 +21,13 @@ func getOutput(c echo.Context) (*utxoledger.Output, error) { return nil, ierrors.Wrapf(err, "failed to get output: %s from the Ledger", outputID.String()) } - return output, nil + return &apimodels.OutputResponse{ + Output: output.Output(), + OutputIDProof: output.OutputIDProof(), + }, nil } -func getOutputMetadata(c echo.Context) (*apimodels.OutputMetadataResponse, error) { +func getOutputMetadata(c echo.Context) (*apimodels.OutputMetadata, error) { outputID, err := httpserver.ParseOutputIDParam(c, restapipkg.ParameterOutputID) if err != nil { return nil, ierrors.Wrapf(err, "failed to parse output ID param: %s", c.Param(restapipkg.ParameterOutputID)) @@ -42,10 +45,46 @@ func getOutputMetadata(c echo.Context) (*apimodels.OutputMetadataResponse, error return newOutputMetadataResponse(output) } -func newOutputMetadataResponse(output *utxoledger.Output) (*apimodels.OutputMetadataResponse, error) { +func getOutputWithMetadata(c echo.Context) (*apimodels.OutputWithMetadataResponse, error) { + outputID, err := httpserver.ParseOutputIDParam(c, restapipkg.ParameterOutputID) + if err != nil { + return nil, ierrors.Wrapf(err, "failed to parse output ID param: %s", c.Param(restapipkg.ParameterOutputID)) + } + + output, spent, err := deps.Protocol.MainEngineInstance().Ledger.OutputOrSpent(outputID) + if err != nil { + return nil, ierrors.Wrapf(err, "failed to get output: %s from the Ledger", outputID.String()) + } + + if spent != nil { + metadata, err := newSpentMetadataResponse(spent) + if err != nil { + return nil, err + } + + return &apimodels.OutputWithMetadataResponse{ + Output: spent.Output().Output(), + OutputIDProof: spent.Output().OutputIDProof(), + Metadata: metadata, + }, nil + } + + metadata, err := newOutputMetadataResponse(output) + if err != nil { + return nil, err + } + + return &apimodels.OutputWithMetadataResponse{ + Output: output.Output(), + OutputIDProof: output.OutputIDProof(), + Metadata: metadata, + }, nil +} + +func newOutputMetadataResponse(output *utxoledger.Output) (*apimodels.OutputMetadata, error) { latestCommitment := deps.Protocol.MainEngineInstance().SyncManager.LatestCommitment() - resp := &apimodels.OutputMetadataResponse{ + resp := &apimodels.OutputMetadata{ BlockID: output.BlockID(), TransactionID: output.OutputID().TransactionID(), OutputIndex: output.OutputID().Index(), @@ -65,10 +104,10 @@ func newOutputMetadataResponse(output *utxoledger.Output) (*apimodels.OutputMeta return resp, nil } -func newSpentMetadataResponse(spent *utxoledger.Spent) (*apimodels.OutputMetadataResponse, error) { +func newSpentMetadataResponse(spent *utxoledger.Spent) (*apimodels.OutputMetadata, error) { latestCommitment := deps.Protocol.MainEngineInstance().SyncManager.LatestCommitment() - resp := &apimodels.OutputMetadataResponse{ + resp := &apimodels.OutputMetadata{ BlockID: spent.BlockID(), TransactionID: spent.OutputID().TransactionID(), OutputIndex: spent.OutputID().Index(),