web3.js 如何修改/添加命令

转载请标注原文地址:https://lilyssh.cn/blockchain/geth-web3-update-command/

前言

以太坊的js交互是靠web3.js调用的。
改完后,需要打包,放到Go Ethereum里测试,以下就是修改命令过程说明。

一、eth 改为 cph

  1. 修改 web3.js/lib/web3.js 文件中 Web3方法。web3.js是基础命令定义处。
1
2
this.eth = new Eth(this);  //修改前
this.cph = new Eth(this); //修改后
  1. 修改go-cypherium/internal/web3ext/web3ext.go 文件中Eth_JS常量定义处。web3ext.go是扩展命令定义处。
1
2
3
4
const Eth_JS = `
web3._extend({
property: 'eth', //修改前
property: 'cph', //修改后
  1. 修改go-cypherium/console/console.go中,init方法。此处为web3.eth命令起个简略别名eth。
    1
    2
    flatten := "var eth = web3.eth; var personal = web3.personal; "  //修改前
    flatten := "var cph = web3.cph; var personal = web3.personal; " //修改后

到此,修改完成!

二、eth.getBlock(n) 改为 eth.getTxBlock(n)

以太坊源码分析 internal包简介

ethapi/api包分析

ethapi/api包主要是进入js的命令行界面后,输入的命令实现部分。

js的命令实现在ethapi/api和node/api中。目前一共有三种api的命令。

(1)第一种是admin相关的命令,这个是通过安全的RPC通道实现的。其结构体为PrivateAdminAPI

1
2
3
4
5
// PrivateAdminAPI is the collection of administrative API methods exposed only
// over a secure RPC channel.
type PrivateAdminAPI struct {
node *Node // Node interfaced by this API
}

(2)第二种是personal相关的命令,主要是负责账户管理相关命令,可以lock和unlock账户。其结构体为PrivateAccountAPI

1
2
3
4
5
6
7
8
// PrivateAccountAPI provides an API to access accounts managed by this node.
// It offers methods to create, (un)lock en list accounts. Some methods accept
// passwords and are therefore considered private by default.
type PrivateAccountAPI struct {
am *accounts.Manager
nonceLock *AddrLocker
b Backend
}

(3)第三种是eth相关的命令,主要是可以操作区块上的相关命令。其结构体为PublicBlockChainAPI

1
2
3
4
5
// PublicBlockChainAPI provides an API to access the Ethereum blockchain.
// It offers only methods that operate on public data that is freely available to anyone.
type PublicBlockChainAPI struct {
b Backend
}

otto包

以太坊的命令是通过在js虚拟机上来实现命令的。而在go语言中,有第三方的otto包,可以直接在go语言中实现js命令。而以太坊代码则使用了otto包来实现搭建js命令。

在otto包中,set方法是设置变量的值,get方法是获取变量的值。

1
2
3
4
// Set the property of the given name to the given value.
func (self Object) Set(name string, value interface{})
// Get the value of the property with the given name.
func (self Object) Get(name string) (Value, error)

Compile是根据输入的路径对js的代码进行编译,返回变量的值。

1
2
3
// Compile will parse the given source and return a Script value or nil and
// an error if there was a problem during compilation.
func (self *Otto) Compile(filename string, src interface{}) (*Script, error)

Run方法会运行相关的js代码,如果有返回值的话会返回。

1
2
// Run will run the given source (parsing it first if necessary), returning the resulting value and error (if any)
func (self Otto) Run(src interface{}) (Value, error)

如何编写自己的以太坊命令

接上篇ethapi.api-analysis分析,如果我们需要在相关模块添加相关命令,首先我们需要找到相关命令所对应的api结构体。

各个命令对应的结构体,包的位置如下:

1
2
3
4
5
6
7
8
9
admin  PrivateAdminAPI,PublicAdminAPI  node/api
debug PrivateDebugAPI eth/api
eth PublicBlockChainAPI ethapi/api
miner PrivateMinerAPI eth/api
net PublicNetAPI ethapi/api
personal PrivateAccountAPI ethapi/api
txpool PublicTxPoolAPI ethapi/api
rpc 所有可调用包集合
web3 所有命令集合

假设我们需要在personal包中添加一个命令,那么我们就在PrivateAccountAPI中添加一个方法:

1
2
3
func (s *PrivateAccountAPI) TestMethod() {
fmt.Print("TestMethod")
}

接下来到internal/web3ext/web3ext.go中,找到personal命令集合,然后添加一条自己的命令:

1
2
3
4
5
6
7
8
const Personal_JS = `
web3._extend(
methods: [
new web3._extend.Method({
name : 'testMethod',
call : 'personal_testMethod'
}), //our method
...

最后到internal/jsre/deps/web3.js中,找到personal方法的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Personal(web3) {
this._requestManager = web3._requestManager;

var self = this;

methods().forEach(function(method) {
method.attachToObject(self);
method.setRequestManager(self._requestManager);
});

properties().forEach(function(p) {
p.attachToObject(self);
p.setRequestManager(self._requestManager);
});
}
var methods = function () {
...

然后再methods中添加你定义的方法名:

1
2
3
4
5
6
var methods = function () {
var testMethod = new Method({
name : 'testMethod',
call : 'personal_testMethod'
});
...

并在最后的return中添加你的方法:

1
2
3
4
5
6
7
8
9
10
return [
newAccount,
testMethod, //our method
importRawKey,
unlockAccount,
ecRecover,
sign,
sendTransaction,
lockAccount
];

这之后在启动命令行,我们就可以调用我们的方法了。结果如下:

1
2
> personal.testMethod()
TestMethodnull

本文由 lilyssh创作。可自由转载、引用,但需署名作者且注明文章出处。


当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器