
# 一、接口描述 
## 1 发布竞猜游戏
### 1.1 生成创建竞猜游戏的交易（未签名）
**请求报文：**
```json
  request: http.post
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "Chain33.CreateTransaction",
  "params": [
    {
      "execer": "guess",
      "actionName": "Start",
      "payload": {
        "topic": "WorldCup Final",
        "options": "A:France;B:Claodia",
        "category": "football",
        "maxBetsOneTime": 10000000000,
        "maxBetsNumber": 100000000000,
        "devFeeFactor": 5,
        "devFeeAddr": "1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7",
        "platFeeFactor": 5,
        "platFeeAddr": "1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX",
        "maxBetHeight": "2000",
        "expireHeight": "100000",
      }
    }
  ]
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|topic|string|竞猜标题，比如：世界杯决赛法国对阵克罗地亚，谁将获得冠军|
|options|string|竞猜选项，以;分割，:前为选项名称（A/B/C或者1/2/3等）比如：A:法国夺冠;B:克罗地亚夺冠|
|category|string|竞猜所属类型，比如"足球"，"football"等，如果不填归入default|
|maxBetsOneTime|int64|一次最多下注数量，比如:10000e8，表示最多1000个bty或者游戏币|
|maxBetsNumber|int64|一局游戏最多投注数量，比如:1000000e8，表示做多100万个bty或者游戏币|
|devFeeFactor|int64|开发者分成比例，单位1/1000，比如：投注额的5/1000|
|devFeeAddr|string|开发者分成账户地址，默认为：1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7|
|platFeeFactor|int64|平台方分成比例，单位1/1000，比如：投注额的5/1000|
|platFeeAddr|string|1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX|
|maxBetHeight|int64|最大下注高度，从创建游戏的高度算起，超过该高度后不允许再下注，是一种保护，可以不填，完全由管理员程序保证及时停止下注|
|expireHeight|int64|超时高度，从创建游戏的高度算起，超过该高度后，游戏将进入过期状态，谁都可以撤销游戏，返回玩家下注，可以不填，完全由管理员程序保证及时停止下注|

**响应报文：**
```json
response:
{
  "id": 2,
  "result": "0a12757365722e702e67756573732e6775657373128c0138050a87010a0e576f726c644375702046696e616c1212413a4672616e63653b423a436c616f6469611a08666f6f7462616c6c2880c8afa0253080d0dbc3f4023805422231443652465a4e7032726836516462635a31643752577542557a3631576536534437480552223150487443684e743355636673735237763774724b536b33574a7441576a4b6a6a5820c0843d30cbbffaeda9b1dcd2023a223139455a316e677138703254507335544c70455a77546a6e6e416766746159616e68",
  "error": null
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|result|string|交易十六进制编码后的字符串|


#### 1.2 交易签名 SignRawTx

**请求报文：**
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "Chain33.SignRawTx",
  "params": [
    {
      "addr": "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt",
      "privKey": "0x8d8523fbd09c27dabc853e99daf167533acaa1e2a2498dc2cb7449cff8137a37",
      "txHex": "0a12757365722e702e67756573732e6775657373128c0138050a87010a0e576f726c644375702046696e616c1212413a4672616e63653b423a436c616f6469611a08666f6f7462616c6c2880c8afa0253080d0dbc3f4023805422231443652465a4e7032726836516462635a31643752577542557a3631576536534437480552223150487443684e743355636673735237763774724b536b33574a7441576a4b6a6a5820a08d0630fe86c8ccf4b490a0323a223139455a316e677138703254507335544c70455a77546a6e6e416766746159616e68",
      "expire": "3600s",
      "index": 0,
      "model": 0
    }
  ]
}
```

**参数说明：**

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

**响应报文：**
```json
{
  "id": 1,
  "result": " ",
  "error": null
}
```

**参数说明：**

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


#### 1.3 发送交易 SendTransaction
**请求报文：**
```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "Chain33.SendTransaction",
  "params": [
    {
      "data": " "
    }
  ]
}
```

**参数说明：**

|参数|类型|是否必填|说明|
|----|----|----|----|
|data|string|是|为上一步签名后的交易数据|

**响应报文：**
```json
{
  "id": 2,
  "result": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
  "error": null
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|result|string|交易发送后，生成的交易哈希（后面可以使用此哈希查询交易状态和历史）|

## 2 参与竞猜游戏
### 2.1 生成参与竞猜游戏的交易（未签名）
**请求报文：**
```json
  request: http.post
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "Chain33.CreateTransaction",
  "params": [
    {
      "execer": "guess",
      "actionName": "Bet",
      "payload": {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
        "option": "A",
        "betsNum": 500000000
      }
    }
  ]
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|游戏ID|
|option|string|投注选项，与创建游戏时的options中的可选选项对应，为其中某一个选项，比如A/B/C/1/2/3/...|
|betsNum|ing64|投注数额，比如5e8|

**响应报文：**
```json
response:
{
  "id": 2,
  "result": "0a12757365722e702e67756573732e677565737312513806124d0a423078643964646466663834373533653138663930323331656132633932386466366566323565656632346130353166333464323264323632623864336463393262341201411880cab5ee0120a08d06308e9087f9a4f9effd393a223139455a316e677138703254507335544c70455a77546a6e6e416766746159616e68",
  "error": null
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|result|string|交易十六进制编码后的字符串|

## ３ 停止某局竞猜游戏投注
### 3.1 生成某局游戏停止投注的交易（未签名）
**请求报文：**
```json
  request: http.post
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "Chain33.CreateTransaction",
  "params": [
    {
      "execer": "guess",
      "actionName": "StopBet",
      "payload": {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4"
      }
    }
  ]
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|停止投注的游戏ID|

说明：　　
该交易必须由游戏发起地址来创建。

**响应报文：**
```json
response:
{
  "id": 2,
  "result": "0a12757365722e702e67756573732e6775657373124838071a440a4230786439646464666638343735336531386639303233316561326339323864663665663235656566323461303531663334643232643236326238643364633932623420a08d0630a58a95b2fbd791de2d3a223139455a316e677138703254507335544c70455a77546a6e6e416766746159616e68",
  "error": null
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|result|string|交易十六进制编码后的字符串|

## 4 公布某局竞猜游戏结果
### ４.1 生成某局游戏公布结果的交易（未签名）
**请求报文：**
```json
  request: http.post
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "Chain33.CreateTransaction",
  "params": [
    {
      "execer": "guess",
      "actionName": "Publish",
      "payload": {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
        "result": "B"
      }
    }
  ]
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|停止投注的游戏ID|
|result|string|最终正确选项，与创建游戏中的options对应，为其中某一个选项A/B/C/1/2/3...|

说明：　　
该交易必须由游戏发起地址来创建。

**响应报文：**
```json
response:
{
  "id": 2,
  "result": "0a12757365722e702e67756573732e6775657373124b38092a470a4230786439646464666638343735336531386639303233316561326339323864663665663235656566323461303531663334643232643236326238643364633932623412014220a08d0630acd1fbe6f7a3fca6733a223139455a316e677138703254507335544c70455a77546a6e6e416766746159616e68",
  "error": null
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|result|string|交易十六进制编码后的字符串|

## 5 撤销某一局竞猜游戏
### 5.1 生成撤销某一局竞猜游戏的交易（未签名）
**请求报文：**
```json
  request: http.post
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "Chain33.CreateTransaction",
  "params": [
    {
      "execer": "guess",
      "actionName": "Abort",
      "payload": {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4"
      }
    }
  ]
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|停止投注的游戏ID|

说明：　　
该交易必须由游戏发起地址来创建。

**响应报文：**
```json
response:
{
  "id": 2,
  "result": "0a12757365722e702e67756573732e67756573731248380822440a4230786439646464666638343735336531386639303233316561326339323864663665663235656566323461303531663334643232643236326238643364633932623420a08d06308fe5d3f9d6aabcbd613a223139455a316e677138703254507335544c70455a77546a6e6e416766746159616e68",
  "error": null
}
```
**参数说明：**

|参数|类型|说明|
|----|----|----|
|result|string|交易十六进制编码后的字符串|


## 6 查询接口
### 6.1 查询指定ID的竞猜游戏详情

**请求报文：**

```json
request: http.post
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "Chain33.Query",
  "params": [
    {
      "execer": "guess",
      "funcName": "QueryGameByID",
      "payload": {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4"
      }
    }
  ]
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|method|string|Chain33.Query|
|execer|string|执行器名，主链上:token, 平行链上:user.p.xxx.token|
|funcName|string|QueryGameByID|
|gameID|string|游戏ID|

**响应报文：**

```json
response:
{
  "id": 0,
  "result": {
    "game": {
      "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
      "status": 15,
      "preStatus": 13,
      "startTime": "1546929007",
      "startHeight": "2923",
      "startTxHash": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
      "startIndex": "32900001",
      "topic": "WorldCup Final",
      "category": "football",
      "options": "A:France;B:Claodia",
      "maxBetHeight": "0",
      "maxBetsOneTime": "10000000000",
      "maxBetsNumber": "100000000000",
      "devFeeFactor": "5",
      "devFeeAddr": "1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7",
      "platFeeFactor": "5",
      "platFeeAddr": "1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX",
      "expireHeight": "1000000",
      "adminAddr": "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt",
      "betsNumber": "1000000000",
      "plays": [
        {
          "addr": "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k",
          "bet": {
            "option": "A",
            "betsNumber": "500000000",
            "isWinner": false,
            "profit": "0",
            "index": "33300001",
            "preIndex": "33200001"
          }
        },
        {
          "addr": "1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU",
          "bet": {
            "option": "B",
            "betsNumber": "500000000",
            "isWinner": true,
            "profit": "990000000",
            "index": "33300001",
            "preIndex": "33200001"
          }
        }
      ],
      "result": "B",
      "betStat": {
        "totalBetTimes": "2",
        "totalBetsNumber": "1000000000",
        "items": [
          {
            "option": "A",
            "betsNumber": "500000000",
            "betsTimes": "1"
          },
          {
            "option": "B",
            "betsNumber": "500000000",
            "betsTimes": "1"
          }
        ]
      },
      "index": "33300001",
      "preIndex": "33200001",
      "drivenByAdmin": true
    }
  },
  "error": null
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|竞猜游戏ID|
|status|int32|游戏状态,11为start,12为bet,13为stopBet,14为abort,15为publish,16为timeout|
|preStatus|int32|上一个状态值，新创建的游戏该值为0|
|startTime|int64|创建游戏的事件戳|
|startHeight|int64|创建游戏的区块高度|
|startTxHash|string|创建游戏的txHash|
|startIndex|int64|创建游戏的交易index值|
|topic|string|竞猜标题，比如：世界杯决赛法国对阵克罗地亚，谁将获得冠军|
|options|string|竞猜选项，以;分割，:前为选项名称（A/B/C或者1/2/3等）比如：A:法国夺冠;B:克罗地亚夺冠|
|category|string|竞猜所属类型，比如"足球"，"football"等，如果不填归入default|
|maxBetHeight|int64|最大下注高度，从创建游戏的高度开始算起，超过该高度将停止下注|
|maxBetsOneTime|int64|一次最多下注数量，比如:10000e8，表示最多1000个bty或者游戏币|
|maxBetsNumber|int64|一局游戏最多投注数量，比如:1000000e8，表示做多100万个bty或者游戏币|
|devFeeFactor|int64|开发者分成比例，单位1/1000，比如：投注额的5/1000|
|devFeeAddr|string|开发者分成账户地址，默认为：1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7|
|platFeeFactor|int64|平台方分成比例，单位1/1000，比如：投注额的5/1000|
|platFeeAddr|string|1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX|
|adminAddr|string|游戏创建地址|
|betsNumber|int64|已下注数量|
|result|string|游戏结果|
|index|int64|游戏切换为当前状态对应的index|
|preIndex|int64|游戏前一个状态对应的index|
|drivenByAdmin|bool|是否完全为管理员驱动，默认:是|
|plays|GuessPlayer|玩家信息|
|GuessPlayer.addr|string|玩家地址信息|
|GuessPlayer.bet|GuessBet|玩家下注信息|
|GuessBet.option|string|玩家下注选项|
|GuessBet.betsNumber|int64|玩家下注数量|
|GuessBet.isWinner|bool|玩家是否获胜|
|GuessBet.profit|int64|获胜奖励|
|GuessBet.index|int64|当前状态索引|
|GuessBet.preIndex|int64|前一个状态的索引，如果无，为0|

### 6.2 查询指定addr参与的竞猜游戏列表

**请求报文：**

```json
request: http.post
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "Chain33.Query",
  "params": [
    {
      "execer": "guess",
      "funcName": "QueryGamesByAddr",
      "payload": {
        "addr": "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k",
        "primaryKey": ""
      }
    }
  ]
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|method|string|Chain33.Query|
|execer|string|执行器名，主链上:token, 平行链上:user.p.xxx.token|
|funcName|string|QueryGamesByAddr|
|addr|string|玩家地址|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

**响应报文：**

```json
response:
{
  "id": 0,
  "result": {
    "records": [
      {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
        "startIndex": "32900001"
      },
      {
        "gameID": "0x386a04a589f08d056451d1258968d323e2f6e7290288daab76596b6631a62ff3",
        "startIndex": "32200001"
      },
      {
        "gameID": "0x41362e9a14291901214e9bd245c5ff5c5a79726b35e5e10f13bcc797d954d2b0",
        "startIndex": "27800001"
      }
    ],
    "primaryKey": "000000000027900001"
  },
  "error": null
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|竞猜游戏ID|
|startIndex|int64|游戏创建时的交易的index值|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|


### 6.3 查询指定adminAddr创建的竞猜游戏列表

**请求报文：**

```json
request: http.post
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "Chain33.Query",
  "params": [
    {
      "execer": "guess",
      "funcName": "QueryGamesByAdminAddr",
      "payload": {
        "adminAddr": "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt",
        "primaryKey": ""
      }
    }
  ]
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|method|string|Chain33.Query|
|execer|string|执行器名，主链上:token, 平行链上:user.p.xxx.token|
|funcName|string|QueryGamesByAdminAddr|
|adminAddr|string|创建游戏的地址|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

**响应报文：**

```json
response:
{
  "id": 0,
  "result": {
    "records": [
      {
        "gameID": "0x417db61d2c9b848fb435d24e4fbe3993097fff71b498cd2291dbe3e8c8321245",
        "startIndex": "33400001"
      },
      {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
        "startIndex": "32900001"
      },
      {
        "gameID": "0x386a04a589f08d056451d1258968d323e2f6e7290288daab76596b6631a62ff3",
        "startIndex": "32200001"
      }
    ],
    "primaryKey": "000000000032200001"
  },
  "error": null
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|竞猜游戏ID|
|startIndex|int64|游戏创建时的交易的index值|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

### 6.4 查询指定status的竞猜游戏列表

**请求报文：**

```json
request: http.post
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "Chain33.Query",
  "params": [
    {
      "execer": "guess",
      "funcName": "QueryGamesByStatus",
      "payload": {
        "status": "11",
        "primaryKey": ""
      }
    }
  ]
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|method|string|Chain33.Query|
|execer|string|执行器名，主链上:token, 平行链上:user.p.xxx.token|
|funcName|string|QueryGamesByStatus|
|status|int32|状态值|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

**响应报文：**

```json
response:
{
  "id": 0,
  "result": {
    "records": [
      {
        "gameID": "0x417db61d2c9b848fb435d24e4fbe3993097fff71b498cd2291dbe3e8c8321245",
        "startIndex": "33400001"
      }
    ],
    "primaryKey": ""
  },
  "error": null
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|竞猜游戏ID|
|status|int32|游戏状态,11为start,12为bet,13为stopBet,14为abort,15为publish,16为timeout|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

### 6.5 查询指定addr的指定status的竞猜游戏列表

**请求报文：**

```json
request: http.post
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "Chain33.Query",
  "params": [
    {
      "execer": "guess",
      "funcName": "QueryGamesByAddrStatus",
      "payload": {
        "addr": "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k",
        "status": "15",
        "primaryKey": ""
      }
    }
  ]
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|method|string|Chain33.Query|
|execer|string|执行器名，主链上:token, 平行链上:user.p.xxx.token|
|funcName|string|QueryGamesByStatus|
|addr|string|玩家地址|
|status|int32|状态值|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

**响应报文：**

```json
response:
{
  "id": 0,
  "result": {
    "records": [
      {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
        "startIndex": "32900001"
      },
      {
        "gameID": "0x386a04a589f08d056451d1258968d323e2f6e7290288daab76596b6631a62ff3",
        "startIndex": "32200001"
      },
      {
        "gameID": "0x41362e9a14291901214e9bd245c5ff5c5a79726b35e5e10f13bcc797d954d2b0",
        "startIndex": "27800001"
      }
    ],
    "primaryKey": "000000000027900001"
  },
  "error": null
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|竞猜游戏ID|
|status|int32|游戏状态,11为start,12为bet,13为stopBet,14为abort,15为publish,16为timeout|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

### 6.6 查询指定adminAddr的指定status的竞猜游戏列表

**请求报文：**

```json
request: http.post
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "Chain33.Query",
  "params": [
    {
      "execer": "guess",
      "funcName": "QueryGamesByAdminStatus",
      "payload": {
        "adminAddr": "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt",
        "status": "11",
        "primaryKey": ""
      }
    }
  ]
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|method|string|Chain33.Query|
|execer|string|执行器名，主链上:token, 平行链上:user.p.xxx.token|
|funcName|string|QueryGamesByStatus|
|adminAddr|string|游戏创建者地址|
|status|int32|状态值|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

**响应报文：**

```json
response:
{
  "id": 0,
  "result": {
    "records": [
      {
        "gameID": "0x417db61d2c9b848fb435d24e4fbe3993097fff71b498cd2291dbe3e8c8321245",
        "startIndex": "33400001"
      }
    ],
    "primaryKey": ""
  },
  "error": null
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|竞猜游戏ID|
|status|int32|游戏状态,11为start,12为bet,13为stopBet,14为abort,15为publish,16为timeout|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

### 6.7 查询指定category的指定status的竞猜游戏列表

**请求报文：**

```json
request: http.post
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "Chain33.Query",
  "params": [
    {
      "execer": "guess",
      "funcName": "QueryGamesByCategoryStatus",
      "payload": {
        "category": "football",
        "status": "15",
        "primaryKey": ""
      }
    }
  ]
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|method|string|Chain33.Query|
|execer|string|执行器名，主链上:token, 平行链上:user.p.xxx.token|
|funcName|string|QueryGamesByStatus|
|adminAddr|string|游戏创建者地址|
|category|string|分类名称|
|status|int32|状态值|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

**响应报文：**

```json
response:
{
  "id": 0,
  "result": {
    "records": [
      {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
        "startIndex": "32900001"
      },
      {
        "gameID": "0x386a04a589f08d056451d1258968d323e2f6e7290288daab76596b6631a62ff3",
        "startIndex": "32200001"
      },
      {
        "gameID": "0x41362e9a14291901214e9bd245c5ff5c5a79726b35e5e10f13bcc797d954d2b0",
        "startIndex": "27800001"
      }
    ],
    "primaryKey": "000000000027800001"
  },
  "error": null
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|gameID|string|竞猜游戏ID|
|status|int32|游戏状态,11为start,12为bet,13为stopBet,14为abort,15为publish,16为timeout|
|primaryKey|string|分页查询的primarykey,如果因为数据比较多导致一次不能获取所有数据，后续查询可以带上前一次查询的primaryKey进行继续查询|

### 6.8 查询指定ID组的竞猜游戏详情

**请求报文：**

```json
request: http.post
{
  "jsonrpc": "2.0",
  "id": 0,
  "method": "Chain33.Query",
  "params": [
    {
      "execer": "guess",
      "funcName": "QueryGamesByIDs",
      "payload": {
        "gameIDs": [
          "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
          "0x386a04a589f08d056451d1258968d323e2f6e7290288daab76596b6631a62ff3"
        ]
      }
    }
  ]
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|method|string|Chain33.Query|
|execer|string|执行器名，主链上:token, 平行链上:user.p.xxx.token|
|funcName|string|QueryGameById|
|gameIDs|[]string|游戏ID列表|

**响应报文：**

```json
response:
{
  "id": 0,
  "result": {
    "games": [
      {
        "gameID": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
        "status": 15,
        "preStatus": 13,
        "startTime": "1546929007",
        "startHeight": "2923",
        "startTxHash": "0xd9dddff84753e18f90231ea2c928df6ef25eef24a051f34d22d262b8d3dc92b4",
        "startIndex": "32900001",
        "topic": "WorldCup Final",
        "category": "football",
        "options": "A:France;B:Claodia",
        "maxBetHeight": "0",
        "maxBetsOneTime": "10000000000",
        "maxBetsNumber": "100000000000",
        "devFeeFactor": "5",
        "devFeeAddr": "1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7",
        "platFeeFactor": "5",
        "platFeeAddr": "1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX",
        "expireHeight": "1000000",
        "adminAddr": "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt",
        "betsNumber": "1000000000",
        "plays": [
          {
            "addr": "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k",
            "bet": {
              "option": "A",
              "betsNumber": "500000000",
              "isWinner": false,
              "profit": "0",
              "index": "33300001",
              "preIndex": "33200001"
            }
          },
          {
            "addr": "1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU",
            "bet": {
              "option": "B",
              "betsNumber": "500000000",
              "isWinner": true,
              "profit": "990000000",
              "index": "33300001",
              "preIndex": "33200001"
            }
          }
        ],
        "result": "B",
        "betStat": {
          "totalBetTimes": "2",
          "totalBetsNumber": "1000000000",
          "items": [
            {
              "option": "A",
              "betsNumber": "500000000",
              "betsTimes": "1"
            },
            {
              "option": "B",
              "betsNumber": "500000000",
              "betsTimes": "1"
            }
          ]
        },
        "index": "33300001",
        "preIndex": "33200001",
        "drivenByAdmin": true
      },
      {
        "gameID": "0x386a04a589f08d056451d1258968d323e2f6e7290288daab76596b6631a62ff3",
        "status": 15,
        "preStatus": 13,
        "startTime": "1546926748",
        "startHeight": "2900",
        "startTxHash": "0x386a04a589f08d056451d1258968d323e2f6e7290288daab76596b6631a62ff3",
        "startIndex": "32200001",
        "topic": "WorldCup Final",
        "category": "football",
        "options": "A:France;B:Claodia",
        "maxBetHeight": "0",
        "maxBetsOneTime": "10000000000",
        "maxBetsNumber": "100000000000",
        "devFeeFactor": "5",
        "devFeeAddr": "1D6RFZNp2rh6QdbcZ1d7RWuBUz61We6SD7",
        "platFeeFactor": "5",
        "platFeeAddr": "1PHtChNt3UcfssR7v7trKSk3WJtAWjKjjX",
        "expireHeight": "1000000",
        "adminAddr": "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt",
        "betsNumber": "1000000000",
        "plays": [
          {
            "addr": "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k",
            "bet": {
              "option": "A",
              "betsNumber": "500000000",
              "isWinner": false,
              "profit": "0",
              "index": "32500001",
              "preIndex": "32400001"
            }
          },
          {
            "addr": "1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU",
            "bet": {
              "option": "B",
              "betsNumber": "500000000",
              "isWinner": true,
              "profit": "990000000",
              "index": "32500001",
              "preIndex": "32400001"
            }
          }
        ],
        "result": "B",
        "betStat": {
          "totalBetTimes": "2",
          "totalBetsNumber": "1000000000",
          "items": [
            {
              "option": "A",
              "betsNumber": "500000000",
              "betsTimes": "1"
            },
            {
              "option": "B",
              "betsNumber": "500000000",
              "betsTimes": "1"
            }
          ]
        },
        "index": "32500001",
        "preIndex": "32400001",
        "drivenByAdmin": true
      }
    ]
  },
  "error": null
}
```

**参数说明：**

|参数|类型|说明|
|----|----|----|
|games|[]GuessGame]|游戏详情列表|

GuessGame的定义参见6.1中的描述



# 二、测试验证步骤及相关命令　 
## 1 测试环境搭建
### 1.1     搭建主链环境和平行链环境，游戏验证主要在平行链上进行，但需要主链配合交易打包  
  
主链　　
>192.168.0.170:8801  
192.168.0.170:8802　　

平行链　　
>192.168.0.233:8901  
192.168.0.233:8902　　

### 1.2     主链上准备三个地址  

创世地址、游戏创建地址 
>14KEKbYtKKQm4wMthSK9J4La4nAiidGozt

测试地址１
>1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k

测试地址２
>1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU


### 1.3     通过如下命令组合，向测试地址１和测试地址２转账bty，用于主链上的交易打包手续费 
      
>./chain33-cli --rpc_laddr="http://192.168.0.170:8801" bty transfer -a 1000 -t 1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k

>./chain33-cli --rpc_laddr="http://192.168.0.170:8801" wallet sign -a 14KEKbYtKKQm4wMthSK9J4La4nAiidGozt -d

>./chain33-cli --rpc_laddr="http://192.168.0.170:8801" wallet send -d


### 1.4     通过如下命令组合，向平行链导入地址私钥　　     

主链上操作　　
#### 1.  解锁  

>./chain33-cli --rpc_laddr="http://192.168.0.170:8801" wallet unlock -p zzh -t 0  


#### 2.  导出测试地址私钥  

>./chain33-cli --rpc_laddr="http://192.168.0.170:8801" account  dump_key -a 1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU  


#### 3.  平行链上导入测试地址私钥  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" account  import_key -k "0x50260dfe781a08739632f244fe8bffad2fd72a41df4abd9e911c6efdc22e04b2" -l zzh  

#### 4.  同样的操作命令，把创世地址和测试地址１、测试地址２的私钥都导入到平行链上  

### 1.5     通过如下命令组合，平行链上从创世地址向测试地址转入游戏币  

平行链上从创世地址转账游戏币到测试地址１：  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." bty transfer -a 100 -t 1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." wallet sign -a 14KEKbYtKKQm4wMthSK9J4La4nAiidGozt -d  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." wallet send -d  

对测试地址２执行类似的操作。　　

### 1.6     通过如下命令组合，平行链上从测试地址向竞猜合约转入游戏币  

平行链上，从测试地址１和测试地址２向竞猜合约guess转账，用于后续的竞猜游戏:  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." bty send_exec -a 100 -e user.p.guess.guess  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." wallet sign -a 1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k -d  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." wallet send -d  

### 1.7    通过如下命令组合，平行链上查看测试地址在竞猜合约中的余额  

查看测试地址在guess合约中的余额:  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." account balance -a 1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k -e user.p.guess.guess  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." account balance -a 1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU -e user.p.guess.guess  

## ２ 使用测试程序predict进行游戏验证  

### 2.1    获取测试程序    

测试程序从如下路径获得  

https://gitlab.33.cn/richardzhang/share/blob/master/predict.go  

拷贝到plugin工程的plugin/dapp/guess目录下编译：  

>go build predict.go    

得到执行程序predict,拷贝到测试目录下备用。  


### 2.2    使用测试程序进行游戏过程验证   

#### 1. 管理员地址创建游戏  

>./predict testCreate 14KEKbYtKKQm4wMthSK9J4La4nAiidGozt  

得到游戏id。

#### 2. 测试地址向游戏下注参与竞猜  

>./predict testBet "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004" "A" "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k"  

>./predict testBet "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004" "B" "1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU"  

#### 3. 使用游戏id查询游戏当前状态信息  

>./predict testQueryGameById "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004"  


#### 4. 非管理员地址尝试修改游戏状态到停止下注状态，失败  

>./predict testStopBet "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004" "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k"  

#### 5. 管理员地址停止游戏，成功  

>./predict testStopBet "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004" "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k"  

#### 6. 非管理员地址尝试发布游戏结果，失败  

>./predict testPublish "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004" "A" "1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU"  

#### 7. 使用游戏id查询游戏当前状态信息  

>./predict testQueryGameById "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004"  

#### 8. 使用管理员地址发布结果，成功  

>./predict testPublish "0x76dae82fcbe554d4b8df5ed1460d71dcac86a50864649a0df43e0c50b245f004" "A" "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"  

#### 9. 游戏结束后，查询余额，确认结算结果正确  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." account balance -a 1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k -e user.p.guess.guess  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." account balance -a 1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU -e user.p.guess.guess  
  
## ３ 使用测chain33-cli进行竞猜游戏测试验证  

### 3.1  测试中会用到的解锁及查询交易的命令  

#### 1.  解锁命令  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" wallet unlock -p zzh -t 0  

#### 2.  查询交易结果  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess." tx query -s 0xa4cb61f1a9008cd0378cf8c06ff1e9baa2127e94178af4a0405c93c0aa606c95  

### 3.2   使用管理员及测试地址签名交易及发送交易的通用命令  

#### 1.  管理员地址签名交易　　

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  wallet sign -a 14KEKbYtKKQm4wMthSK9J4La4nAiidGozt -d   

#### 2.  测试地址１签名交易  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  wallet sign -a 1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k -d  

#### 3.  测试地址2签名交易  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  wallet sign -a 1hb93FMDVVxhfzK2ziDLCZqL3wxggoFZU -d  

#### 4.  发送签名后的交易  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  wallet send -d   

### 3.3   使用命令行创建竞猜游戏  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess start -t "WorldCup Final" -o "A:France;B:Claodia" -c "sport" -m 1000 -s 10 -n 100 -e 10000 -d 5 -p 5 -g 0.01  

得到结果用3.2.1中的方式使用管理员地址进行签名，并使用3.2.4发送交易，交易结果可以用3.1.2命令查看。  

交易hash即为本局竞猜游戏的id.  


### 3.３  测试地址参与竞猜游戏  

#### 1.  游戏地址１参与竞猜游戏下注  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess bet -b 2000000000 -f 0.01 -g 0x5203a692d73406e447b99a151dd9c63b40064fff3ed86a7bda4a821b669edb43 -o "B"  

得到结果用3.2.2中的方式使用管理员地址进行签名，并使用3.2.4发送交易，交易结果可以用3.1.2命令查看。　

#### 2.  游戏地址2参与竞猜游戏下注  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess bet -b 2000000000 -f 0.01 -g 0x5203a692d73406e447b99a151dd9c63b40064fff3ed86a7bda4a821b669edb43 -o "A"  

得到结果用3.2.3中的方式使用管理员地址进行签名，并使用3.2.4发送交易，交易结果可以用3.1.2命令查看。　

#### 3.  管理员地址修改游戏状态为：停止投注状态  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess stop  -g 0x09c972ddf49bc52269cc6c6426691a360bf2e60544588b8135c6f833f732ee96 -f 0.01   
  

得到结果用3.2.1中的方式使用管理员地址进行签名，并使用3.2.4发送交易，交易结果可以用3.1.2命令查看。  


#### 4.  管理员地址公布游戏结果  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess publish -g 0x5203a692d73406e447b99a151dd9c63b40064fff3ed86a7bda4a821b669edb43 -f 0.01   

 得到结果用3.2.1中的方式使用管理员地址进行签名，并使用3.2.4发送交易，交易结果可以用3.1.2命令查看。  

使用2.2.9命令确认结算结果是否正确。  


#### 5.  管理员地址撤销游戏（在没有公布结果前，是可以撤销的，再新建一局游戏进行测试）  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess abort -g  0xc4ee4b059523ac61b509eadc94b05e6813ad7facc7a7003264e1494ae77e0bc3 -f 0.01  


得到结果用3.2.1中的方式使用管理员地址进行签名，并使用3.2.4发送交易，交易结果可以用3.1.2命令查看。    

#### 6.  查询命令  

```go
./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query --help
query info  

Usage:  
  -cli guess query [flags]  

Flags:  
  -a, --addr string        address  
  -m, --adminAddr string   admin address  
  -c, --category string    game category (default "default")  
  -d, --gameIDs string     gameIDs
  -g, --gameId string      game Id
  -h, --help               help for query
  -i, --index int          index
  -s, --status int32       status
  -t, --type int32         query type, 1:Ids,2:Id,3:Addr,4:Status,5:AdminAddr,6:AddrStatus,7:AdminStatus,8:CategoryStatus (default 1)

Global Flags:
      --paraName string    parachain
      --rpc_laddr string   http url (default "http://localhost:8801")
```

(1) 使用游戏id集合查询多个游戏详情：  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query -t 1 -d "0xb2e8fb328a0a7f88661a304497ff256e0803c8a73874c70c273950be7408ef3a"  

(2) 使用单个游戏id查询单个游戏详情：

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query -t 2 -g "0x09c972ddf49bc52269cc6c6426691a360bf2e60544588b8135c6f833f732ee96"  

(3) 查询某个玩家地址参与的游戏列表，每次最多返回20条记录  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query -t 3 -a 1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k  

(4) 根据游戏状态查询游戏列表，每次最多返回20条记录  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query -t 4 -s 12  

游戏状态,11为start,12为bet,13为stopBet,14为abort,15为publish,16为timeout

(5) 根据管理员地址查询该地址创建的游戏列表，每次最多返回20条记录  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query -t 5 -m 14KEKbYtKKQm4wMthSK9J4La4nAiidGozt  

(6) 根据玩家地址、状态查询该地址参与的当前为特定状态的游戏列表，每次最多返回20条记录  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query -t 6 -a 1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k -s 12  

该命令查询该地址参与的正在进行下注的游戏列表。　　

(7) 根据管理员地址、状态查询该地址创建的当前为特定状态的游戏列表，每次最多返回20条记录  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query -t 7 -m 14KEKbYtKKQm4wMthSK9J4La4nAiidGozt -s 12  

该命令查询该地址创建的正在进行下注的游戏列表。　　

(8) 根据游戏类别、状态查询游戏类别、状态符合条件的游戏列表，每次最多返回20条记录  

>./chain33-cli --rpc_laddr="http://192.168.0.233:8901" --paraName="user.p.guess."  guess query -t 8 -c football -s 12   

该命令查询类别为football的正在进行下注的游戏列表。  

