Skip to content

Chain33钱包

QM edited this page Dec 21, 2020 · 1 revision

1 钱包的定义

钱包,顾名思义是装钱的包,有传统的钱包和虚拟的电子钱包。众所周知的比特币 数字货币钱包就属于后者,电子钱包。 虚拟钱包中存放了虚拟货币,可以通过钱包,接收或者消费虚拟货币。需要说明的是,虚拟钱包中存放的并不是钱,而是管理密钥、地址、跟踪余额和创建交易的软件。有了密钥就可以随意支配密钥对应地址上的虚拟资产。

2. 数字钱包的机制

2.1 助记词和钱包的关系

助记词就是一串字符串。它是从一个单词表(包含2048个单词)中随机选择12-24个 单词组成的。有了助记词就可以通过(bip协议)生成成千上万个私钥,我们只需要记住助记词,就可以管理这些“无数”个私钥,继而支配这些私钥对应的地址上的虚拟资产。所以,虚拟钱包里要有私钥,就得先有助记词。我们可以通过助记词,在任一个钱包中,恢复我们的钱包私钥,地址等信息。

2.2 助记词和私钥的关系

虚拟钱包的助记词大都遵循bip标准。bip是一种BTC改进协议(Bitcoin Improvement proposals 的缩写)BIP 和 Bitcoin 的关系,就像是 RFC 之于 Internet。 虚拟钱包中主要用到BIP39.BIP32.BIP44协议

  1. BIP39协议:主要是通过助记词和输入的密码来创建一个Seed
  2. BIP32协议:通过Seed来生成主公私钥对。
  3. BIP44协议:通过主公私钥和币种以及索引,来创建任意多个子公私钥。
2.3 钱包账户地址

钱包账户地址是通过钱包公钥生成,一个钱包可以创建任意多个钱包账户地址,通过 2.1,2.2章节的学习,我们知道钱包地址的创建就是基于bip44标准,通过我们输入的币种类型,index(账户地址索引,index=1,2,3....来表示创建地址的索引,index不同,生成的公钥就不同),来创建index对应的公钥,继而根据不同币种的地址生成算法,生成账户地址。

2.4 钱包账户label

钱包账户的label 的最用是用来标识具体的某个地址,方便用户对某个地址用途的快速识别。是一个钱包账户地址的属性标记。在chain33钱包中,钱包的标签lable是不许重复的。

2.5 钱包交易列表

钱包的交易账单是根据节点程序解析获取到的每一个区块,如果交易里有钱包相关的地址,就会存储在钱包数据库中。

3 Chain33钱包的操作

3.1 创建钱包助记词

使用钱包,第一步要操作的就是创建钱包助记词

3.1.1 创建英文助记词
curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.GenSeed","params":[{"lang":0}]}' -H "Content-Type:application/json" -X POST http://47.xx.33.61:8901

参数说明:

  1. id:只是一个int类型的标识字段,没有特殊含义,可以作为接口ID来标识。
  2. method:表明调用的具体接口方法
  3. params:要填写接口参数,这个创建助记词的接口中有个参数lang 0:标识创建英文seed(助记词) 1:中文助记词

返回结果: 返回的助记词是从2048个单词表中,随机抽选15个单词,重复的概率非常低,可以认为是唯一的。

{
    "id":1,
    "result":{
        "seed":"old dance shiver head obscure judge effort grain shoe praise drill swing play brief donkey"
    },
    "error":null
}
3.1.2 创建中文助记词
curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.GenSeed","params":[{"lang":1}]}' -H "Content-Type:application/json" -X POST http://47.xx.33.61:8901

返回结果:

{
    "id":1,
    "result":{
        "seed":"以 尸 数 乃 叛 球 顿 神 撤 换 宁 险 烯 缓 问"
    },
    "error":null
}
3.2 导入助记词到钱包,并把助记词备份好,以防丢失
curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.SaveSeed","params":[{"seed":"old dance shiver head obscure judge effort grain shoe praise drill swing play brief donkey","passwd":"a12345678"}]}' -H "Content-Type:application/json" -X POST http://47.xx.33.61:8901

