Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
share
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
黄刚
share
Commits
0c84ad7b
Commit
0c84ad7b
authored
Jan 11, 2019
by
Hugo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add js合约
parent
0af31f0b
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
447 additions
and
0 deletions
+447
-0
js合约.md
js合约.md
+365
-0
数据发布预言机合约接口及测试.md
数据发布预言机合约接口及测试.md
+82
-0
No files found.
js合约.md
0 → 100644
View file @
0c84ad7b
## 1 jsvm 接口
## 1 jsvm 接口
[
TOC
]
### 1.1 部署一个jsvm合约 CreateTransaction
> 这里创建的是原始交易,除此之外,还需要进行交易的签名以及发送操作
> 如果合约中要使用数字货币,在调用合约前需要先向合约充值
**请求报文:**
```
json
{
"jsonrpc"
:
"2.0"
,
"method"
:
"Chain33.CreateTransaction"
,
"params"
:
[
{
"execer"
:
"string"
,
"actionName"
:
"string"
,
"payload"
:
{
"code"
:
"string"
,
"name"
:
"string"
}
}
],
"id"
:
int
32
,
}
```
**参数说明:**
|参数|类型|是否必填|说明|
|----|----|----|----|----|
|execer|string|是|执行器名称,这里固定为jsvm|
|actionName|string|是|操作名称,这里固定为Create|
|payload.code|string|是|javascript代码|
|payload.name|string|是|合约名|
**响应报文:**
```
json
{
"id"
:
int
32
,
"result"
:
"string"
,
"error"
:
null
}
```
**参数说明:**
|参数|类型|说明|
|----|----|----|
|result|string|交易内容十六进制字符串|
**示例:**
Request1 部署合约交易:
```
json
{
"method"
:
"Chain33.CreateTransaction"
,
"params"
:
[
{
"execer"
:
"jsvm"
,
"actionName"
:
"Create"
,
"payload"
:
{
"code"
:
"//........................
\n
//............: ............... 0 - 10 ......... hash(......... + 9) (.....................) NewGame()
\n
//............................................................ Guess()
\n
//...... CloseGame()
\n
function Init(context) {
\n
this.kvc = new kvcreator(
\"
init
\"
)
\n
this.context = context
\n
return this.kvc.receipt()
\n
}
\n\n
var MIN_WAIT_BLOCK = 2
\n
var RAND_MAX = 10
\n\n
function ExecInit() {
\n
this.acc = new account(this.kvc,
\"
coins
\"
,
\"
bty
\"
)
\n
}
\n\n
Exec.prototype.NewGame = function(args) {
\n
var game = {__type__ :
\"
game
\"
}
\n
game.gameid = this.txID()
\n
game.height = this.context.height
\n
game.randhash = args.randhash
\n
game.bet = args.bet
\n
game.hash = this.context.txhash
\n
game.obet = game.bet
\n
game.addr = this.context.from
\n
game.status = 1 //open
\n
//............ 9000...,......js... int .........
\n
if (game.bet < 10 * COINS || game.bet > 10000000 * COINS) {
\n
throwerr(
\"
bet low than 10 or hight than 10000000
\"
)
\n
}
\n
if (this.kvc.get(game.randhash)) { //......randhash ..................
\n
throwerr(
\"
dup rand hash
\"
)
\n
}
\n
var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
\n
throwerr(err)
\n
this.kvc.add(game.gameid, game)
\n
this.kvc.add(game.randhash,
\"
ok
\"
)
\n
this.kvc.addlog(game)
\n
return this.kvc.receipt()
\n
}
\n\n
Exec.prototype.Guess = function(args) {
\n
var match = {__type__ :
\"
match
\"
}
\n
match.gameid = args.gameid
\n
match.bet = args.bet
\n
match.id = this.txID()
\n
match.addr = this.context.from
\n
match.hash = this.context.txhash
\n
match.num = args.num
\n
var game = this.kvc.get(match.gameid)
\n
if (!game) {
\n
throwerr(
\"
guess: game id not found
\"
)
\n
}
\n
if (game.status != 1) {
\n
throwerr(
\"
guess: game status not open
\"
)
\n
}
\n
if (this.context.from == game.addr) {
\n
throwerr(
\"
guess: game addr and match addr is same
\"
)
\n
}
\n
if (match.bet < 1 * COINS || match.bet > game.bet / RAND_MAX) {
\n
throwerr(
\"
match bet litte than 1 or big than game.bet/10
\"
)
\n
}
\n
var err = this.acc.execFrozen(this.name, this.context.from, match.bet)
\n
console.log(this.name, this.context.from, err)
\n
throwerr(err)
\n
this.kvc.add(match.id, match)
\n
this.kvc.addlog(match)
\n
return this.kvc.receipt()
\n
}
\n\n
Exec.prototype.CloseGame = function(args) {
\n
var local = MatchLocalTable(this.kvc)
\n
var game = this.kvc.get(args.gameid)
\n
if (!game) {
\n
throwerr(
\"
game id not found
\"
)
\n
}
\n
var querykey = local.get(
\"
gameid
\"
, args)
\n
var matches = local.query(
\"
gameid
\"
, querykey,
\"\"
, 0, 1)
\n
if (!matches) {
\n
matches = []
\n
}
\n
var n = -1
\n
for (var i = 0; i < RAND_MAX; i++) {
\n
if (Sha256(args.randstr + i) == game.randhash) {
\n
n = i
\n
}
\n
}
\n
if (n == -1) {
\n
throwerr(
\"
err rand str
\"
)
\n
}
\n
//.........................................................
\n
if (this.context.height - game.height < MIN_WAIT_BLOCK) {
\n
throwerr(
\"
close game must wait
\"
+MIN_WAIT_BLOCK+
\"
block
\"
)
\n
}
\n
for (var i = 0; i < matches.length; i++) {
\n
var match = matches[i].left
\n
if (match.num == n) {
\n
//................................................................................................ this
\n
win.call(this, game, match)
\n
} else {
\n
fail.call(this, game, match)
\n
}
\n
}
\n
if (game.bet > 0) {
\n
var err = this.acc.execActive(this.name, game.addr, game.bet)
\n
throwerr(err)
\n
game.bet = 0
\n
}
\n
game.status = 2
\n
this.kvc.add(game.gameid, game)
\n
this.kvc.addlog(game)
\n
return this.kvc.receipt()
\n
}
\n\n
function win(game, match) {
\n
var amount = (RAND_MAX - 1) * match.bet
\n
if (game.bet - amount < 0) {
\n
amount = game.bet
\n
}
\n
var err
\n
if (amount > 0) {
\n
err = this.acc.execTransFrozenToActive(this.name, game.addr, match.addr, amount)
\n
throwerr(err,
\"
execTransFrozenToActive
\"
)
\n
game.bet -= amount
\n
}
\n
err = this.acc.execActive(this.name, match.addr, match.bet)
\n
throwerr(err,
\"
execActive
\"
)
\n
}
\n\n
function fail(game, match) {
\n
var amount = match.bet
\n
err = this.acc.execTransFrozenToFrozen(this.name, match.addr, game.addr, amount)
\n
throwerr(err)
\n
game.bet += amount
\n
}
\n\n
Exec.prototype.ForceCloseGame = function(args) {
\n
var local = new MatchLocalTable(this.kvc)
\n
var game = this.kvc.get(args.id)
\n
if (!game) {
\n
throwerr(
\"
game id not found
\"
)
\n
}
\n
var matches = local.getmath(args.id)
\n
if (!matches) {
\n
matches = []
\n
}
\n
if (this.context.height - game.height < 100) {
\n
throwerr(
\"
force close game must wait 100 block
\"
)
\n
}
\n
for (var i = 0; i < matches.length; i++) {
\n
var match = matches[i]
\n
win.call(this.kvc, game, match)
\n
}
\n
if (game.bet > 0) {
\n
var err = this.acc.execActive(this.name, game.addr, game.bet)
\n
throwerr(err)
\n
game.bet = 0
\n
}
\n
game.status = 2
\n
this.kvc.add(game.gameid, game)
\n
this.kvc.addlog(game)
\n
return this.kvc.receipt()
\n
}
\n\n
ExecLocal.prototype.NewGame = function(args) {
\n
return localprocess.call(this, args)
\n
}
\n\n
ExecLocal.prototype.Guess = function(args) {
\n
return localprocess.call(this, args)
\n
}
\n\n
ExecLocal.prototype.CloseGame = function(args) {
\n
return localprocess.call(this, args)
\n
}
\n\n
ExecLocal.prototype.ForceCloseGame = function(args) {
\n
return localprocess.call(this, args)
\n
}
\n\n
function localprocess(args) {
\n
var local = MatchGameTable(this.kvc)
\n
local.addlogs(this.logs)
\n
local.save()
\n
return this.kvc.receipt()
\n
}
\n\n
Query.prototype.ListGameByAddr = function(args) {
\n
var local = GameLocalTable(this.kvc)
\n
var q = local.query(
\"
addr
\"
, args.addr, args.primaryKey, args.count, args.direction)
\n
return querytojson(q)
\n
}
\n\n
Query.prototype.ListMatchByAddr = function(args) {
\n
var local = MatchGameTable(this.kvc)
\n
var q= local.query(
\"
addr#status
\"
, args[
\"
addr#status
\"
], args.primaryKey, args.count, args.direction)
\n
return querytojson(q)
\n
}
\n\n
function GameLocalTable(kvc) {
\n
this.config = {
\n
\"
#tablename
\"
:
\"
game
\"
,
\n
\"
#primary
\"
:
\"
gameid
\"
,
\n
\"
#db
\"
:
\"
localdb
\"
,
\n
\"
gameid
\"
:
\"
%018d
\"
,
\n
\"
status
\"
:
\"
%d
\"
,
\n
\"
hash
\"
:
\"
%s
\"
,
\n
\"
addr
\"
:
\"
%s
\"
,
\n
}
\n
this.defaultvalue = {
\n
\"
gameid
\"
: 0,
\n
\"
status
\"
: 0,
\n
\"
hash
\"
:
\"\"
,
\n
\"
addr
\"
:
\"\"
,
\n
}
\n
return new Table(kvc, this.config, this.defaultvalue)
\n
}
\n\n
function MatchLocalTable(kvc) {
\n
this.config = {
\n
\"
#tablename
\"
:
\"
match
\"
,
\n
\"
#primary
\"
:
\"
id
\"
,
\n
\"
#db
\"
:
\"
localdb
\"
,
\n
\"
id
\"
:
\"
%018d
\"
,
\n
\"
gameid
\"
:
\"
%018d
\"
,
\n
\"
hash
\"
:
\"
%s
\"
,
\n
\"
addr
\"
:
\"
%s
\"
,
\n
}
\n
this.defaultvalue = {
\n
\"
id
\"
: 0,
\n
\"
gameid
\"
: 0,
\n
\"
hash
\"
:
\"\"
,
\n
\"
addr
\"
:
\"\"
,
\n
}
\n
return new Table(kvc, this.config, this.defaultvalue)
\n
}
\n\n
function MatchGameTable(kvc) {
\n
return new JoinTable(MatchLocalTable(kvc), GameLocalTable(kvc),
\"
addr#status
\"
)
\n
}
\n
"
,
"name"
:
"game"
}
}
],
"id"
:
0
}
```
### 1.2 调用创建的jsvm合约的方法 CreateTransaction
**请求报文:**
```
json
{
"jsonrpc"
:
"2.0"
,
"id"
:
0
,
"method"
:
"Chain33.CreateTransaction"
,
"params"
:
[
{
"execer"
:
"string"
,
"actionName"
:
"string"
,
"payload"
:
{
"name"
:
"string"
,
"funcname"
:
"string"
,
"args"
:
"string"
}
}
],
}
```
**参数说明:**
|参数|类型|说明|
|----|----|----|
|execer|string|合约名字,固定格式为user.jsvm.xxxx|
|actionName|string|调用,这里固定为Call|
|payload.name|string|合约名字,之前定义的名字|
|payload.funcname|string|调用的方法名|
|payload.args|string|参数列表|
**响应报文:**
```
json
{
"id"
:
int
32
,
"result"
:
"string"
,
"error"
:
null
}
```
**参数说明:**
|参数|类型|说明|
|----|----|----|
|result|string|交易内容十六进制字符串|
**示例:**
Request:
```
json
{
"jsonrpc"
:
"2.0"
,
"id"
:
0
,
"method"
:
"Chain33.CreateTransaction"
,
"params"
:
[
{
"execer"
:
"user.jsvm.game"
,
"actionName"
:
"Call"
,
"payload"
:
{
"name"
:
"game"
,
"funcname"
:
"NewGame"
,
"args"
:
"{
\"
bet
\"
:10000000000,
\"
randhash
\"
:
\"
0x5d2ac15654aa1859af80d1dfa5d7a5775c359fe3a49abce03796f4fbc313b57f
\"
}"
}
}
],
}
```
Response:
```
json
{
"id"
:
0
,
"result"
:
"0a0e757365722e6a73766d2e67616d651279180112750a0467616d6512074e657747616d651a647b22626574223a31303030303030303030302c202272616e6468617368223a22307835643261633135363534616131383539616638306431646661356437613537373563333539666533613439616263653033373936663466626333313362353766227d20a08d0630ae97b68eead9ec99083a2231356d6a48594e76506b534d72703353517874637a584c3663696e4d414564654b73"
,
"error"
:
null
}
```
### 1.3 查询创建的jsvm合约
**请求报文:**
```
json
{
"jsonrpc"
:
"2.0"
,
"method"
:
"Chain33.Query"
,
"params"
:
[
{
"execer"
:
"string"
,
"funcName"
:
"string"
,
"payload"
:
{
"name"
:
"string"
,
"funcname"
:
"string"
,
"args"
:
"{
\"
addr
\"
:
\"
14KEKbYtKKQm4wMthSK9J4La4nAiidGozt
\"
,
\"
count
\"
:20}"
}
}
],
"id"
:
0
}
```
**参数说明:**
|参数|类型|是否必填|说明|
|----|----|----|----|----|
|execer|string|是|执行器名称,这里固定为jsvm|
|funcName|string|是|操作名称,这里固定为Query|
|payload.name|string|是|合约名|
|payload.funcname|string|是|javascript中定义的查询方法名|
|payload.args|string|是|javascript中定义的查询方法的参数列表,用json格式表示|
**响应报文:**
```
json
{
"id"
:
int
32
,
"result"
:
{
"data"
:
"string"
},
"error"
:
null
}
```
**参数说明:**
|参数|类型说明|
|----|----|----|----|
|result.data|string|查询结果|
**示例:**
Request:
```
json
{
"method"
:
"Chain33.Query"
,
"params"
:
[
{
"execer"
:
"jsvm"
,
"funcName"
:
"Query"
,
"payload"
:
{
"name"
:
"game"
,
"funcname"
:
"ListGameByAddr"
,
"args"
:
"{
\"
addr
\"
:
\"
14KEKbYtKKQm4wMthSK9J4La4nAiidGozt
\"
,
\"
count
\"
:20}"
}
}
],
"id"
:
0
}
```
Response:
```
json
{
"id"
:
0
,
"result"
:
{
"data"
:
"[{
\"
left
\"
:{
\"
__type__
\"
:
\"
game
\"
,
\"
addr
\"
:
\"
14KEKbYtKKQm4wMthSK9J4La4nAiidGozt
\"
,
\"
bet
\"
:10000000000,
\"
gameid
\"
:121400000,
\"
hash
\"
:
\"
0xd3894f7ab60a535d8de47f8a5e06d7c127a22bfe9ff8f1e00971fae19091126f
\"
,
\"
height
\"
:1214,
\"
obet
\"
:10000000000,
\"
randhash
\"
:
\"
0x5d2ac15654aa1859af80d1dfa5d7a5775c359fe3a49abce03796f4fbc313b57f
\"
,
\"
status
\"
:1}}]"
},
"error"
:
null
}
```
### 1.4 如何用JavaScript写一个自己的合约
>一般js文件包含如下规则:
>定义Init(context)函数:该函数在部署合约时会被调用,作用是为一个合约准备资源,主要是存储对象kvcreator和上下文信息。
>定义Exec对象的xxxx方法:将一些数据写入stateDB,并传递一些需要记录在表中的log信息
>定义ExecLocal对象的xxxx:将log信息写入表或写入一些数据到localDB
>定义Query对象的xxxx方法:查询表中的数据或者
>基于chain33的框架,通过上面1.2的Call调用将会依次执行对应的Exec.的xxxx方法和ExecLocal的xxxx方法,比如Call的payload.funcname为"NewGame",就会依次执行Exec的NewGame方法和ExecLocal的NewGame方法。
下面结合game.js具体介绍一下
>game.js定义了一种猜数字的游戏,游戏规则:
>庄家出一个 0 - 10 的数字 hash(随机数 + 9) (一共的赔偿金额)。 对应NewGame方法。
>用户可以猜这个数字,多个用户都可以猜测。对应Guess方法
>开奖。对应CloseGame方法
>注意:像上述三个的方法,Exec对象和ExecLocal对象要分别实现的一个同名的方法。
#### 1.4.1 定义存储结构
为了存储上述信息,需要创建三张表,一张GameLocalTable,一张MatchLocalTable,一张MatchGameTable,其中MatchGameTable是基于上述两表的连接表类似于关系数据库的join操作产生的临时表。
创建一张表包含config和defaultvalue两部分,config设置表结构,包含表属性配置项(用#开头)和列属性配置两类,表属性有表名,主键和存储db类型三个。defaultvalue用于设置列属性的默认值。
下面是创建GameLocalTable的代码
```
js
function
GameLocalTable
(
kvc
)
{
this
.
config
=
{
"#tablename"
:
"game"
,
//定义表名
"#primary"
:
"gameid"
,
//定义主键
"#db"
:
"localdb"
,
//定义存储的db类型,一般为localdb
"gameid"
:
"%018d"
,
//表主键,游戏id,可以用交易总索引(txID())定义
"status"
:
"%d"
,
//游戏状态:0-未开始,1-开始,2-关闭
"hash"
:
"%s"
,
//交易hash
"addr"
:
"%s"
,
//创建交易者的地址
}
this
.
defaultvalue
=
{
"gameid"
:
0
,
"status"
:
0
,
"hash"
:
""
,
"addr"
:
""
,
}
return
new
Table
(
kvc
,
this
.
config
,
this
.
defaultvalue
)
}
```
下面是创建MatchLocalTable的代码
```
js
function
MatchLocalTable
(
kvc
)
{
this
.
config
=
{
"#tablename"
:
"match"
,
//定义表名
"#primary"
:
"id"
,
//定义主键
"#db"
:
"localdb"
,
//定义存储的db类型,一般为localdb
"id"
:
"%018d"
,
//表主键,可以用交易总索引(txID())定义
"gameid"
:
"%018d"
,
//表外键,对应GameLocalTable表主键
"hash"
:
"%s"
,
//交易hash
"addr"
:
"%s"
,
//参与游戏的猜数字者的地址
}
this
.
defaultvalue
=
{
"id"
:
0
,
"gameid"
:
0
,
"hash"
:
""
,
"addr"
:
""
,
}
return
new
Table
(
kvc
,
this
.
config
,
this
.
defaultvalue
)
}
```
下面是创建MatchGameTable的代码
```
js
function
MatchGameTable
(
kvc
)
{
//参数lefttable是使用外键的表,数据量相对较大,参数index是需要查询连接表的字段名
return
new
JoinTable
(
MatchLocalTable
(
kvc
),
GameLocalTable
(
kvc
),
"addr#status"
)
}
```
#### 1.4.2 Init函数
```
js
function
Init
(
context
)
{
this
.
kvc
=
new
kvcreator
(
"init"
)
//创建init类型对象,用于存储key,value值
this
.
context
=
context
//保存上下文信息
return
this
.
kvc
.
receipt
()
}
```
#### 1.4.3 Exec的xxxx方法
此方法可以通过上面1.2的方法调用到,xxxx与payload.funcname值一致。主要作用是通过kvc.add()将一些信息写入stateDB,通过kvc.addlog()传递log信息。
```
js
Exec
.
prototype
.
NewGame
=
function
(
args
)
{
//
var
game
=
{
__type__
:
"game"
}
game
.
gameid
=
this
.
txID
()
game
.
height
=
this
.
context
.
height
game
.
randhash
=
args
.
randhash
game
.
bet
=
args
.
bet
game
.
hash
=
this
.
context
.
txhash
game
.
obet
=
game
.
bet
game
.
addr
=
this
.
context
.
from
game
.
status
=
1
//open
//最大值是 9000万,否则js到 int 会溢出
if
(
game
.
bet
<
10
*
COINS
||
game
.
bet
>
10000000
*
COINS
)
{
throwerr
(
"bet low than 10 or hight than 10000000"
)
}
if
(
this
.
kvc
.
get
(
game
.
randhash
))
{
//如果randhash 已经被使用了
throwerr
(
"dup rand hash"
)
}
var
err
=
this
.
acc
.
execFrozen
(
this
.
name
,
this
.
context
.
from
,
game
.
bet
)
//冻结庄家的奖池
throwerr
(
err
)
this
.
kvc
.
add
(
game
.
gameid
,
game
)
//存储key:gameid与value:game到stateDB
this
.
kvc
.
add
(
game
.
randhash
,
"ok"
)
//存储key:randhash与value:"ok"到stateDB
this
.
kvc
.
addlog
(
game
)
//传递game对象到ExecLocal.prototype.NewGame
return
this
.
kvc
.
receipt
()
}
```
#### 1.4.4 ExecLocal的xxxx方法
此方法将对应的Exec的xxxx方法传递的log信息写入到对应的表中,或者调用kvc.add()直接将数据写入stateDB。
```
js
function
localprocess
(
args
)
{
var
local
=
MatchGameTable
(
this
.
kvc
)
local
.
addlogs
(
this
.
logs
)
//操作join表,达到自动更新关联表的目的
local
.
save
()
//保存数据
return
this
.
kvc
.
receipt
()
}
ExecLocal
.
prototype
.
NewGame
=
function
(
args
)
{
return
localprocess
.
call
(
this
,
args
)
}
```
#### 1.4.5 Query的xxxx方法
此方法可以通过上面1.3的方法调用到,xxxx与payload.funcname值一致,实现按照传入参数查询数据的功能,可以通过表进行查询,也可以直接查询localDB。
```
js
//提供按照游戏创建者地址查询game信息
Query
.
prototype
.
ListGameByAddr
=
function
(
args
)
{
var
local
=
GameLocalTable
(
this
.
kvc
)
var
q
=
local
.
query
(
"addr"
,
args
.
addr
,
args
.
primaryKey
,
args
.
count
,
args
.
direction
)
return
querytojson
(
q
)
}
```
\ No newline at end of file
数据发布预言机合约接口及测试.md
0 → 100644
View file @
0c84ad7b
# 一、接口描述
# 一、接口描述
## 1 发布事件
### 1.1 生成发布事件的交易(未签名)
**请求报文:**
```
json
{
"jsonrpc"
:
"2.0"
,
"method"
:
"Chain33.CreateTransaction"
,
"params"
:
[
{
"execer"
:
"oracle"
,
"actionName"
:
"EventPublish"
,
"payload"
:
{
"type"
:
"string"
,
"subType"
:
"string"
,
"time"
:
int
64
,
"content"
:
"string"
,
"introduction"
:
"string"
}
}
],
"id"
:
int
32
}
```
**参数说明:**
|参数|类型|说明|
|----|----|----|
|type|string|事件类型|
|subType|string|事件子类型|
|time|int64|事件结果预计公布时间,UTC时间|
|content|string|事件内容,例如可以用json格式表示|
|introduction|string|事件介绍|
**响应报文**
```
json
{
"id"
:
int
32
,
"result"
:
"string"
,
"error"
:
null
}
```
**参数说明:**
|参数|类型|说明|
|----|----|----|
|result|string|交易十六进制编码后的字符串|
**示例**
Request:
```
json
{
"method"
:
"Chain33.CreateTransaction"
,
"params"
:
[
{
"execer"
:
"oracle"
,
"actionName"
:
"EventPublish"
,
"payload"
:
{
"type"
:
"football"
,
"subType"
:
"Premier League"
,
"time"
:
1548084600
,
"content"
:
"test"
,
"introduction"
:
"test2"
}
}
],
"id"
:
0
}
```
Response:
```
json
{
"id"
:
0
,
"result"
:
"0a066f7261636c65123138010a2d1208666f6f7462616c6c1a0e5072656d696572204c656167756520f8ca97e2052a04746573743205746573743220a08d06309a95a2ce81b6aabf1d3a22314350794a7152427a4c4b537a504c44416845454d64666f53464450513965477448"
,
"error"
:
null
}
```
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment