Skip to content

Commit

Permalink
Merge pull request #21 from axone-protocol/feat/get-resource-gov
Browse files Browse the repository at this point in the history
Implement `GetResourceGovAddr`
  • Loading branch information
bdeneux authored Sep 6, 2024
2 parents e7b3ffb + 940d27a commit a8caad1
Show file tree
Hide file tree
Showing 8 changed files with 418 additions and 54 deletions.
39 changes: 18 additions & 21 deletions dataverse/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,22 @@ import (
"context"
"fmt"

cgschema "github.com/axone-protocol/axone-contract-schema/go/cognitarium-schema/v5"
dvschema "github.com/axone-protocol/axone-contract-schema/go/dataverse-schema/v5"
"google.golang.org/grpc"
)

type Client interface {
// GetResourceGovAddr returns the governance address of a resource.
// It queries the cognitarium to get the governance address (law-stone contract address)
// of a resource. The resource is identified by its DID.
GetResourceGovAddr(context.Context, string) (string, error)
ExecGov(context.Context, string, string) (interface{}, error)
}

type client struct {
dataverseClient dvschema.QueryClient
cognitariumAddr string
}

func NewDataverseClient(ctx context.Context, dataverseClient dvschema.QueryClient) (Client, error) {
cognitariumAddr, err := getCognitariumAddr(ctx, dataverseClient)
if err != nil {
return nil, fmt.Errorf("failed to get cognitarium address: %w", err)
}

return &client{
dataverseClient,
cognitariumAddr,
}, nil
dataverseClient dvschema.QueryClient
cognitariumClient cgschema.QueryClient
}

func NewClient(ctx context.Context,
Expand All @@ -39,15 +31,20 @@ func NewClient(ctx context.Context,
return nil, fmt.Errorf("failed to create dataverse client: %w", err)
}

return NewDataverseClient(ctx, dataverseClient)
}
cognitariumAddr, err := getCognitariumAddr(ctx, dataverseClient)
if err != nil {
return nil, fmt.Errorf("failed to get cognitarium address: %w", err)
}

func (c *client) GetResourceGovAddr(_ context.Context, _ string) (string, error) {
panic("not implemented")
}
cognitariumClient, err := cgschema.NewQueryClient(grpcAddr, cognitariumAddr, opts...)
if err != nil {
return nil, fmt.Errorf("failed to create cognitarium client: %w", err)
}

func (c *client) ExecGov(_ context.Context, _ string, _ string) (interface{}, error) {
panic("not implemented")
return &client{
dataverseClient,
cognitariumClient,
}, nil
}