参数说明:

  1. seed:为Chain33.GenSeed创建的助记词字符串。
  2. passwd:为加密钱包助记词,同时也是设置钱包密码所用,passwd必须是数字和字母组合,8-30个字符都可以,否则会返回错误。

返回结果:

      
{
    "id":1,
    "result":{
        "isOK":true,
        "msg":""
    },
    "error":null
}

在助记词已经导入之后,就不能再导入其他助记词了,否则会报错

{
    "id":1,
    "result":{
        "isOK":false,
        "msg":"ErrSeedExist"
    },
    "error":null
}
3.3 修改钱包密码

钱包在导入助记词的时候,就相当与设置了初始密码,如果想修改密码可以使用 Chain33.SetPasswd 方法设置。

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.SetPasswd","params":[{"oldPass":"a12345678","newPass":"abc12345"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801
{"id":1,"result":{"isOK":true,"msg":""},"error":null}

返回结果:

{
    "id":1,
    "result":{
        "isOK":true,
        "msg":""
    },
    "error":null
}
3.4 创建账户 NewAccount

钱包的每个地址相当于个独立的账户,创建账户需要为该账户指定一个label即标签 主要方便识别,在钱包中,不允许有相当的标签存在。钱包中创建账户的方法: Chain33.NewAccount

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.NewAccount","params":[{"label":"test1"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

返回结果:

{
    "id":1,
    "result":{
        "acc":{
            "addr":"1GeumeGhCuKJSsxTJpNsX7QjojPBn8FQQm"
        },
        "label":"test1"
    },
    "error":null
}

如果在此时,我们继续用相同的标签创建该地址:

会返回错误的结果:

{
    "id":1,
    "result":null,
    "error":"ErrLabelHasUsed"
}
3.5 查看账户列表

钱包可以几乎创建“无数个地址”,2亿个地址是没问题的,如果我们要查看钱包的地址,需要调用钱包接口 Chain333.GetAccounts

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.GetAccounts","params":[{"withoutBalance":true}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

参数: 1.withoutBalance: bool

false:返回账户列表,没有余额

true: 返回账户列表,包含余额

当withoutBalance =true

返回结果:

{
    "id":1,
    "result":{
        "wallets":[
            {
                "acc":{
                    "currency":0,
                    "balance":0,
                    "frozen":0,
                    "addr":"12CpL25ubcMkiM6AN9MbSFgautbGRQuiL4"
                },
                "label":"node award"
            },
            {
                "acc":{
                    "currency":0,
                    "balance":0,
                    "frozen":0,
                    "addr":"1GeumeGhCuKJSsxTJpNsX7QjojPBn8FQQm"
                },
                "label":"test1"
            }
        ]
    },
    "error":null
}

当withoutBalance =false 显示余额信息

      
{
    "id":1,
    "result":{
        "wallets":[
            {
                "acc":{
                    "currency":0,
                    "balance":107600000,
                    "frozen":0,
                    "addr":"12CpL25ubcMkiM6AN9MbSFgautbGRQuiL4"
                },
                "label":"node award"
            },
            {
                "acc":{
                    "currency":0,
                    "balance":0,
                    "frozen":0,
                    "addr":"1GeumeGhCuKJSsxTJpNsX7QjojPBn8FQQm"
                },
                "label":"test1"
            }
        ]
    },
    "error":null
}
3.6 合并账户余额 MergeBalance

如果我们钱包账户的地址很多,有很多地址上有币,为了便于管理,我们可以通过 Chain33.MergeBalance 接口合并所有账户地址的余额到一个指定的地址上1GeumeGhCuKJSsxTJpNsX7QjojPBn8FQQm。

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.MergeBalance","params":[{"to":"1GeumeGhCuKJSsxTJpNsX7QjojPBn8FQQm"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

此示例中我们故意把钱包上锁,返回的结果如下:


