// Package xmrpayclnt is a client library for the MoneroPay v2 HTTP API. // // All amounts are in piconero. package xmrpayclnt import ( "bytes" "encoding/json" "log" "net/http" "net/url" "os" "git.samanthony.xyz/jttp" "gitlab.com/moneropay/moneropay/v2/pkg/model" ) const ( balancePath = "/balance" healthPath = "/health" receivePath = "/receive" ) var lg = log.New(os.Stderr, "xmrpayclnt: ", log.LstdFlags) type Client struct { c *jttp.Client endpoint *url.URL } // New creates a client that will connect to the MoneroPay server at // endpoint. func New(endpoint *url.URL) *Client { return WithClient(&http.Client{}, endpoint) } // WithClient creates a MoneroPay client that will use the given HTTP // client to connect to the MoneroPay server at endpoint. func WithClient(c *http.Client, endpoint *url.URL) *Client { return &Client{jttp.NewClient(c), endpoint} } // Balance returns the entire wallet balance. func (c *Client) Balance() (model.BalanceResponse, error) { url := c.endpoint.JoinPath(balancePath) req, err := http.NewRequest(http.MethodGet, url.String(), nil) if err != nil { return model.BalanceResponse{}, err } var bal model.BalanceResponse err = c.c.Do(req, http.StatusOK, &bal) return bal, err } // Health returns true if all required services are up. func (c *Client) Health() (bool, error) { url := c.endpoint.JoinPath(healthPath) req, err := http.NewRequest(http.MethodGet, url.String(), nil) if err != nil { return false, err } var health model.HealthResponse err = c.c.Do(req, http.StatusOK, &health) return err == nil, err } // NewTx creates a subaddress for incoming transfers. func (c *Client) NewTx(amount uint64, description string) (model.ReceivePostResponse, error) { return c.postReceive(amount, description, "") } // NewTxWithCallback creates a subaddress and a callback to monitor it. func (c *Client) NewTxWithCallback(amount uint64, description string, ch *CallbackHandler) (model.ReceivePostResponse, Callback, error) { cb := ch.listen() if resp, err := c.postReceive(amount, description, cb.url.String()); err == nil { return resp, cb, nil } else { cb.Close() return resp, Callback{}, err } } // GetTxStatus retrieves information about a transfer on a subaddress. func (c *Client) GetTxStatus(address string) (model.ReceiveGetResponse, error) { var resp model.ReceiveGetResponse url := c.endpoint.JoinPath(receivePath, address) req, err := http.NewRequest(http.MethodGet, url.String(), nil) if err != nil { return resp, err } err = c.c.Do(req, http.StatusOK, &resp) return resp, err } func (c *Client) postReceive(amount uint64, description string, callbackUrl string) (model.ReceivePostResponse, error) { var resp model.ReceivePostResponse body := new(bytes.Buffer) enc := json.NewEncoder(body) err := enc.Encode(model.ReceivePostRequest{amount, callbackUrl, description}) if err != nil { return resp, err } url := c.endpoint.JoinPath(receivePath) req, err := http.NewRequest(http.MethodPost, url.String(), body) if err != nil { return resp, err } err = c.c.Do(req, http.StatusOK, &resp) return resp, err }