1

I have been stuck with this for a couple of hours now and was hoping one of you could help me out with an elegant solution.

Basically, I have the following struct:

type GetERC20TransferResponse struct {
Data struct {
    Address       string    `json:"address"`
    UpdatedAt     time.Time `json:"updated_at"`
    NextUpdateAt  time.Time `json:"next_update_at"`
    QuoteCurrency string    `json:"quote_currency"`
    ChainID       int       `json:"chain_id"`
    Items         []struct {
        BlockSignedAt    time.Time   `json:"block_signed_at"`
        BlockHeight      int         `json:"block_height"`
        TxHash           string      `json:"tx_hash"`
        TxOffset         int         `json:"tx_offset"`
        Successful       bool        `json:"successful"`
        FromAddress      string      `json:"from_address"`
        FromAddressLabel interface{} `json:"from_address_label"`
        ToAddress        string      `json:"to_address"`
        ToAddressLabel   interface{} `json:"to_address_label"`
        Value            string      `json:"value"`
        ValueQuote       float64     `json:"value_quote"`
        GasOffered       int         `json:"gas_offered"`
        GasSpent         int         `json:"gas_spent"`
        GasPrice         int64       `json:"gas_price"`
        FeesPaid         interface{} `json:"fees_paid"`
        GasQuote         float64     `json:"gas_quote"`
        GasQuoteRate     float64     `json:"gas_quote_rate"`
        Transfers        []struct {
            BlockSignedAt        time.Time   `json:"block_signed_at"`
            TxHash               string      `json:"tx_hash"`
            FromAddress          string      `json:"from_address"`
            FromAddressLabel     interface{} `json:"from_address_label"`
            ToAddress            string      `json:"to_address"`
            ToAddressLabel       interface{} `json:"to_address_label"`
            ContractDecimals     int         `json:"contract_decimals"`
            ContractName         string      `json:"contract_name"`
            ContractTickerSymbol string      `json:"contract_ticker_symbol"`
            ContractAddress      string      `json:"contract_address"`
            LogoURL              string      `json:"logo_url"`
            TransferType         string      `json:"transfer_type"`
            Delta                string      `json:"delta"`
            Balance              interface{} `json:"balance"`
            QuoteRate            float64     `json:"quote_rate"`
            DeltaQuote           float64     `json:"delta_quote"`
            BalanceQuote         interface{} `json:"balance_quote"`
            MethodCalls          interface{} `json:"method_calls"`
        } `json:"transfers"`
    } `json:"items"`
    Pagination struct {
        HasMore    bool        `json:"has_more"`
        PageNumber int         `json:"page_number"`
        PageSize   int         `json:"page_size"`
        TotalCount interface{} `json:"total_count"`
    } `json:"pagination"`
} `json:"data"`
Error        bool        `json:"error"`
ErrorMessage interface{} `json:"error_message"`
ErrorCode    interface{} `json:"error_code"`

Now working with this data has not proved to difficult, but now I am trying to do something of which I am not sure it is even possible. Basically I created another struct called Transfer:

type Transfer []struct {
BlockSignedAt        time.Time   `json:"block_signed_at"`
TxHash               string      `json:"tx_hash"`
FromAddress          string      `json:"from_address"`
FromAddressLabel     interface{} `json:"from_address_label"`
ToAddress            string      `json:"to_address"`
ToAddressLabel       interface{} `json:"to_address_label"`
ContractDecimals     int         `json:"contract_decimals"`
ContractName         string      `json:"contract_name"`
ContractTickerSymbol string      `json:"contract_ticker_symbol"`
ContractAddress      string      `json:"contract_address"`
LogoURL              string      `json:"logo_url"`
TransferType         string      `json:"transfer_type"`
Delta                string      `json:"delta"`
Balance              interface{} `json:"balance"`
QuoteRate            float64     `json:"quote_rate"`
DeltaQuote           float64     `json:"delta_quote"`
BalanceQuote         interface{} `json:"balance_quote"`
MethodCalls          interface{} `json:"method_calls"`

}

Which is just the part of response.Data.Items that I need. Now my question is how do I take just this part out of the GetERC20TransferReponse struct, seperate it, then return it.

Flow is like this:

  1. Look inside the GetERC20TransferResponse to see what the value is of TransferType.
  2. Based on transfertype perform operations / save stuff from the response.Data.Items[1] / Transfer []struct part of the GetERC20TransferResponse

In short, what would be quite elegant is that when I call the function that checks if TransferType is 0, 1 or 2, it will also return the entire "Transfers" part of the GetERC20TransferResponse struct and return it as well so I don't have to access the struct again.

This is for an open-source tool I am developing which needs to be in Go (which I am relatively new to) for speed reasons.

1 Answers1

0

I suggest first breaking the whole response 'GetERC20TransferResponse' into individual structs as

// single transfer
type Transfer struct {
    BlockSignedAt        time.Time   `json:"block_signed_at"`
    TxHash               string      `json:"tx_hash"`
    FromAddress          string      `json:"from_address"`
    FromAddressLabel     interface{} `json:"from_address_label"`
    ToAddress            string      `json:"to_address"`
    ToAddressLabel       interface{} `json:"to_address_label"`
    ContractDecimals     int         `json:"contract_decimals"`
    ContractName         string      `json:"contract_name"`
    ContractTickerSymbol string      `json:"contract_ticker_symbol"`
    ContractAddress      string      `json:"contract_address"`
    LogoURL              string      `json:"logo_url"`
    TransferType         string      `json:"transfer_type"`
    Delta                string      `json:"delta"`
    Balance              interface{} `json:"balance"`
    QuoteRate            float64     `json:"quote_rate"`
    DeltaQuote           float64     `json:"delta_quote"`
    BalanceQuote         interface{} `json:"balance_quote"`
    MethodCalls          interface{} `json:"method_calls"`
}
    //single ERC items
type ERCItems struct {
    BlockSignedAt    time.Time   `json:"block_signed_at"`
    BlockHeight      int         `json:"block_height"`
    TxHash           string      `json:"tx_hash"`
    TxOffset         int         `json:"tx_offset"`
    Successful       bool        `json:"successful"`
    FromAddress      string      `json:"from_address"`
    FromAddressLabel interface{} `json:"from_address_label"`
    ToAddress        string      `json:"to_address"`
    ToAddressLabel   interface{} `json:"to_address_label"`
    Value            string      `json:"value"`
    ValueQuote       float64     `json:"value_quote"`
    GasOffered       int         `json:"gas_offered"`
    GasSpent         int         `json:"gas_spent"`
    GasPrice         int64       `json:"gas_price"`
    FeesPaid         interface{} `json:"fees_paid"`
    GasQuote         float64     `json:"gas_quote"`
    GasQuoteRate     float64     `json:"gas_quote_rate"`
    Transfers        []Transfer  `json:"transfers"`
}
//response data
type Data struct {
    Address       string     `json:"address"`
    UpdatedAt     time.Time  `json:"updated_at"`
    NextUpdateAt  time.Time  `json:"next_update_at"`
    QuoteCurrency string     `json:"quote_currency"`
    ChainID       int        `json:"chain_id"`
    Items         []ERCItems `json:"items"`
    Pagination    struct {
        HasMore    bool        `json:"has_more"`
        PageNumber int         `json:"page_number"`
        PageSize   int         `json:"page_size"`
        TotalCount interface{} `json:"total_count"`
    } `json:"pagination"`
}

//general response
type GetERC20TransferResponse struct {
    Data         Data        `json:"data"`
    Error        bool        `json:"error"`
    ErrorMessage interface{} `json:"error_message"`
    ErrorCode    interface{} `json:"error_code"`
}

This allows you to have fine grained control of the response object.After that you can simple have a function that inspects the model to check for transfer type and picks the transfers as need be for example

 func main() {
    response := GetERC20TransferResponse{}

    // get all items from the response
    items := response.Data.Items

    // slice to store transfers that match the required transfer type
    transfers := make([]Transfer, 0)

    // iterate through all items to and further iterate through all transfers adding
    // the whole transfers if any matches the required transfer types
    for _, item := range items {
        for _, transfer := range item.Transfers {
            if transfer.TransferType == "0" || transfer.TransferType == "1" || transfer.TransferType == "2" {
                transfers = append(transfers, item.Transfers...)
                break
            }
        }
    }

}

refactor as need be

Daniel Kiptoon
  • 314
  • 1
  • 7