func getCognitariumAddr(ctx context.Context, dvClient dvschema.QueryClient) (string, error) {
Expand Down
106 changes: 73 additions & 33 deletions dataverse/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,100 @@ import (
"fmt"
"testing"

schema "github.com/axone-protocol/axone-contract-schema/go/dataverse-schema/v5"
dvschema "github.com/axone-protocol/axone-contract-schema/go/dataverse-schema/v5"
"github.com/axone-protocol/axone-sdk/dataverse"
"github.com/axone-protocol/axone-sdk/testutil"
. "github.com/smartystreets/goconvey/convey"
"go.uber.org/mock/gomock"
)

func TestClient_NewDataverseClient(t *testing.T) {
func TestClient_NewClient(t *testing.T) {
tests := []struct {
name string
returnedErr error
wantErr error
wantAddr string
name string
grpcAddr string
contractAddr string
wantErr error
}{
{
name: "receive an cognitarium address",
returnedErr: nil,
wantErr: nil,
wantAddr: "addr",
name: "should call get cognitarium address with invalid grpc address",
grpcAddr: "invalid",
contractAddr: "did:key:zQ3shuwMJ",
wantErr: fmt.Errorf("failed to get cognitarium address"),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
Convey("Given a gRPC addr and contract addr", t, func() {
Convey("When Client is created", func() {
client, err := dataverse.NewClient(context.Background(), test.grpcAddr, test.contractAddr)

Convey("The client should be created or return an error", func() {
So(err.Error(), ShouldContainSubstring, test.wantErr.Error())
if test.wantErr == nil {
So(client, ShouldNotBeNil)
} else {
So(client, ShouldBeNil)
}
})
})
})
})
}
}

func Test_GetCognitariumAddr(t *testing.T) {
tests := []struct {
name string
address string
err error
wantErr error
wantResult string
}{
{
name: "receive an error",
returnedErr: fmt.Errorf("error"),
wantErr: fmt.Errorf("failed to get cognitarium address: %w", fmt.Errorf("error")),
wantAddr: "",
name: "valid dataverse client",
address: "addr",
err: nil,
wantErr: nil,
wantResult: "addr",
},
{
name: "dataverse client return error",
address: "",
err: fmt.Errorf("error"),
wantErr: fmt.Errorf("error"),
wantResult: "",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
Convey("Given a mocked dataverse client", t, func() {
controller := gomock.NewController(t)
defer controller.Finish()

mockClient := testutil.NewMockDataverseQueryClient(controller)
mockClient.EXPECT().
Dataverse(gomock.Any(), gomock.Any()).
Return(
&schema.DataverseResponse{
TriplestoreAddress: schema.Addr(test.wantAddr),
},
test.returnedErr,
).
Times(1)
mockDataverse := testutil.NewMockDataverseQueryClient(controller)
if test.err != nil {
mockDataverse.EXPECT().
Dataverse(gomock.Any(), gomock.Any()).
Return(nil, test.err).
Times(1)
} else {
mockDataverse.EXPECT().
Dataverse(gomock.Any(), gomock.Any()).
Return(&dvschema.DataverseResponse{TriplestoreAddress: dvschema.Addr(test.address)}, nil).
Times(1)
}

Convey("When Client is created", func() {
client, err := dataverse.NewDataverseClient(context.Background(), mockClient)
Convey("When getCognitariumAddr is called", func() {
addr, err := dataverse.GetCognitariumAddr(context.Background(), mockDataverse)

Convey("Then the client should be created if no error on dataverse client", func() {
So(err, ShouldEqual, test.wantErr)
if test.wantErr == nil {
So(client, ShouldNotBeNil)
Convey("Then should return expected result or error", func() {
if test.err == nil {
So(addr, ShouldEqual, test.wantResult)
So(err, ShouldBeNil)
} else {
So(client, ShouldBeNil)
So(addr, ShouldEqual, "")
So(err, ShouldNotBeNil)
So(err.Error(), ShouldEqual, test.wantErr.Error())
}
})
})
Expand Down
30 changes: 30 additions & 0 deletions dataverse/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dataverse

import "fmt"

type MessageError string

const (
ErrNoResult MessageError = "no result found in binding"
ErrVarNotFound MessageError = "variable not found in binding result"
ErrType MessageError = "variable result type mismatch in binding result"
)

type DVError struct {
message MessageError
detail error
}

func (e *DVError) Error() string {
if e.detail == nil {
return fmt.Sprintf("%v", e.message)
}
return fmt.Sprintf("%v: %v", e.message, e.detail)
}

func NewDVError(message MessageError, detail error) error {
return &DVError{
message: message,
detail: detail,
}
}
18 changes: 18 additions & 0 deletions dataverse/export_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package dataverse

import (
cgschema "github.com/axone-protocol/axone-contract-schema/go/cognitarium-schema/v5"
dvschema "github.com/axone-protocol/axone-contract-schema/go/dataverse-schema/v5"
)

func NewDataverseClient(
dataverseClient dvschema.QueryClient,
cognitariumClient cgschema.QueryClient,
) Client {
return &client{
dataverseClient,
cognitariumClient,
}
}

var GetCognitariumAddr = getCognitariumAddr
34 changes: 34 additions & 0 deletions dataverse/governance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package dataverse

import (
"context"
"fmt"

cgschema "github.com/axone-protocol/axone-contract-schema/go/cognitarium-schema/v5"
)

func (c *client) GetResourceGovAddr(ctx context.Context, resourceDID string) (string, error) {
query := buildGetResourceGovAddrRequest(resourceDID)
response, err := c.cognitariumClient.Select(ctx, &cgschema.QueryMsg_Select{Query: query})
if err != nil {
return "", err
}

if len(response.Results.Bindings) != 1 {
return "", NewDVError(ErrNoResult, nil)
}

codeBinding, ok := response.Results.Bindings[0]["code"]
if !ok {
return "", NewDVError(ErrVarNotFound, nil)
}
code, ok := codeBinding.ValueType.(cgschema.URI)
if !ok {
return "", NewDVError(ErrType, fmt.Errorf("expected URI, got %T", codeBinding.ValueType))
}
return string(*code.Value.Full), nil
}

func (c *client) ExecGov(_ context.Context, _ string, _ string) (interface{}, error) {
panic("not implemented")
}
Loading

0 comments on commit a8caad1

Please sign in to comment.