{
    "id":1,
    "result":null,
    "error":"ErrWalletIsLocked"
}

所以,在钱包上锁的状态下,我们是无法进行转账的,当钱包解锁后,重试合并余额

{
    "id":1,
    "result":{
        "hashes":[
            "0xba69265249ca3d8ad0564e1710be5f4b79b599caaa49c8e36d01aeacc3707a37"
        ]
    },
    "error":null
}

hashes 是一个数组结构,如果钱包里有多个地址有余额,就会产生多笔交易,所以就会有多笔交易哈希,查询具体的交易信息,可以去区块链浏览器中查看。

在刚才的示例中,我们是合并到钱包的其中一个账户上,现在我们尝试把钱包的地址上的余额合并到钱包外面的地址中 135YwNqSgiEQxuwXfPbmRmH2Y53Edg8d48

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.MergeBalance","params":[{"to":"135YwNqSgiEQxuwXfPbmRmH2Y53Edg8d48"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

返回结果:

      
{
    "id":1,
    "result":{
        "hashes":[
            "0x4162eefcc1ab70805340c05ab0f94a6f98c9818c618d48da7f79ed4c41ddea82"
        ]
    },
    "error":null
}
3.7 导出私钥

如果我门想把钱包其中一个账户地址的私钥导出去,可以使用Chain33.Dumpprivkey 把私钥导出来

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.DumpPrivkey","params":[{"data":"1GeumeGhCuKJSsxTJpNsX7QjojPBn8FQQm"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

返回结果:

{
    "id":1,
    "result":{
        "data":"0x5586b6f22c476d69940aac0921ae836936010a0109b125299362170158axxxx"
    },
    "error":null
}
3.8 导入私钥

我们可以把从钱包A的账户地址上导出的私钥导入到钱包B中,这时候需要使用 Chain33.ImportPrivkey

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.ImportPrivkey","params":[{"privkey":"0x5586b6f22c476d69940aac09d4ae83f6936010a0109b125299362170158a5dd8","label":"test2"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

返回结果:

{
    "id":1,
    "result":{
        "acc":{
            "addr":"113Sd7TySTQJPZBzokYuwCdCwDVhRGyZFU"
        },
        "label":"test2"
    },
    "error":null
}

注意:导入钱包的私钥,如果钱包文件删除,或者损坏后,导入的钱包私钥以及地址将不能通过这个钱包助记词恢复出来。

3.9 钱包转账

钱包转账有多种方式:

  1. 通过钱包接口 发送交易 Chain33.SendToAddress
  2. 通过构造,签名,发送接口 发送交易,这一步需要多个接口联合调用Chain33.CreateRawTransaction,Chain33.SignRawTx,Chain33.SendTransaction.
3.9.1 通过钱包接口 Chain33.SendToAddress 发送交易

用这个接口时,需要钱包处于解锁状态,否则 发送不会成功。

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.SendToAddress","params":[{"from":"1GeumeGhCuKJSsxTJpNsX7QjojPBn8FQQm","to":"135YwNqSgiEQxuwXfPbmRmH2Y53Edg8d48","amount":10000000,"note":"test transfer"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

参数 类型 是否必填 说明 from string 是 来源地址 to string 是 发送到地址 amount int64 是 发送金额 1 coins=10^8 note string 是 备注 isToken bool 是 是否是token类型的转账(非token转账这个不用填) tokenSymbol string 是 toekn的symbol(非token转账这个不用填)

返回结果:

{
    "id":1,
    "result":{
        "hash":"0xe7bab678077e3c00b42a726dc76909ac2af2c959e78f89c76aa65d191ab80129"
    },
    "error":null
}
3.9.2 通过通过构造,签名,发送接口 发送交易

构造交易 单笔 构造 BTY的交易

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.CreateRawTransaction","params":[{"to":"135YwNqSgiEQxuwXfPbmRmH2Y53Edg8d48","amount":10000000,"fee":100000,"note":"test transfer"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

