eth.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. package dgn
  2. import (
  3. "context"
  4. "crypto/ecdsa"
  5. "encoding/json"
  6. "fmt"
  7. "github.com/ethereum/go-ethereum"
  8. "github.com/ethereum/go-ethereum/accounts/abi"
  9. "github.com/ethereum/go-ethereum/common"
  10. "github.com/ethereum/go-ethereum/ethclient"
  11. "github.com/ybbus/jsonrpc/v2"
  12. "log"
  13. "math/big"
  14. "net/http"
  15. "strconv"
  16. "strings"
  17. comm "sync-block/common"
  18. "sync-block/dgn/fourbyte"
  19. "sync-block/model"
  20. "sync-block/util"
  21. //"github.com/cellcrypto/dangnn"
  22. //"github.com/cellcrypto/dangnn/common"
  23. "github.com/ethereum/go-ethereum/common/hexutil"
  24. "github.com/ethereum/go-ethereum/common/math"
  25. "github.com/ethereum/go-ethereum/core/types"
  26. "github.com/ethereum/go-ethereum/crypto"
  27. "github.com/pkg/errors"
  28. "golang.org/x/crypto/sha3"
  29. )
  30. type Eth struct {
  31. host string
  32. client *ethclient.Client
  33. RpcClient jsonrpc.RPCClient
  34. conifg *comm.BlockConfig
  35. ByteDb *fourbyte.Database
  36. AbiParsed *abi.ABI
  37. }
  38. var LogTransferSignHash = crypto.Keccak256Hash([]byte("Transfer(address,address,uint256)"))
  39. // Erc20ABI is the input ABI used to generate the binding from.
  40. 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\"}]"
  41. func New(rawurl string, config *comm.BlockConfig) (*Eth, error) {
  42. client, err := ethclient.Dial(rawurl)
  43. if err != nil {
  44. fmt.Printf("Failed to connect to eth: %v", err)
  45. return nil, err
  46. }
  47. var opts *jsonrpc.RPCClientOpts
  48. opts = &jsonrpc.RPCClientOpts{
  49. HTTPClient: &http.Client{
  50. Timeout: util.MustParseDuration("120s"), // 시간은 100만건당 40초 정도로 설정해야 된다.
  51. },
  52. CustomHeaders: nil,
  53. }
  54. rpcClient := jsonrpc.NewClientWithOpts(rawurl, opts)
  55. db, err := fourbyte.New()
  56. if err != nil {
  57. fmt.Printf("Failed to Read to 4bytejson: %v", err)
  58. return nil, err
  59. }
  60. parsed, err := abi.JSON(strings.NewReader(Erc20ABI))
  61. if err != nil {
  62. fmt.Printf("failed loaded abi parser: %v", err)
  63. return nil, err
  64. }
  65. return &Eth{host: rawurl, client: client, RpcClient: rpcClient, conifg: config, ByteDb: db, AbiParsed: &parsed}, nil
  66. }
  67. func (this *Eth) GetTxByHash(hash string) (tx model.Tx, err error) {
  68. response, err := this.RpcClient.Call("eth_getTransactionByHash", hash)
  69. if err != nil {
  70. return
  71. }
  72. log.Printf("%+v\n\n\n", response.Result)
  73. err = response.GetObject(&tx)
  74. if err != nil {
  75. return
  76. }
  77. return
  78. }
  79. func (this *Eth) GetLastBlockNumber() (*big.Int, error) {
  80. header, err := this.client.HeaderByNumber(context.Background(), nil)
  81. if err != nil {
  82. return nil, err
  83. }
  84. return header.Number, nil
  85. }
  86. type txExtraInfo struct {
  87. BlockNumber *string `json:"blockNumber,omitempty"`
  88. BlockHash *common.Hash `json:"blockHash,omitempty"`
  89. From *common.Address `json:"from,omitempty"`
  90. }
  91. type rpcTransaction struct {
  92. tx *types.Transaction
  93. txExtraInfo
  94. }
  95. func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error {
  96. if err := json.Unmarshal(msg, &tx.tx); err != nil {
  97. return err
  98. }
  99. return json.Unmarshal(msg, &tx.txExtraInfo)
  100. }
  101. type rpcBlock struct {
  102. Hash common.Hash `json:"hash"`
  103. Transactions []rpcTransaction `json:"transactions"`
  104. UncleHashes []common.Hash `json:"uncles"`
  105. }
  106. func (this *Eth) GetBlockByNumber(number *big.Int) (*Block, error) {
  107. rpcResp, err := this.RpcClient.Call("eth_getBlockByNumber", fmt.Sprintf("0x%x", number.Uint64()),true)
  108. //b, err := this.client.BlockByNumber(context.Background(), number)
  109. if err != nil {
  110. return nil, err
  111. }
  112. if rpcResp.Result != nil {
  113. var body *rpcBlock
  114. var head *BHeader
  115. data, _:= json.Marshal(rpcResp.Result)
  116. if err := json.Unmarshal(data, &head); err != nil {
  117. return nil, err
  118. }
  119. //fmt.Println(data)
  120. err = json.Unmarshal(data, &body)
  121. // Load uncles because they are not included in the block response.
  122. var uncles []*BHeader
  123. if len(body.UncleHashes) > 0 {
  124. uncles = make([]*BHeader, len(body.UncleHashes))
  125. reqs := make([]*jsonrpc.RPCRequest, len(body.UncleHashes))
  126. for i := range reqs {
  127. reqs[i] = &jsonrpc.RPCRequest{
  128. Method: "eth_getUncleByBlockHashAndIndex",
  129. Params: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))},
  130. }
  131. }
  132. uncleData, err := this.RpcClient.CallBatch(reqs)
  133. if err != nil {
  134. return nil, err
  135. }
  136. fmt.Println(uncleData)
  137. fmt.Println(uncles)
  138. err = json.Unmarshal(data, &body)
  139. for i := range uncleData {
  140. uncleMarshal, _:= json.Marshal(uncleData[i].Result)
  141. err = json.Unmarshal(uncleMarshal, &uncles[i])
  142. uncles[i].Hash()
  143. if uncles[i] == nil {
  144. return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:])
  145. }
  146. }
  147. }
  148. // Fill the sender cache of transactions in the block.
  149. txs := make([]*types.Transaction, len(body.Transactions))
  150. for i, tx := range body.Transactions {
  151. if tx.From != nil {
  152. setSenderFromServer(tx.tx, *tx.From, body.Hash)
  153. }
  154. txs[i] = tx.tx
  155. }
  156. return NewBlockWithHeader(head).WithBody(txs, uncles), nil
  157. }
  158. return nil, nil
  159. }
  160. const ETH = 1_000_000_000_000_000_000
  161. const DGC = 10_000_000_000_000_000
  162. var (
  163. GenesisReword = math.MustParseBig256("3000000000000000000") // 300DGC = 3ETH
  164. CarratReward = math.MustParseBig256("3300000000000000000") // 330DGC = 3.3ETH
  165. CarrathardforkheightMainnet = uint64(400000)
  166. CarrathardforkheightTestnet = uint64(641800)
  167. )
  168. // 당근을 위해 커스터마이징 된 부분
  169. func getFixedRewardForDangnn(height uint64, mainnet bool) *big.Int {
  170. if mainnet == true {
  171. if height >= CarrathardforkheightMainnet {
  172. return new(big.Int).Set(CarratReward)
  173. }
  174. } else {
  175. if height >= CarrathardforkheightTestnet {
  176. return new(big.Int).Set(CarratReward)
  177. }
  178. }
  179. return new(big.Int).Set(GenesisReword)
  180. }
  181. func (this *Eth) GetRewardForUncle(height uint64, mainnet bool) *big.Int {
  182. reward := getFixedRewardForDangnn(height, mainnet)
  183. return new(big.Int).Div(reward, new(big.Int).SetInt64(32))
  184. }
  185. func (this *Eth) GetUncleReward(uHeight, height uint64, mainnet bool) *big.Int {
  186. reward := getFixedRewardForDangnn(height, mainnet)
  187. k := int64(height - uHeight)
  188. reward.Mul(big.NewInt(8-k), reward)
  189. reward.Div(reward, big.NewInt(8))
  190. return reward
  191. }
  192. func (this *Eth) GetReward(b *Block, rts types.Receipts) (blockReward *big.Int, txFee *big.Int, rewardForUncles *big.Int, err error) {
  193. correctHeight := b.Number().Uint64()
  194. fixedReward := getFixedRewardForDangnn(correctHeight, this.conifg.MainNet)
  195. blockReward = fixedReward
  196. txFee = big.NewInt(0)
  197. txs := b.Transactions()
  198. for i, rt := range rts {
  199. gasUsed := big.NewInt(int64(rt.GasUsed))
  200. fee := new(big.Int).Mul(gasUsed, txs[i].GasPrice())
  201. txFee.Add(txFee, fee)
  202. }
  203. uncleCount := len(b.Uncles())
  204. if uncleCount > 2 {
  205. uncleCount = 2
  206. }
  207. uncleReward := this.GetRewardForUncle( correctHeight, this.conifg.MainNet)
  208. rewardForUncles = big.NewInt(0).Mul( uncleReward, big.NewInt(int64(uncleCount)))
  209. // fixed_Fee + tx_fee + uncle_include_fee
  210. blockReward.Add(blockReward, txFee)
  211. blockReward.Add(blockReward, rewardForUncles)
  212. return blockReward, txFee, rewardForUncles, nil
  213. }
  214. func (this *Eth) GetTxReceipts(transactions types.Transactions) (ret types.Receipts, err error) {
  215. for _, tx := range transactions {
  216. receipt, err := this.client.TransactionReceipt(context.Background(), tx.Hash())
  217. if err != nil {
  218. return nil, err
  219. }
  220. if receipt != nil {
  221. ret = append(ret, receipt)
  222. }
  223. }
  224. return
  225. }
  226. func (this *Eth) GetTxReceipt(txhash string) (ret *types.Receipt, err error) {
  227. receipt, err := this.client.TransactionReceipt(context.Background(), common.HexToHash(txhash))
  228. if err != nil {
  229. return
  230. }
  231. if receipt != nil {
  232. ret = receipt
  233. }
  234. return
  235. }
  236. //func (this *Eth) GetToken(contractAddr common.Address) (token *erc20.Erc20, err error) {
  237. // token, err = erc20.NewErc20(contractAddr, this.client)
  238. // return
  239. //}
  240. func (this *Eth) GetUncleBlockByBlockNumberAndIndex(blockNo uint64, idx int) (interface{}, error) {
  241. b, err := this.RpcClient.Call("eth_getUncleByBlockNumberAndIndex", fmt.Sprintf("0x%x", blockNo), fmt.Sprintf("0x%x", idx))
  242. if err != nil {
  243. return "", err
  244. }
  245. return b.Result, nil
  246. }
  247. func (this *Eth) CreateWallet() (privateKey, walletAddr string) {
  248. key, err := crypto.GenerateKey()
  249. if err != nil {
  250. log.Fatal(err)
  251. }
  252. privateKeyBytes := crypto.FromECDSA(key)
  253. privateKey = hexutil.Encode(privateKeyBytes)[2:]
  254. publicKey := key.Public()
  255. publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
  256. if !ok {
  257. log.Fatal("error casting public key to ECDSA")
  258. }
  259. publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
  260. //log.Println(hexutil.Encode(publicKeyBytes)[4:])
  261. //address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
  262. hash := sha3.NewLegacyKeccak256()
  263. hash.Write(publicKeyBytes[1:])
  264. walletAddr = hexutil.Encode(hash.Sum(nil)[12:])
  265. return
  266. }
  267. func (this *Eth) GetWalletAddressFromPrivateKey(privateKey string) (string, error) {
  268. if privateKey[:2] == "0x" {
  269. privateKey = privateKey[2:]
  270. }
  271. pkey, err := crypto.HexToECDSA(privateKey)
  272. if err != nil {
  273. return "", err
  274. }
  275. publicKey := pkey.Public()
  276. publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
  277. if !ok {
  278. return "", errors.New("error casting public key to ECDSA")
  279. }
  280. fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
  281. return fromAddress.Hex(), nil
  282. }
  283. func (this *Eth) Transfer(privateKey, to string, valueInWei, gasPrice *big.Int, gasLimit uint64) (txHash string, err error) {
  284. if privateKey[:2] == "0x" {
  285. privateKey = privateKey[2:]
  286. }
  287. if to[:2] == "0x" {
  288. to = to[2:]
  289. }
  290. pkey, err := crypto.HexToECDSA(privateKey)
  291. if err != nil {
  292. return
  293. }
  294. publicKey := pkey.Public()
  295. publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
  296. if !ok {
  297. err = errors.New("error casting public key to ECDSA")
  298. }
  299. fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
  300. nonce, err := this.getNonce(fromAddress.Hex())
  301. if err != nil {
  302. return
  303. }
  304. toAddress := common.HexToAddress(to)
  305. tx := types.NewTransaction(nonce, toAddress, valueInWei, gasLimit, gasPrice, nil)
  306. chainID, err := this.client.NetworkID(context.Background())
  307. if err != nil {
  308. return
  309. }
  310. signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), pkey)
  311. if err != nil {
  312. log.Fatal(err)
  313. }
  314. err = this.client.SendTransaction(context.Background(), signedTx)
  315. if err != nil {
  316. return
  317. }
  318. txHash = signedTx.Hash().Hex()
  319. log.Printf("tx sent: %s\n", txHash)
  320. return
  321. }
  322. func (this *Eth) getNonce(fromAddress string) (uint64, error) {
  323. resp, err := this.RpcClient.Call("eth_getTransactionCount", fromAddress, "pending")
  324. if err != nil {
  325. return 0, err
  326. }
  327. m := resp.Result.(string)
  328. nonce, err := hexutil.DecodeUint64(m)
  329. return nonce, err
  330. }
  331. func (this *Eth) GetSuggestedGasPrice() (*big.Int, error) {
  332. gasPrice, err := this.client.SuggestGasPrice(context.Background())
  333. return gasPrice, err
  334. }
  335. func (this *Eth) GetEstimatedGasLimit(tokenAddr, pkey, toAddr string, tokenAmount *big.Int) ([]byte, uint64, error) {
  336. if strings.HasPrefix(pkey, "0x") {
  337. pkey = pkey[2:]
  338. }
  339. privateKey, err := crypto.HexToECDSA(pkey)
  340. if err != nil {
  341. return nil, 0, err
  342. }
  343. publicKey := privateKey.Public()
  344. publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
  345. if !ok {
  346. err = errors.New("error casting public key to ECDSA")
  347. return nil, 0, err
  348. }
  349. fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
  350. toAddress := common.HexToAddress(toAddr)
  351. tokenAddress := common.HexToAddress(tokenAddr)
  352. transferFnSignature := []byte("transfer(address,uint256)")
  353. hash := sha3.NewLegacyKeccak256()
  354. hash.Write(transferFnSignature)
  355. methodID := hash.Sum(nil)[:4]
  356. paddedAddress := common.LeftPadBytes(toAddress.Bytes(), 32)
  357. paddedAmount := common.LeftPadBytes(tokenAmount.Bytes(), 32)
  358. var data []byte
  359. data = append(data, methodID...)
  360. data = append(data, paddedAddress...)
  361. data = append(data, paddedAmount...)
  362. gasLimit, err := this.client.EstimateGas(context.Background(), ethereum.CallMsg{
  363. From: fromAddress,
  364. To: &tokenAddress,
  365. Data: data,
  366. })
  367. return data, gasLimit, err
  368. }
  369. func (this *Eth) TransferToken(tokenAddr, pkey, toAddr string, tokenAmount *big.Int, gasPrice *big.Int, gasLimit uint64) (txHash string, err error) {
  370. if strings.HasPrefix(pkey, "0x") {
  371. pkey = pkey[2:]
  372. }
  373. privateKey, err := crypto.HexToECDSA(pkey)
  374. if err != nil {
  375. return "", err
  376. }
  377. publicKey := privateKey.Public()
  378. publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
  379. if !ok {
  380. err = errors.New("error casting public key to ECDSA")
  381. return "", err
  382. }
  383. fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
  384. nonce, err := this.getNonce(fromAddress.Hex())
  385. if err != nil {
  386. return "", err
  387. }
  388. value := big.NewInt(0) // in wei (0 eth)
  389. tokenAddress := common.HexToAddress(tokenAddr)
  390. data, _, err := this.GetEstimatedGasLimit(tokenAddr, pkey, toAddr, tokenAmount)
  391. if err != nil {
  392. return "", err
  393. }
  394. v := &transferValue{
  395. nonce: nonce,
  396. gasLimit: gasLimit,
  397. gasPrice: gasPrice,
  398. }
  399. log.Printf("nonce: %d, gas price: %d, gas limit: %d\n", nonce, v.gasPrice, v.gasLimit) // 25624
  400. //gasPrice = gasPrice.Add(gasPrice, big.NewInt(100_000_000))
  401. //gasPrice = big.NewInt(5320000000)
  402. tx := types.NewTransaction(v.nonce, tokenAddress, value, v.gasLimit, v.gasPrice, data)
  403. chainID, err := this.client.NetworkID(context.Background())
  404. if err != nil {
  405. return "", err
  406. }
  407. signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)
  408. if err != nil {
  409. return "", err
  410. }
  411. err = this.client.SendTransaction(context.Background(), signedTx)
  412. if err != nil {
  413. return "", err
  414. }
  415. return signedTx.Hash().Hex(), nil
  416. }
  417. func (this *Eth) GetTokenBalance(tokenAddress, address string) (balance *big.Int, err error) {
  418. b, err := this.GetTokenBalanceOf(common.HexToAddress(tokenAddress), common.HexToAddress(address))
  419. //token.Transfer(&bind.TransactOpts{
  420. // From: common.Address{},
  421. // Nonce: nil,
  422. // Signer: nil,
  423. // Value: nil,
  424. // GasPrice: nil,
  425. // GasFeeCap: nil,
  426. // GasTipCap: nil,
  427. // GasLimit: 0,
  428. // Context: nil,
  429. // NoSend: false,
  430. //}, common.HexToAddress(address), big.NewInt(100))
  431. return b, err
  432. }
  433. func (this *Eth) GetBalance(address string) (balance *big.Int, err error) {
  434. resp, err := this.RpcClient.Call("eth_getBalance", address, "latest")
  435. if err != nil {
  436. return
  437. }
  438. b, _ := new(big.Int).SetString(resp.Result.(string)[2:], 16)
  439. return b, nil
  440. }
  441. func (this *Eth) GetInternalTxsByHash(blockNo uint64, txHash string, lastBlockNo uint64) (calls []model.Call, err error) {
  442. args := make([]interface{}, 0)
  443. args = append(args, txHash)
  444. args = append(args, map[string]interface {
  445. }{
  446. "tracer": "callTracer",
  447. "reexec": lastBlockNo - blockNo + 20,
  448. })
  449. resp, err := this.RpcClient.Call("debug_traceTransaction", args)
  450. if err != nil {
  451. log.Printf("debug_traceTransaction failed blockNo:%v txHas:%v\n", blockNo, txHash)
  452. return nil, err
  453. }
  454. m, ok := resp.Result.(map[string]interface{})
  455. if !ok {
  456. return
  457. }
  458. data, err := json.Marshal(m["calls"])
  459. if err != nil {
  460. return
  461. }
  462. err = json.Unmarshal(data, &calls)
  463. if err != nil {
  464. return
  465. }
  466. return
  467. }
  468. // totalSupply() :0x18160ddd
  469. func (this *Eth) GetTokenTotalSupply(cntrAddr common.Address) (balance *big.Int, err error) {
  470. resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
  471. "data": "0x18160ddd",
  472. "to": cntrAddr,
  473. },"latest")
  474. switch {
  475. case err != nil:
  476. return nil, err
  477. case resp.Error != nil:
  478. return nil, resp.Error
  479. case resp.Result == nil:
  480. return nil, errors.New("no result in JSON-RPC response")
  481. default:
  482. b, ret := new(big.Int).SetString(resp.Result.(string)[2:],16)
  483. if ret != true {
  484. return nil, errors.New("SetString: no result in JSON-RPC response")
  485. }
  486. return b, nil
  487. }
  488. }
  489. // "name()" : 0x06fdde03
  490. func (this *Eth) GetTokenName(cntrAddr common.Address) ( string, error) {
  491. resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
  492. "data": "0x06fdde03",
  493. "to": cntrAddr,
  494. },"latest")
  495. switch {
  496. case err != nil:
  497. return "", err
  498. case resp.Error != nil:
  499. return "", resp.Error
  500. case resp.Result == nil:
  501. return "", errors.New("no result in JSON-RPC response")
  502. default:
  503. bytes := hexutil.MustDecode(resp.Result.(string))
  504. result, err := this.AbiParsed.Unpack("name", bytes)
  505. if err != nil || result == nil {
  506. return "", err
  507. }
  508. return result[0].(string), err
  509. }
  510. }
  511. // Decimals() (0x313ce567)
  512. func (this *Eth) GetTokenDecimals(cntrAddr common.Address) (uint8, error) {
  513. resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
  514. "data": "0x313ce567",
  515. "to": cntrAddr,
  516. },"latest")
  517. switch {
  518. case err != nil:
  519. return 0, err
  520. case resp.Error != nil:
  521. return 0, resp.Error
  522. case resp.Result == nil:
  523. return 0, errors.New("no result in JSON-RPC response")
  524. default:
  525. b, ret := new(big.Int).SetString(resp.Result.(string)[2:],16)
  526. if ret != true {
  527. return 0, errors.New("SetString: no result in JSON-RPC response")
  528. }
  529. return uint8(b.Uint64()), nil
  530. }
  531. }
  532. // "95d89b41": "symbol()",
  533. func (this *Eth) GetTokenSymbol(cntrAddr common.Address) (string, error) {
  534. resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
  535. "data": "0x95d89b41",
  536. "to": cntrAddr,
  537. },"latest")
  538. switch {
  539. case err != nil:
  540. return "", err
  541. case resp.Error != nil:
  542. return "", resp.Error
  543. case resp.Result == nil:
  544. return "", errors.New("err")
  545. default:
  546. bytes := hexutil.MustDecode(resp.Result.(string))
  547. result, err := this.AbiParsed.Unpack("name", bytes)
  548. if err != nil || result == nil {
  549. return "", err
  550. }
  551. return result[0].(string), err
  552. }
  553. }
  554. func HexToUint64(u uint64) string {
  555. enc := strconv.FormatUint(u,16)
  556. lenth0 := 64 - len(enc)
  557. for i := 0; i < lenth0;i++ {
  558. enc = "0" + enc
  559. }
  560. return enc
  561. }
  562. // "c87b56dd": "tokenURI(uint256)",
  563. func (this *Eth) GetNFTTokenURI(cntrAddr common.Address,tokenURI uint64) (string, error) {
  564. resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
  565. "data": "0xc87b56dd" + HexToUint64(tokenURI),
  566. "to": cntrAddr,
  567. },"latest")
  568. switch {
  569. case err != nil:
  570. return "", err
  571. case resp.Error != nil:
  572. return "", resp.Error
  573. case resp.Result == nil:
  574. return "", errors.New("err")
  575. default:
  576. bytes := hexutil.MustDecode(resp.Result.(string))
  577. result, err := this.AbiParsed.Unpack("tokenURI", bytes)
  578. if err != nil || result == nil {
  579. return "", err
  580. }
  581. return result[0].(string), err
  582. }
  583. }
  584. // "70a08231": "balanceOf(address)",
  585. func (this *Eth) GetTokenBalanceOf(cntrAddr common.Address, ownerAddr common.Address) (balance *big.Int, err error) {
  586. resp, err := this.RpcClient.Call("eth_call", map[string]interface{}{
  587. "data": "0x70a08231000000000000000000000000" + ownerAddr.String()[2:],
  588. "to": cntrAddr,
  589. },"latest")
  590. switch {
  591. case err != nil:
  592. return nil, err
  593. case resp.Error != nil:
  594. return nil, resp.Error
  595. case resp.Result == nil:
  596. return nil, errors.New("no result in JSON-RPC response")
  597. default:
  598. b, ret := new(big.Int).SetString(resp.Result.(string)[2:],16)
  599. if ret != true {
  600. return nil, errors.New("SetString: no result in JSON-RPC response")
  601. }
  602. return b, nil
  603. }
  604. }