ブロックチェーンアプリケーションを最初から開発する(15)--Ethereumトランザクションマッチングクエリ

1.ブロック内トランザクションを取得します

1.1最新のブロックでトランザクションの詳細を取得する

最新のブロックを取得し、それを変数numに入れます

num, err := rc.Client.GetLatestBlockNumber()

ブロックのブロック情報を取得し、それを変数resに入れます

res, err := rc.Client.GetBlockByNumber(num, true)
if err != nil {
	logger.Error("GetBlockMatchTx", "step", "GetBlockByNumber", "err", err.Error())
	return BlockInfo{}, 0, err
}

新しいオブジェクトを定義するために、Ethereumのブロック構造は「ゼロからのブロックチェーンアプリケーションの開発(9)」で説明されています。

block := new(taskcommon.Block)

ブロック情報を含むresB変数をシリアル化し、シリアル番号にエラーがあるかどうかを判別し、resB変数の逆シリアル化にエラーがあるかどうかを判別します。

resB, err := json.Marshal(res)
if err != nil {
	logger.Error("GetBlockMatchTx", "step", "Marshal res", "err", err.Error())
	return BlockInfo{}, 0, err
}
if err := json.Unmarshal(resB, &block); err != nil {
	logger.Error("GetBlockMatchTx", "step", "Unmarshal block", "err", err.Error())
	return BlockInfo{}, 0, err
}

このメソッドの終了後に実行する遅延関数

defer func() {
	if r := recover(); r != nil {
		//fmt.Printf("捕获到的错误:%s\n", r)
		logger.Error("GetBlockMatchTx", "step", "block info", "panic blockNumber", num, "err", r)
	}
}()

照会されたブロックの高さを取得します

bnum, _ := common.HexToInt64(block.Number)

ブロック内のトランザクション情報、ブロックの高さ、エラー情報を返します

return BlockInfo{TxDatas: block.TxDatas}, bnum, nil

完全なコード

// GetLastBlockTx 获取区块内匹配的交易
func (rc *RequestChain) GetLastBlockTx() (BlockInfo, int64, error) {
    
	num, err := rc.Client.GetLatestBlockNumber()
	res, err := rc.Client.GetBlockByNumber(num, true)
	if err != nil {
		logger.Error("GetBlockMatchTx", "step", "GetBlockByNumber", "err", err.Error())
		return BlockInfo{}, 0, err
	}
	block := new(taskcommon.Block)
	resB, err := json.Marshal(res)
	if err != nil {
		logger.Error("GetBlockMatchTx", "step", "Marshal res", "err", err.Error())
		return BlockInfo{}, 0, err
	}
	if err := json.Unmarshal(resB, &block); err != nil {
		logger.Error("GetBlockMatchTx", "step", "Unmarshal block", "err", err.Error())
		return BlockInfo{}, 0, err
	}
	defer func() {
		if r := recover(); r != nil {
			//fmt.Printf("捕获到的错误:%s\n", r)
			logger.Error("GetBlockMatchTx", "step", "block info", "panic blockNumber", num, "err", r)
		}
	}()
	bnum, _ := common.HexToInt64(block.Number)
	return BlockInfo{TxDatas: block.TxDatas}, bnum, nil
}

1.2指定されたブロックでトランザクションの詳細を取得する

指定されたブロックのトランザクションの詳細を取得することは上記の方法と同じですが、指定されたブロックにはブロックの高さパラメーターが必要であるため、ここでコードが繰り返されることはありません。

// GetBlockMatchTx 获取区块内匹配的交易
func (rc *RequestChain) GetBlockMatchTx(blockNumber string) (BlockInfo, error) {
	res, err := rc.Client.GetBlockByNumber(blockNumber, true)
	if err != nil {
		logger.Error("GetBlockMatchTx", "step", "GetBlockByNumber", "err", err.Error())
		return BlockInfo{}, err
	}
	block := new(taskcommon.Block)
	resB, err := json.Marshal(res)
	if err != nil {
		logger.Error("GetBlockMatchTx", "step", "Marshal res", "err", err.Error())
		return BlockInfo{}, err
	}
	if err := json.Unmarshal(resB, &block); err != nil {
		logger.Error("GetBlockMatchTx", "step", "Unmarshal block", "err", err.Error())
		return BlockInfo{}, err
	}
	defer func() {
		if r := recover(); r != nil {
			//fmt.Printf("捕获到的错误:%s\n", r)
			logger.Error("GetBlockMatchTx", "step", "block info", "panic blockNumber", blockNumber)
		}
	}()

	return BlockInfo{TxDatas: block.TxDatas}, nil
}

2.一致するトランザクションレシートの主な情報を取得します

トランザクションのトランザクション受領情報を照会します

// 分析回执
res, err := rc.Client.GetTransactionReceipt(hash)
if err != nil {
	logger.Error("GetMatchBuyTxHashInfo", "step", "GetTransactionReceipt", "hash", hash, "err", err.Error())
	return TransferReceiptInfo{}, err
}

新しいオブジェクトを定義するために、Ethereumトランザクション構造は「ゼロからのブロックチェーンアプリケーションの開発(9)」で説明されています。

txReceipt := new(taskcommon.TxReceipt)

ブロック情報を含むresB変数をシリアル化し、シリアル番号にエラーがあるかどうかを判別し、resB変数の逆シリアル化にエラーがあるかどうかを判別します。

