Skip to content

GRPC 交易接口

linj edited this page Nov 23, 2022 · 1 revision

交易接口

[TOC]

1 构造并发送交易

要发送一个交易,均需要经过三个步骤:构造交易->交易签名->发送交易;

**构造交易:**填写交易的关键信息,从而构造一条完整的交易数据; **交易签名:**对交易数据进行签名,即标识交易的所有者身份,也防止交易数据被篡改; **发送交易:**将交易数据发送到区块链上去执行;

下面分别介绍三个接口

1.1 构造交易 CreateRawTransaction

调用接口

rpc CreateRawTransaction(CreateTx) returns (UnsignTx) {}

参数:

  1. ctx context.Context 类型,默认可以用context.Background(), 其他用法可以参考context 包内容
  2. CreateTx 结构体参数展示
message CreateTx {
    string to          = 1;
    int64  amount      = 2;
    int64  fee         = 3;
    bytes  note        = 4;
    bool   isWithdraw  = 5;
    bool   isToken     = 6;
    string tokenSymbol = 7;
    string execName    = 8;
    string execer      = 9;
}

参数说明:

参数 类型 是否必填 说明
to string 发送到地址;如果是合约的充提则为合约地址,合约地址为execName转换而来,详情查看ConvertExectoAddr接口
amount int64 发送金额,注意基础货币单位为10^8
fee int64 手续费,注意基础货币单位为10^8
note bytes 备注
isToken bool 是否是token类型的转账 (非token转账这个不用填 包括平行链的基础代币转账也不用填)
isWithdraw bool 是否为从合约中提款的交易,普通转账为false
tokenSymbol string token 的 symbol (非token转账这个不用填)
execName string 目标合约名,如果要构造平行链上的转账或普通转账,此参数置空
execer string 资产的执行器名称,如果是普通转账,此处应填coins,如果是构造平行链的基础代币,此处要填写user.p.xxx.coins token同上

返回数据:

message UnsignTx {
    bytes data = 1;
}

参数说明:

参数 类型 说明
data bytes 交易对象的十六进制字符串编码

1.2 交易签名 SignRawTx

调用接口

rpc SignRawTx(ReqSignRawTx) returns (ReplySignRawTx) {}

参数:

message ReqSignRawTx {
    string addr    = 1;
    string privkey = 2;
    string txHex   = 3;
    string expire  = 4;
    int32  index   = 5;
    // 签名的模式类型
    // 0:普通交易
    // 1:隐私交易
    // int32  mode  = 6;
    string token = 7;
    int64  fee   = 8;
    // bytes  newExecer = 9;
    string newToAddr = 10;
}

参数说明:

参数 类型 是否必填 说明
addr string addr与privkey可以只输入其一,如果使用addr则依赖钱包中存储的私钥签名
privkey string addr与privkey可以只输入其一,如果使用privkey则直接签名
txHex string 上一步生成的原始交易数据
expire string 过期时间可输入如"300s","-1.5h"或者"2h45m"的字符串,有效时间单位为"ns", "us" (or "µs"), "ms", "s", "m", "h"
index int32 若是签名交易组,则为要签名的交易序号,从1开始,小于等于0则为签名组内全部交易
token string token 名称
fee int64 费用
newToAddr string -

返回数据:

message ReplySignRawTx {
    string txHex = 1;
}

参数说明:

参数 类型 说明
txHex string 交易签名后的十六进制字符串

1.3 发送交易 SendTransaction

调用接口

rpc SendTransaction(Transaction) returns (Reply) {}

参数:

message Transaction {
    bytes     execer    = 1;
    bytes     payload   = 2;
    Signature signature = 3;
    int64     fee       = 4;
    int64     expire    = 5;
    //随机ID,可以防止payload 相同的时候,交易重复
    int64 nonce = 6;
    //对方地址,如果没有对方地址,可以为空
    string to         = 7;
    int32  groupCount = 8;
    bytes  header     = 9;
    bytes  next       = 10;
    int32  chainID    = 11;
}

