123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721 |
- package dgn
- import (
- "context"
- "crypto/ecdsa"
- "encoding/json"
- "fmt"
- "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/ethclient"
- "github.com/ybbus/jsonrpc/v2"
- "log"
- "math/big"
- "net/http"
- "strconv"
- "strings"
- comm "sync-block/common"
- "sync-block/dgn/fourbyte"
- "sync-block/model"
- "sync-block/util"
- //"github.com/cellcrypto/dangnn"
- //"github.com/cellcrypto/dangnn/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/common/math"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/pkg/errors"
- "golang.org/x/crypto/sha3"
- )
- type Eth struct {
- host string
- client *ethclient.Client
- RpcClient jsonrpc.RPCClient
- conifg *comm.BlockConfig
- ByteDb *fourbyte.Database
- AbiParsed *abi.ABI
- }
- var LogTransferSignHash = crypto.Keccak256Hash([]byte("Transfer(address,address,uint256)"))
- // Erc20ABI is the input ABI used to generate the binding from.
- const Erc20ABI = "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
- func New(rawurl string, config *comm.BlockConfig) (*Eth, error) {
- client, err := ethclient.Dial(rawurl)
- if err != nil {
- fmt.Printf("Failed to connect to eth: %v", err)
- return nil, err
- }
- var opts *jsonrpc.RPCClientOpts
- opts = &jsonrpc.RPCClientOpts{
- HTTPClient: &http.Client{
- Timeout: util.MustParseDuration("120s"), // 시간은 100만건당 40초 정도로 설정해야 된다.
- },
- CustomHeaders: nil,
- }
- rpcClient := jsonrpc.NewClientWithOpts(rawurl, opts)
- db, err := fourbyte.New()
- if err != nil {
- fmt.Printf("Failed to Read to 4bytejson: %v", err)
- return nil, err
- }
- parsed, err := abi.JSON(strings.NewReader(Erc20ABI))
- if err != nil {
- fmt.Printf("failed loaded abi parser: %v", err)
- return nil, err
- }
- return &Eth{host: rawurl, client: client, RpcClient: rpcClient, conifg: config, ByteDb: db, AbiParsed: &parsed}, nil
- }
- func (this *Eth) GetTxByHash(hash string) (tx model.Tx, err error) {
- response, err := this.RpcClient.Call("eth_getTransactionByHash", hash)
- if err != nil {
- return
- }
- log.Printf("%+v\n\n\n", response.Result)
- err = response.GetObject(&tx)
- if err != nil {
- return
- }
- return
- }
- func (this *Eth) GetLastBlockNumber() (*big.Int, error) {
- header, err := this.client.HeaderByNumber(context.Background(), nil)
- if err != nil {
- return nil, err
- }
- return header.Number, nil
- }
- type txExtraInfo struct {
- BlockNumber *string `json:"blockNumber,omitempty"`
- BlockHash *common.Hash `json:"blockHash,omitempty"`
- From *common.Address `json:"from,omitempty"`
- }
- type rpcTransaction struct {
- tx *types.Transaction
- txExtraInfo
- }
- func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error {
- if err := json.Unmarshal(msg, &tx.tx); err != nil {
- return err
- }
- return json.Unmarshal(msg, &tx.txExtraInfo)
- }
- type rpcBlock struct {
- Hash common.Hash `json:"hash"`
- Transactions []rpcTransaction `json:"transactions"`
- UncleHashes []common.Hash `json:"uncles"`
- }
- func (this *Eth) GetBlockByNumber(number *big.Int) (*Block, error) {
- rpcResp, err := this.RpcClient.Call("eth_getBlockByNumber", fmt.Sprintf("0x%x", number.Uint64()),true)
- //b, err := this.client.BlockByNumber(context.Background(), number)
- if err != nil {
- return nil, err
- }
- if rpcResp.Result != nil {
- var body *rpcBlock
- var head *BHeader
- data, _:= json.Marshal(rpcResp.Result)
- if err := json.Unmarshal(data, &head); err != nil {
- return nil, err
- }
- //fmt.Println(data)
- err = json.Unmarshal(data, &body)
- // Load uncles because they are not included in the block response.
- var uncles []*BHeader
- if len(body.UncleHashes) > 0 {
- uncles = make([]*BHeader, len(body.UncleHashes))
- reqs := make([]*jsonrpc.RPCRequest, len(body.UncleHashes))
- for i := range reqs {
- reqs[i] = &jsonrpc.RPCRequest{
- Method: "eth_getUncleByBlockHashAndIndex",
- Params: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))},
- }
- }
- uncleData, err := this.RpcClient.CallBatch(reqs)
- if err != nil {
- return nil, err
- }
- fmt.Println(uncleData)
- fmt.Println(uncles)
- err = json.Unmarshal(data, &body)
- for i := range uncleData {
- uncleMarshal, _:= json.Marshal(uncleData[i].Result)
- err = json.Unmarshal(uncleMarshal, &uncles[i])
- uncles[i].Hash()
- if uncles[i] == nil {
- return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:])
- }
- }
- }
- // Fill the sender cache of transactions in the block.
- txs := make([]*types.Transaction, len(body.Transactions))
- for i, tx := range body.Transactions {
- if tx.From != nil {
- setSenderFromServer(tx.tx, *tx.From, body.Hash)
- }
- txs[i] = tx.tx
- }
- return NewBlockWithHeader(head).WithBody(txs, uncles), nil
- }
- return nil, nil
- }
- const ETH = 1_000_000_000_000_000_000
- const DGC = 10_000_000_000_000_000
- var (
- GenesisReword = math.MustParseBig256("3000000000000000000") // 300DGC = 3ETH
- CarratReward = math.MustParseBig256("3300000000000000000") // 330DGC = 3.3ETH
- CarrathardforkheightMainnet = uint64(400000)
- CarrathardforkheightTestnet = uint64(641800)
- )
- // 당근을 위해 커스터마이징 된 부분
- func getFixedRewardForDangnn(height uint64, mainnet bool) *big.Int {
- if mainnet == true {
- if height >= CarrathardforkheightMainnet {
- return new(big.Int).Set(CarratReward)
- }
- } else {
- if height >= CarrathardforkheightTestnet {
- return new(big.Int).Set(CarratReward)
- }
- }
- return new(big.Int).Set(GenesisReword)
- }
- func (this *Eth) GetRewardForUncle(height uint64, mainnet bool) *big.Int {
- reward := getFixedRewardForDangnn(height, mainnet)
- return new(big.Int).Div(reward, new(big.Int).SetInt64(32))
- }
- func (this *Eth) GetUncleReward(uHeight, height uint64, mainnet bool) *big.Int {
- reward := getFixedRewardForDangnn(height, mainnet)
- k := int64(height - uHeight)
- reward.Mul(big.NewInt(8-k), reward)
- reward.Div(reward, big.NewInt(8))
- return reward
- }
- func (this *Eth) GetReward(b *Block, rts types.Receipts) (blockReward *big.Int, txFee *big.Int, rewardForUncles *big.Int, err error) {
- correctHeight := b.Number().Uint64()
- fixedReward := getFixedRewardForDangnn(correctHeight, this.conifg.MainNet)
- blockReward = fixedReward
- txFee = big.NewInt(0)
- txs := b.Transactions()
- for i, rt := range rts {
- gasUsed := big.NewInt(int64(rt.GasUsed))
- fee := new(big.Int).Mul(gasUsed, txs[i].GasPrice())
- txFee.Add(txFee, fee)
- }
- uncleCount := len(b.Uncles())
- if uncleCount > 2 {
- uncleCount = 2
- }
- uncleReward := this.GetRewardForUncle( correctHeight, this.conifg.MainNet)
- rewardForUncles = big.NewInt(0).Mul( uncleReward, big.NewInt(int64(uncleCount)))
- // fixed_Fee + tx_fee + uncle_include_fee
- blockReward.Add(blockReward, txFee)
- blockReward.Add(blockReward, rewardForUncles)
- return blockReward, txFee, rewardForUncles, nil
- }
- func (this *Eth) GetTxReceipts(transactions types.Transactions) (ret types.Receipts, err error) {
- for _, tx := range transactions {
- receipt, err := this.client.TransactionReceipt(context.Background(), tx.Hash())
- if err != nil {
- return nil, err
- }
- if receipt != nil {
- ret = append(ret, receipt)
- }
- }
- return
- }
- func (this *Eth) GetTxReceipt(txhash string) (ret *types.Receipt, err error) {
- receipt, err := this.client.TransactionReceipt(context.Background(), common.HexToHash(txhash))
- if err != nil {
- return
- }
- if receipt != nil {
- ret = receipt
- }
- return
- }
- //func (this *Eth) GetToken(contractAddr common.Address) (token *erc20.Erc20, err error) {
- // token, err = erc20.NewErc20(contractAddr, this.client)
- // return
- //}
- func (this *Eth) GetUncleBlockByBlockNumberAndIndex(blockNo uint64, idx int) (interface{}, error) {
- b, err := this.RpcClient.Call("eth_getUncleByBlockNumberAndIndex", fmt.Sprintf("0x%x", blockNo), fmt.Sprintf("0x%x", idx))
- if err != nil {
- return "", err
- }
- return b.Result, nil
- }
- func (this *Eth) CreateWallet() (privateKey, walletAddr string) {
- key, err := crypto.GenerateKey()
- if err != nil {
- log.Fatal(err)
- }
- privateKeyBytes := crypto.FromECDSA(key)
- privateKey = hexutil.Encode(privateKeyBytes)[2:]
- publicKey := key.Public()
- publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
- if !ok {
- log.Fatal("error casting public key to ECDSA")
- }
- publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
- //log.Println(hexutil.Encode(publicKeyBytes)[4:])
- //address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
- hash := sha3.NewLegacyKeccak256()
- hash.Write(publicKeyBytes[1:])
- walletAddr = hexutil.Encode(hash.Sum(nil)[12:])
- return
- }
- func (this *Eth) GetWalletAddressFromPrivateKey(privateKey string) (string, error) {
- if privateKey[:2] == "0x" {
- privateKey = privateKey[2:]
- }
- pkey, err := crypto.HexToECDSA(privateKey)
- if err != nil {
- return "", err
- }
- publicKey := pkey.Public()
- publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
- if !ok {
- return "", errors.New("error casting public key to ECDSA")
- }
- fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
- return fromAddress.Hex(), nil
- }
- func (this *Eth) Transfer(privateKey, to string, valueInWei, gasPrice *big.Int, gasLimit uint64) (txHash string, err error) {
- if privateKey[:2] == "0x" {
- privateKey = privateKey[2:]
- }
- if to[:2] == "0x" {
- to = to[2:]
- }
- pkey, err := crypto.HexToECDSA(privateKey)
- if err != nil {
- return
- }
- publicKey := pkey.Public()
- publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
- if !ok {
- err = errors.New("error casting public key to ECDSA")
- }
- fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
- nonce, err := this.getNonce(fromAddress.Hex())
- if err != nil {
- return
- }
- toAddress := common.HexToAddress(to)
- tx := types.NewTransaction(nonce, toAddress, valueInWei, gasLimit, gasPrice, nil)
- chainID, err := this.client.NetworkID(context.Background())
- if err != nil {
- return
- }
- signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), pkey)
- if err != nil {
- log.Fatal(err)
- }
- err = this.client.SendTransaction(context.Background(), signedTx)
- if err != nil {
- return
- }
- txHash = signedTx.Hash().Hex()
- log.Printf("tx sent: %s\n", txHash)
- return
- }
- func (this *Eth) getNonce(fromAddress string) (uint64, error) {
- resp, err := this.RpcClient.Call("eth_getTransactionCount", fromAddress, "pending")
- if err != nil {
- return 0, err
- }
- m := resp.Result.(string)
- nonce, err := hexutil.DecodeUint64(m)
- return nonce, err
- }
- func (this *Eth) GetSuggestedGasPrice() (*big.Int, error) {
- gasPrice, err := this.client.SuggestGasPrice(context.Background())
- return gasPrice, err
- }
- func (this *Eth) GetEstimatedGasLimit(tokenAddr, pkey, toAddr string, tokenAmount *big.Int) ([]byte, uint64, error) {
- if strings.HasPrefix(pkey, "0x") {
- pkey = pkey[2:]
- }
- privateKey, err := crypto.HexToECDSA(pkey)
- if err != nil {
- return nil, 0, err
- }
- publicKey := privateKey.Public()
- publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
- if !ok {
- err = errors.New("error casting public key to ECDSA")
- return nil, 0, err
- }
- fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
- toAddress := common.HexToAddress(toAddr)
- tokenAddress := common.HexToAddress(tokenAddr)
- transferFnSignature := []byte("transfer(address,uint256)")
- hash := sha3.NewLegacyKeccak256()
- hash.Write(transferFnSignature)
- methodID := hash.Sum(nil)[:4]
- paddedAddress := common.LeftPadBytes(toAddress.Bytes(), 32)
- paddedAmount := common.LeftPadBytes(tokenAmount.Bytes(), 32)
- var data []byte
- data = append(data, methodID...)
- data = append(data, paddedAddress...)
- data = append(data, paddedAmount...)
- gasLimit, err := this.client.EstimateGas(context.Background(), ethereum.CallMsg{
- From: fromAddress,
- To: &tokenAddress,
- Data: data,
- })
- return data, gasLimit, err
- }
- func (this *Eth) TransferToken(tokenAddr, pkey, toAddr string, tokenAmount *big.Int, gasPrice *big.Int, gasLimit uint64) (txHash string, err error) {
- if strings.HasPrefix(pkey, "0x") {
- pkey = pkey[2:]
- }
- privateKey, err := crypto.HexToECDSA(pkey)
- if err != nil {
- return "", err
- }
- publicKey := privateKey.Public()
- publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
- if !ok {
- err = errors.New("error casting public key to ECDSA")
- return "", err
- }
- fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
- nonce, err := this.getNonce(fromAddress.Hex())
- if err != nil {
- return "", err
- }
- value := big.NewInt(0) // in wei (0 eth)
- tokenAddress := common.HexToAddress(tokenAddr)
- data, _, err := this.GetEstimatedGasLimit(tokenAddr, pkey, toAddr, tokenAmount)
- if err != nil {
- return "", err
- }
- v := &transferValue{
- nonce: nonce,
- gasLimit: gasLimit,
- gasPrice: gasPrice,
- }
- log.Printf("nonce: %d, gas price: %d, gas limit: %d\n", nonce, v.gasPrice, v.gasLimit) // 25624
- //gasPrice = gasPrice.Add(gasPrice, big.NewInt(100_000_000))
- //gasPrice = big.NewInt(5320000000)
- tx := types.NewTransaction(v.nonce, tokenAddress, value, v.gasLimit, v.gasPrice, data)
- chainID, err := this.client.NetworkID(context.Background())
- if err != nil {
- return "", err
- }
- signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)
- if err != nil {
- return "", err
- }
- err = this.client.SendTransaction(context.Background(), signedTx)
- if err != nil {
- return "", err
- }
- return signedTx.Hash().Hex(), nil
- }
- func (this *Eth) GetTokenBalance(tokenAddress, address string) (balance *big.Int, err error) {
- b, err := this.GetTokenBalanceOf(common.HexToAddress(tokenAddress), common.HexToAddress(address))
- //token.Transfer(&bind.TransactOpts{
- // From: common.Address{},
- // Nonce: nil,
- // Signer: nil,
- // Value: nil,
- // GasPrice: nil,
- // GasFeeCap: nil,
- // GasTipCap: nil,
- // GasLimit: 0,
- // Context: nil,
- // NoSend: false,
- //}, common.HexToAddress(address), big.NewInt(100))
- return b, err
- }
- func (this *Eth) GetBalance(address string) (balance *big.Int, err error) {
- resp, err := this.RpcClient.Call("eth_getBalance", address, "latest")
- if err != nil {
- return
- }
- b, _ := new(big.Int).SetString(resp.Result.(string)[2:], 16)
- return b, nil
- }
- func (this *Eth) GetInternalTxsByHash(blockNo uint64, txHash string, lastBlockNo uint64) (calls []model.Call, err error) {
- args := make([]interface{}, 0)
- args = append(args, txHash)
- args = append(args, map[string]interface {
- }{
- "tracer": "callTracer",
- "reexec": lastBlockNo - blockNo + 20,
- })
- resp, err := this.RpcClient.Call("debug_traceTransaction", args)
- if err != nil {
- log.Printf("debug_traceTransaction failed blockNo:%v txHas:%v\n", blockNo, txHash)
- return nil, err
- }
- m, ok := resp.Result.(map[string]interface{})
- if !ok {
- return
- }
- data, err := json.Marshal(m["calls"])
- if err != nil {
- return
- }
- err = json.Unmarshal(data, &calls)
- if err != nil {
- return
- }
- return
- }
- // totalSupply() :0x18160ddd
- func (this *Eth) GetTokenTotalSupply(cntrAddr common.Address) (balance *big.Int, err error) {
- resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
- "data": "0x18160ddd",
- "to": cntrAddr,
- },"latest")
- switch {
- case err != nil:
- return nil, err
- case resp.Error != nil:
- return nil, resp.Error
- case resp.Result == nil:
- return nil, errors.New("no result in JSON-RPC response")
- default:
- b, ret := new(big.Int).SetString(resp.Result.(string)[2:],16)
- if ret != true {
- return nil, errors.New("SetString: no result in JSON-RPC response")
- }
- return b, nil
- }
- }
- // "name()" : 0x06fdde03
- func (this *Eth) GetTokenName(cntrAddr common.Address) ( string, error) {
- resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
- "data": "0x06fdde03",
- "to": cntrAddr,
- },"latest")
- switch {
- case err != nil:
- return "", err
- case resp.Error != nil:
- return "", resp.Error
- case resp.Result == nil:
- return "", errors.New("no result in JSON-RPC response")
- default:
- bytes := hexutil.MustDecode(resp.Result.(string))
- result, err := this.AbiParsed.Unpack("name", bytes)
- if err != nil || result == nil {
- return "", err
- }
- return result[0].(string), err
- }
- }
- // Decimals() (0x313ce567)
- func (this *Eth) GetTokenDecimals(cntrAddr common.Address) (uint8, error) {
- resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
- "data": "0x313ce567",
- "to": cntrAddr,
- },"latest")
- switch {
- case err != nil:
- return 0, err
- case resp.Error != nil:
- return 0, resp.Error
- case resp.Result == nil:
- return 0, errors.New("no result in JSON-RPC response")
- default:
- b, ret := new(big.Int).SetString(resp.Result.(string)[2:],16)
- if ret != true {
- return 0, errors.New("SetString: no result in JSON-RPC response")
- }
- return uint8(b.Uint64()), nil
- }
- }
- // "95d89b41": "symbol()",
- func (this *Eth) GetTokenSymbol(cntrAddr common.Address) (string, error) {
- resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
- "data": "0x95d89b41",
- "to": cntrAddr,
- },"latest")
- switch {
- case err != nil:
- return "", err
- case resp.Error != nil:
- return "", resp.Error
- case resp.Result == nil:
- return "", errors.New("err")
- default:
- bytes := hexutil.MustDecode(resp.Result.(string))
- result, err := this.AbiParsed.Unpack("name", bytes)
- if err != nil || result == nil {
- return "", err
- }
- return result[0].(string), err
- }
- }
- func HexToUint64(u uint64) string {
- enc := strconv.FormatUint(u,16)
- lenth0 := 64 - len(enc)
- for i := 0; i < lenth0;i++ {
- enc = "0" + enc
- }
- return enc
- }
- // "c87b56dd": "tokenURI(uint256)",
- func (this *Eth) GetNFTTokenURI(cntrAddr common.Address,tokenURI uint64) (string, error) {
- resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
- "data": "0xc87b56dd" + HexToUint64(tokenURI),
- "to": cntrAddr,
- },"latest")
- switch {
- case err != nil:
- return "", err
- case resp.Error != nil:
- return "", resp.Error
- case resp.Result == nil:
- return "", errors.New("err")
- default:
- bytes := hexutil.MustDecode(resp.Result.(string))
- result, err := this.AbiParsed.Unpack("tokenURI", bytes)
- if err != nil || result == nil {
- return "", err
- }
- return result[0].(string), err
- }
- }
- // "70a08231": "balanceOf(address)",
- func (this *Eth) GetTokenBalanceOf(cntrAddr common.Address, ownerAddr common.Address) (balance *big.Int, err error) {
- resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
- "data": "0x70a08231000000000000000000000000" + ownerAddr.String()[2:],
- "to": cntrAddr,
- },"latest")
- switch {
- case err != nil:
- return nil, err
- case resp.Error != nil:
- return nil, resp.Error
- case resp.Result == nil:
- return nil, errors.New("no result in JSON-RPC response")
- default:
- b, ret := new(big.Int).SetString(resp.Result.(string)[2:],16)
- if ret != true {
- return nil, errors.New("SetString: no result in JSON-RPC response")
- }
- return b, nil
- }
- }
|