API
/getNodeInfo
GET
概要: 获得节点的信息
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getNodeInfo
响应格式
一个成功响应的例子
200 OK
{
    "build_time": "20190329_164908+0800",
    "git_hash": "5d0d3917bae2afab2758c7fe0519b95981252901",
    "mode": "ModeNormal",
    "network": 
    {
        "id": "12D3KooWQ1Uh2tu9GLybc6PwwZHfKkCSFQ3hS9wFUD7mF3xW5KwC",
        "peer_count": 30
    },
    "code_version": "3.0.7",
    "server_time": "1554292230570963220"
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| build_time | string | 构建可执行程序的时间 | 
| git_hash | string | 版本的git hash | 
| mode | string | 节点运行模式, ModeNormal - 正常模式,ModeSync - 同步块模式,ModeInit - 初始化模式 | 
| network | NetworkInfo network | 网络连接信息 | 
| code_version | string | 代码版本号 | 
| server_time | string | 服务器当前时间戳,单位纳秒 | 
NetworkInfo
| 字段 | 类型 | 描述 | 
|---|---|---|
| id | string | 本节点的ID | 
| peer_count | int32 | 邻居节点的数量 | 
/getChainInfo
GET
概要: 获得区块链的信息
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getChainInfo
响应格式
一个成功响应的例子
200 OK
{
    "net_name": "debugnet",
    "protocol_version": "1.0",
    "chain_id": 1024,
    "head_block": "16041",
    "head_block_hash": "DLJVtko6nQnAdvQ7y6dXHo3WMdG324yRLz8tPKk9tGHu",
    "lib_block": "16028",
    "lib_block_hash": "8apn7vCvQ6s9PFBzGfaXrvyL5eAaLNc4mEAgnTMoW8tC",
    "witness_list": ["IOST2K9GKzVazBRLPTkZSCMcyMayKv7dWgdHD8uuWPzjfPdzj93x6J", "IOST2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd", "IOST7E4T5rG9wjPZXDeM1zjhhWU3ZswtPQ1heeRUFUxntr65sYRBi"],
    "lib_witness_list": ["IOST2K9GKzVazBRLPTkZSCMcyMayKv7dWgdHD8uuWPzjfPdzj93x6J", "IOST2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd", "IOST7E4T5rG9wjPZXDeM1zjhhWU3ZswtPQ1heeRUFUxntr65sYRBi"],
    "pending_witness_list": ["IOST2K9GKzVazBRLPTkZSCMcyMayKv7dWgdHD8uuWPzjfPdzj93x6J", "IOST2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd", "IOST7E4T5rG9wjPZXDeM1zjhhWU3ZswtPQ1heeRUFUxntr65sYRBi"],
    "head_block_time": "1552917911507043000",
    "lib_block_time": "1552917911507043000"
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| net_name | string | 网络名字,例如mainnet或testnet | 
| protocol_version | string | iost协议版本 | 
| chain_id | uint32 | 网络 ID | 
| head_block | int64 | 最新块的块号 | 
| head_block_hash | string | 最新块的hash | 
| lib_block | int64 | 不可逆块的高度 | 
| lib_block_hash | string | 不可逆块的hash | 
| witness_list | repeated string | 当前造块节点的pubkey列表 | 
| lib_witness_list | repeated string | 不可逆块时刻的造块节点的pubkey列表 | 
| pending_witness_list | repeated string | 下一轮造块节点的pubkey列表 | 
| head_block_time | int64 | 最新块的区块时间 | 
| lib_block_time | int64 | 不可逆块的区块时间 | 
/getGasRatio
GET
概要: 获取当前上链交易的 gas 倍率信息,方便用户合理设置自己交易的 gas 倍率。
建议使用比 lowest_gas_ratio 稍高的 gas ratio 值,来保证交易尽快上链。
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getGasRatio
响应格式
一个成功响应的例子
200 OK
{
    "lowest_gas_ratio": 1.5,
    "median_gas_ratio": 1.76
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| lowest_gas_ratio | double | 最新的 block 中的打包成功的所有合约的最低 gas ratio | 
| median_gas_ratio | double | 最新的 block 中的打包成功的所有合约的中位数 gas ratio | 
/getRAMInfo
GET
概要: 获取当前区块链的RAM信息,包括用量和价格。
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getRAMInfo
响应格式
一个成功响应的例子
200 OK
{
    "available_ram": "96207067431",
    "buy_price": 0.04227129323234719,
    "sell_price": 0.00014551844642842057,
    "total_ram": "137438953472",
    "used_ram": "41231886041"
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| available_ram | int64 | 可用 RAM 数量,以 byte 为单位 | 
| used_ram | int64 | 已经出售的 RAM 数量,以 byte 为单位 | 
| total_ram | int64 | 系统总计 RAM 数量,以 byte 为单位 | 
| buy_price | double | 此刻购买 RAM 的价格,以 IOST/byte 为单位,已经包含手续费 | 
| sell_price | double | 此刻购买 RAM 的价格,以 IOST/byte 为单位 | 
/getTxByHash/{hash}
GET
概要: 通过交易hash获取交易数据
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getTxByHash/6eGkZoXPQtYXdh7dBSXe2L1ckUCDj4egRn4fXtS2ACnR
| 字段 | 类型 | 描述 | 
|---|---|---|
| hash | string | 交易的hash | 
响应格式
一个成功响应的例子
200 OK
{
    "status": "IRREVERSIBLE",
    "transaction": {
        "hash": "6eGkZoXPQtYXdh7dBSXe2L1ckUCDj4egRn4fXtS2ACnR",
        "time": "1544269519362042000",
        "expiration": "1544279519362041000",
        "gas_ratio": 1,
        "gas_limit": 50000,
        "delay": "0",
        "chain_id": 1024,
        "actions": [{
            "contract": "ContractTBv8ZDKUhTyeS4MomdcHRrXnJMELa5usSMHP6QJntFQ",
            "action_name": "transfer",
            "data": "[\"admin\",\"i1544269477\",1]"
        }],
        "signers": [],
        "publisher": "admin",
        "referred_tx": "",
        "amount_limit": [],
        "tx_receipt": null
    },
    "block_number": "4047298"
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| status | enum | PENDING-交易在缓存中, PACKED - 交易在非不可逆块中,IRREVERSIBLE - 交易在不可逆的块中 | 
| transaction | Transaction transaction | 交易数据 | 
| block_number | string | 交易所在的区块号 | 
Transaction
| 字段 | 类型 | 描述 | 
|---|---|---|
| hash | string | 交易的hash | 
| time | int64 | 交易的时间戳 | 
| expiration | int64 | 交易的过期时间 | 
| gas_ratio | double | Gas费率,建议设置成1(1.00 ~ 100.00),可以通过提高费率来让交易更容易被打包 | 
| gas_limit | double | Gas上限,执行交易所消耗的Gas不会超过这个上限 | 
| delay | int64 | 延迟时间,交易会在延迟时间之后被执行,单位纳秒 | 
| chain_id | uint32 | 网络 ID | 
| actions | repeated Action | 交易的最小执行单元 | 
| signers | repeated string | 交易的签名列表 | 
| publisher | string | 交易提交者,承担交易的执行费用 | 
| referred_tx | string | 交易生成依赖,用于延迟交易 | 
| amount_limit | repeated AmountLimit | 用户可以设置的花费token的限制, 如 {"iost": 100} 即本次交易对于每个签名者花费iost不超过100 | 
| tx_receipt | TxReceipt tx_receipt | 交易Action的receipt | 
Action
| 字段 | 类型 | 描述 | 
|---|---|---|
| contract | string | 调用的合约名字 | 
| action_name | string | 调用的合约函数名 | 
| data | string | 调用的具体参数。把所有的参数生成 array 后再用 json 序列化,一般形如 '["a_string",13]' | 
AmountLimit
| 字段 | 类型 | 描述 | 
|---|---|---|
| token | string | token 名字 | 
| value | double | 这种 token 对应的限额 | 
TxReceipt
| 字段 | 类型 | 描述 | 
|---|---|---|
| tx_hash | string | 交易的hash | 
| gas_usage | double | 交易执行的Gas消耗 | 
| ram_usage | map<string, int64> | 交易的RAM消耗,map-key - 账户名,map-value - 使用RAM量 | 
| status_code | enum | 交易执行状态,SUCCESS - 成功,GAS_RUN_OUT - Gas不足,BALANCE_NOT_ENOUGH - 余额不足,WRONG_PARAMETER - 错误参数, RUNTIME_ERROR - 运行时错误, TIMEOUT - 超时, WRONG_TX_FORMAT - 交易格式错误, DUPLICATE_SET_CODE - 重复设置set code, UNKNOWN_ERROR - 未知错误 | 
| message | string | status_code的详细描述信息 | 
| returns | repeated string | 每个Action的返回值 | 
| receipts | repeated Receipt | event功能使用 | 
Receipt
| 字段 | 类型 | 描述 | 
|---|---|---|
| func_name | string | abi函数的名字 | 
| content | string | 内容 | 
/getTxReceiptByTxHash/{hash}
GET
概要: 通过交易hash获取交易receipt数据
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getTxReceiptByTxHash/6eGkZoXPQtYXdh7dBSXe2L1ckUCDj4egRn4fXtS2ACnR
| 字段 | 类型 | 描述 | 
|---|---|---|
| hash | string | receipt的hash | 
响应格式
一个成功响应的例子
200 OK
{
    "tx_hash": "6eGkZoXPQtYXdh7dBSXe2L1ckUCDj4egRn4fXtS2ACnR",
    "gas_usage": 6633,
    "ram_usage": {
        "admin": "0",
        "issue.iost": "0"
    },
    "status_code": "SUCCESS",
    "message": "",
    "returns": ["[\"\"]"],
    "receipts": [{
        "func_name": "token.iost/transfer",
        "content": "[\"iost\",\"admin\",\"i1544269477\",\"1\",\"\"]"
    }]
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| tx_receipt | TxReceipt | 交易的receipt | 
/getBlockByHash/{hash}/{complete}
GET
概要: 通过block hash获取block的数据
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getBlockByHash/4c9GHyGLi6hUqB4d6zGFcywycYKucsmWsbgvhPe31GaY/false
| 字段 | 类型 | 描述 | 
|---|---|---|
| hash | string | block hash | 
| complete | bool | true - 显示block中的交易, false - 不显示block中交易详情 | 
响应格式
一个成功响应的例子
200 OK
{
    "status": "IRREVERSIBLE",
    "block": {
        "hash": "4c9GHyGLi6hUqB4d6zGFcywycYKucsmWsbgvhPe31GaY",
        "version": "0",
        "parent_hash": "G4njPLnYskU4DcuTz5CwpLPETcfH6yN78V8emge8t21f",
        "tx_merkle_hash": "HHKAG2D7Kon2on5SqV66ZsfdNk9Wus8yhWqdTb86wgPJ",
        "tx_receipt_merkle_hash": "FXr8Mf7hr568MP23BFWJiBUej2xSj3M7416WAKJpswzx",
        "number": "2",
        "witness": "IOST2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd",
        "time": "1544262978309033000",
        "gas_usage": 0,
        "tx_count": "1",
        "info": null,
        "transactions": []
    }
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| status | enum | PENDIND - block在缓存中,IRREVERSIBLE - block不可逆 | 
| block | Block block | block结构体 | 
Block
| 字段 | 类型 | 描述 | 
|---|---|---|
| hash | string | block hash | 
| version | int64 | bock版本号 | 
| parent_hash | string | block父块的hash | 
| tx_merkle_hash | string | 所有交易的merkle tree hash | 
| tx_receipt_merkle_hash | string | 所有receipt的merkle tree hash | 
| number | int64 | block号 | 
| witness | string | block生产者的pubkey | 
| time | int64 | block生产时间 | 
| gas_usage | double | block中交易消耗的总Gas | 
| tx_count | int64 | block中交易总数 | 
| info | Info info | 保留字段 | 
| transactions | repeated Transaction | 交易字段 | 
Info
| 字段 | 类型 | 描述 | 
|---|---|---|
| mode | int32 | 并发的模式,0 - 不并发, 1 - 并发 | 
| thread | int32 | 交易并发执行的线程数量 | 
| batch_index | repeated int32 | 交易的索引 | 
/getBlockByNumber/{number}/{complete}
GET
概要: 通过block号获取block的数据
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getBlockByNumber/3/false
| 字段 | 类型 | 描述 | 
|---|---|---|
| number | int64 | block号 | 
| complete | bool | true - 显示block中的交易, false - 不显示block中交易详情 | 
响应格式
一个成功响应的例子
200 OK
{
    "status": "IRREVERSIBLE",
    "block": {
        "hash": "HPZyoPQ44vsyLDRspjgrySyHnpuiGwckPx8uNtHZugJW",
        "version": "0",
        "parent_hash": "4c9GHyGLi6hUqB4d6zGFcywycYKucsmWsbgvhPe31GaY",
        "tx_merkle_hash": "HHKAG2D7Kon2on5SqV66ZsfdNk9Wus8yhWqdTb86wgPJ",
        "tx_receipt_merkle_hash": "62pESNUGDVsH4B1BCymJvmjGxPu5bb4R3u4x45K9Ybdq",
        "number": "3",
        "witness": "IOST2YKPmRDGy5xLR7Gv65CN5nQ3vMmVhRjAsEM7Gj9xcB1LWgZUAd",
        "time": "1544262978609003000",
        "gas_usage": 0,
        "tx_count": "1",
        "info": null,
        "transactions": []
    }
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| status | enum | PENDIND - block在缓存中,IRREVERSIBLE - block不可逆 | 
| block | Block block | block结构体 | 
/getAccount/{name}/{by_longest_chain}
GET
概要: 获取账号信息
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getAccount/admin/true
| 字段 | 类型 | 描述 | 
|---|---|---|
| name | string | 账户名 | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
响应格式
一个成功响应的例子
200 OK
{
    "name": "admin",
    "balance": 20999997618.36,
    "gas_info": {
        "current_total": 30000000,
        "transferable_gas": 0,
        "pledge_gas": 30000000,
        "increase_speed": 115,
        "limit": 30000000,
        "pledged_info": [
            {
                "pledger": "admin",
                "amount": 100
            },
            {
                "pledger": "foundation",
                "amount": 100
            },
            {
                "pledger": "producer000",
                "amount": 100
            }
        ]
    },
    "ram_info": {
        "available": "100000",
        "used": "0",
        "total": "100000"
    },
    "permissions": {
        "active": {
            "name": "active",
            "group_names": [],
            "items": [
                {
                    "id": "Gcv8c2tH8qZrUYnKdEEdTtASsxivic2834MQW6mgxqto",
                    "is_key_pair": true,
                    "weight": "100",
                    "permission": ""
                }
            ],
            "threshold": "100"
        },
        "owner": {
            "name": "owner",
            "group_names": [],
            "items": [
                {
                    "id": "Gcv8c2tH8qZrUYnKdEEdTtASsxivic2834MQW6mgxqto",
                    "is_key_pair": true,
                    "weight": "100",
                    "permission": ""
                }
            ],
            "threshold": "100"
        }
    },
    "groups": {},
    "frozen_balances": [],
    "vote_infos": []
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| name | string | 账户名字 | 
| balance | double | 余额 | 
| gas_info | GasInfo gas_info | Gas信息 | 
| ram_info | RAMInfo | Ram信息 | 
| permissions | map<string, Permission> | 权限 | 
| groups | map<string, Group> | 权限组 | 
| frozen_balances | repeated FrozenBalance | 冻结余额信息 | 
| vote_infos | repeated VoteInfo | 投票信息 | 
GasInfo
| 字段 | 类型 | 描述 | 
|---|---|---|
| current_total | double | 当前Gas总量 | 
| transferable_gas | double | 可以流通的Gas量 | 
| pledge_gas | double | 质押获得的Gas | 
| increase_speed | double | 每秒增加的Gas | 
| limit | double | 质押Token获得的Gas上限 | 
| pledged_info | repeated PledgeInfo | 本账号帮其他账号质押的信息 | 
PledgeInfo
| 字段 | 类型 | 描述 | 
|---|---|---|
| pledger | string | 接受本账号质押的账号 | 
| amount | double | 本账号给 pledger 质押的金额 | 
RAMInfo
| 字段 | 类型 | 描述 | 
|---|---|---|
| available | int64 | 可用的RAM bytes | 
| used | int64 | 已使用的RAM bytes | 
| total | int64 | 总共RAM bytes | 
Permission
| 字段 | 类型 | 描述 | 
|---|---|---|
| name | string | 权限名字 | 
| group_names | repeated string | 权限组名字 | 
| items | repeated Item | 权限信息 | 
| threshold | int64 | 权限阈值 | 
Item
| 字段 | 类型 | 描述 | 
|---|---|---|
| id | string | 权限名字或者key pair id | 
| is_key_pair | bool | true - id是key pair, false - id为权限名字 | 
| weight | int64 | 权限权重 | 
| permission | string | 权限 | 
Group
| 字段 | 类型 | 描述 | 
|---|---|---|
| name | string | 组名字 | 
| items | repeated Item | 权限组信息 | 
FrozenBalance
| 字段 | 类型 | 描述 | 
|---|---|---|
| amount | double | 金额 | 
| time | int64 | 解冻时间 | 
VoteInfo
| 字段 | 类型 | 描述 | 
|---|---|---|
| option | string | 候选人 | 
| votes | string | 投票数 | 
| cleared_votes | string | 被清零投票数 | 
/getTokenBalance/{account}/{token}/{by_longest_chain}
GET
概要: 获取账号指定代币的余额
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getTokenBalance/admin/iost/true
| 字段 | 类型 | 描述 | 
|---|---|---|
| account | string | 账号名 | 
| token | string | 代币名字 | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
响应格式
一个成功响应的例子
200 OK
{
    "balance": 982678652,
    "frozen_balances": []
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| balance | double | 余额 | 
| frozen_balances | repeated FrozenBalance | 冻结信息 | 
/getContract/{id}/{by_longest_chain}
GET
概要: 通过合约ID获取合约数据
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getContract/base.iost/true
| 字段 | 类型 | 描述 | 
|---|---|---|
| id | string | 合约的ID | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
响应格式
一个成功响应的例子
200 OK
{
    "id": "base.iost",
    "code": "const producerPermission = 'active';\nconst voteStatInterval = 200;\nclass Base {\n    constructor() {\n    }\n    init() {\n        _IOSTInstruction_counter.incr(12);this._put('execBlockNumber', 0);\n    }\n    InitAdmin(adminID) {\n        _IOSTInstruction_counter.incr(4);const bn = block.number;\n        if (_IOSTInstruction_counter.incr(8),_IOSTBinaryOp(bn, 0, '!==')) {\n            _IOSTInstruction_counter.incr(14);throw new Error('init out of genesis block');\n        }\n        _IOSTInstruction_counter.incr(12);this._put('adminID', adminID);\n    }\n    can_update(data) {\n        _IOSTInstruction_counter.incr(12);const admin = this._get('adminID');\n        _IOSTInstruction_counter.incr(12);this._requireAuth(admin, producerPermission);\n        return true;\n    }\n    _requireAuth(account, permission) {\n        _IOSTInstruction_counter.incr(12);const ret = BlockChain.requireAuth(account, permission);\n        if (_IOSTInstruction_counter.incr(8),_IOSTBinaryOp(ret, true, '!==')) {\n            _IOSTInstruction_counter.incr(22);throw new Error(_IOSTBinaryOp('require auth failed. ret = ', ret, '+'));\n        }\n    }\n    _get(k) {\n        _IOSTInstruction_counter.incr(12);const val = storage.get(k);\n        if (_IOSTInstruction_counter.incr(8),_IOSTBinaryOp(val, '', '===')) {\n            return null;\n        }\n        _IOSTInstruction_counter.incr(12);return JSON.parse(val);\n    }\n    _put(k, v) {\n        _IOSTInstruction_counter.incr(24);storage.put(k, JSON.stringify(v));\n    }\n    _vote() {\n        _IOSTInstruction_counter.incr(12);BlockChain.callWithAuth('vote_producer.iost', 'Stat', `[]`);\n    }\n    _bonus(data) {\n        _IOSTInstruction_counter.incr(24);BlockChain.callWithAuth('bonus.iost', 'IssueContribute', JSON.stringify([data]));\n    }\n    _saveBlockInfo() {\n        _IOSTInstruction_counter.incr(12);let json = storage.get('current_block_info');\n        _IOSTInstruction_counter.incr(36);storage.put(_IOSTBinaryOp('chain_info_', block.parentHash, '+'), JSON.stringify(json));\n        _IOSTInstruction_counter.incr(24);storage.put('current_block_info', JSON.stringify(block));\n    }\n    Exec(data) {\n        _IOSTInstruction_counter.incr(12);this._saveBlockInfo();\n        _IOSTInstruction_counter.incr(4);const bn = block.number;\n        _IOSTInstruction_counter.incr(12);const execBlockNumber = this._get('execBlockNumber');\n        if (_IOSTInstruction_counter.incr(8),_IOSTBinaryOp(bn, execBlockNumber, '===')) {\n            return true;\n        }\n        _IOSTInstruction_counter.incr(12);this._put('execBlockNumber', bn);\n        if (_IOSTInstruction_counter.incr(16),_IOSTBinaryOp(_IOSTBinaryOp(bn, voteStatInterval, '%'), 0, '===')) {\n            _IOSTInstruction_counter.incr(12);this._vote();\n        }\n        _IOSTInstruction_counter.incr(12);this._bonus(data);\n    }\n}\n_IOSTInstruction_counter.incr(7);module.exports = Base;",
    "language": "javascript",
    "version": "1.0.0",
    "abis": [{
        "name": "Exec",
        "args": ["json"],
        "amount_limit": []
    }, {
        "name": "can_update",
        "args": ["string"],
        "amount_limit": []
    }, {
        "name": "InitAdmin",
        "args": ["string"],
        "amount_limit": []
    }, {
        "name": "init",
        "args": [],
        "amount_limit": []
    }]
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| id | string | 合约的id | 
| code | string | 合约的代码 | 
| language | string | 合约语言 | 
| version | string | 合约版本 | 
| abis | repeated ABI | 合约的abis | 
ABI
| 字段 | 类型 | 描述 | 
|---|---|---|
| name | string | 接口的名字 | 
| args | repeated string | 接口的参数 | 
| amount_limit | repeated AmountLimit | 金额限制 | 
/getContractStorage
POST
概要: 获取合约的存储数据
请求格式
一个请求格式的例子
curl -X POST http://127.0.0.1:30001/getContractStorage -d '{"id":"token.iost","key":"TIiost","field":"decimal","by_longest_chain":true}'
| 字段 | 类型 | 描述 | 
|---|---|---|
| id | string | 智能合约的ID | 
| key | string | StateDB的key | 
| field | string | 从StateDB中得到值,如果StateDB[key]是一个map,那么需要设置field(可以得到StateDB[key][field]的值) | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
响应格式
一个成功响应的例子
200 OK
{"data":"8","block_hash":"GFfWHwe9cdw5aHaTDExFm2DBzaV9wdgybTQpHsQsbaKS","block_number":"38194"}
| 字段 | 类型 | 描述 | 
|---|---|---|
| data | string | 存储的数据 | 
| block_hash | string | 这个数据来自的区块的 hash | 
| block_number | string | 这个数据来自的区块的编号 | 
/getContractStorageFields
POST
概要: 获取合约存储中 map 的 key 列表,最多返回 256 条。注意:开发者不应该依赖此接口获取合约中一个 map 的所有 key,若有这样的需求,需要自己维护所有的 key。详见 mapKeys。
请求格式
一个请求格式的例子
curl -X POST http://127.0.0.1:30001/getContractStorageFields -d '{"id":"token.iost","key":"TIiost","by_longest_chain":true}'
| 字段 | 类型 | 描述 | 
|---|---|---|
| id | string | 智能合约的ID | 
| key | struct | StateDB的key | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
响应格式
一个成功响应的例子
200 OK
{
    "fields": ["issuer","totalSupply","supply","canTransfer","onlyIssuerCanTransfer","defaultRate","decimal","fullName"]
}
/getBatchContractStorage
POST
概要: 批量获取合约的存储数据
请求格式
一个请求格式的例子
curl -X POST http://127.0.0.1:30001/getBatchContractStorage -d '{"id":"token.iost","key_fields":[{"field":"supply","key":"TIiost"}, {"field":"decimal","key":"TIiost"}, {"field":"xxxx","key":"xxxx"}],"by_longest_chain":true}'
| 字段 | 类型 | 描述 | 
|---|---|---|
| id | string | 智能合约的ID | 
| key_fields | repeated KeyField | 要批量查询的 key-field,返回值的顺序与传入顺序一致 | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
KeyField
| 字段 | 类型 | 描述 | 
|---|---|---|
| key | string | StateDB的key | 
| field | string | 从StateDB中得到值,如果StateDB[key]是一个map,那么需要设置field(可以得到StateDB[key][field]的值) | 
响应格式
一个成功响应的例子
200 OK
{"datas":["2100000000000000000","8","null"],"block_hash":"3Tv3QUPRhhAj7L3j6DCEtkKycXtkeFgAMU3zZU3HA6Qr","block_number":"39123"}
| 字段 | 类型 | 描述 | 
|---|---|---|
| datas | repeated string | 存储的数据,返回顺序与传入顺序一致 | 
| block_hash | string | 这个数据来自的区块的 hash | 
| block_number | string | 这个数据来自的区块的编号 | 
/sendTx
POST
概要:    
把交易发到节点上。
节点收到这个交易后,首先会做基本检查,如果不通过则返回错误,如果通过,则将本交易加入交易池中,并且返回交易的 Hash。
用户在一段时间之后,可以使用这个收到的 Hash 通过 getTxByHash 或 getTxReceiptByTxHash 接口来查询本交易的状态,查看是否执行成功。
注意:   
此接口需要先计算交易的哈希和签名,直接调用较为复杂。
普通用户可以使用 命令行工具 发送交易。
开发者可以使用 Javascript SDK 中的函数接口发送交易。
请求参数
| 字段 | 类型 | 描述 | 
|---|---|---|
| time | int64 | 交易产生时间。UnixEpoch起始,单位纳秒 | 
| expiration | int64 | 交易过期时间。UnixEpoch起始,单位纳秒。如果造块节点在过期时间之后才收到交易,则不会执行 | 
| gas_ratio | double | GAS倍率。本交易按照默认GAS的 gas_ratio 倍来支付费用。倍率越高,越会被优先执行。合理的取值范围是 [1.0, 100.0] | 
| gas_limit | double | 交易最大允许的GAS,最少设置为 50000 | 
| delay | int64 | 延迟交易中使用。延迟执行的纳秒数。非延迟交易设为0 | 
| chain_id | uint32 | 网络 ID | 
| actions | repeated Action | 交易中的具体调用 | 
| amount_limit | repeated AmountLimit | 交易的 token 限制。可以指定多种 token 和对应的数量限制。如果交易超过这些限制,则执行失败 | 
| publisher | string | 交易发送者的 ID | 
| publisher_sigs | repeated Signature | publisher 的签名,签名过程如下。publisher 可以提供多个签名,对应多种不同的权限。可以参考权限系统的文档 | 
| signers | repeated string | 除 publisher 之外的签名人 ID。可以为空 | 
| signatures | repeated Signature | signers 的签名。每个 signer 可以有一个或多个签名,因此长度不低于 signers 长度 | 
Signature
| 字段 | 类型 | 描述 | 
|---|---|---|
| algorithm | string | 加密算法。目前仅支持 "ED25519" 和 "SECP256K1" | 
| signature | string | 合约序列化后使用 sha3 做 hash,之后使用私钥做签名。Base64 编码。细节见对应文档 | 
| public_key | string | 本签名使用的公钥。Base64 编码 | 
响应格式
| 字段 | 类型 | 描述 | 
|---|---|---|
| hash | string | 交易的 hash | 
| pre_tx_receipt | TxReceipt | 被RPC节点预先执行的交易的receipt,需要 RPC 节点打开预执行开关才会返回这个字段 | 
交易签名
交易的签名过程分为三步:将交易结构体转为字节数组;使用 sha3 算法对字节数组计算哈希;使用私钥对哈希进行签名。
- 交易结构体转字节数组 - 交易结构体转字节数组算法为,将交易的每个字段按照声明顺序转成字节数组,然后在不定长类型(比如 string 和结构体)前加上长度,并拼接。各种字段类型转成字节数组的方式见下表: - 字段类型 - 转换方法 - 示例 - int - 按照大端序转成字节数组 - 如 int64(1023) 对应的字节数组为 [0 0 0 0 0 0 3 255] - string - 将字符串中每个字符对应的字节进行拼接并在前面加上长度 - 如 "iost" 对应的字节数组为 [0 0 0 4 105 111 115 116] - 数组 - 将数组的每个元素转为字节数组并拼接,再在其前面加上数组的长度 - 如 ["iost" "iost"] 对应的字节数组为 [0 0 0 2 0 0 0 4 105 111 115 116 0 0 0 4 105 111 115 116] - map - 将字典的每对 key:value 分别转成字节数组并拼接, 然后按照 key 升序排列后拼接每一对,再在其前面加上 map 的长度 - 如 ["b":"iost", "a":"iost"] 对应的字节数组为 [0 0 0 2 0 0 0 1 97 0 0 0 4 105 111 115 116 0 0 0 1 98 0 0 0 4 105 111 115 116] - 交易字段声明顺序为 "time"、"expiration"、"gas_ratio"、"gas_limit"、 "delay"、"chain_id"、"reserved"、"signers"、"actions"、"amount_limit"、"signatures",所以交易结构体转字节数组伪代码为: - func TxToBytes(t transaction) []byte { return Int64ToBytes(t.time) + Int64ToBytes(t. expiration) + Int64ToBytes(int64(t.gas_ratio * 100)) + Int64ToBytes(int64(t.gas_limit * 100)) + // 注意 gas_ratio 和 gas_limit 需要乘以 100 并转成 int64 Int64ToBytes(t.delay) + Int32ToBytes(t.chain_id) + BytesToBytes(t.reserved) + // reserved 为预留字段,只需要在序列化的时候写入空字节数组即可,RPC 请求参数不需要带上此字段 ArrayToBytes(t.signers) + ArrayToBytes(t.actions) + ArrayToBytes(t.amount_limit) + ArrayToBytes(t.signatures) }
- 使用 sha3 算法对字节数组计算哈希 - 需要利用各个语言对应的 sha3 库对上一步的结果计算哈希,得到哈希的字节数组。 
- 使用私钥对哈希进行签名 - iost 支持两种非对称加密算法:"Ed25519" 和 "Secp256k1"。两种算法签名的过程一样:先生成公私钥对,然后使用私钥对上一步的哈希字节数组进行签名。 
 publisher_sigs 签名的私钥必须跟交易字段中的 "publisher" 账户对应,signatures 签名的私钥必须跟交易字段中的 "signers" 账户对应。signatures 用于多重签名,不是必需的,但 publisher_sigs 签名必须要有。交易执行花费的 gas 会从 publisher 账户扣除。
请求示例
假设账户 testaccount 要发送一笔交易,给 anothertest 账户转账 100 iost。
- 构建交易 - { "time": 1544709662543340000, "expiration": 1544709692318715000, "gas_ratio": 1, "gas_limit": 500000, "delay": 0, "chain_id": 1024, "signers": [], "actions": [ { "contract": "token.iost", "action_name": "transfer", "data": "[\"iost\", \"testaccount\", \"anothertest\", \"100\", \"this is an example transfer\"]", }, ], "amount_limit": [ { "token": "*", "value": "unlimited", }, ], "signatures": [], }
- 计算哈希 - 利用上述算法序列化后并 sha3 后,得到哈希值 "/gB8TJQibGI7Kem1v4vJPcJ7vHP48GuShYfd/7NhZ3w="。 
- 计算签名 - 假设 testaccount 账户的公私钥算法为 ED25519,公钥为 "lDS+SdM+aiVHbDyXapvrsgyKxFg9mJuHWPZb/INBRWY=",私钥为 "gkpobuI3gbFGstgfdymLBQAGR67ulguDzNmLXEJSWaGUNL5J0z5qJUdsPJdqm+uyDIrEWD2Ym4dY9lv8g0FFZg==",利用私钥对上一步的哈希签名,得到 "/K1HM0OEbfJ4+D3BmalpLmb03WS7BeCz4nVHBNbDrx3/A31aN2RJNxyEKhv+VSoWctfevDNRnL1kadRVxSt8CA==" 
- 发送交易 - 现在完整的交易请求参数为: - { "time": 1544709662543340000, "expiration": 1544709692318715000, "gas_ratio": 1, "gas_limit": 500000, "delay": 0, "chain_id": 1024, "signers": [], "actions": [ { "contract": "token.iost", "action_name": "transfer", "data": "[\"iost\", \"testaccount\", \"anothertest\", \"100\", \"this is an example transfer\"]", }, ], "amount_limit": [ { "token": "*", "value": "unlimited", }, ], "signatures": [], "publisher": "testaccount", "publisher_sigs": [ { "algorithm": "ED25519", "public_key": "lDS+SdM+aiVHbDyXapvrsgyKxFg9mJuHWPZb/INBRWY=", "signature": "/K1HM0OEbfJ4+D3BmalpLmb03WS7BeCz4nVHBNbDrx3/A31aN2RJNxyEKhv+VSoWctfevDNRnL1kadRVxSt8CA==", }, ], }- 对上述结构进行 json 序列化后,发送如下 rpc 请求即可: - curl -X POST http://127.0.0.1:30001/sendTx -d '{"actions":[{"action_name":"transfer","contract":"token.iost","data":"[\"iost\", \"testaccount\", \"anothertest\", \"100\", \"this is an example transfer\"]"}],"amount_limit":[{"token":"*","value":"unlimited"}],"delay":0,"chain_id":1024, "expiration": 1544709692318715000,"gas_limit":500000,"gas_ratio":1,"publisher":"testaccount","publisher_sigs":[{"algorithm":"ED25519","public_key":"lDS+SdM+aiVHbDyXapvrsgyKxFg9mJuHWPZb/INBRWY=","signature":"/K1HM0OEbfJ4+D3BmalpLmb03WS7BeCz4nVHBNbDrx3/A31aN2RJNxyEKhv+VSoWctfevDNRnL1kadRVxSt8CA=="}],"signatures":[],"signers":[],"time": 1544709662543340000}'
/execTx
POST
概要:    
把交易发到节点,立刻执行,但是不会被上链共识,也不会被持久化。
本接口可以用来在测试合约的执行结果是否符合预期。当然,由于调用时间不同,execTx 的行为不能保证和正式链上执行完全一致。
请求格式
本接口请求格式和 /sendTx 相同。
响应格式
本接口响应格式和 /getTxReceiptByTxHash 相同。
/subscribe
POST
概要: 订阅事件,包括智能合约中触发的事件和交易执行完的事件。
请求格式
一个请求格式的例子
curl -X POST http://127.0.0.1:30001/subscribe -d '{"topics":["CONTRACT_RECEIPT"], "filter":{"contract_id":"token.iost"}}'
| 字段 | 类型 | 描述 | 
|---|---|---|
| topics | repeated enum | 订阅的事件主题,枚举类型有两种值,CONTRACT_EVENT-合约中触发的事件, CONTRACT_RECEIPT-交易执行完的事件 | 
| filter | Filter | 收到的事件会按照 filter 中的字段过滤,若不传这一字段,则会收到所有 topics 中的事件数据 | 
Filter
| 字段 | 类型 | 描述 | 
|---|---|---|
| contract_id | string | 智能合约的 id | 
响应格式
一个成功响应的例子
{"result":{"event":{"topic":"CONTRACT_RECEIPT","data":"[\"contribute\",\"producer00001\",\"900\"]","time":"1545646637413936000"}}}
{"result":{"event":{"topic":"CONTRACT_RECEIPT","data":"[\"contribute\",\"producer00001\",\"900\"]","time":"1545646637711757000"}}}
{"result":{"event":{"topic":"CONTRACT_RECEIPT","data":"[\"contribute\",\"producer00001\",\"900\"]","time":"1545646638013188000"}}}
{"result":{"event":{"topic":"CONTRACT_RECEIPT","data":"[\"contribute\",\"producer00001\",\"900\"]","time":"1545646638317840000"}}}
...
| 字段 | 类型 | 描述 | 
|---|---|---|
| topic | enum | 事件的主题,CONTRACT_EVENT-合约中触发的事件, CONTRACT_RECEIPT-交易执行完的事件 | 
| data | string | 事件数据 | 
| time | int64 | 事件的时间戳 | 
/getCandidateBonus/{name}/{by_longest_chain}
GET
概要: 获取节点可领取的投票收益
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getCandidateBonus/erebus/1
| 字段 | 类型 | 描述 | 
|---|---|---|
| name | string | 节点账户名 | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
响应格式
一个成功响应的例子
200 OK
{
    "bonus": 111866.61819617149
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| bonus | double | 可领取的投票收益 | 
/getVoterBonus/{name}/{by_longest_chain}
GET
概要: 获取投票者可领取的投票收益
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getVoterBonus/admin/1
| 字段 | 类型 | 描述 | 
|---|---|---|
| name | string | 投票者账户名 | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
响应格式
一个成功响应的例子
200 OK
{
    "bonus": 94875.58356478,
    "detail":
    {
        "dapppub": 15414.37339835,
        "iostamerica": 17212.96477434,
        "laomao": 9895.73931972,
        "metanyx": 29877.55014659,
        "sutler": 20924.99488913,
        "tokenpocket": 1549.96103665
    }
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| bonus | double | 可领取的总投票收益 | 
| detail | map<string, double> | 从每个候选人得到的收益 | 
/getTokenInfo/{symbol}/{by_longest_chain}
GET
概要: 获取 token 信息
请求格式
一个请求格式的例子
curl http://127.0.0.1:30001/getTokenInfo/iost/1
| 字段 | 类型 | 描述 | 
|---|---|---|
| symbol | string | token 名字 | 
| by_longest_chain | bool | true - 从最长链得到数据,false - 从不可逆块得到数据 | 
响应格式
一个成功响应的例子
200 OK
{
    "symbol": "iost",
    "full_name": "iost",
    "issuer": "issue.iost",
    "total_supply": "9000000000000000000",
    "current_supply": "2100000000000000000",
    "decimal": 8,
    "can_transfer": true,
    "only_issuer_can_transfer": false,
    "total_supply_float": 90000000000,
    "current_supply_float": 21000000000
}
| 字段 | 类型 | 描述 | 
|---|---|---|
| symbol | string | token 名字 | 
| full_name | string | token 全称 | 
| issuer | string | token 发行人 | 
| total_supply | string | token 总发行量,其值等于 total_supply_float 乘以 decimal | 
| current_supply | string | token 当前发行量,其值等于 current_supply_float 乘以 decimal | 
| total_supply_float | double | token 总发行量 | 
| current_supply_float | double | token 当前发行量 | 
| decimal | int | token 小数位 | 
| can_transfer | bool | token 能否进行转账 | 
| only_issuer_can_transfer | bool | 是否只能由代币发行者转账 | 