message Signature {
    int32 ty     = 1;
    bytes pubkey = 2;
    bytes signature = 3;
}

参数说明:

参数 类型 是否必填 说明
execer bytes 资产的执行器名称,如果是普通转账,此处应填coins,如果是构造平行链的基础代币,此处要填写user.p.xxx.coins token同上
payload bytes 参数
signature Signature 签名
signature.ty int32 签名类型,1 -> secp256k1; 2 -> ed25519; 3 -> sm2; 4 -> OnetimeED25519; -> RingBaseonED25519
signature.pubkey bytes 公钥
signature.signature bytes 签名 //当ty为5时,格式应该用RingSignature去解析
fee int64 手续费,注意基础货币单位为10^8,默认10^5,即Fee=1e5
expire int64 超时时间
nonce int64 随机ID
to string 发送到地址;如果是合约的充提则为合约地址,合约地址为execName转换而来,详情查看ConvertExectoAddr接口
groupCount int32 交易组
header bytes 区块头
next bytes 下一个交易的哈希
chainID bool chain ID

返回数据:

message Reply {
    bool  isOk = 1;
    bytes msg  = 2;
}

参数说明:

参数 类型 说明
isOk bool 执行是否成功,true 成功
msg bytes 交易信息

go 代码示例: 假定 grpc服务地址:localhost:8802

package main

import (
	"context"
	"github.com/33cn/chain33/common"
	chan33Ty "github.com/33cn/chain33/types"
	"google.golang.org/grpc"
)

func main() {
	conn, err := grpc.Dial("localhost:8802", grpc.WithInsecure(), grpc.WithBlock(), grpc.FailOnNonTempDialError(true))
	if err != nil {
		//异常处理逻辑
		panic(err)
	}
	defer conn.Close()
	gclient := chan33Ty.NewChain33Client(conn)
	txData, err := gclient.CreateRawTransaction(context.Background(), &chan33Ty.CreateTx{Amount: 10000000, To: "16hXXX", Execer: "coins"})
	if err != nil {
		panic(err)
	}
	signedTx, err := gclient.SignRawTx(context.Background(), &chan33Ty.ReqSignRawTx{Privkey: "xxx", TxHex: common.ToHex(txData.Data)})
	if err != nil {
		panic(err)
	}

	txBytes, err := common.FromHex(signedTx.TxHex)
	if err != nil {
		panic(err)
	}
	var tx chan33Ty.Transaction
	chan33Ty.Decode(txBytes, &tx)
	reply, err := gclient.SendTransaction(context.Background(), &tx)
	if err != nil {
		panic(err)
	}
	t.Log(reply.IsOk, common.ToHex(reply.Msg))
}

1.4 构造并发送不收手续费交易 CreateNoBalanceTransaction(平行链)

在平行链的使用场景中,可以发送不收手续费的交易,具体步骤如下: 构造交易 -> 平行链交易包装 -> 交易签名 -> 发送交易 后面的交易签名步骤里需要注意一点,参数index需填2

它和普通交易相比,多了一个 平行链交易包装 的步骤,对应接口如下

调用接口

rpc CreateNoBalanceTransaction(NoBalanceTx) returns (ReplySignRawTx) {}

参数:

message NoBalanceTx {
    string txHex   = 1;
    string payAddr = 2;
    string privkey = 3;
    string expire  = 4;
}

参数说明:

参数 类型 是否必填 说明
txHex string 未签名的原始交易数据
payAddr string 用于付费的地址,这个地址要在主链上存在,并且里面有比特元用于支付手续费, payAddr与privkey可以只输入其一,如果使用payAddr则依赖钱包中存储的私钥签名
privkey string 对应于payAddr的私钥。如果payAddr已经导入到平行链,可以只传地址
expire string 过期时间可输入如"300s","-1.5h"或者"2h45m"的字符串,有效时间单位为"ns", "us" (or "µs"), "ms", "s", "m", "h", 不传递默认设置永不过期