resB, err := json.Marshal(res)
if err != nil {
	logger.Error("GetMatchBuyTxHashInfo", "step", "Marshal res", "err", err.Error())
	return TransferReceiptInfo{}, err
}
if err := json.Unmarshal(resB, &txReceipt); err != nil {
	logger.Error("GetMatchBuyTxHashInfo", "step", "Unmarshal block", "err", err.Error())
	return TransferReceiptInfo{}, err
}

各トランザクションには、戻り値やログなどのトランザクションの実行結果と、「1」(成功)または「0」(失敗)のイベント結果ステータスを含むレシートがあります。

if txReceipt.Status != "0x1" {
		return TransferReceiptInfo{}, errors.New("contract vm running false")
	}

ハッシュハッシュとアドレス変数からを定義する

matchTopic := "0x6656db943f28baede9b164738dc5fa235b9da60d5c20a38b0eb0230c21196254"
matchAddr := "0x6e60F5243e1a3F0Be3F407b5AFE9e5395ee82aa2"

以下は、nftによってスナップアップされたいくつかのビジネスコードですが、ここでは無視されます

for _, value := range txReceipt.Logs {
	if value.Address != matchAddr {
		continue
	}
	if strings.ToLower(value.Topics[0]) == matchTopic && len(value.Topics) == 4 {
		var record TransferReceiptInfo
		record.OrderId = value.Topics[2][2:]
		record.NftContract = value.Topics[3]
		if len(clearZero(value.Data[2:66])) == 0 {
			record.NftId = "0"
		} else {
			record.NftId = clearZero(value.Data[2:66])
		}
		record.NftNums = clearZero(value.Data[66:130])
		record.NftAmount = clearZero(value.Data[194:258])
		// 计算nft 单价
		nftAmount, _ := new(big.Int).SetString(record.NftAmount, 16)
		nftNums, _ := new(big.Int).SetString(record.NftNums, 16)
		record.UnitPrice = clearZero(hex.EncodeToString(new(big.Int).Div(nftAmount, nftNums).Bytes()))
		return record, nil
	}
}

完全なコード

// GetMatchReceiptInfo 获取匹配交易回执主要信息
func (rc *RequestChain) GetMatchReceiptInfo(hash string) (TransferReceiptInfo, error) {
	defer func() {
		if r := recover(); r != nil {
			//fmt.Printf("%s 捕获到的错误:%s\n", hash,r)
			//logger.Error("GetMatchReceiptInfo", "setp", "txReceipt info", "panic hash", hash)
		}
	}()

	// 分析回执
	res, err := rc.Client.GetTransactionReceipt(hash)
	if err != nil {
		logger.Error("GetMatchBuyTxHashInfo", "step", "GetTransactionReceipt", "hash", hash, "err", err.Error())
		return TransferReceiptInfo{}, err
	}
	txReceipt := new(taskcommon.TxReceipt)
	resB, err := json.Marshal(res)
	if err != nil {
		logger.Error("GetMatchBuyTxHashInfo", "step", "Marshal res", "err", err.Error())
		return TransferReceiptInfo{}, err
	}
	if err := json.Unmarshal(resB, &txReceipt); err != nil {
		logger.Error("GetMatchBuyTxHashInfo", "step", "Unmarshal block", "err", err.Error())
		return TransferReceiptInfo{}, err
	}

	if txReceipt.Status != "0x1" {
		return TransferReceiptInfo{}, errors.New("contract vm running false")
	}
	matchTopic := "0x6656db943f28baede9b164738dc5fa235b9da60d5c20a38b0eb0230c21196254"
	matchAddr := "0x7b4452dd6c38597fa9364ac8905c27ea44425832"
	for _, value := range txReceipt.Logs {
		if value.Address != matchAddr {
			continue
		}
		if strings.ToLower(value.Topics[0]) == matchTopic && len(value.Topics) == 4 {
			var record TransferReceiptInfo
			record.OrderId = value.Topics[2][2:]
			record.NftContract = value.Topics[3]
			if len(clearZero(value.Data[2:66])) == 0 {
				record.NftId = "0"
			} else {
				record.NftId = clearZero(value.Data[2:66])
			}
			record.NftNums = clearZero(value.Data[66:130])
			record.NftAmount = clearZero(value.Data[194:258])
			// 计算nft 单价
			nftAmount, _ := new(big.Int).SetString(record.NftAmount, 16)
			nftNums, _ := new(big.Int).SetString(record.NftNums, 16)
			record.UnitPrice = clearZero(hex.EncodeToString(new(big.Int).Div(nftAmount, nftNums).Bytes()))
			return record, nil
		}
	}
	return TransferReceiptInfo{}, errors.New("no record")
}

3.ブロック内のトランザクション数を取得します

ブロックを取得せずにトランザクションを反復処理する1つの方法は、クライアントのTransactionInBlockメソッドを呼び出すことです。このメソッドは、ブロック内トランザクションのブロックハッシュとインデックス値のみを受け入れます。TransactionCountを呼び出して、ブロック内のトランザクションの数を調べることができます。

blockHash := common.HexToHash("0x9e8751ebb5069389b855bba72d94902cc385042661498a415979b7b6ee9ba4b9")
count, err := client.TransactionCount(context.Background(), blockHash)
if err != nil {
  log.Fatal(err)
}

for idx := uint(0); idx < count; idx++ {
  tx, err := client.TransactionInBlock(context.Background(), blockHash, idx)
  if err != nil {
    log.Fatal(err)
  }

  fmt.Println(tx.Hash().Hex()) // 0x5d49fcaa394c97ec8a9c3e7bd9e8388d420fb050a52083ca52ff24b3b65bc9c2
}

おすすめ

転載: blog.csdn.net/cljdsc/article/details/122748778