152 lines
4.0 KiB
Go
152 lines
4.0 KiB
Go
package tron
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Client is the subset of tronpy's Tron client used by kisstron.
|
|
type Client struct {
|
|
provider *HTTPProvider
|
|
network string
|
|
feeLimit int64
|
|
}
|
|
|
|
// NewClient builds a client for the given network and node endpoint. A zero or
|
|
// empty endpoint selects the network default.
|
|
func NewClient(network, endpoint string, feeLimit int64, apiKey string) *Client {
|
|
return &Client{
|
|
provider: NewHTTPProvider(endpoint, 20*time.Second, apiKey),
|
|
network: network,
|
|
feeLimit: feeLimit,
|
|
}
|
|
}
|
|
|
|
// Provider exposes the underlying HTTP provider (used for diagnostics).
|
|
func (c *Client) Provider() *HTTPProvider { return c.provider }
|
|
|
|
func (c *Client) GetAccount(addr string) (map[string]any, error) {
|
|
b58, err := ToBase58CheckAddress(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ret, err := c.provider.makeRequest("wallet/getaccount", map[string]any{"address": b58, "visible": true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(ret) == 0 {
|
|
return nil, ErrAddressNotFound
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (c *Client) GetAccountResource(addr string) (map[string]any, error) {
|
|
b58, err := ToBase58CheckAddress(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ret, err := c.provider.makeRequest("wallet/getaccountresource", map[string]any{"address": b58, "visible": true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(ret) == 0 {
|
|
return nil, ErrAddressNotFound
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (c *Client) getLatestSolidBlockID() (string, error) {
|
|
info, err := c.provider.makeRequest("wallet/getnodeinfo", nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
block, _ := info["solidityBlock"].(string)
|
|
if block == "" {
|
|
return "", ErrAPI
|
|
}
|
|
return block[strings.LastIndex(block, ",ID:")+4:], nil
|
|
}
|
|
|
|
func (c *Client) broadcast(tx *Transaction) (map[string]any, error) {
|
|
payload, err := c.provider.makeRequest("wallet/broadcasttransaction", tx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := handleAPIError(payload); err != nil {
|
|
return nil, err
|
|
}
|
|
if _, ok := payload["txid"]; !ok {
|
|
payload["txid"] = tx.TxID
|
|
}
|
|
return payload, nil
|
|
}
|
|
|
|
func (c *Client) getTransactionInfo(txid string) (map[string]any, error) {
|
|
if len(txid) != 64 {
|
|
return nil, ErrBadHash
|
|
}
|
|
ret, err := c.provider.makeRequest("wallet/gettransactioninfobyid", map[string]any{"value": txid, "visible": true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := handleAPIError(ret); err != nil {
|
|
return nil, err
|
|
}
|
|
if len(ret) == 0 {
|
|
return nil, ErrTransactionNotFound
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func (c *Client) GetContract(addr string) (*Contract, error) {
|
|
b58, err := ToBase58CheckAddress(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
info, err := c.provider.makeRequest("wallet/getcontract", map[string]any{"value": b58, "visible": true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := handleAPIError(info); err != nil {
|
|
return nil, wrapErr(ErrContractNotFound, err.Error())
|
|
}
|
|
return &Contract{Address: b58, client: c}, nil
|
|
}
|
|
|
|
// triggerConstantContract performs a read-only contract call and returns the
|
|
// first constant result (hex, without 0x).
|
|
func (c *Client) triggerConstantContract(owner, contractAddr, functionSelector, parameter string) (string, error) {
|
|
ownerB58, err := ToBase58CheckAddress(owner)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
contractB58, err := ToBase58CheckAddress(contractAddr)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
ret, err := c.provider.makeRequest("wallet/triggerconstantcontract", map[string]any{
|
|
"owner_address": ownerB58,
|
|
"contract_address": contractB58,
|
|
"function_selector": functionSelector,
|
|
"parameter": parameter,
|
|
"visible": true,
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if err := handleAPIError(ret); err != nil {
|
|
return "", err
|
|
}
|
|
if res, ok := ret["result"].(map[string]any); ok {
|
|
if _, bad := res["message"]; bad {
|
|
return "", ErrTvm
|
|
}
|
|
}
|
|
results, ok := ret["constant_result"].([]any)
|
|
if !ok || len(results) == 0 {
|
|
return "", ErrTvm
|
|
}
|
|
first, _ := results[0].(string)
|
|
return first, nil
|
|
}
|