返回数据:

message ReplySignRawTx {
    string txHex = 1;
}

参数说明:

参数 类型 说明
txHex string 未签名的原始交易数据

1.5 构造多笔并发送不收手续费交易 CreateNoBlanaceTxs(平行链)

同1.1.4 一样,可以创建发送不需要手续费的交易,不同的是,1.1.4接口只能构造单笔免手续费交易,而本接口可以创建多笔免手续费交易

调用接口

rpc CreateNoBalanceTxs(NoBalanceTxs) returns (ReplySignRawTx) {}

参数:

message NoBalanceTxs {
    repeated string txHexs  = 1;
    string          payAddr = 2;
    string          privkey = 3;
    string          expire  = 4;
}

参数说明:

参数 类型 是否必填 说明
txHexs []string 未签名的原始交易数据
payAddr string 用于付费的地址,这个地址要在主链上存在,并且里面有比特元用于支付手续费, payAddr与privkey可以只输入其一,如果使用payAddr则依赖钱包中存储的私钥签名
privkey string 对应于payAddr的私钥。如果payAddr已经导入到平行链,可以只传地址
expire string 过期时间可输入如"300s","-1.5h"或者"2h45m"的字符串,有效时间单位为"ns", "us" (or "µs"), "ms", "s", "m", "h", 不传递默认设置永不过期

返回数据:

message ReplySignRawTx {
    string txHex = 1;
}

参数说明:

参数 类型 说明
txHex string 未签名的原始交易数据

1.6 重写交易 ReWriteRawTx

支持对原始交易或交易组参数重写

调用接口

rpc ReWriteTx(ReWriteRawTx)returns(UnsignTx){}

参数:

message ReWriteRawTx {
    string tx = 1;
    // bytes  execer = 2;
    string to     = 3;
    string expire = 4;
    int64  fee    = 5;
    int32  index  = 6;
}

参数说明:

参数 类型 是否必填 说明
to string 重写交易的目的地址,只有单笔交易生效,交易组不生效
fee int64 重写交易的费用,交易组只会修改第一笔交易的费用
tx string 需要重写的原始交易数据
expire string 过期时间可输入如"300ms",”-1.5h”或者”2h45m”的字符串,有效时间单位为”ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”
index int32 若是交易组,则为要重写的交易序号,从1开始,小于等于0则为交易组内全部交易

返回数据:

message UnsignTx {
    bytes data = 1;
}

参数说明:

参数 类型 说明
data bytes 重写之后交易的十六进制字符串

1.7 错误信息

code output description
txExistErr transaction exists 该交易已存在mempool中
lowFeeErr low transaction fee 交易费过低
manyTxErr you have too many transactions 同一账户在mempool中有超过10笔交易
signErr wrong signature 签名错误
lowBalanceErr low balance 余额不足
bigMsgErr message too big 消息过大
expireErr message expired 消息过期
loadAccountsErr loadacconts error 匹配账户错误
emptyTxErr empty transaction 交易为空
dupTxErr duplicated transaction 重复交易
memNotReadyErr mempool not ready mempool未启动
memFullErr mempool is full mempool已满

2 根据哈希查询交易信息 QueryTransaction

调用接口

rpc QueryTransaction(ReqHash) returns (TransactionDetail) {}

参数:

message ReqHash {
    bytes hash    = 1;
    bool  upgrade = 2;
}

参数说明:

参数 类型 是否必填 说明
hash bytes 交易哈希
upgrade bool 是否升级

返回数据:

message TransactionDetail {
    Transaction tx            = 1;
    ReceiptData receipt       = 2;
    repeated bytes proofs     = 3;
    int64          height     = 4;
    int64          index      = 5;
    int64          blocktime  = 6;
    int64          amount     = 7;
    string         fromaddr   = 8;
    string         actionName = 9;
    repeated Asset assets     = 10;
    repeated TxProof txProofs = 11;
    bytes            fullHash = 12;
}

message ReceiptData {
    int32    ty              = 1;
    repeated ReceiptLog logs = 3;
}

参数说明:

参数 类型 说明
tx Transaction 交易基本信息
receipt ReceiptData 交易执行结果信息
actionName string 操作名称,不同的执行器可能会有不同的值,如coins(transfer,withdraw,genesis),ticket(genesis,open,close,miner)
receipt.Ty int32 receipt.ty == 1 表示执行失败;receipt.ty == 2 表示执行成功

3 根据地址获取交易信息 GetTransactionByAddr

调用接口

rpc GetTransactionByAddr(ReqAddr) returns (ReplyTxInfos) {}

参数:

message ReqAddr {
    string addr = 1;
    //表示取所有/from/to/其他的hash列表
    int32 flag      = 2;
    int32 count     = 3;
    int32 direction = 4;
    // height start
    int64 height    = 5;
    int64 index     = 6;
    int64 heightEnd = 7;
}

参数说明:

参数 类型 是否必填 说明
addr string 要查询的账户地址
count int32 返回的数据条数
direction int32 查询的方向;0:正向查询,区块高度从低到高;-1:反向查询;
flag int32 交易类型;0:所有涉及到addr的交易; 1:addr作为发送方; 2:addr作为接收方;
height int64 交易所在的block高度,-1:表示从最新的开始向后取;大于等于0的值,从具体的高度+具体index开始取
index int64 交易所在block中的索引,取值0--100000

返回数据:

message ReplyTxInfos {
    repeated ReplyTxInfo txInfos = 1;
}

message ReplyTxInfo {
    bytes    hash         = 1;
    int64    height       = 2;
    int64    index        = 3;
    repeated Asset assets = 4;
}

message Asset {
    string exec   = 1;
    string symbol = 2;
    int64  amount = 3;
}

参数说明:

参数 类型 说明
txInfos []ReplyTxInfo 交易数组;包含交易的哈希、高度、以及资产信息;
txInfos.hash bytes 交易 id,可以通过接口 QueryTransaction 获取具体的交易信息
txInfos.assets []Asset 资产信息, 列出交易相关的资产。 可能整个数组 为 null

4 根据哈希数组批量获取交易信息 GetTransactionByHashes

调用接口

rpc GetTransactionByHashes(ReqHashes) returns (TransactionDetails) {}

参数:

message ReqHashes {
    repeated bytes hashes = 1;
}

参数说明:

参数 类型 是否必填 说明
hashes []bytes 交易ID列表

返回数据:

message TransactionDetails {
    repeated TransactionDetail txs = 1;
}

message TransactionDetail {
    Transaction tx            = 1;
    ReceiptData receipt       = 2;
    repeated bytes proofs     = 3;
    int64          height     = 4;
    int64          index      = 5;
    int64          blocktime  = 6;
    int64          amount     = 7;
    string         fromaddr   = 8;
    string         actionName = 9;
    repeated Asset assets     = 10;
    repeated TxProof txProofs = 11;
    bytes            fullHash = 12;
}

参数说明:

参数 类型 说明
txs []TransactionDetail 单个交易详情信息,请参考 QueryTransaction接口

3 根据哈希获取交易的字符串 GetHexTxByHash

调用接口

rpc GetHexTxByHash(ReqHash) returns (HexTx) {}

参数:

message ReqHash {
    bytes hash    = 1;
    bool  upgrade = 2;
}

参数说明:

参数 类型 是否必填 说明
hash bytes 交易哈希

返回数据:

message HexTx {
    string tx = 1;
}

参数说明:

参数 类型 说明
tx string 交易对象的十六进制编码数据

