Conflux js-sdk与以太坊 js-sdk区别(未完成)

1,126 阅读9分钟

Web3.js vs js-conflux-sdk

js-conflux-sdk 最新版本为1.x, 与0.x有很大差别, 但由于其还在测试阶段,本文只对0.13.4Web3进行对照,待1.x版本稳定后, 再针对1.x与Web3进行对照。 Web3js-conflux-sdk 都是最顶层模块,他们包含了其它子模块以及在顶层暴露了一些子模块中的方法方便开发者快捷使用,我们这里只比较各模块,而不再对这些快捷方法做特别说明。

模块对比

Web3js-conflux-sdk 有对应关系的主要有以下模块:

Ethereum中的模块Conflux中的模块功能
EthConflux用于管理连接节点,与节点交互,发送rpc请求,包含读取状态、发送交易等
Contract + abiContract用于操作智能合约,包含创建合约实例、调动合约方法,以及提供一些根据abi编解码的功能
accountsaccount + Message + Transaction用于管理账户,包含创建、删除账户,及使用账户对消息或交易进行签名等操作
utilsutil工具类,提供一些通用函数,例如hex格式转换,单位转换,私钥转公钥及地址,生成随机私钥,判断数据类型,sha3等,方便dapp开发及其他js包使用

各模块方法对比

Conflux模块 Vs Eth模块

以下是Conflux模块包含的方法及与Eth模块的对应关系,该模块主要封装了JSONRPC与节点交互,还有一部分JSONRPC暂未实现,将来会实现所有RPC。具体RPC介绍请参见 Conflux JSONRPC介绍Conflux RPC与Ethereum RPC的区别 这里的Epoch Number指用于划分一组Conflux区块为一个Epoch,Conflux区块链是以Epoch为顺序组织的。

Conflux Conflux模块 | Ethereum Eth模块 | 对应RPC --|--|--|--|-- setProvider |setProvider|-| getStatus |getChainId|cfx_getStatus getGasPrice |getGasPrice|cfx_gasPrice getEpochNumber |getBlockNumber|cfx_epochNumber getBalance |getBalance|cfx_getBalance getNextNonce |getBlockTransactionCount|cfx_getNextNonce getBlockByEpochNumber |getBlock|cfx_getBlockByEpochNumber getBlocksByEpochNumber |-|cfx_getBlocksByEpoch getBlockByHash |getBlock|cfx_getBlockByHash getBlockByHashWithPivotAssumption |-|cfx_getBlockByHashWithPivotAssumption getTransactionByHash |getTransaction|cfx_getTransactionByHash getTransactionReceipt |getTransactionReceipt|cfx_getTransactionReceipt sendTransaction |sendTransaction|cfx_sendTransaction sendRawTransaction |sendSignedTransaction|cfx_sendRawTransaction getCode |getCode|cfx_getCode call |call|cfx_call estimateGasAndCollateral |estimateGas|cfx_estimateGasAndCollateral getLogs | getPastLogs(contract模块)|cfx_getLogs getBestBlockHash |-|cfx_getBestBlockHash getConfirmationRiskByHash |-|cfx_getConfirmationRiskByHash close |-|-

Contract 模块对比

Conflux Contract 模块Eth Contract + abi 模块
contract.mymethodmethods.myMethod.call
contract.mymethod.callmethods.myMethod.call
contract.mymethod.decodeDatadecodeParameters
contract.mymethod.decodeOutputs-
contract.mymethod.encodeDatamethods.myMethod.encodeABI
contract.mymethod.sendmethods.myMethod.send
contract.mymethod.estimateGasAndCollateralmethods.myMethod.estimateGas
contract.myEvent.getLogsgetPastLogs
contract.myEvent.encodeTopics-
contract.myEvent.decodeLogdecodeLog(ABI模块)
contract.abi.decodeDatadecodeParameters
contract.abi.decodeLogdecodeLog(ABI模块)

accounts 模块对比

Conflux Account模块Ethereum Accounts模块
randomcreate
decryptdecrypt
encryptencrypt
signTransactionsignTransaction
signMessagesign
Conflux Message模块Ethereum Accounts模块
signsign
recoverrecover
hash (getter)-
from (getter)-
signsign
Conflux Transaction模块Ethereum Accounts模块
hash (getter)-
from (getter)-
signsignTransaction
recoverrecover
encode-
serialize-

utils 模块对比