返回结果:

      
{
    "id":1,
    "result":"0a05636f696e73123c18010a381080ade2041a0d74657374207472616e73666572222231333559774e715367694551787577586650626d526d48325935334564673864343820a08d0630b9cff09aec88c1cf6f3a2231333559774e715367694551787577586650626d526d483259353345646738643438",
    "error":null
}

参数 类型 是否必填 说明 to string 是 发送到地址 amount int64 是 发送金额,注意基础货币单位为10^8 fee int64 是 手续费,注意基础货币单位为10^8 note string 否 备注 isToken bool 否 是否是token类型的转账 (非token转账这个不用填 包括平行链的基础代币转账也不用填) isWithdraw bool 是 是否为取款交易 tokenSymbol string 否 token 的 symbol (非token转账这个不用填) execName string 是 TransferToExec(转到合约) 或 Withdraw(从合约中提款),如果要构造平行链上的转账,此参数置空 execer string - 执行器名称 如果是构造平行链的基础代币,此处要填写user.p.xxx.coins

如果是非平行链: execer 不用填

如果是非token

isToken,tokenSymbol 不用填

如果打币Send交易:isWithdraw 不用填

如果要构造BTY主链下token的交易

curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.CreateRawTransaction","params":[{"to":"135YwNqSgiEQxuwXfPbmRmH2Y53Edg8d48","amount":10000000,"fee":100000,"note":"test transfer","isToken":true,"tokenSymbol":"mytokenName"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

返回结果:

      
{
    "id":1,
    "result":"0a05746f6b656e1249380422450a0b6d79746f6b656e4e616d651080ade2041a0d74657374207472616e73666572222231333559774e715367694551787577586650626d526d48325935334564673864343820a08d06308bc5dbc8a1b7b9946d3a2231333559774e715367694551787577586650626d526d483259353345646738643438",
    "error":null
}

如果我们要构造平行链的交易

  1. 构造平行链的基础代币coins的交易 isToken=false tokenSymbol 不用填 isWithdraw 不用填 execName 不用填 execer=具体平行连的名称 例如: execer=user.p.daitao.coins 如果我们构造平行链下的token 交易 execer=user.p.pdaitao.token
curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.CreateRawTransaction","params":[{"to":"135YwNqSgiEQxuwXfPbmRmH2Y53Edg8d48","amount":10000000,"fee":100000,"note":"test transfer","execer":"user.p.daitao.coins"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

返回结果:

      
{
    "id":1,
    "result":"0a13757365722e702e64616974616f2e636f696e73123c18010a381080ade2041a0d74657374207472616e73666572222231333559774e715367694551787577586650626d526d48325935334564673864343820a08d0630e1a5c0fdd5cdb5fc3b3a2231333559774e715367694551787577586650626d526d483259353345646738643438",
    "error":null
}
  1. 构造平行链下的token 交易 isToken=false tokenSymbol 不用填 isWithdraw 不用填 execName 不用填 execer=具体平行连的名称 例如: execer=user.p.daitao.token
curl --data '{"jsonrpc":"2.0","id":1,"method":"Chain33.CreateRawTransaction","params":[{"to":"135YwNqSgiEQxuwXfPbmRmH2Y53Edg8d48","amount":10000000,"fee":100000,"note":"test transfer","isToken":true,"tokenSymbol":"mytokenName","execer":"user.p.daitao.token"}]}' -H "Content-Type:application/json" -X POST http://localhost:9801

返回结果:

{
    "id":1,
    "result":"0a13757365722e702e64616974616f2e746f6b656e1249380422450a0b6d79746f6b656e4e616d651080ade2041a0d74657374207472616e73666572222231333559774e715367694551787577586650626d526d48325935334564673864343820a08d0630dd83bbc4caa0d1da1e3a2231333559774e715367694551787577586650626d526d483259353345646738643438",
    "error":null
}

返回的result 数据就是构造后编码的16进制数据,你可以在https://mainnet.bityuan.com/decode-tx 网站上解析这些交易数据