From fef04db42cf92c3cb33f54eb86a0348d4fd7511f Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Fri, 11 Mar 2022 04:57:29 +0200 Subject: [PATCH 01/10] docs(markdown): fix readme toc Signed-off-by: Marko Kungla --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 44fac06..a88c4f2 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ import ( - [Revert](#revert) - [Type](#type) - [Scope](#scope) -- [| **markdown** | Markdown files |](#-markdown--markdown-files-) - [Subject](#subject) - [Body](#body) - [Footer](#footer) @@ -429,6 +428,7 @@ Samples: ``` docs(markdown): update readme examples + ``` ``` @@ -482,6 +482,7 @@ The following is the list of supported scopes: | **endpoint** | Changes related to api endpoints | | **godoc** | Go documentation | | **markdown** | Markdown files | + --- #### Subject From c6b8dd2f8378bc6696cb37188608a0a980f548c6 Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 16:37:14 +0200 Subject: [PATCH 02/10] feat(client): enhance rate limiter Use golang.org/x/time/rate for client rate limiter closes #2 Signed-off-by: Marko Kungla --- client.go | 12 ++---------- go.mod | 1 + go.sum | 2 ++ koios.go | 37 +++++++++++++++++++++---------------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/client.go b/client.go index 0bc93f2..6f08d65 100644 --- a/client.go +++ b/client.go @@ -105,21 +105,13 @@ func (c *Client) request( c.mux.RUnlock() - // optain lock to update last ts and total - // request count. Lock will block if another request is already queued. - // e.g. in other go routine. - c.mux.Lock() - // handle rate limit - for !c.lastRequest.IsZero() && time.Since(c.lastRequest) < c.reqInterval { + if err := c.r.Wait(ctx); err != nil { + return nil, err } - c.lastRequest = time.Now() c.totalReq++ - // Release client so that other requests can use it. - c.mux.Unlock() - req, err := http.NewRequestWithContext(ctx, strings.ToUpper(method), requrl, body) if err != nil { if res != nil { diff --git a/go.mod b/go.mod index a1a249f..4d83584 100644 --- a/go.mod +++ b/go.mod @@ -6,4 +6,5 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.7.0 golang.org/x/text v0.3.7 + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 ) diff --git a/go.sum b/go.sum index be53028..10b2d94 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs= +golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= diff --git a/koios.go b/koios.go index 0b7762e..a6ff9b2 100644 --- a/koios.go +++ b/koios.go @@ -38,6 +38,7 @@ import ( "github.com/shopspring/decimal" "golang.org/x/text/cases" "golang.org/x/text/language" + "golang.org/x/time/rate" ) // MainnetHost : is primay and default api host. @@ -57,7 +58,7 @@ const ( DefaultPort uint16 = 443 DefaultSchema = "https" LibraryVersion = "v0" - DefaultRateLimit uint8 = 5 + DefaultRateLimit int = 5 DefaultOrigin = "https://github.com/cardano-community/koios-go-client" ) @@ -78,17 +79,17 @@ var ( type ( // Client is api client instance. Client struct { - mux sync.RWMutex - host string - version string - port uint16 - schema string - origin string - url *url.URL - client *http.Client - commonHeaders http.Header - reqInterval time.Duration - lastRequest time.Time + r *rate.Limiter + mux sync.RWMutex + host string + version string + port uint16 + schema string + origin string + url *url.URL + client *http.Client + commonHeaders http.Header + totalReq uint64 reqStatsEnabled bool } @@ -281,6 +282,12 @@ func New(opts ...Option) (*Client, error) { } } + if c.r == nil { + if err := RateLimit(DefaultRateLimit)(c); err != nil { + return nil, err + } + } + // Sets default origin if option was not provided. _ = Origin(DefaultOrigin)(c) @@ -366,14 +373,12 @@ func HTTPClient(client *http.Client) Option { // RateLimit sets requests per second this client is allowed to create // and effectievely rate limits outgoing requests. // Let's respect usage of the community provided resources. -func RateLimit(reqps uint8) Option { +func RateLimit(reqps int) Option { return func(c *Client) error { if reqps == 0 { return ErrRateLimitRange } - c.mux.Lock() - defer c.mux.Unlock() - c.reqInterval = time.Second / time.Duration(reqps) + c.r = rate.NewLimiter(rate.Every(time.Second), reqps) return nil } } From bd0276a132edf64a75f1f3c4ffcd87d36c317885 Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 16:53:57 +0200 Subject: [PATCH 03/10] feat: deprecate TotalRequests Remove TotalRequests since there is no practical need for it at this point. We may consider to add it back if there would be requirement for it. e.g. if client would have time base total request limit req/p day etc. closes #3 Signed-off-by: Marko Kungla --- client.go | 9 --------- koios.go | 7 +++---- koios_test.go | 3 --- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/client.go b/client.go index 6f08d65..2007331 100644 --- a/client.go +++ b/client.go @@ -73,13 +73,6 @@ func (c *Client) BaseURL() string { return c.url.String() } -// TotalRequests retruns number of total requests made by API client. -func (c *Client) TotalRequests() uint64 { - c.mux.RLock() - defer c.mux.RUnlock() - return c.totalReq -} - func (c *Client) request( ctx context.Context, res *Response, @@ -110,8 +103,6 @@ func (c *Client) request( return nil, err } - c.totalReq++ - req, err := http.NewRequestWithContext(ctx, strings.ToUpper(method), requrl, body) if err != nil { if res != nil { diff --git a/koios.go b/koios.go index a6ff9b2..4d2af56 100644 --- a/koios.go +++ b/koios.go @@ -79,7 +79,9 @@ var ( type ( // Client is api client instance. Client struct { - r *rate.Limiter + r *rate.Limiter + reqStatsEnabled bool + mux sync.RWMutex host string version string @@ -89,9 +91,6 @@ type ( url *url.URL client *http.Client commonHeaders http.Header - - totalReq uint64 - reqStatsEnabled bool } // Option is callback function which can be implemented diff --git a/koios_test.go b/koios_test.go index afcd606..e0d7796 100644 --- a/koios_test.go +++ b/koios_test.go @@ -29,8 +29,6 @@ func TestNewDefaults(t *testing.T) { api, err := New() assert.NoError(t, err) if assert.NotNil(t, api) { - assert.Equal(t, uint64(0), api.TotalRequests(), "total requests should be 0 by default") - raw := fmt.Sprintf( "%s://%s/api/%s/", DefaultSchema, @@ -55,7 +53,6 @@ func TestOptions(t *testing.T) { ) assert.NoError(t, err) if assert.NotNil(t, api) { - assert.Equal(t, uint64(0), api.TotalRequests(), "total requests should be 0 by default") assert.Equal(t, "http://localhost:8080/api/v1/", api.BaseURL(), "invalid default base url") } } From 0d6518af423aa12d77c33060818a00faac2ae78c Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 17:09:40 +0200 Subject: [PATCH 04/10] feat: secure way how options applied closes: #7 Signed-off-by: Marko Kungla --- enpoint_test.go | 1 - koios.go | 142 ++++++++++++++++++++++++------------------------ koios_test.go | 6 +- 3 files changed, 75 insertions(+), 74 deletions(-) diff --git a/enpoint_test.go b/enpoint_test.go index 3a45a93..659839b 100644 --- a/enpoint_test.go +++ b/enpoint_test.go @@ -86,7 +86,6 @@ func Test404s(t *testing.T) { assert.Equal(t, http.StatusNotFound, res.StatusCode) // errors with stats should be same - koios.CollectRequestsStats(true)(api) res2, err := api.GetGenesis(context.TODO()) assert.Error(t, err) assert.Nil(t, res2.Data) diff --git a/koios.go b/koios.go index 4d2af56..22208cc 100644 --- a/koios.go +++ b/koios.go @@ -93,9 +93,11 @@ type ( commonHeaders http.Header } - // Option is callback function which can be implemented - // to change configurations options of API Client. - Option func(*Client) error + // Option is callback function to apply + // configurations options of API Client. + Option struct { + apply func(*Client) error + } // Address defines type for _address. Address string @@ -257,7 +259,7 @@ func New(opts ...Option) (*Client, error) { // set default base url _ = c.updateBaseURL() // set default rate limit for outgoing requests. - _ = RateLimit(DefaultRateLimit)(c) + _ = RateLimit(DefaultRateLimit).apply(c) // set default common headers c.commonHeaders.Set("Accept", "application/json") @@ -275,26 +277,26 @@ func New(opts ...Option) (*Client, error) { ) // Apply provided options - for _, setOpt := range opts { - if err := setOpt(c); err != nil { + for _, opt := range opts { + if err := opt.apply(c); err != nil { return nil, err } } if c.r == nil { - if err := RateLimit(DefaultRateLimit)(c); err != nil { + if err := RateLimit(DefaultRateLimit).apply(c); err != nil { return nil, err } } // Sets default origin if option was not provided. - _ = Origin(DefaultOrigin)(c) + _ = Origin(DefaultOrigin).apply(c) // If HttpClient option was not provided // use default http.Client if c.client == nil { // there is really no point to check that error - _ = HTTPClient(nil)(c) + _ = HTTPClient(nil).apply(c) } return c, nil @@ -303,69 +305,68 @@ func New(opts ...Option) (*Client, error) { // Host returns option apply func which can be used to change the // baseurl hostname https:///api/v0/ func Host(host string) Option { - return func(c *Client) error { - c.mux.Lock() - c.host = host - c.mux.Unlock() - return c.updateBaseURL() + return Option{ + apply: func(c *Client) error { + c.host = host + return c.updateBaseURL() + }, } } -// APIVersion returns option apply func which can be used to change the +// APIVersion returns option to apply change of the // baseurl api version https://api.koios.rest/api// func APIVersion(version string) Option { - return func(c *Client) error { - c.mux.Lock() - c.version = version - c.mux.Unlock() - return c.updateBaseURL() + return Option{ + apply: func(c *Client) error { + c.version = version + return c.updateBaseURL() + }, } } // Port returns option apply func which can be used to change the // baseurl port https://api.koios.rest:/api/v0/ func Port(port uint16) Option { - return func(c *Client) error { - c.mux.Lock() - c.port = port - c.mux.Unlock() - return c.updateBaseURL() + return Option{ + apply: func(c *Client) error { + c.port = port + return c.updateBaseURL() + }, } } // Schema returns option apply func which can be used to change the // baseurl schema ://api.koios.rest/api/v0/. func Schema(schema string) Option { - return func(c *Client) error { - c.mux.Lock() - c.schema = schema - c.mux.Unlock() - return c.updateBaseURL() + return Option{ + apply: func(c *Client) error { + c.schema = schema + return c.updateBaseURL() + }, } } // HTTPClient enables to set htt.Client to be used for requests. -// http.Client can only be set once. func HTTPClient(client *http.Client) Option { - return func(c *Client) error { - if c.client != nil { - return ErrHTTPClientChange - } - c.mux.Lock() - defer c.mux.Unlock() - if client == nil { - client = &http.Client{ - Timeout: time.Second * 60, + return Option{ + apply: func(c *Client) error { + if c.client != nil { + return ErrHTTPClientChange } - } - if client.Timeout == 0 { - return ErrHTTPClientTimeoutSetting - } - c.client = client - if c.client.Transport == nil { - c.client.Transport = http.DefaultTransport - } - return nil + if client == nil { + client = &http.Client{ + Timeout: time.Second * 60, + } + } + if client.Timeout == 0 { + return ErrHTTPClientTimeoutSetting + } + c.client = client + if c.client.Transport == nil { + c.client.Transport = http.DefaultTransport + } + return nil + }, } } @@ -373,12 +374,14 @@ func HTTPClient(client *http.Client) Option { // and effectievely rate limits outgoing requests. // Let's respect usage of the community provided resources. func RateLimit(reqps int) Option { - return func(c *Client) error { - if reqps == 0 { - return ErrRateLimitRange - } - c.r = rate.NewLimiter(rate.Every(time.Second), reqps) - return nil + return Option{ + apply: func(c *Client) error { + if reqps == 0 { + return ErrRateLimitRange + } + c.r = rate.NewLimiter(rate.Every(time.Second), reqps) + return nil + }, } } @@ -392,27 +395,26 @@ func RateLimit(reqps int) Option { // It's not required, but considered as good practice so that Cardano Community // can provide HA services for Cardano ecosystem. func Origin(origin string) Option { - return func(c *Client) error { - u, err := url.ParseRequestURI(origin) - if err != nil { - return err - } - - c.mux.Lock() - defer c.mux.Unlock() - c.origin = u.String() - return nil + return Option{ + apply: func(c *Client) error { + u, err := url.ParseRequestURI(origin) + if err != nil { + return err + } + c.origin = u.String() + return nil + }, } } // CollectRequestsStats when enabled uses httptrace is used // to collect detailed timing information about the request. func CollectRequestsStats(enabled bool) Option { - return func(c *Client) error { - c.mux.Lock() - defer c.mux.Unlock() - c.reqStatsEnabled = enabled - return nil + return Option{ + apply: func(c *Client) error { + c.reqStatsEnabled = enabled + return nil + }, } } diff --git a/koios_test.go b/koios_test.go index e0d7796..b4c1ab9 100644 --- a/koios_test.go +++ b/koios_test.go @@ -59,11 +59,11 @@ func TestOptions(t *testing.T) { func TestOptionErrs(t *testing.T) { client, _ := New() - assert.Error(t, HTTPClient(http.DefaultClient)(client), + assert.Error(t, HTTPClient(http.DefaultClient).apply(client), "should not allow changing http client.") - assert.Error(t, RateLimit(0)(client), + assert.Error(t, RateLimit(0).apply(client), "should not unlimited requests p/s") - assert.Error(t, Origin("localhost")(client), + assert.Error(t, Origin("localhost").apply(client), "origin should be valid http origin") _, err := New(Origin("localhost.localdomain")) assert.Error(t, err, "New should return err when option is invalid") From f09aa1f2c3539b66286c5e010dd1072a9373355f Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 17:17:10 +0200 Subject: [PATCH 05/10] feat: remove client mutexes We do not need to lock client anymore since client with changed options would become light copy of the initial client created. closes #5 Signed-off-by: Marko Kungla --- client.go | 8 +------- koios.go | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/client.go b/client.go index 2007331..7772fbd 100644 --- a/client.go +++ b/client.go @@ -68,8 +68,6 @@ func (c *Client) GET( // BaseURL returns currently used base url e.g. https://api.koios.rest/api/v0 func (c *Client) BaseURL() string { - c.mux.RLock() - defer c.mux.RUnlock() return c.url.String() } @@ -86,7 +84,7 @@ func (c *Client) request( ) path = strings.TrimLeft(path, "/") - c.mux.RLock() + if query == nil { requrl = c.url.ResolveReference(&url.URL{Path: path}).String() } else { @@ -96,8 +94,6 @@ func (c *Client) request( res.RequestURL = requrl } - c.mux.RUnlock() - // handle rate limit if err := c.r.Wait(ctx); err != nil { return nil, err @@ -211,8 +207,6 @@ func (c *Client) requestWithStats(req *http.Request, res *Response) (*http.Respo } func (c *Client) updateBaseURL() error { - c.mux.Lock() - defer c.mux.Unlock() raw := fmt.Sprintf("%s://%s", c.schema, c.host) if c.port != 80 && c.port != 443 { raw = fmt.Sprintf("%s:%d", raw, c.port) diff --git a/koios.go b/koios.go index 22208cc..051e6a2 100644 --- a/koios.go +++ b/koios.go @@ -32,7 +32,6 @@ import ( "net/url" "runtime" "strings" - "sync" "time" "github.com/shopspring/decimal" @@ -82,7 +81,6 @@ type ( r *rate.Limiter reqStatsEnabled bool - mux sync.RWMutex host string version string port uint16 From ed7271500b9859db5db0c010bf47eb2906607cd3 Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 18:22:50 +0200 Subject: [PATCH 06/10] feat: reduce Client fields in favor of url.URL We can modify url.URL pointer instead of having reference fields on Client it self. closes #6 Signed-off-by: Marko Kungla --- client.go | 11 ++++++----- koios.go | 47 ++++++++++++++++++++++++----------------------- koios_test.go | 4 ++-- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/client.go b/client.go index 7772fbd..2dc1e16 100644 --- a/client.go +++ b/client.go @@ -90,6 +90,7 @@ func (c *Client) request( } else { requrl = c.url.ResolveReference(&url.URL{Path: path, RawQuery: query.Encode()}).String() } + if res != nil { res.RequestURL = requrl } @@ -206,12 +207,12 @@ func (c *Client) requestWithStats(req *http.Request, res *Response) (*http.Respo return rsp, nil } -func (c *Client) updateBaseURL() error { - raw := fmt.Sprintf("%s://%s", c.schema, c.host) - if c.port != 80 && c.port != 443 { - raw = fmt.Sprintf("%s:%d", raw, c.port) +func (c *Client) setBaseURL(schema, host, version string, port uint16) error { + raw := fmt.Sprintf("%s://%s", schema, host) + if port != 80 && port != 443 { + raw = fmt.Sprintf("%s:%d", raw, port) } - raw += "/api/" + c.version + "/" + raw += "/api/" + version + "/" u, err := url.ParseRequestURI(raw) if err != nil { return err diff --git a/koios.go b/koios.go index 051e6a2..b39c485 100644 --- a/koios.go +++ b/koios.go @@ -55,7 +55,7 @@ const ( TestnetHost = "testnet.koios.rest" DefaultAPIVersion = "v0" DefaultPort uint16 = 443 - DefaultSchema = "https" + DefaultScheme = "https" LibraryVersion = "v0" DefaultRateLimit int = 5 DefaultOrigin = "https://github.com/cardano-community/koios-go-client" @@ -73,6 +73,7 @@ var ( ErrNoAddress = errors.New("missing address") ErrNoPoolID = errors.New("missing pool id") ErrResponse = errors.New("got unexpected response") + ErrScheme = errors.New("scheme must be http or https") ) type ( @@ -80,14 +81,10 @@ type ( Client struct { r *rate.Limiter reqStatsEnabled bool + url *url.URL + client *http.Client - host string - version string - port uint16 - schema string origin string - url *url.URL - client *http.Client commonHeaders http.Header } @@ -248,14 +245,11 @@ type ( // ). func New(opts ...Option) (*Client, error) { c := &Client{ - host: MainnetHost, - version: DefaultAPIVersion, - port: DefaultPort, - schema: DefaultSchema, commonHeaders: make(http.Header), } // set default base url - _ = c.updateBaseURL() + _ = c.setBaseURL(DefaultScheme, MainnetHost, DefaultAPIVersion, DefaultPort) + // set default rate limit for outgoing requests. _ = RateLimit(DefaultRateLimit).apply(c) @@ -305,8 +299,8 @@ func New(opts ...Option) (*Client, error) { func Host(host string) Option { return Option{ apply: func(c *Client) error { - c.host = host - return c.updateBaseURL() + c.url.Host = fmt.Sprint(host, ":", c.url.Port()) + return nil }, } } @@ -316,8 +310,12 @@ func Host(host string) Option { func APIVersion(version string) Option { return Option{ apply: func(c *Client) error { - c.version = version - return c.updateBaseURL() + url, err := c.url.Parse("/api/" + version + "/") + if err != nil { + return err + } + c.url = url + return nil }, } } @@ -327,19 +325,22 @@ func APIVersion(version string) Option { func Port(port uint16) Option { return Option{ apply: func(c *Client) error { - c.port = port - return c.updateBaseURL() + c.url.Host = fmt.Sprint(c.url.Hostname(), ":", port) + return nil }, } } -// Schema returns option apply func which can be used to change the -// baseurl schema ://api.koios.rest/api/v0/. -func Schema(schema string) Option { +// Scheme returns option apply func which can be used to change the +// baseurl scheme ://api.koios.rest/api/v0/. +func Scheme(scheme string) Option { return Option{ apply: func(c *Client) error { - c.schema = schema - return c.updateBaseURL() + c.url.Scheme = scheme + if scheme != "http" && scheme != "https" { + return ErrScheme + } + return nil }, } } diff --git a/koios_test.go b/koios_test.go index b4c1ab9..38b5a74 100644 --- a/koios_test.go +++ b/koios_test.go @@ -31,7 +31,7 @@ func TestNewDefaults(t *testing.T) { if assert.NotNil(t, api) { raw := fmt.Sprintf( "%s://%s/api/%s/", - DefaultSchema, + DefaultScheme, MainnetHost, DefaultAPIVersion, ) @@ -46,7 +46,7 @@ func TestOptions(t *testing.T) { Host("localhost"), APIVersion("v1"), Port(8080), - Schema("http"), + Scheme("http"), RateLimit(100), Origin("http://localhost.localdomain"), CollectRequestsStats(true), From abc2a03b9587d5f1cb3412cf6f643a3f0baef1c7 Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 18:32:07 +0200 Subject: [PATCH 07/10] fix: apply origin header Signed-off-by: Marko Kungla --- koios.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/koios.go b/koios.go index b39c485..65071ad 100644 --- a/koios.go +++ b/koios.go @@ -83,9 +83,7 @@ type ( reqStatsEnabled bool url *url.URL client *http.Client - - origin string - commonHeaders http.Header + commonHeaders http.Header } // Option is callback function to apply @@ -396,11 +394,11 @@ func RateLimit(reqps int) Option { func Origin(origin string) Option { return Option{ apply: func(c *Client) error { - u, err := url.ParseRequestURI(origin) + o, err := url.ParseRequestURI(origin) if err != nil { return err } - c.origin = u.String() + c.commonHeaders.Set("Origin", o.String()) return nil }, } From 25c8196067a7e7ebfdf70acb90127bfd3d2e95be Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 19:56:57 +0200 Subject: [PATCH 08/10] feat: add Client WithOptions WithOptions returns new light clone of client with modified options applied. closes #4 Signed-off-by: Marko Kungla --- client.go | 18 +++++++++ koios.go | 26 +++++++++++-- network.go | 39 +++++++++---------- transaction.go | 102 ++++++++++++++++++++++++++----------------------- 4 files changed, 113 insertions(+), 72 deletions(-) diff --git a/client.go b/client.go index 2dc1e16..7a241c8 100644 --- a/client.go +++ b/client.go @@ -28,6 +28,24 @@ import ( "time" ) +// WithOptions returns new light clone of client with modified options applied. +func (c *Client) WithOptions(opts ...Option) (*Client, error) { + nc := &Client{ + r: c.r, + reqStatsEnabled: c.reqStatsEnabled, + url: c.url, + client: c.client, + commonHeaders: c.commonHeaders.Clone(), + } + // Apply provided options + for _, opt := range opts { + if err := opt.apply(c); err != nil { + return nil, err + } + } + return nc, nil +} + // HEAD sends api http HEAD request to provided relative path with query params // and returns an HTTP response. func (c *Client) HEAD( diff --git a/koios.go b/koios.go index 65071ad..6ae48b2 100644 --- a/koios.go +++ b/koios.go @@ -297,7 +297,11 @@ func New(opts ...Option) (*Client, error) { func Host(host string) Option { return Option{ apply: func(c *Client) error { - c.url.Host = fmt.Sprint(host, ":", c.url.Port()) + if c.url.Port() == "" || c.url.Port() == "80" || c.url.Port() == "443" { + c.url.Host = host + } else { + c.url.Host = fmt.Sprint(host, ":", c.url.Port()) + } return nil }, } @@ -436,6 +440,11 @@ func readAndUnmarshalResponse(rsp *http.Response, res *Response, dest interface{ res.applyError(body, err) return err } + if len(body) == 0 { + return nil + } + + defer res.ready() if err = json.Unmarshal(body, dest); err != nil { res.applyError(body, err) return err @@ -445,11 +454,20 @@ func readAndUnmarshalResponse(rsp *http.Response, res *Response, dest interface{ func (r *Response) applyError(body []byte, err error) { r.Error = &ResponseError{} - _ = json.Unmarshal(body, r.Error) - if err != nil && len(r.Error.Message) == 0 { + if len(body) != 0 { + _ = json.Unmarshal(body, r.Error) + } + defer r.ready() + + if err == nil { + return + } + + if len(r.Error.Message) == 0 { r.Error.Message = err.Error() + } else { + r.Error.Message = fmt.Sprintf("%s: %s", err.Error(), r.Error.Message) } - r.ready() } func (r *Response) ready() { diff --git a/network.go b/network.go index 147374d..55552bb 100644 --- a/network.go +++ b/network.go @@ -138,47 +138,44 @@ type ( // GetTip returns the tip info about the latest block seen by chain. func (c *Client) GetTip(ctx context.Context) (res *TipResponse, err error) { res = &TipResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/tip", nil, nil, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/tip", nil, nil, nil) + if err != nil { + return res, err + } tips := []Tip{} err = readAndUnmarshalResponse(rsp, &res.Response, &tips) if len(tips) == 1 { res.Data = &tips[0] } - res.ready() - return + return res, err } // GetGenesis returns the Genesis parameters used to start specific era on chain. -func (c *Client) GetGenesis(ctx context.Context) (res *GenesisResponse, err error) { - res = &GenesisResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/genesis", nil, nil, nil) - +func (c *Client) GetGenesis(ctx context.Context) (*GenesisResponse, error) { + res := &GenesisResponse{} + rsp, err := c.request(ctx, &res.Response, "GET", "/genesis", nil, nil, nil) + if err != nil { + return res, err + } genesisres := []Genesis{} err = readAndUnmarshalResponse(rsp, &res.Response, &genesisres) - if len(genesisres) == 1 { res.Data = &genesisres[0] } - res.ready() - return + return res, err } // GetTotals returns the circulating utxo, treasury, rewards, supply and // reserves in lovelace for specified epoch, all epochs if empty. -func (c *Client) GetTotals(ctx context.Context, epoch *EpochNo) (res *TotalsResponse, err error) { +func (c *Client) GetTotals(ctx context.Context, epoch *EpochNo) (*TotalsResponse, error) { params := url.Values{} if epoch != nil { params.Set("_epoch_no", fmt.Sprint(*epoch)) } - res = &TotalsResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/totals", nil, params, nil) - - totals := []Totals{} - err = readAndUnmarshalResponse(rsp, &res.Response, &totals) - if len(totals) > 0 { - res.Data = totals + res := &TotalsResponse{} + rsp, err := c.request(ctx, &res.Response, "GET", "/totals", nil, params, nil) + if err != nil { + return res, err } - res.ready() - return + return res, readAndUnmarshalResponse(rsp, &res.Response, &res.Data) } diff --git a/transaction.go b/transaction.go index 309a036..c1e5b88 100644 --- a/transaction.go +++ b/transaction.go @@ -259,33 +259,36 @@ func (c *Client) GetTxInfo(ctx context.Context, tx TxHash) (res *TxInfoResponse, } // GetTxsInfos returns detailed information about transaction(s). -func (c *Client) GetTxsInfos(ctx context.Context, txs []TxHash) (res *TxsInfosResponse, err error) { - res = &TxsInfosResponse{} +func (c *Client) GetTxsInfos(ctx context.Context, txs []TxHash) (*TxsInfosResponse, error) { + res := &TxsInfosResponse{} if len(txs) == 0 || len(txs[0]) == 0 { - err = ErrNoTxHash + err := ErrNoTxHash res.applyError(nil, err) - return + return res, err } - rsp, _ := c.request(ctx, &res.Response, "POST", "/tx_info", txHashesPL(txs), nil, nil) - err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() - return + rsp, err := c.request(ctx, &res.Response, "POST", "/tx_info", txHashesPL(txs), nil, nil) + if err != nil { + return res, err + } + return res, readAndUnmarshalResponse(rsp, &res.Response, &res.Data) } // GetTxsUTxOs returns UTxO set (inputs/outputs) of transactions. -func (c *Client) GetTxsUTxOs(ctx context.Context, txs []TxHash) (res *TxUTxOsResponse, err error) { - res = &TxUTxOsResponse{} +func (c *Client) GetTxsUTxOs(ctx context.Context, txs []TxHash) (*TxUTxOsResponse, error) { + res := &TxUTxOsResponse{} if len(txs) == 0 || len(txs[0]) == 0 { - err = ErrNoTxHash + err := ErrNoTxHash res.applyError(nil, err) - return + return res, err } - rsp, _ := c.request(ctx, &res.Response, "POST", "/tx_utxos", txHashesPL(txs), nil, nil) - err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() - return + rsp, err := c.request(ctx, &res.Response, "POST", "/tx_utxos", txHashesPL(txs), nil, nil) + if err != nil { + return res, err + } + + return res, readAndUnmarshalResponse(rsp, &res.Response, &res.Data) } // GetTxMetadata returns metadata information (if any) for given transaction. @@ -300,49 +303,53 @@ func (c *Client) GetTxMetadata(ctx context.Context, tx TxHash) (res *TxMetadataR } // GetTxsMetadata returns metadata for requested transaction(s). -func (c *Client) GetTxsMetadata(ctx context.Context, txs []TxHash) (res *TxsMetadataResponse, err error) { - res = &TxsMetadataResponse{} +func (c *Client) GetTxsMetadata(ctx context.Context, txs []TxHash) (*TxsMetadataResponse, error) { + res := &TxsMetadataResponse{} if len(txs) == 0 { - err = ErrNoTxHash + err := ErrNoTxHash res.applyError(nil, err) - return + return res, err } - rsp, _ := c.request(ctx, &res.Response, "POST", "/tx_metadata", txHashesPL(txs), nil, nil) - err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() - return + rsp, err := c.request(ctx, &res.Response, "POST", "/tx_metadata", txHashesPL(txs), nil, nil) + if err != nil { + return res, err + } + + return res, readAndUnmarshalResponse(rsp, &res.Response, &res.Data) } // GetTxMetaLabels retruns a list of all transaction metalabels. -func (c *Client) GetTxMetaLabels(ctx context.Context) (res *TxMetaLabelsResponse, err error) { - res = &TxMetaLabelsResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/tx_metalabels", nil, nil, nil) - err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() - return +func (c *Client) GetTxMetaLabels(ctx context.Context) (*TxMetaLabelsResponse, error) { + res := &TxMetaLabelsResponse{} + rsp, err := c.request(ctx, &res.Response, "GET", "/tx_metalabels", nil, nil, nil) + if err != nil { + return res, err + } + return res, readAndUnmarshalResponse(rsp, &res.Response, &res.Data) } // SubmitSignedTx Submit an transaction to the network. -func (c *Client) SubmitSignedTx(ctx context.Context, stx TxBodyJSON) (res *SubmitSignedTxResponse, err error) { - var cborb []byte - res = &SubmitSignedTxResponse{} +func (c *Client) SubmitSignedTx(ctx context.Context, stx TxBodyJSON) (*SubmitSignedTxResponse, error) { + res := &SubmitSignedTxResponse{} var method = "POST" - cborb, err = hex.DecodeString(stx.CborHex) + cborb, err := hex.DecodeString(stx.CborHex) if err != nil { res.RequestMethod = method res.StatusCode = 400 - return + res.applyError(nil, err) + return res, err } h := http.Header{} h.Set("Content-Type", "application/cbor") h.Set("Content-Length", fmt.Sprint(len(cborb))) - rsp, _ := c.request(ctx, &res.Response, method, "/submittx", bytes.NewBuffer(cborb), nil, h) - err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() - return + rsp, err := c.request(ctx, &res.Response, method, "/submittx", bytes.NewBuffer(cborb), nil, h) + if err != nil { + return res, err + } + return res, readAndUnmarshalResponse(rsp, &res.Response, &res.Data) } // GetTxStatus returns status of transaction. @@ -357,18 +364,19 @@ func (c *Client) GetTxStatus(ctx context.Context, tx TxHash) (res *TxStatusRespo } // GetTxsStatuses returns status of transaction(s). -func (c *Client) GetTxsStatuses(ctx context.Context, txs []TxHash) (res *TxsStatusesResponse, err error) { - res = &TxsStatusesResponse{} +func (c *Client) GetTxsStatuses(ctx context.Context, txs []TxHash) (*TxsStatusesResponse, error) { + res := &TxsStatusesResponse{} if len(txs) == 0 { - err = ErrNoTxHash + err := ErrNoTxHash res.applyError(nil, err) - return + return res, err } - rsp, _ := c.request(ctx, &res.Response, "POST", "/tx_status", txHashesPL(txs), nil, nil) - err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() - return + rsp, err := c.request(ctx, &res.Response, "POST", "/tx_status", txHashesPL(txs), nil, nil) + if err != nil { + return res, err + } + return res, readAndUnmarshalResponse(rsp, &res.Response, &res.Data) } func txHashesPL(txs []TxHash) io.Reader { From ff3c3738b92428fd17f0ecc837022e454a4a5f17 Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 20:25:28 +0200 Subject: [PATCH 09/10] fix: reduce superfluous ignored err checks closes: #8 Signed-off-by: Marko Kungla --- account.go | 47 +++++++++++++++++++++++++++++------------------ address.go | 40 ++++++++++++++++++++++------------------ asset.go | 32 +++++++++++++++++++++----------- block.go | 20 ++++++++++++-------- client.go | 6 +++++- epoch.go | 12 ++++++++---- pool.go | 42 +++++++++++++++++++++++++++++------------- script.go | 12 ++++++++---- 8 files changed, 134 insertions(+), 77 deletions(-) diff --git a/account.go b/account.go index 62f7008..495e171 100644 --- a/account.go +++ b/account.go @@ -117,7 +117,11 @@ type ( // GetAccountList returns a list of all accounts. func (c *Client) GetAccountList(ctx context.Context) (res *AccountListResponse, err error) { res = &AccountListResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/account_list", nil, nil, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/account_list", nil, nil, nil) + + if err != nil { + return + } accs := []struct { ID StakeAddress `json:"id"` @@ -145,7 +149,10 @@ func (c *Client) GetAccountInfo(ctx context.Context, addr Address) (res *Account params := url.Values{} params.Set("_address", string(addr)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/account_info", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/account_info", nil, params, nil) + if err != nil { + return + } addrs := []AccountInfo{} err = readAndUnmarshalResponse(rsp, &res.Response, &addrs) @@ -153,7 +160,6 @@ func (c *Client) GetAccountInfo(ctx context.Context, addr Address) (res *Account if len(addrs) == 1 { res.Data = &addrs[0] } - res.ready() return } @@ -171,10 +177,11 @@ func (c *Client) GetAccountRewards( params.Set("_epoch_no", fmt.Sprint(*epoch)) } - rsp, _ := c.request(ctx, &res.Response, "GET", "/account_rewards", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/account_rewards", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } @@ -188,10 +195,11 @@ func (c *Client) GetAccountUpdates( params := url.Values{} params.Set("_stake_address", string(addr)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/account_updates", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/account_updates", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } @@ -204,8 +212,10 @@ func (c *Client) GetAccountAddresses( params := url.Values{} params.Set("_address", string(addr)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/account_addresses", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/account_addresses", nil, params, nil) + if err != nil { + return + } addrs := []struct { Addr Address `json:"address"` }{} @@ -217,7 +227,6 @@ func (c *Client) GetAccountAddresses( res.Data = append(res.Data, a.Addr) } } - res.ready() return } @@ -230,10 +239,11 @@ func (c *Client) GetAccountAssets( params := url.Values{} params.Set("_address", string(addr)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/account_assets", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/account_assets", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - - res.ready() return } @@ -246,9 +256,10 @@ func (c *Client) GetAccountHistory( params := url.Values{} params.Set("_address", string(addr)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/account_history", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/account_history", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - - res.ready() return } diff --git a/address.go b/address.go index 84e8ea8..271d3cb 100644 --- a/address.go +++ b/address.go @@ -100,26 +100,27 @@ func (c *Client) GetAddressInfo(ctx context.Context, addr Address) (res *Address params := url.Values{} params.Set("_address", string(addr)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/address_info", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/address_info", nil, params, nil) + if err != nil { + return + } addrs := []AddressInfo{} err = readAndUnmarshalResponse(rsp, &res.Response, &addrs) if len(addrs) == 1 { res.Data = &addrs[0] } - res.ready() return } // GetAddressTxs returns the transaction hash list of input address array, // optionally filtering after specified block height (inclusive). -//nolint: dupl -func (c *Client) GetAddressTxs(ctx context.Context, addrs []Address, h uint64) (res *AddressTxsResponse, err error) { - res = &AddressTxsResponse{} + +func (c *Client) GetAddressTxs(ctx context.Context, addrs []Address, h uint64) (*AddressTxsResponse, error) { + res := &AddressTxsResponse{} if len(addrs) == 0 { - err = ErrNoAddress + err := ErrNoAddress res.applyError(nil, err) - return + return res, err } var payload = struct { @@ -136,8 +137,10 @@ func (c *Client) GetAddressTxs(ctx context.Context, addrs []Address, h uint64) ( defer w.Close() }() - rsp, _ := c.request(ctx, &res.Response, "POST", "/address_txs", rpipe, nil, nil) - + rsp, err := c.request(ctx, &res.Response, "POST", "/address_txs", rpipe, nil, nil) + if err != nil { + return res, err + } atxs := []struct { Hash TxHash `json:"tx_hash"` }{} @@ -149,7 +152,6 @@ func (c *Client) GetAddressTxs(ctx context.Context, addrs []Address, h uint64) ( res.Data = append(res.Data, tx.Hash) } } - res.ready() return res, err } @@ -165,16 +167,17 @@ func (c *Client) GetAddressAssets(ctx context.Context, addr Address) (res *Addre params := url.Values{} params.Set("_address", string(addr)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/address_assets", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/address_assets", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } // GetCredentialTxs returns the transaction hash list of input // payment credential array, optionally filtering after specified block height (inclusive). -//nolint: dupl + func (c *Client) GetCredentialTxs( ctx context.Context, creds []PaymentCredential, @@ -201,8 +204,10 @@ func (c *Client) GetCredentialTxs( defer w.Close() }() - rsp, _ := c.request(ctx, &res.Response, "POST", "/credential_txs", rpipe, nil, nil) - + rsp, err := c.request(ctx, &res.Response, "POST", "/credential_txs", rpipe, nil, nil) + if err != nil { + return + } atxs := []struct { Hash TxHash `json:"tx_hash"` }{} @@ -214,6 +219,5 @@ func (c *Client) GetCredentialTxs( res.Data = append(res.Data, tx.Hash) } } - res.ready() return res, err } diff --git a/asset.go b/asset.go index 2af316f..d926c6b 100644 --- a/asset.go +++ b/asset.go @@ -156,7 +156,10 @@ type ( // GetAssetList returns the list of all native assets (paginated). func (c *Client) GetAssetList(ctx context.Context) (res *AssetListResponse, err error) { res = &AssetListResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/asset_list", nil, nil, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/asset_list", nil, nil, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) return } @@ -173,8 +176,12 @@ func (c *Client) GetAssetAddressList( params.Set("_asset_policy", string(policy)) params.Set("_asset_name", string(name)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/asset_address_list", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/asset_address_list", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) + return } @@ -192,15 +199,16 @@ func (c *Client) GetAssetInfo( params.Set("_asset_policy", string(policy)) params.Set("_asset_name", string(name)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/asset_info", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/asset_info", nil, params, nil) + if err != nil { + return + } info := []AssetInfo{} err = readAndUnmarshalResponse(rsp, &res.Response, &info) if len(info) == 1 { res.Data = &info[0] } - res.ready() return } @@ -219,15 +227,16 @@ func (c *Client) GetAssetSummary( params.Set("_asset_policy", string(policy)) params.Set("_asset_name", string(name)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/asset_summary", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/asset_summary", nil, params, nil) + if err != nil { + return + } summary := []AssetSummary{} err = readAndUnmarshalResponse(rsp, &res.Response, &summary) if len(summary) == 1 { res.Data = &summary[0] } - res.ready() return } @@ -244,14 +253,15 @@ func (c *Client) GetAssetTxs( params.Set("_asset_policy", string(policy)) params.Set("_asset_name", string(name)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/asset_txs", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/asset_txs", nil, params, nil) + if err != nil { + return + } atxs := []AssetTxs{} err = readAndUnmarshalResponse(rsp, &res.Response, &atxs) if len(atxs) == 1 { res.Data = &atxs[0] } - res.ready() return } diff --git a/block.go b/block.go index cb3d775..2040c19 100644 --- a/block.go +++ b/block.go @@ -87,9 +87,11 @@ type ( // GetBlocks returns summarised details about all blocks (paginated - latest first). func (c *Client) GetBlocks(ctx context.Context) (res *BlocksResponse, err error) { res = &BlocksResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/blocks", nil, nil, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/blocks", nil, nil, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } @@ -99,15 +101,16 @@ func (c *Client) GetBlockInfo(ctx context.Context, hash BlockHash) (res *BlockIn params := url.Values{} params.Set("_block_hash", string(hash)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/block_info", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/block_info", nil, params, nil) + if err != nil { + return + } blockpl := []Block{} err = readAndUnmarshalResponse(rsp, &res.Response, &blockpl) if len(blockpl) == 1 { res.Data = &blockpl[0] } - res.ready() return } @@ -118,8 +121,10 @@ func (c *Client) GetBlockTxHashes(ctx context.Context, hash BlockHash) (res *Blo params := url.Values{} params.Set("_block_hash", string(hash)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/block_txs", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/block_txs", nil, params, nil) + if err != nil { + return + } blockTxs := []struct { Hash TxHash `json:"tx_hash"` }{} @@ -130,6 +135,5 @@ func (c *Client) GetBlockTxHashes(ctx context.Context, hash BlockHash) (res *Blo res.Data = append(res.Data, tx.Hash) } } - res.ready() return } diff --git a/client.go b/client.go index 7a241c8..d34eb70 100644 --- a/client.go +++ b/client.go @@ -34,7 +34,6 @@ func (c *Client) WithOptions(opts ...Option) (*Client, error) { r: c.r, reqStatsEnabled: c.reqStatsEnabled, url: c.url, - client: c.client, commonHeaders: c.commonHeaders.Clone(), } // Apply provided options @@ -43,6 +42,11 @@ func (c *Client) WithOptions(opts ...Option) (*Client, error) { return nil, err } } + + if nc.client == nil { + nc.client = c.client + } + return nc, nil } diff --git a/epoch.go b/epoch.go index 69cadd5..d03ecfd 100644 --- a/epoch.go +++ b/epoch.go @@ -173,9 +173,11 @@ func (c *Client) GetEpochInfo(ctx context.Context, epoch *EpochNo) (res *EpochIn params.Set("_epoch_no", fmt.Sprint(*epoch)) } - rsp, _ := c.request(ctx, &res.Response, "GET", "/epoch_info", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/epoch_info", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } @@ -188,8 +190,10 @@ func (c *Client) GetEpochParams(ctx context.Context, epoch *EpochNo) (res *Epoch params.Set("_epoch_no", fmt.Sprint(*epoch)) } - rsp, _ := c.request(ctx, &res.Response, "GET", "/epoch_params", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/epoch_params", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } diff --git a/pool.go b/pool.go index 91df2d5..2a90b17 100644 --- a/pool.go +++ b/pool.go @@ -314,7 +314,10 @@ type ( // GetPoolList returns the list of all currently registered/retiring (not retired) pools. func (c *Client) GetPoolList(ctx context.Context) (res *PoolListResponse, err error) { res = &PoolListResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/pool_list", nil, nil, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/pool_list", nil, nil, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) return } @@ -339,9 +342,11 @@ func (c *Client) GetPoolInfos(ctx context.Context, pids []PoolID) (res *PoolInfo return } - rsp, _ := c.request(ctx, &res.Response, "POST", "/pool_info", poolIdsPL(pids), nil, nil) + rsp, err := c.request(ctx, &res.Response, "POST", "/pool_info", poolIdsPL(pids), nil, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } @@ -359,9 +364,12 @@ func (c *Client) GetPoolDelegators( if epoch != nil { params.Set("_epoch_no", fmt.Sprint(*epoch)) } - rsp, _ := c.request(ctx, &res.Response, "GET", "/pool_delegators", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/pool_delegators", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() + return } @@ -379,9 +387,11 @@ func (c *Client) GetPoolBlocks( if epoch != nil { params.Set("_epoch_no", fmt.Sprint(*epoch)) } - rsp, _ := c.request(ctx, &res.Response, "GET", "/pool_blocks", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/pool_blocks", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } @@ -398,9 +408,11 @@ func (c *Client) GetPoolUpdates( params.Set("_pool_bech32", fmt.Sprint(*pid)) } - rsp, _ := c.request(ctx, &res.Response, "GET", "/pool_updates", nil, params, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/pool_updates", nil, params, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } @@ -409,9 +421,11 @@ func (c *Client) GetPoolUpdates( func (c *Client) GetPoolRelays(ctx context.Context) (res *PoolRelaysResponse, err error) { res = &PoolRelaysResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/pool_relays", nil, nil, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/pool_relays", nil, nil, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } @@ -420,9 +434,11 @@ func (c *Client) GetPoolRelays(ctx context.Context) (res *PoolRelaysResponse, er func (c *Client) GetPoolMetadata(ctx context.Context) (res *PoolMetadataResponse, err error) { res = &PoolMetadataResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/pool_metadata", nil, nil, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/pool_metadata", nil, nil, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) - res.ready() return } diff --git a/script.go b/script.go index 7a3f85d..e377c12 100644 --- a/script.go +++ b/script.go @@ -87,7 +87,10 @@ type ( // hashes along with their creation transaction hashes. func (c *Client) GetScriptList(ctx context.Context) (res *ScriptListResponse, err error) { res = &ScriptListResponse{} - rsp, _ := c.request(ctx, &res.Response, "GET", "/script_list", nil, nil, nil) + rsp, err := c.request(ctx, &res.Response, "GET", "/script_list", nil, nil, nil) + if err != nil { + return + } err = readAndUnmarshalResponse(rsp, &res.Response, &res.Data) return } @@ -102,14 +105,15 @@ func (c *Client) GetScriptRedeemers( params := url.Values{} params.Set("_script_hash", fmt.Sprint(sh)) - rsp, _ := c.request(ctx, &res.Response, "GET", "/script_redeemers", nil, params, nil) - + rsp, err := c.request(ctx, &res.Response, "GET", "/script_redeemers", nil, params, nil) + if err != nil { + return + } r := []ScriptRedeemers{} err = readAndUnmarshalResponse(rsp, &res.Response, &r) if len(r) == 1 { res.Data = &r[0] } - res.ready() return } From e679845bd80476702faa5951747f17c5e126735a Mon Sep 17 00:00:00 2001 From: Marko Kungla Date: Tue, 15 Mar 2022 21:32:59 +0200 Subject: [PATCH 10/10] test: add tests for net errors ref #5 Signed-off-by: Marko Kungla --- enpoint_test.go | 234 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/enpoint_test.go b/enpoint_test.go index 659839b..7eb7f48 100644 --- a/enpoint_test.go +++ b/enpoint_test.go @@ -53,6 +53,11 @@ func TestNetworkTipEndpoint(t *testing.T) { assert.Len(t, expected, 1) assert.Equal(t, &expected[0], res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetTip(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestNetworkGenesiEndpoint(t *testing.T) { @@ -71,6 +76,11 @@ func TestNetworkGenesiEndpoint(t *testing.T) { assert.Len(t, expected, 1) assert.Equal(t, &expected[0], res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetGenesis(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func Test404s(t *testing.T) { @@ -118,6 +128,11 @@ func TestNetworkTotalsEndpoint(t *testing.T) { testHeaders(t, spec, res2.Response) assert.Len(t, expected, 1) assert.Equal(t, expected[0], res2.Data[0]) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetTotals(context.TODO(), nil) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestEpochInfoEndpoint(t *testing.T) { @@ -140,6 +155,11 @@ func TestEpochInfoEndpoint(t *testing.T) { assert.Len(t, expected, 1) assert.Equal(t, expected[0], res.Data[0]) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetEpochInfo(context.TODO(), &epoch) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestEpochParamsEndpoint(t *testing.T) { @@ -162,6 +182,11 @@ func TestEpochParamsEndpoint(t *testing.T) { assert.Len(t, expected, 1) assert.Equal(t, expected[0], res.Data[0]) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetEpochParams(context.TODO(), &epoch) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestAccountListEndpoint(t *testing.T) { @@ -183,6 +208,11 @@ func TestAccountListEndpoint(t *testing.T) { for _, e := range expected { assert.Contains(t, res.Data, e.StakeAddress) } + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAccountList(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestAccountInfoEndpoint(t *testing.T) { @@ -206,6 +236,11 @@ func TestAccountInfoEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoAddress) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing address") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAccountInfo(context.TODO(), koios.Address(spec.Request.Query.Get("_address"))) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestAccountRewardsEndpoint(t *testing.T) { @@ -228,6 +263,11 @@ func TestAccountRewardsEndpoint(t *testing.T) { assert.Len(t, expected, 1) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAccountRewards(context.TODO(), koios.StakeAddress(spec.Request.Query.Get("_address")), &epoch) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestAccountUpdatesEndpoint(t *testing.T) { @@ -245,6 +285,11 @@ func TestAccountUpdatesEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAccountUpdates(context.TODO(), koios.StakeAddress(spec.Request.Query.Get("_address"))) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestAccountAddressesEndpoint(t *testing.T) { @@ -266,6 +311,11 @@ func TestAccountAddressesEndpoint(t *testing.T) { for _, e := range expected { assert.Contains(t, res.Data, e.Address) } + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAccountAddresses(context.TODO(), koios.StakeAddress(spec.Request.Query.Get("_address"))) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestAccountAssetsEndpoint(t *testing.T) { expected := []koios.AccountAsset{} @@ -282,6 +332,11 @@ func TestAccountAssetsEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAccountAssets(context.TODO(), koios.StakeAddress(spec.Request.Query.Get("_address"))) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestAccountHistoryEndpoint(t *testing.T) { @@ -299,6 +354,11 @@ func TestAccountHistoryEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAccountHistory(context.TODO(), koios.StakeAddress(spec.Request.Query.Get("_address"))) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetAddressInfoEndpoint(t *testing.T) { @@ -321,6 +381,11 @@ func TestGetAddressInfoEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoAddress) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing address") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAddressInfo(context.TODO(), koios.Address(spec.Request.Query.Get("_address"))) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetAddressTxsEndpoint(t *testing.T) { @@ -354,6 +419,11 @@ func TestGetAddressTxsEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoAddress) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing address") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAddressTxs(context.TODO(), []koios.Address{koios.Address(spec.Request.Query.Get("_address"))}, 0) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetAddressAssetsEndpoint(t *testing.T) { @@ -376,6 +446,11 @@ func TestGetAddressAssetsEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoAddress) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing address") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAddressAssets(context.TODO(), koios.Address(spec.Request.Query.Get("_address"))) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetCredentialTxsEndpoint(t *testing.T) { @@ -409,6 +484,11 @@ func TestGetCredentialTxsEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoAddress) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing address") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetCredentialTxs(context.TODO(), payload.Credentials, payload.AfterBlockHeight) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestAssetListEndpoint(t *testing.T) { @@ -426,6 +506,11 @@ func TestAssetListEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAssetList(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetAssetAddressListEndpoint(t *testing.T) { @@ -447,6 +532,15 @@ func TestGetAssetAddressListEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAssetAddressList( + context.TODO(), + koios.PolicyID(spec.Request.Query.Get("_asset_policy")), + koios.AssetName(spec.Request.Query.Get("_asset_name")), + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetAssetInfoEndpoint(t *testing.T) { @@ -468,6 +562,15 @@ func TestGetAssetInfoEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, &expected[0], res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAssetInfo( + context.TODO(), + koios.PolicyID(spec.Request.Query.Get("_asset_policy")), + koios.AssetName(spec.Request.Query.Get("_asset_name")), + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetAssetSummaryEndpoint(t *testing.T) { @@ -489,6 +592,15 @@ func TestGetAssetSummaryEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, &expected[0], res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAssetSummary( + context.TODO(), + koios.PolicyID(spec.Request.Query.Get("_asset_policy")), + koios.AssetName(spec.Request.Query.Get("_asset_name")), + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetAssetTxsEndpoint(t *testing.T) { @@ -510,6 +622,15 @@ func TestGetAssetTxsEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, &expected[0], res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetAssetTxs( + context.TODO(), + koios.PolicyID(spec.Request.Query.Get("_asset_policy")), + koios.AssetName(spec.Request.Query.Get("_asset_name")), + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetBlockInfoEndpoint(t *testing.T) { @@ -530,6 +651,14 @@ func TestGetBlockInfoEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, &expected[0], res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetBlockInfo( + context.TODO(), + koios.BlockHash(spec.Request.Query.Get("_block_hash")), + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetBlockTxsEndpoint(t *testing.T) { @@ -554,6 +683,14 @@ func TestGetBlockTxsEndpoint(t *testing.T) { for _, e := range expected { assert.Contains(t, res.Data, e.TxHash) } + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetBlockTxHashes( + context.TODO(), + koios.BlockHash(spec.Request.Query.Get("_block_hash")), + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetBlocksEndpoint(t *testing.T) { @@ -571,6 +708,11 @@ func TestGetBlocksEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetBlocks(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetPoolBlocksEndpoint(t *testing.T) { @@ -596,6 +738,15 @@ func TestGetPoolBlocksEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetPoolBlocks( + context.TODO(), + koios.PoolID(spec.Request.Query.Get("_pool_bech32")), + &epoch, + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetPoolDelegatorsEndpoint(t *testing.T) { @@ -621,6 +772,15 @@ func TestGetPoolDelegatorsEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetPoolDelegators( + context.TODO(), + koios.PoolID(spec.Request.Query.Get("_pool_bech32")), + &epoch, + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetPoolInfoEndpoint(t *testing.T) { @@ -644,6 +804,14 @@ func TestGetPoolInfoEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoPoolID) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing pool id") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetPoolInfo( + context.TODO(), + koios.PoolID(spec.Request.Query.Get("_pool_bech32")), + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetPoolListEndpoint(t *testing.T) { @@ -661,6 +829,11 @@ func TestGetPoolListEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetPoolList(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetPoolMetadataEndpoint(t *testing.T) { @@ -678,6 +851,11 @@ func TestGetPoolMetadataEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetPoolMetadata(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetPoolRelaysEndpoint(t *testing.T) { @@ -695,6 +873,11 @@ func TestGetPoolRelaysEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetPoolRelays(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetPoolUpdatesEndpoint(t *testing.T) { @@ -714,6 +897,14 @@ func TestGetPoolUpdatesEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetPoolUpdates( + context.TODO(), + &poolID, + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetScriptListEndpoint(t *testing.T) { @@ -731,6 +922,11 @@ func TestGetScriptListEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetScriptList(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetScriptRedeemersEndpoint(t *testing.T) { @@ -749,6 +945,14 @@ func TestGetScriptRedeemersEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, &expected[0], res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetScriptRedeemers( + context.TODO(), + koios.ScriptHash(spec.Request.Query.Get("_script_hash")), + ) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetTxInfoEndpoint(t *testing.T) { @@ -779,6 +983,11 @@ func TestGetTxInfoEndpoint(t *testing.T) { if assert.NotNil(t, res2.Error) { assert.Equal(t, koios.ErrNoTxHash.Error(), res2.Error.Message) } + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetTxInfo(context.TODO(), payload.TxHashes[0]) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetTxMetadataEndpoint(t *testing.T) { @@ -807,6 +1016,11 @@ func TestGetTxMetadataEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoTxHash) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing transaxtion hash(es)") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetTxMetadata(context.TODO(), payload.TxHashes[0]) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetTxMetaLabelsEndpoint(t *testing.T) { @@ -824,6 +1038,11 @@ func TestGetTxMetaLabelsEndpoint(t *testing.T) { testHeaders(t, spec, res.Response) assert.Equal(t, expected, res.Data) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetTxMetaLabels(context.TODO()) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetTxStatusEndpoint(t *testing.T) { @@ -852,6 +1071,11 @@ func TestGetTxStatusEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoTxHash) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing transaxtion hash(es)") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetTxStatus(context.TODO(), payload.TxHashes[0]) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetTxsUTxOsEndpoint(t *testing.T) { @@ -880,6 +1104,11 @@ func TestGetTxsUTxOsEndpoint(t *testing.T) { assert.ErrorIs(t, err, koios.ErrNoTxHash) assert.Nil(t, res2.Data, "response data should be nil if arg is invalid") assert.Equal(t, res2.Error.Message, "missing transaxtion hash(es)") + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.GetTxsUTxOs(context.TODO(), payload.TxHashes) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } func TestGetTxSubmit(t *testing.T) { @@ -901,6 +1130,11 @@ func TestGetTxSubmit(t *testing.T) { assert.Error(t, err, "submited tx should return error") testHeaders(t, spec, res2.Response) + + c, err := api.WithOptions(koios.Host("127.0.0.2:80")) + assert.NoError(t, err) + _, err = c.SubmitSignedTx(context.TODO(), payload) + assert.EqualError(t, err, "dial tcp: lookup 127.0.0.2:80: no such host") } // loadEndpointTestSpec load specs for endpoint.