Skip to content

Commit

Permalink
add contract endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
chris124567 committed Oct 29, 2024
1 parent 404270f commit 6c1260d
Show file tree
Hide file tree
Showing 5 changed files with 434 additions and 18 deletions.
75 changes: 73 additions & 2 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ type (
Contracts(ids []types.FileContractID) (result []explorer.FileContract, err error)
ContractsKey(key types.PublicKey) (result []explorer.FileContract, err error)
ContractRevisions(id types.FileContractID) (result []explorer.FileContract, err error)
V2Contracts(ids []types.FileContractID) (result []explorer.V2FileContract, err error)
V2ContractsKey(key types.PublicKey) (result []explorer.V2FileContract, err error)
V2ContractRevisions(id types.FileContractID) (result []explorer.V2FileContract, err error)
Search(id types.Hash256) (explorer.SearchType, error)

Hosts(pks []types.PublicKey) ([]explorer.Host, error)
Expand Down Expand Up @@ -485,6 +488,7 @@ func (s *server) outputsSiafundHandler(jc jape.Context) {

jc.Encode(outputs[0])
}

func (s *server) contractsIDHandler(jc jape.Context) {
var id types.FileContractID
if jc.DecodeParam("id", &id) != nil {
Expand Down Expand Up @@ -532,6 +536,68 @@ func (s *server) contractsBatchHandler(jc jape.Context) {
jc.Encode(fcs)
}

func (s *server) v2ContractsIDHandler(jc jape.Context) {
var id types.FileContractID
if jc.DecodeParam("id", &id) != nil {
return
}
fcs, err := s.e.V2Contracts([]types.FileContractID{id})
if jc.Check("failed to get contract", err) != nil {
return
} else if len(fcs) == 0 {
jc.Error(explorer.ErrContractNotFound, http.StatusNotFound)
return
}
jc.Encode(fcs[0])
}

func (s *server) v2ContractsBatchHandler(jc jape.Context) {
var ids []types.FileContractID
if jc.Decode(&ids) != nil {
return
} else if len(ids) > maxIDs {
jc.Error(ErrTooManyIDs, http.StatusBadRequest)
return
}

fcs, err := s.e.V2Contracts(ids)
if jc.Check("failed to get contracts", err) != nil {
return
}
jc.Encode(fcs)
}

func (s *server) v2ContractsIDRevisionsHandler(jc jape.Context) {
var id types.FileContractID
if jc.DecodeParam("id", &id) != nil {
return
}

fcs, err := s.e.V2ContractRevisions(id)
if errors.Is(err, explorer.ErrContractNotFound) {
jc.Error(fmt.Errorf("%w: %v", err, id), http.StatusNotFound)
return
} else if jc.Check("failed to fetch contract revisions", err) != nil {
return
}
jc.Encode(fcs)
}

func (s *server) pubkeyV2ContractsHandler(jc jape.Context) {
var key types.PublicKey
if jc.DecodeParam("key", &key) != nil {
return
}
fcs, err := s.e.V2ContractsKey(key)
if jc.Check("failed to get contracts", err) != nil {
return
} else if len(fcs) == 0 {
jc.Error(explorer.ErrContractNotFound, http.StatusNotFound)
return
}
jc.Encode(fcs)
}

func (s *server) pubkeyContractsHandler(jc jape.Context) {
var key types.PublicKey
if jc.DecodeParam("key", &key) != nil {
Expand Down Expand Up @@ -630,8 +696,13 @@ func NewServer(e Explorer, cm ChainManager, s Syncer) http.Handler {
"GET /contracts/:id/revisions": srv.contractsIDRevisionsHandler,
"POST /contracts": srv.contractsBatchHandler,

"GET /pubkey/:key/contracts": srv.pubkeyContractsHandler,
"GET /pubkey/:key/host": srv.pubkeyHostHandler,
"GET /v2/contracts/:id": srv.v2ContractsIDHandler,
"GET /v2/contracts/:id/revisions": srv.v2ContractsIDRevisionsHandler,
"POST /v2/contracts": srv.v2ContractsBatchHandler,

"GET /pubkey/:key/v2/contracts": srv.pubkeyV2ContractsHandler,
"GET /pubkey/:key/contracts": srv.pubkeyContractsHandler,
"GET /pubkey/:key/host": srv.pubkeyHostHandler,

"GET /metrics/block": srv.blocksMetricsHandler,
"GET /metrics/block/:id": srv.blocksMetricsIDHandler,
Expand Down
19 changes: 19 additions & 0 deletions explorer/explorer.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ type Store interface {
Contracts(ids []types.FileContractID) (result []FileContract, err error)
ContractsKey(key types.PublicKey) (result []FileContract, err error)
ContractRevisions(id types.FileContractID) (result []FileContract, err error)
V2Contracts(ids []types.FileContractID) (result []V2FileContract, err error)
V2ContractsKey(key types.PublicKey) (result []V2FileContract, err error)
V2ContractRevisions(id types.FileContractID) (result []V2FileContract, err error)
SiacoinElements(ids []types.SiacoinOutputID) (result []SiacoinOutput, err error)
SiafundElements(ids []types.SiafundOutputID) (result []SiafundOutput, err error)

Expand Down Expand Up @@ -263,6 +266,22 @@ func (e *Explorer) ContractRevisions(id types.FileContractID) (result []FileCont
return e.s.ContractRevisions(id)
}

// V2Contracts returns the contracts with the specified IDs.
func (e *Explorer) V2Contracts(ids []types.FileContractID) (result []V2FileContract, err error) {
return e.s.V2Contracts(ids)
}

// V2ContractsKey returns the contracts for a particular ed25519 key.
func (e *Explorer) V2ContractsKey(key types.PublicKey) (result []V2FileContract, err error) {
return e.s.V2ContractsKey(key)
}

// V2ContractRevisions returns all the revisions of the contract with the
// specified ID.
func (e *Explorer) V2ContractRevisions(id types.FileContractID) (result []V2FileContract, err error) {
return e.s.V2ContractRevisions(id)
}

// SiacoinElements returns the siacoin elements with the specified IDs.
func (e *Explorer) SiacoinElements(ids []types.SiacoinOutputID) (result []SiacoinOutput, err error) {
return e.s.SiacoinElements(ids)
Expand Down
40 changes: 24 additions & 16 deletions internal/testutil/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,24 +165,9 @@ func CheckV2Transaction(t *testing.T, expectTxn types.V2Transaction, gotTxn expl
for i := range expectTxn.FileContracts {
expected := expectTxn.FileContracts[i]
got := gotTxn.FileContracts[i]
gotFC := got.V2FileContractElement.V2FileContract

Equal(t, "id", expectTxn.V2FileContractID(expectTxn.ID(), i), types.FileContractID(got.ID))
Equal(t, "capacity", expected.Capacity, gotFC.Capacity)
Equal(t, "filesize", expected.Filesize, gotFC.Filesize)
Equal(t, "proof height", expected.ProofHeight, gotFC.ProofHeight)
Equal(t, "expiration height", expected.ExpirationHeight, gotFC.ExpirationHeight)
Equal(t, "renter output address", expected.RenterOutput.Address, gotFC.RenterOutput.Address)
Equal(t, "renter output value", expected.RenterOutput.Address, gotFC.RenterOutput.Address)
Equal(t, "host output address", expected.HostOutput.Address, gotFC.HostOutput.Address)
Equal(t, "host output value", expected.HostOutput.Address, gotFC.HostOutput.Address)
Equal(t, "missed host value", expected.MissedHostValue, gotFC.MissedHostValue)
Equal(t, "total collateral", expected.TotalCollateral, gotFC.TotalCollateral)
Equal(t, "renter public key", expected.RenterPublicKey, gotFC.RenterPublicKey)
Equal(t, "host public key", expected.HostPublicKey, gotFC.HostPublicKey)
Equal(t, "revision number", expected.RevisionNumber, gotFC.RevisionNumber)
Equal(t, "renter signature", expected.RenterSignature, gotFC.RenterSignature)
Equal(t, "host signature", expected.HostSignature, gotFC.HostSignature)
CheckV2FC(t, expected, got)
}

Equal(t, "attestations", len(expectTxn.Attestations), len(gotTxn.Attestations))
Expand Down Expand Up @@ -264,3 +249,26 @@ func CheckFC(t *testing.T, revision, resolved, valid bool, expected types.FileCo
Equal(t, "missed proof output value", expected.MissedProofOutputs[i].Value, gotFC.MissedProofOutputs[i].Value)
}
}

// CheckV2FC checks the retrieved file contract with the source file contract
// in addition to checking the resolved and valid fields.
func CheckV2FC(t *testing.T, expected types.V2FileContract, got explorer.V2FileContract) {
t.Helper()

gotFC := got.V2FileContractElement.V2FileContract
Equal(t, "capacity", expected.Capacity, gotFC.Capacity)
Equal(t, "filesize", expected.Filesize, gotFC.Filesize)
Equal(t, "proof height", expected.ProofHeight, gotFC.ProofHeight)
Equal(t, "expiration height", expected.ExpirationHeight, gotFC.ExpirationHeight)
Equal(t, "renter output address", expected.RenterOutput.Address, gotFC.RenterOutput.Address)
Equal(t, "renter output value", expected.RenterOutput.Address, gotFC.RenterOutput.Address)
Equal(t, "host output address", expected.HostOutput.Address, gotFC.HostOutput.Address)
Equal(t, "host output value", expected.HostOutput.Address, gotFC.HostOutput.Address)
Equal(t, "missed host value", expected.MissedHostValue, gotFC.MissedHostValue)
Equal(t, "total collateral", expected.TotalCollateral, gotFC.TotalCollateral)
Equal(t, "renter public key", expected.RenterPublicKey, gotFC.RenterPublicKey)
Equal(t, "host public key", expected.HostPublicKey, gotFC.HostPublicKey)
Equal(t, "revision number", expected.RevisionNumber, gotFC.RevisionNumber)
Equal(t, "renter signature", expected.RenterSignature, gotFC.RenterSignature)
Equal(t, "host signature", expected.HostSignature, gotFC.HostSignature)
}
Loading

0 comments on commit 6c1260d

Please sign in to comment.