Conflux util 模块Ethereum utils模块
format.any (setter)-
format.hex (setter)toHex, numberToHex
format.uInt (setter)-
format.bigInt (setter)toBN
format.bigUInt (setter)-
format.hexUInt (setter)-
format.riskNumber (setter)-
format.epochNumber (setter)-
format.address (setter)bytesToHex
format.publicKey (setter)bytesToHex
format.privateKey (setter)bytesToHex
format.signature (setter)bytesToHex
format.blockHash (setter)bytesToHex
format.txHash (setter)bytesToHex
format.buffer (setter)toHex + hexToBytes
format.boolean (setter)-
sha3sha3
checksumAddresstoChecksumAddress
randomBuffer-
randomPrivateKeyrandomHex
privateKeyToPublicKeyprivateKeyToAccount(Accounts模块)
publicKeyToAddressprivateKeyToAccount(Accounts模块)
privateKeyToAddressprivateKeyToAccount(Accounts模块)
ecdsaSignsign(Accounts模块)
ecdsaRecoverrecover(Accounts模块)
encryptencrypt(Accounts模块)
decryptdecrypt(Accounts模块)
unit.fromCFXToGDrip-
unit.fromCFXToDriptoWei
unit.fromGDripToCFX-
unit.fromGDripToDrip-
unit.fromDripToCFXfromWei
unit.fromDripToGDrip-

使用对比

初始化

初始化Web3实例

var Web3 = require('web3');
// "Web3.providers.givenProvider" will be set if in an Ethereum supported browser.
var web3 = new Web3(Web3.givenProvider || 'ws://some.local-or-remote.node:8546');
// or
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));

初始化Conflux实例

Conflux实例化与web3类似,但当前版本还不支持 webscoket provider

const { Conflux } = require('js-conflux-sdk');
const cfx = new Conflux({url:'http://testnet-jsonrpc.conflux-chain.org:12537'});

读状态

Ethereum读状态

web3.eth.getBalance("0x107d73d8a49eeb85d32cf465507dd71d507100c1").then(console.log);
> "1000000000000"

Conflux读状态

await cfx.getBalance("0x107d73d8a49eeb85d32cf465507dd71d507100c1");
// or
cfx.getBalance("0x107d73d8a49eeb85d32cf465507dd71d507100c1").then(console.log)
> "1000000000000"

发送交易

web3 发送交易

web3发送交易后通过event方式在以下各个阶段达成时通知:

  • transactionHash 交易已发送
  • receipt 交易已执行
  • confirmation 交易已确认
  • error 交易执行失败
// compiled solidity source code using https://remix.ethereum.org
var code = "603d80600c6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463c6888fa18114602d57005b6007600435028060005260206000f3";

// using the callback
web3.eth.sendTransaction({
    from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe',
    data: code // deploying a contracrt
}, function(error, hash){
    ...
});

// using the promise
web3.eth.sendTransaction({
    from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe',
    to: '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe',
    value: '1000000000000000'
})
.then(function(receipt){
    ...
});

// using the event emitter
web3.eth.sendTransaction({
    from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe',
    to: '0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe',
    value: '1000000000000000'
})
.on('transactionHash', function(hash){
    ...
})
.on('receipt', function(receipt){
    ...
})
.on('confirmation', function(confirmationNumber, receipt){ ... })
.on('error', console.error); // If a out of gas error, the second parameter is the receipt.

Conflux发送交易

js-conflux-sdk 由于当前版本没有钱包系统,所以发送交易时需要直接指定Account; sendTransaction返回的是一个 Promise.<PendingTransaction>对象, 可以直接await获取transaction hash

也可以通过该对象方法在不同状态下返回transactiontransaction receipt, 方法列举如下:

  • get在发送完成后返回transaction,
  • mined在打包完成后返回transaction,
  • executed在执行完成后返回transaction receipt,
  • confirmedtransaction risk < threshold时返回transaction receipt
const account = cfx.Account(your_private_key);

const promise = cfx.sendTransaction({ // Not await here, just get promise
      from: account,
      to: "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe",
      value: Drip.fromCFX(0.007),
    });
> await promise; // transaction
   "0x91fbdfb33f3a585f932c627abbe268c7e3aedffc1633f9338f9779c64702c688"
> await promise.get(); // get transaction
   {
    "blockHash": null,
    "transactionIndex": null,
    "hash": "0x91fbdfb33f3a585f932c627abbe268c7e3aedffc1633f9338f9779c64702c688",
    ...
   }
> await promise.mined(); // wait till transaction mined
   {
    "blockHash": "0xe9b22ce311003e26c7330ac54eea9f8afea0ffcd4905828f27c9e2c02f3a00f7",
    "transactionIndex": 0,
    "hash": "0x91fbdfb33f3a585f932c627abbe268c7e3aedffc1633f9338f9779c64702c688",
    ...
   }
> await promise.executed(); // wait till transaction executed in right status. and return it's receipt.
   {
    "blockHash": "0xe9b22ce311003e26c7330ac54eea9f8afea0ffcd4905828f27c9e2c02f3a00f7",
    "index": 0,
    "transactionHash": "0x91fbdfb33f3a585f932c627abbe268c7e3aedffc1633f9338f9779c64702c688",
    "outcomeStatus": 0,
    ...
   }
> await promise.confirmed(); // wait till transaction risk coefficient '<' threshold.
   {
    "blockHash": "0xe9b22ce311003e26c7330ac54eea9f8afea0ffcd4905828f27c9e2c02f3a00f7",
    "index": 0,
    "transactionHash": "0x91fbdfb33f3a585f932c627abbe268c7e3aedffc1633f9338f9779c64702c688",
    "outcomeStatus": 0,
    ...
   }