4 获取地址相关摘要信息 GetAddrOverview

调用接口

rpc GetAddrOverview(ReqAddr) returns (AddrOverview) {}

参数:

message ReqAddr {
    string addr = 1;
    //表示取所有/from/to/其他的hash列表
    int32 flag      = 2;
    int32 count     = 3;
    int32 direction = 4;
    int64 height    = 5;
    int64 index     = 6;
}

参数说明:

参数 类型 是否必填 说明
addr string 要查询的账户地址
count int32 返回的数据条数
direction int32 查询的方向;0:正向查询,区块高度从低到高;-1:反向查询;
flag int32 交易类型;0:所有涉及到addr的交易; 1:addr作为发送方; 2:addr作为接收方;
height int64 交易所在的block高度,-1:表示从最新的开始向后取;大于等于0的值,从具体的高度+具体index开始取
index int64 交易所在block中的索引,取值0--100000

注意:本接口目前只是用到了addr参数,其它参数均无意义;

返回数据:

message AddrOverview {
    int64 reciver = 1;
    int64 balance = 2;
    int64 txCount = 3;
}

参数说明:

参数 类型 说明
reciver int64 一共接收的金额
txCount int64 交易量计数
balance int64 当前余额

7 将合约名转成实际地址 ConvertExectoAddr

调用接口

rpc ConvertExectoAddr(ReqString) returns (ReplyString) {}

参数:

message ReqString {
    string data = 1;
}

参数说明:

参数 类型 是否必填 说明
data string 执行器名称,如果需要往执行器中转币这样的操作,需要调用些接口将执行器名转成实际地址

返回数据:

message ReplyString {
    string data = 1;
}

参数说明:

参数 类型 说明
data string 转换生成的地址字符串

5 构造交易组 CreateRawTxGroup

调用接口

rpc CreateRawTxGroup(CreateTransactionGroup) returns (UnsignTx) {}

参数:

message CreateTransactionGroup {
    repeated string txs = 1;
}

参数说明:

参数 类型 是否必填 说明
txs []string 十六进制格式交易数组

返回数据:

message UnsignTx {
    bytes data = 1;
}

参数说明:

参数 类型 说明
data bytes 交易组对象的十六进制字符串

6 获取单元交易费率 GetProperFee

调用接口

rpc GetProperFee(ReqProperFee) returns (ReplyProperFee) {}

参数:

message ReqProperFee {
    int32 txCount = 1;
    int32 txSize  = 2;
}

参数说明:

参数 类型 是否必填 说明
txCount int32 预发送的交易个数,单个交易发送默认空即可
txSize int32 预发送交易的大小, 单位Byte, 字节
  • 通常采用默认传递即可
  • 对于阶梯交易费模式,在同时发送多笔交易时, 可以指定将要发送的个数和总大小(字节)进行前瞻性估计

返回数据:

message ReplyProperFee {
    int64 properFee = 1;
}

参数说明:

参数 类型 说明
properFee int64 每KB交易大小所需交易费, 单位1/108的BTY

设置说明:

  • 手动设置 上述接口返回的是单元大小的交易费率, 即每KB所需的交易费, 同时交易需要在签名前设置交易费,需要预估签名数据所占用大小,普通交易公私钥签名可预设为300字节
//参考代码
txFee := int64((txSizeKB+300)/1000+1) * properFee
  • 自动设置 bityuan 6.2.1+版本, 以下接口支持自动设置合适交易费

    • Chain33.SendToAddress
    • Chain33.SignRawTx(交易费参数保留未设置或为0)
  • 失败处理 在实际应用中, 仍然可能出现交易费过低导致失败情况, 建议代码中增加出错处理, 如失败时将交易费倍数递增(需要重新签名且注意设置上限,通常是0.1), 或者等待一段时间继续尝试 相关错误码:

"ErrTxFeeTooLow" 交易手续费太低

Clone this wiki locally