github.com/0chain/gosdk@v1.17.11/sdks/zbox.go (about)

     1  package sdks
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"net"
     8  	"net/http"
     9  	"net/url"
    10  
    11  	"github.com/0chain/errors"
    12  	"github.com/0chain/gosdk/constants"
    13  	"github.com/0chain/gosdk/core/encryption"
    14  	"github.com/0chain/gosdk/core/resty"
    15  	"github.com/0chain/gosdk/core/sys"
    16  	"github.com/0chain/gosdk/core/zcncrypto"
    17  	"github.com/0chain/gosdk/zboxcore/client"
    18  )
    19  
    20  // ZBox  sdk client instance
    21  type ZBox struct {
    22  	// ClientID client id
    23  	ClientID string
    24  	// ClientKey client key
    25  	ClientKey string
    26  	// SignatureScheme signature scheme
    27  	SignatureScheme string
    28  
    29  	// Wallet wallet
    30  	Wallet *zcncrypto.Wallet
    31  
    32  	// NewRequest create http request
    33  	NewRequest func(method, url string, body io.Reader) (*http.Request, error)
    34  }
    35  
    36  // New create an sdk client instance given its configuration
    37  //   - clientID client id of the using client
    38  //   - clientKey client key of the using client
    39  //   - signatureScheme signature scheme for transaction encryption
    40  //   - wallet wallet of the using client
    41  func New(clientID, clientKey, signatureScheme string, wallet *zcncrypto.Wallet) *ZBox {
    42  	s := &ZBox{
    43  		ClientID:        clientID,
    44  		ClientKey:       clientKey,
    45  		SignatureScheme: signatureScheme,
    46  		Wallet:          wallet,
    47  		NewRequest:      http.NewRequest,
    48  	}
    49  
    50  	return s
    51  }
    52  
    53  // InitWallet init wallet from json
    54  //   - js json string of wallet
    55  func (z *ZBox) InitWallet(js string) error {
    56  	return json.Unmarshal([]byte(js), &z.Wallet)
    57  }
    58  
    59  // SignRequest sign request with client_id, client_key and sign by adding headers to the request
    60  //   - req http request
    61  //   - allocationID allocation id
    62  func (z *ZBox) SignRequest(req *http.Request, allocationID string) error {
    63  
    64  	if req == nil {
    65  		return errors.Throw(constants.ErrInvalidParameter, "req")
    66  	}
    67  
    68  	req.Header.Set("X-App-Client-ID", z.ClientID)
    69  	req.Header.Set("X-App-Client-Key", z.ClientKey)
    70  
    71  	hash := encryption.Hash(allocationID)
    72  
    73  	sign, err := sys.Sign(hash, z.SignatureScheme, client.GetClientSysKeys())
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	// ClientSignatureHeader represents http request header contains signature.
    79  	req.Header.Set("X-App-Client-Signature", sign)
    80  
    81  	return nil
    82  }
    83  
    84  // CreateTransport create http.Transport with default dial timeout
    85  func (z *ZBox) CreateTransport() *http.Transport {
    86  	return &http.Transport{
    87  		Dial: (&net.Dialer{
    88  			Timeout: resty.DefaultDialTimeout,
    89  		}).Dial,
    90  		TLSHandshakeTimeout: resty.DefaultDialTimeout,
    91  	}
    92  }
    93  
    94  // BuildUrls build full request url given base urls, query string, path format and path args
    95  //   - baseURLs base urls
    96  //   - queryString query string
    97  //   - pathFormat path format
    98  //   - pathArgs path args
    99  func (z *ZBox) BuildUrls(baseURLs []string, queryString map[string]string, pathFormat string, pathArgs ...interface{}) []string {
   100  
   101  	requestURL := pathFormat
   102  	if len(pathArgs) > 0 {
   103  		requestURL = fmt.Sprintf(pathFormat, pathArgs...)
   104  	}
   105  
   106  	if len(queryString) > 0 {
   107  		requestQuery := make(url.Values)
   108  		for k, v := range queryString {
   109  			requestQuery.Add(k, v)
   110  		}
   111  
   112  		requestURL += "?" + requestQuery.Encode()
   113  	}
   114  
   115  	list := make([]string, len(baseURLs))
   116  	for k, v := range baseURLs {
   117  		list[k] = v + requestURL
   118  	}
   119  
   120  	return list
   121  }
   122  
   123  // DoPost do post request with request and handle
   124  //   - req request instance
   125  //   - handle handle function for the response
   126  func (z *ZBox) DoPost(req *Request, handle resty.Handle) *resty.Resty {
   127  
   128  	opts := make([]resty.Option, 0, 5)
   129  
   130  	opts = append(opts, resty.WithRetry(resty.DefaultRetry))
   131  	opts = append(opts, resty.WithRequestInterceptor(func(r *http.Request) error {
   132  		return z.SignRequest(r, req.AllocationID) //nolint
   133  	}))
   134  
   135  	if len(req.ContentType) > 0 {
   136  		opts = append(opts, resty.WithHeader(map[string]string{
   137  			"Content-Type": req.ContentType,
   138  		}))
   139  	}
   140  
   141  	opts = append(opts, resty.WithTransport(z.CreateTransport()))
   142  
   143  	r := resty.New(opts...).Then(handle)
   144  
   145  	return r
   146  }