-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: import initial version of library from optmint
- Loading branch information
Showing
8 changed files
with
346 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package cnc | ||
|
||
import ( | ||
"context" | ||
"encoding/hex" | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/go-resty/resty/v2" | ||
) | ||
|
||
type Client struct { | ||
c *resty.Client | ||
} | ||
|
||
func NewClient(baseURL string, options ...Option) (*Client, error) { | ||
c := &Client{ | ||
c: resty.New(), | ||
} | ||
|
||
c.c.SetBaseURL(baseURL) | ||
|
||
for _, option := range options { | ||
if err := option(c); err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
return c, nil | ||
} | ||
|
||
func (c *Client) Header(ctx context.Context, height uint64) /* Header */ error { | ||
_ = headerPath() | ||
return errors.New("method Header not implemented") | ||
} | ||
|
||
func (c *Client) Balance(ctx context.Context) error { | ||
_ = balanceEndpoint | ||
return errors.New("method Balance not implemented") | ||
} | ||
|
||
func (c *Client) SubmitTx(ctx context.Context, tx []byte) /* TxResponse */ error { | ||
_ = submitTxEndpoint | ||
return errors.New("method SubmitTx not implemented") | ||
} | ||
|
||
func (c *Client) SubmitPFD(ctx context.Context, namespaceID [8]byte, data []byte, gasLimit uint64) (*TxResponse, error) { | ||
req := SubmitPFDRequest{ | ||
NamespaceID: hex.EncodeToString(namespaceID[:]), | ||
Data: hex.EncodeToString(data), | ||
GasLimit: gasLimit, | ||
} | ||
var res TxResponse | ||
var rpcErr string | ||
_, err := c.c.R(). | ||
SetContext(ctx). | ||
SetBody(req). | ||
SetResult(&res). | ||
SetError(&rpcErr). | ||
Post(submitPFDEndpoint) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if rpcErr != "" { | ||
return nil, errors.New(rpcErr) | ||
} | ||
return &res, nil | ||
} | ||
|
||
func (c *Client) NamespacedShares(ctx context.Context, namespaceID [8]byte, height uint64) ([][]byte, error) { | ||
var res struct { | ||
Shares [][]byte `json:"shares"` | ||
Height uint64 `json:"height"` | ||
} | ||
|
||
err := c.callNamespacedEndpoint(ctx, namespaceID, height, namespacedSharesEndpoint, &res) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return res.Shares, nil | ||
} | ||
|
||
func (c *Client) NamespacedData(ctx context.Context, namespaceID [8]byte, height uint64) ([][]byte, error) { | ||
var res struct { | ||
Data [][]byte `json:"data"` | ||
Height uint64 `json:"height"` | ||
} | ||
|
||
err := c.callNamespacedEndpoint(ctx, namespaceID, height, namespacedDataEndpoint, &res) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return res.Data, nil | ||
} | ||
|
||
// callNamespacedEndpoint fetches result of /namespaced_{type} family of endpoints into result (this should be pointer!) | ||
func (c *Client) callNamespacedEndpoint(ctx context.Context, namespaceID [8]byte, height uint64, endpoint string, result interface{}) error { | ||
var rpcErr string | ||
_, err := c.c.R(). | ||
SetContext(ctx). | ||
SetResult(result). | ||
SetError(&rpcErr). | ||
Get(namespacedPath(endpoint, namespaceID, height)) | ||
if err != nil { | ||
return err | ||
} | ||
if rpcErr != "" { | ||
return errors.New(rpcErr) | ||
} | ||
return nil | ||
} | ||
|
||
func headerPath() string { | ||
return fmt.Sprintf("%s/%s", headerEndpoint, heightKey) | ||
} | ||
|
||
func namespacedPath(endpoint string, namespaceID [8]byte, height uint64) string { | ||
return fmt.Sprintf("%s/%s/height/%d", endpoint, hex.EncodeToString(namespaceID[:]), height) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package cnc | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestNewClient(t *testing.T) { | ||
cases := []struct { | ||
name string | ||
options []Option | ||
expectedError error | ||
}{ | ||
{"without options", nil, nil}, | ||
{"with timeout", []Option{WithTimeout(1 * time.Second)}, nil}, | ||
} | ||
|
||
for _, c := range cases { | ||
t.Run(c.name, func(t *testing.T) { | ||
client, err := NewClient("", c.options...) | ||
assert.ErrorIs(t, err, c.expectedError) | ||
if c.expectedError != nil { | ||
assert.Nil(t, client) | ||
} else { | ||
assert.NotNil(t, client) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestNamespacedShares(t *testing.T) { | ||
t.Skip() | ||
client, err := NewClient("http://localhost:26658") | ||
assert.NoError(t, err) | ||
assert.NotNil(t, client) | ||
|
||
shares, err := client.NamespacedShares(context.TODO(), [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, 8) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, shares) | ||
assert.Len(t, shares, 4) | ||
} | ||
|
||
func TestSubmitPDF(t *testing.T) { | ||
t.Skip() | ||
client, err := NewClient("http://localhost:26658", WithTimeout(30*time.Second)) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, client) | ||
|
||
txRes, err := client.SubmitPFD(context.TODO(), [8]byte{1, 2, 3, 4, 5, 6, 7, 8}, []byte("random data"), 100000) | ||
assert.NoError(t, err) | ||
assert.NotNil(t, txRes) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package cnc | ||
|
||
const ( | ||
headerEndpoint = "/header" | ||
balanceEndpoint = "/balance" | ||
submitTxEndpoint = "/submit_tx" | ||
submitPFDEndpoint = "/submit_pfd" | ||
namespacedSharesEndpoint = "/namespaced_shares" | ||
namespacedDataEndpoint = "/namespaced_data" | ||
|
||
heightKey = "height" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// Package cnrc implements a Celestia Node REST Client | ||
package cnc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module github.com/celestiaorg/go-cnc | ||
|
||
go 1.17 | ||
|
||
require ( | ||
github.com/go-resty/resty/v2 v2.7.0 | ||
github.com/gogo/protobuf v1.3.2 | ||
github.com/stretchr/testify v1.7.1 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.0 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= | ||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= | ||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= | ||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= | ||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= | ||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= | ||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM= | ||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | ||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package cnc | ||
|
||
import "time" | ||
|
||
type Option func(*Client) error | ||
|
||
func WithTimeout(timeout time.Duration) Option { | ||
return func(c *Client) error { | ||
c.c.SetTimeout(timeout) | ||
return nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package cnc | ||
|
||
import "github.com/gogo/protobuf/types" | ||
|
||
// SubmitPFDRequest represents a request to submit a PayForData transaction. | ||
type SubmitPFDRequest struct { | ||
NamespaceID string `json:"namespace_id"` | ||
Data string `json:"data"` | ||
GasLimit uint64 `json:"gas_limit"` | ||
} | ||
|
||
// Types below are copied from celestia-node (or cosmos-sdk dependency of celestia node, to be precise) | ||
// They are needed for proper deserialization. | ||
// It's probably far from the best approach to those types, but it's simple and works. | ||
// Some alternatives: | ||
// 1. Generate types from protobuf definitions (and automate updating of protobuf files) | ||
// 2. Extract common dependency that defines all types used in RPC. | ||
|
||
// TxResponse defines a structure containing relevant tx data and metadata. The | ||
// tags are stringified and the log is JSON decoded. | ||
type TxResponse struct { | ||
// The block height | ||
Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` | ||
// The transaction hash. | ||
TxHash string `protobuf:"bytes,2,opt,name=txhash,proto3" json:"txhash,omitempty"` | ||
// Namespace for the Code | ||
Codespace string `protobuf:"bytes,3,opt,name=codespace,proto3" json:"codespace,omitempty"` | ||
// Response code. | ||
Code uint32 `protobuf:"varint,4,opt,name=code,proto3" json:"code,omitempty"` | ||
// Result bytes, if any. | ||
Data string `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` | ||
// The output of the application's logger (raw string). May be | ||
// non-deterministic. | ||
RawLog string `protobuf:"bytes,6,opt,name=raw_log,json=rawLog,proto3" json:"raw_log,omitempty"` | ||
// The output of the application's logger (typed). May be non-deterministic. | ||
Logs ABCIMessageLogs `protobuf:"bytes,7,rep,name=logs,proto3,castrepeated=ABCIMessageLogs" json:"logs"` | ||
// Additional information. May be non-deterministic. | ||
Info string `protobuf:"bytes,8,opt,name=info,proto3" json:"info,omitempty"` | ||
// Amount of gas requested for transaction. | ||
GasWanted int64 `protobuf:"varint,9,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"` | ||
// Amount of gas consumed by transaction. | ||
GasUsed int64 `protobuf:"varint,10,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` | ||
// The request transaction bytes. | ||
Tx *types.Any `protobuf:"bytes,11,opt,name=tx,proto3" json:"tx,omitempty"` | ||
// Time of the previous block. For heights > 1, it's the weighted median of | ||
// the timestamps of the valid votes in the block.LastCommit. For height == 1, | ||
// it's genesis time. | ||
Timestamp string `protobuf:"bytes,12,opt,name=timestamp,proto3" json:"timestamp,omitempty"` | ||
} | ||
|
||
// ABCIMessageLogs represents a slice of ABCIMessageLog. | ||
type ABCIMessageLogs []ABCIMessageLog | ||
|
||
// ABCIMessageLog defines a structure containing an indexed tx ABCI message log. | ||
type ABCIMessageLog struct { | ||
MsgIndex uint32 `protobuf:"varint,1,opt,name=msg_index,json=msgIndex,proto3" json:"msg_index,omitempty"` | ||
Log string `protobuf:"bytes,2,opt,name=log,proto3" json:"log,omitempty"` | ||
// Events contains a slice of Event objects that were emitted during some | ||
// execution. | ||
Events StringEvents `protobuf:"bytes,3,rep,name=events,proto3,castrepeated=StringEvents" json:"events"` | ||
} | ||
|
||
// StringAttributes defines a slice of StringEvents objects. | ||
type StringEvents []StringEvent | ||
|
||
// StringEvent defines en Event object wrapper where all the attributes | ||
// contain key/value pairs that are strings instead of raw bytes. | ||
type StringEvent struct { | ||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` | ||
Attributes []Attribute `protobuf:"bytes,2,rep,name=attributes,proto3" json:"attributes"` | ||
} | ||
|
||
// Attribute defines an attribute wrapper where the key and value are | ||
// strings instead of raw bytes. | ||
type Attribute struct { | ||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` | ||
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` | ||
} |