需要注意的地方:

发送交易时,建议先使用 estimateGasAndCollateral 返回预估的gas使用数量和存储抵押数量;然而由于实际执行消耗与预估结果有差异,为了防止交易执行失败,建议在实际发送交易时,设置gaslimitstorage_limit的值为预估值 * 4/3

参数EpochHeight表示这笔交易将会在 Epoch[EpochHeight-100000 , EpochHeight+100000] 的区间内执行,当超出这个区间这笔交易将被丢弃,建议设置当前Epoch值即可。

部署合约

部署合约实质就是发送一笔data为合约bytecodetonull的交易

web3部署合约

web3可以通过直接发送交易的方式部署,也可以通过contract实例部署

// send transaction directly
await web3.eth.sendTransaction({
    from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe',
    data: contract_bytecode,
})
> {
  "status": true,
  "contractAddress": "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe",
  ...
}

// or use contract instance
var myContract = new web3.eth.Contract(contract_abi, '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe', {
    from: '0x1234567890123456789012345678901234567891', // default from address
    ...
});
myContract.deploy({
    data: '0x12345...',
    arguments: [123, 'My String']
})
.send({
    from: '0x1234567890123456789012345678901234567891',
    gas: 1500000,
    gasPrice: '30000000000000'
}, function(error, transactionHash){ ... })
.on('error', function(error){ ... })
.on('transactionHash', function(transactionHash){ ... })
.on('receipt', function(receipt){
   console.log(receipt.contractAddress) // contains the new contract address
})
.on('confirmation', function(confirmationNumber, receipt){ ... })
.then(function(newContractInstance){
    console.log(newContractInstance.options.address) // instance with the new contract address
});

conflux部署合约

conflux当前只能通过发送交易的方式部署,transaction receiptcontractCreated字段就是部署后的合约地址

const account = cfx.Account(your_private_key);

await cfx.sendTransaction({ // Not await here, just get promise
      from: account,
      data: contract_bytecode,
    }).executed();
>  {
   "outcomeStatus": 0,
   "contractCreated": "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe",
   ...
   }

调用合约

调用合约分两种:

  • 一种是读状态,不需要发送交易,读状态web3跟conflux都使用call方法。
  • 一种是修改合约状态,需要发送交易,修改合约状态web3使用send,conflux使用sendTransaction

web3调用合约

// create contract instance
var myContract = new web3.eth.Contract(contract_abi, contract_address);

// calling a method
myContract.methods.myMethod(123).call({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'}, function(error, result){
    ...
});

// or sending and using a promise
myContract.methods.myMethod(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
.then(function(receipt){
    // receipt can also be a new contract instance, when coming from a "contract.deploy({...}).send()"
    ...
});

conflux调用合约

conflux 调用合约与web3类似,需要注意的地方是调用合约发送交易前建议根据estimateGasAndCollateral得到的gasUsed与storageCollateralized计算gas(同以太坊的gasLimit)与storageLimit; 由于实际执行交易时使用的gas与storageCollateralized与预估可能会有差别,为了防止失败,建议设置 gas = estimated.gasUsed * 4 / 3,storageLimit = estimated.storageCollateralized * 4 /3

// create contract instance
var myContract = cfx.Contract({
    abi: contract_abi,
    address: contract_address
});

// call
await contract.myCallMethod(123)
await contract.myCallMethod().call(123)

// send
// set gasLimit and sotrageLimit large 1/3 than estimated value
const estimated = await contract.mySendMethod(123).estimateGasAndCollateral({from: '0x1e0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'});
let gasLimit = JSBI.multiply(estimated.gasUsed, JSBI.BigInt(4))
gasLimit = JSBI.divide(gasLimit, JSBI.BigInt(3))
let storageLimit = JSBI.multiply(estimated.storageCollateralized, JSBI.BigInt(4))
storageLimit = JSBI.divide(storageLimit, JSBI.BigInt(3))

// send transaction
await contract.mySendMethod(123).sendTransaction({from: "addres",gasLimit:estimated.gas*4/3}).executed();

eth 中的其它模块

除了以上介绍的模块,web3中还包含了以下模块;这些模块conflux中暂时还没有对应模块,将来可能支持类似功能

web3模块作用
personal使用所请求节点的账户进行签名、锁定、解锁等操作
shh用于使用whisper协议传播消息
bzz用于与swarm交互,swarm是一个分布式文件存储系统
net获取节点信息
subscribe订阅链上产生的新时间,包含logs,pendingTransactions,newBlockHeaders.syncing
ens用于操作以太坊的域名服务
Iban以太坊地址格式与IBAN(国际银行帐号) BBAN(基本银行账号)地址格式的转换

文章引用

  1. js-conflux-sdk 用户手册
  2. Web3 v1.2.11 用户手册
  3. Conflux JSONRPC介绍
  4. Conflux RPC与Ethereum RPC的区别