From 4380ff555b7465cf14011959ea8a68d50953ecbd Mon Sep 17 00:00:00 2001 From: Wanghaizhou Date: Tue, 10 Nov 2020 17:28:11 +0800 Subject: [PATCH] UPDATE: use BigInt for nodejs, JSBI for browser --- README.md | 200 +----------- api.md | 488 +++++++++++++++------------- docs/getting_start.md | 53 ++- docs/how_to_send_tx.md | 301 ++++++++++------- docs/interact_with_contract.md | 23 +- package.json | 8 +- src/CONST.js | 2 +- src/Conflux.js | 313 +++++++++--------- src/contract/Contract.js | 122 ++++--- src/contract/abi/BoolCoder.js | 2 +- src/contract/abi/IntegerCoder.js | 2 +- src/provider/WebSocketProvider.js | 2 +- src/util/format.js | 50 +-- src/util/jsbi.js | 42 +++ test/conflux/after.test.js | 59 ++-- test/contract/EventCoder.test.js | 2 +- test/contract/FunctionCoder.test.js | 2 +- test/contract/contract.test.js | 2 +- test/contract/valueCoder.test.js | 2 +- test/util/format.test.js | 2 +- test/util/jsbi.test.js | 126 +++++++ yarn.lock | 2 +- 22 files changed, 964 insertions(+), 841 deletions(-) create mode 100644 src/util/jsbi.js create mode 100644 test/util/jsbi.test.js diff --git a/README.md b/README.md index c6252404..33b74eb4 100644 --- a/README.md +++ b/README.md @@ -12,49 +12,37 @@ JavaScript Conflux Software Development Kit 2. Add `cfx.InternalContract(name)` to interact with Conflux internal contracts. 3. Add websocket provider, support pub/sub 4. Provide `Drip` to easily convert unit between CFX, Drip, Gdrip +5. Use `JSBI` for front-end, native `BigInt` for back-end Check the [complete changelog](./CHANGE_LOG.md) -## Installation - -`npm install js-conflux-sdk` - ## Quick Usage ### Nodejs ```javascript const { Conflux } = require('js-conflux-sdk'); -async function main() { - // initialize a Conflux object - const conflux = new Conflux({ - url: 'http://test.confluxrpc.org', - logger: console, // for debug - }); - // get balance - const balance = await conflux.getBalance('0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b'); - // Note you should console.log a JSBI's string representation, directly log a JSBI is very ugly. - console.log(balance.toString()); // 10098788868004995614504 -} - -main(); +const conflux = new Conflux({ + url: 'http://test.confluxrpc.org', + logger: console, // for debug +}); ``` require deep nested file/dir -``` javascript +```javascript const util = require('js-conflux-sdk/src/util'); ``` ### Frontend #### umd -``` javascript +```javascript import { Conflux } from 'js-conflux-sdk/dist/js-conflux-sdk.umd.min.js'; ``` or if your bundler supports the [`browser` field](https://docs.npmjs.com/files/package.json#browser) in `package.json` -``` javascript +```javascript import { Conflux } from 'js-conflux-sdk'; ``` @@ -70,181 +58,13 @@ or ``` - ## Documentation * [Quick Intro (Recommend to read)](./docs/quick_intro.md) * [Complete document for send transaction](./docs/how_to_send_tx.md) * [Interacting with contract](./docs/interact_with_contract.md) -* [API](https://github.com/Conflux-Chain/js-conflux-sdk/blob/master/api.md) - -## Examples - -* [Create conflux instance](https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/0_create_conflux.js) -* [Account and balance](https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/1_account_and_balance.js) -* [Send transaction](https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/2_send_transaction.js) -* [Query epoch block transaction](https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/3_epoch_block_transaction.js) -* [Contract deploy and call](https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/4_contract_deploy_and_call.js) -* [Contract override](https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/5_contract_override.js) - -### Send transaction simple - -```js -const { Conflux, Drip } = require('js-conflux-sdk'); - -async function main() { - const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); - const account = conflux.wallet.addPrivateKey(PRIVATE_KEY); // create account instance and add to wallet - - const receipt = await conflux.sendTransaction({ - from: account.address, // sender address which added into conflux.wallet - to: ADDRESS, // receiver address - value: Drip.fromCFX(0.1), // 0.1 CFX = 100000000000000000 Drip - }).executed(); // wait till transaction executed and get receipt - - console.log(receipt); // outcomeStatus 0 means success - /* - { - "index": 0, - "epochNumber": 784649, - "outcomeStatus": 0, - "gasUsed": "21000", - "gasFee": "21000000000000", - "blockHash": "0xfa7c6d9d0c8ae436f1c9c785a316ac6cc4db16286eede3dd3d5c6a5a22ad5f9e", - "contractCreated": null, - "from": "0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "stateRoot": "0x166cbcbfd747505d91237ccd8f849fd6882ad0e6d8b9923ca3c44891cf2b8753", - "to": "0x1ead8630345121d19ee3604128e5dc54b36e8ea6", - "transactionHash": "0x50cd13d5f97dd867d4ca65e24eb642f6444c07d6af8143018c558df456f11e63" - } - */ -} - -main(); -``` - -### Send transaction complete - -For the detail explanation of these fields check [official doc](https://developer.conflux-chain.org/docs/conflux-doc/docs/send_transaction#installation). - -```javascript -const { Conflux, Drip } = require('js-conflux-sdk'); - -async function main() { - const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); - const account = conflux.wallet.addPrivateKey(PRIVATE_KEY); // create account instance and add to wallet - - const estimate = await conflux.estimateGasAndCollateral({ to, value }); - const status = await conflux.getStatus(); - - const txHash = await conflux.sendTransaction({ - from: account.address, // or just `from: account` - to: ADDRESS, - value: Drip.fromGDrip(100), // 100 GDrip = 100000000000 Drip - gas: estimate.gasUsed, - storageLimit: estimate.storageCollateralized, - chainId: status.chainId, - data: null, - nonce: await conflux.getNextNonce(ADDRESS), - gasPrice: await conflux.getGasPrice(), - epochHeight: await conflux.getEpochNumber(), - }); - console.log(txHash); - - // you might need wait minute here... - await new Promise(resolve => setTimeout(resolve, 30*1000)); - - const transaction = await conflux.getTransactionByHash(txHash); - console.log(transaction); - - const receipt = await conflux.getTransactionReceipt(txHash); - console.log(receipt); -} - -main(); -``` - -### Deploy contract - -```javascript -const { Conflux } = require('js-conflux-sdk'); -const { abi, bytecode } = MINI_ERC20; // see https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/contract/miniERC20.json - -async function main() { - const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); - const account = conflux.wallet.addPrivateKey(PRIVATE_KEY); // create account instance and add to wallet - const contract = conflux.Contract({ abi, bytecode }); - - const receipt = await contract.constructor('MiniERC20', 18, 'MC', 10000) - .sendTransaction({ from: account }) - .executed(); - console.log(receipt); - /* - { - "index": 0, - "epochNumber": 318456, - "outcomeStatus": 0, - "gasUsed": "1054531", - "gasFee": "1054531000000000", - "blockHash": "0x4a8b07e2694e358af075f7a9e96e78842b77ac2d511e2ab33f6acfff34a5846c", - "contractCreated": "0x8a9c270e1a99c05ca90ef0f0008b8f6444cf1a97", - "from": "0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "stateRoot": "0x0940d4870e25bae1e7a5e5d7c19411b41922c025aa3de61aea2be17759673b1a", - "to": null, - "transactionHash": "0x6f55e67b486b5ef0c658c6d50cb5b89a2a2ddfecc1a1f2e414bbbefe36ef8dd5" - } - */ - - // create contract address "0x8a9c270e1a99c05ca90ef0f0008b8f6444cf1a97" -} - -main(); -``` - -### Call contract - -```javascript -const { Conflux } = require('js-conflux-sdk'); -const { abi } = MINI_ERC20; // see https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/contract/miniERC20.json - -async function main() { - const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); - const account = conflux.wallet.addPrivateKey(PRIVATE_KEY); // create account instance and add to wallet - const contract = conflux.Contract({ abi, address: '0x8a9c270e1a99c05ca90ef0f0008b8f6444cf1a97' }); - - const name = await contract.name(); // call method without arguments - console.log(name); // MiniERC20 - // user can set options by `contract.name().call({ from: account, ... })` - - const balance = await contract.balanceOf(account.address); // call method with arguments - console.log(balance); // "10000" JSBI - - const txHash = await contract.transfer(ADDRESS, 10).sendTransaction({ from: account }); // send method transaction - console.log(txHash); // 0xb31eb095b62bed1ef6fee6b7b4ee43d4127e4b42411e95f761b1fdab89780f1a - // user can set options by `contract.transfer(ADDRESS, 10).sendTransaction({ from: account, gasPrice: , ... })` -} - -main(); -``` - -## Change log - -[see](https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/CHANGE_LOG.md) - - -## Conflux Docs - -1. [Official developer documentation](https://developer.conflux-chain.org/) -2. [RPC](https://developer.conflux-chain.org/docs/conflux-doc/docs/json_rpc) -3. [Subscribtion](https://developer.conflux-chain.org/docs/conflux-doc/docs/pubsub) -4. [Conflux Portal](https://portal.conflux-chain.org/) - +* [API](./api.md) ## TODO -* use native BigInt in node.js, use JSBI in browser. -* TODO support [CIP 23](https://github.com/Conflux-Chain/CIPs/blob/master/CIPs/cip-23.md) +* support [CIP 23](https://github.com/Conflux-Chain/CIPs/blob/master/CIPs/cip-23.md) diff --git a/api.md b/api.md index c0911772..c8c4941b 100644 --- a/api.md +++ b/api.md @@ -319,11 +319,11 @@ Get status ``` > await conflux.getStatus() { - "chainId": 2, - "epochNumber": 324105, - "blockNumber": 426341, - "pendingTxNumber": 40, - "bestHash": "0xef08f2702335f149afc021607511ffae49df8bb56b2afb7f42de02d9cbbf7ef6" + chainId: 1029, + epochNumber: 1117476, + blockNumber: 2230973, + pendingTxNumber: 4531, + bestHash: '0x8d581f13fa0548f2751450a7dabd871777875c9ccdf0d8bd629e07a7a5a7917a' } ``` @@ -339,7 +339,7 @@ Returns the current price per gas in Drip. ``` > await conflux.getGasPrice(); - '1' + 1n ``` ### Conflux.prototype.getInterestRate @@ -360,7 +360,7 @@ epochNumber | `string,number` | false | 'latest_state' | See [format.sendTx]( ``` > await conflux.getInterestRate(); - "2522880000000" + 2522880000000n ``` ### Conflux.prototype.getAccumulateInterestRate @@ -381,7 +381,7 @@ epochNumber | `string,number` | false | 'latest_state' | See [format.sendTx]( ``` > await conflux.getAccumulateInterestRate() - "76269979767787603657181926319926" + 76357297457647044505744908994993n ``` ### Conflux.prototype.getAccount @@ -409,15 +409,15 @@ admin `string`: admin of the account. * **Examples** ``` -> await conflux.getAccount('0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b'); +> await conflux.getAccount('0x1c1e72f0c37968557b3d85a3f32747792798bbde'); { - "accumulatedInterestReturn": "0", - "balance": "0", - "collateralForStorage": "0", - "nonce": "0", - "stakingBalance": "0", - "admin": "0x0000000000000000000000000000000000000000", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + accumulatedInterestReturn: 0n, + balance: 824812401057514588670n, + collateralForStorage: 174187500000000000000n, + nonce: 1449n, + stakingBalance: 0n, + admin: '0x0000000000000000000000000000000000000000', + codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' } ``` @@ -439,8 +439,8 @@ epochNumber | `string,number` | false | 'latest_state' | See [format.sendTx]( * **Examples** ``` -> await conflux.getBalance("0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b"); - '10098788868004995614504' +> await conflux.getBalance("0x1c1e72f0c37968557b3d85a3f32747792798bbde"); + 824812401057514588670n ``` ### Conflux.prototype.getStakingBalance @@ -461,8 +461,8 @@ epochNumber | `string,number` | false | 'latest_state' | See [format.sendTx]( * **Examples** ``` -> await conflux.getStakingBalance('0x194770007dda54cF92009BFF0dE90c06F603a09f', 'latest_state'); - '6334100968004995614504' +> await conflux.getStakingBalance('0x1c1e72f0c37968557b3d85a3f32747792798bbde', 'latest_state'); + 0n ``` ### Conflux.prototype.getNextNonce @@ -483,8 +483,8 @@ epochNumber | `string,number` | false | | See [format.sendTx](#util/f * **Examples** ``` -> await conflux.getNextNonce("0x1be45681ac6c53d5a40475f7526bac1fe7590fb8"); - "3" +> await conflux.getNextNonce("0x1c1e72f0c37968557b3d85a3f32747792798bbde"); + 1449n ``` ### Conflux.prototype.getAdmin @@ -505,8 +505,8 @@ epochNumber | `string,number` | false | 'latest_state' | See [format.sendTx]( * **Examples** ``` -> conflux.getAdmin('0x8af71f222b6e05b47d8385fe437fe2f2a9ec1f1f') - "0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c" +> conflux.getAdmin('0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98') + "0x1c1e72f0c37968557b3d85a3f32747792798bbde" ``` ### Conflux.prototype.getEpochNumber @@ -625,29 +625,33 @@ detail | `boolean` | false | false | If `true` it returns the full trans * **Examples** ``` -> await conflux.getBlockByHash('0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7'); +> await conflux.getBlockByHash('0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390'); { - "epochNumber": 455, - "blame": 0, - "height": 455, - "size": 122, - "timestamp": 1594912954, - "gasLimit": "30000000", - "difficulty": "30000", - "transactions": [ - "0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8" + epochNumber: 6, + blame: 0, + height: 6, + size: 352, + timestamp: 1603901780, + gasLimit: 30000000n, + gasUsed: 61118n, + difficulty: 20000000000n, + transactions: [ + '0xaad69c8c814aec3e418b68f60917c607920a531e7082dd2c642323b43ecadb94', + '0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce' ], - "adaptive": false, - "deferredLogsBloomHash": "0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5", - "deferredReceiptsRoot": "0x09f8709ea9f344a810811a373b30861568f5686e649d6177fd92ea2db7477508", - "deferredStateRoot": "0x2124f4f35df1abeb01a43ed25c6b7ea5a56bbc2bdb3ab3feb096e3911e522181", - "hash": "0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7", - "miner": "0x100000000000000000000000000000000000007c", - "nonce": "0xcc2eadd8c5c369ff", - "parentHash": "0x9ced22205ac0fe96ad27be9c0add073ce49582220b8fd1006edf16a402aef9b4", - "powQuality": "0x167d3", - "refereeHashes": [], - "transactionsRoot": "0x5a31184b86d8b88a3860649c17a4b7b4d3c7ef35fea971afb1f44081feff5b60" + adaptive: false, + deferredLogsBloomHash: '0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5', + deferredReceiptsRoot: '0x09f8709ea9f344a810811a373b30861568f5686e649d6177fd92ea2db7477508', + deferredStateRoot: '0x50c0fcbc5bafa7d1dba7b19c87629830106a6be8d0adf505cdc656bb43535d69', + hash: '0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390', + miner: '0x1f323dccb24606b061db9e3a1277b8db99f1c1b2', + nonce: '0x17d86f2f6', + parentHash: '0xc8a412b4b77b48d61f694975f032d109f26bb0f9fc02e4b221d67a382fab386b', + powQuality: '0x5a0f86a6f4', + refereeHashes: [ + '0x73cd891aea310e2c0b8644de91746c7353cebfffb780126bc06101b20689c893' + ], + transactionsRoot: '0xd2f08676484ba2a3738194f44542eb29fb290b8ed74bf007f132fe51d89b2e7c' } ``` @@ -669,7 +673,7 @@ blockHash | `string` | true | | Hash of a block * **Examples** ``` -> await conflux.getConfirmationRiskByHash('0x24dcc768132dc7f651d7cb35c52e7bba632eda073d8743f81cfe905ff7e4157a') +> await conflux.getConfirmationRiskByHash('0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390') 1e-8 ``` @@ -689,7 +693,7 @@ transactionHash | `string` | true | | hash of a transaction - blockHash `string`: hash of the block where this transaction was in and got executed. `null` when its pending. - contractCreated `string|null`: address of created contract. `null` when it's not a contract creating transaction - data `string`: the data send along with the transaction. -- epochHeight `number`: TODO +- epochHeight `number`: epoch height - from `string`: address of the sender. - gas `BigInt`: gas provided by the sender. - gasPrice `number`: gas price provided by the sender in Drip. @@ -698,8 +702,8 @@ transactionHash | `string` | true | | hash of a transaction - r `string`: ECDSA signature r - s `string`: ECDSA signature s - status `number`: 0 for success, 1 for error occured, `null` when the transaction is skipped or not packed. -- storageLimit `BigInt`: TODO -- chainId `number`: TODO +- storageLimit `BigInt`: storage limit in bytes +- chainId `number`: chain id - to `string`: address of the receiver. null when its a contract creation transaction. - transactionIndex `number`: integer of the transactions's index position in the block. `null` when its pending. - v `string`: ECDSA recovery id @@ -708,27 +712,27 @@ transactionHash | `string` | true | | hash of a transaction * **Examples** ``` -> await conflux.getTransactionByHash('0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8'); +> await conflux.getTransactionByHash('0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce'); { - "nonce": "0", - "value": "1000000000000000000000000000000000", - "gasPrice": "3", - "gas": "16777216", - "v": 1, - "transactionIndex": 0, - "status": 0, - "storageLimit": "65536", - "chainId": 2, - "epochHeight": 454, - "blockHash": "0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7", - "contractCreated": null, - "data": "0x", - "from": "0x1be45681ac6c53d5a40475f7526bac1fe7590fb8", - "hash": "0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8", - "r": "0x85f6729aa1e709202318bd6746c4a232a379eaa4cd9c2ea24c7babdbd09085cd", - "s": "0x7101e1e2ee4ddfcef8879358df0cb0792f34712116f100b76c8e9582625acd2f", - "to": "0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c" - } + nonce: 0n, + gasPrice: 10n, + gas: 200000n, + value: 0n, + storageLimit: 1024n, + epochHeight: 0, + chainId: 1029, + v: 1, + status: 0, + transactionIndex: 1, + blockHash: '0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390', + contractCreated: null, + data: '0xfebe49090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162788589c8e386863f217faef78840919fb2854', + from: '0x108b8b1333523a79ac363d8f41805e81b085d55d', + hash: '0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce', + r: '0x495da01ae9f445847022a8bc7df0198577ba75f88b26699f61afb435bb9c50bc', + s: '0x2291051b1c53db1d6bfe2fb29be1bf512d063e726dc6b98aaf0f2259b7456be0', + to: '0x83bf953c8b687f0d1b8d2243a3e0654ec1f70d1b' + } ``` ### Conflux.prototype.getTransactionReceipt @@ -760,21 +764,22 @@ transactionHash | `string` | true | | Hash of a transaction * **Examples** ``` -> await conflux.getTransactionReceipt('0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8'); +> await conflux.getTransactionReceipt('0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce'); { - "index": 0, - "epochNumber": 455, - "outcomeStatus": 0, - "gasUsed": "21000", - "gasFee": "37748736", - "blockHash": "0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7", - "contractCreated": null, - "from": "0x1be45681ac6c53d5a40475f7526bac1fe7590fb8", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "stateRoot": "0x19d109e6fe9f5a75cc54543af4beab08c0f23fdf95eea33b1afe5a9ef8b770dc", - "to": "0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c", - "transactionHash": "0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8" + index: 1, + epochNumber: 6, + outcomeStatus: 0, + gasUsed: 30559n, + gasFee: 1500000n, + blockHash: '0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390', + contractCreated: null, + from: '0x108b8b1333523a79ac363d8f41805e81b085d55d', + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + stateRoot: '0xd6a7c2c14cb0d1233010acca98e114db5a10e0b94803d23b01a6777b7fd3b2fd', + to: '0x83bf953c8b687f0d1b8d2243a3e0654ec1f70d1b', + transactionHash: '0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce', + txExecErrorMsg: null } ``` @@ -826,14 +831,14 @@ password | `string` | false | | Password for remote node. ``` > packedTx = await conflux.sendTransaction({from:account, to:address, value:0}).get(); // await till transaction packed { - "nonce": "8", - "value": "0", - "gasPrice": "1000000000", - "gas": "21000", + "nonce": 8n, + "value": 0n, + "gasPrice": 1000000000n, + "gas": 21000n, "v": 0, "transactionIndex": null, "status": null, - "storageLimit": "0", + "storageLimit": 0n, "chainId": 1, "epochHeight": 791394, "blockHash": null, @@ -850,14 +855,14 @@ password | `string` | false | | Password for remote node. ``` > minedTx = await conflux.sendTransaction({from:account, to:address, value:0}).mined(); // await till transaction mined { - "nonce": "8", - "value": "0", - "gasPrice": "1000000000", - "gas": "21000", + "nonce": 8n, + "value": 0n, + "gasPrice": 1000000000n, + "gas": 21000n, "v": 0, "transactionIndex": 0, "status": 0, - "storageLimit": "0", + "storageLimit": 0n, "chainId": 1, "epochHeight": 791394, "blockHash": "0xdb2d2d438dcdee8d61c6f495bd363b1afb68cb0fdff16582c08450a9ca487852", @@ -877,8 +882,8 @@ password | `string` | false | | Password for remote node. "index": 0, "epochNumber": 791402, "outcomeStatus": 0, - "gasUsed": "21000", - "gasFee": "21000000000000", + "gasUsed": 21000n, + "gasFee": 21000000000000n, "blockHash": "0xdb2d2d438dcdee8d61c6f495bd363b1afb68cb0fdff16582c08450a9ca487852", "contractCreated": null, "from": "0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b", @@ -896,8 +901,8 @@ password | `string` | false | | Password for remote node. "index": 0, "epochNumber": 791402, "outcomeStatus": 0, - "gasUsed": "21000", - "gasFee": "21000000000000", + "gasUsed": 21000n, + "gasFee": 21000000000000n, "blockHash": "0xdb2d2d438dcdee8d61c6f495bd363b1afb68cb0fdff16582c08450a9ca487852", "contractCreated": null, "from": "0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b", @@ -1006,13 +1011,13 @@ epochNumber | `string,number` | false | 'latest_state' | See [format.sendTx]( * **Examples** ``` -> await conflux.getSponsorInfo('0x866aca87ff33a0ae05d2164b3d999a804f583222') +> await conflux.getSponsorInfo('0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98') { - "sponsorBalanceForCollateral": "0", - "sponsorBalanceForGas": "0", - "sponsorGasBound": "0", - "sponsorForCollateral": "0x0000000000000000000000000000000000000000", - "sponsorForGas": "0x0000000000000000000000000000000000000000" + sponsorBalanceForCollateral: 410625000000000000000n, + sponsorBalanceForGas: 9999999993626232440n, + sponsorGasBound: 10000000000n, + sponsorForCollateral: '0x8d5adbcaf5714924830591586f05302bf87f74bd', + sponsorForGas: '0x8d5adbcaf5714924830591586f05302bf87f74bd' } ``` @@ -1034,8 +1039,8 @@ epochNumber | | false | 'latest_state' | See [format.sendTx](#util/f * **Examples** ``` -> await conflux.getCollateralForStorage('0xc94770007dda54cf92009bff0de90c06f603a09f') - "158972490234375000" +> await conflux.getCollateralForStorage('0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98') + 89375000000000000000n ``` ### Conflux.prototype.call @@ -1104,29 +1109,29 @@ options.limit | `number` | false | | ``` > await conflux.getLogs({ - address: '0x866aca87ff33a0ae05d2164b3d999a804f583222', - fromEpoch: 0, - toEpoch: 'latest_mined', + address: '0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98', + fromEpoch: 39802, + toEpoch: 39802, limit: 1, - topics: ['0x93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db153'] + topics: ['0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d'], }); [ - { - "address": "0x866aca87ff33a0ae05d2164b3d999a804f583222", - "blockHash": "0x0ecbc75aca22cd1566a18c6a7a55f235ae12684c2749b40ac91262d6e8783b0b", - "data": "0x", - "epochNumber": 1504, - "logIndex": 2, - "topics": [ - "0x93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db153", - "0x000000000000000000000000873c4bd4d847bcf7dc066bf4a7cd31dcf182258c", - "0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b", - "0x000000000000000000000000873c4bd4d847bcf7dc066bf4a7cd31dcf182258c" - ], - "transactionHash": "0x2a696f7be50c364333bc145f082e79da3a6e730318b7f7822e3e1fe22e42560b", - "transactionIndex": 0, - "transactionLogIndex": 2 - } + { + epochNumber: 39802, + logIndex: 2, + transactionIndex: 0, + transactionLogIndex: 2, + address: '0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98', + blockHash: '0xca00158a2a508170278d5bdc5ca258b6698306dd8c30fdba32266222c79e57e6', + data: '0x', + topics: [ + '0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d', + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000001c1e72f0c37968557b3d85a3f32747792798bbde', + '0x0000000000000000000000001c1e72f0c37968557b3d85a3f32747792798bbde' + ], + transactionHash: '0xeb75f47002720311f1709e36d7f7e9a91ee4aaa469a1de892839cb1ef66a9939' + } ] ``` @@ -1214,25 +1219,23 @@ The newHeads topic streams all new block headers participating in the consensus. > subscription = await conflux.subscribeNewHeads() > subscription.on('data', data=>console.log(data)) { - difficulty: '19874410', - epochNumber: null, - gasLimit: '30000000', - height: 566239, - powQuality: '39637224', - timestamp: 1602644636, - adaptive: false, - blame: 0, - deferredLogsBloomHash: '0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5', - deferredReceiptsRoot: '0x35182c1c5f1fbb0864758585d94cefcb794619ba8ef4a7adc2e3d48e85a2d4b0', - deferredStateRoot: '0x2cf6ee27ed82e76c585ca46838746907512b86aab04f9f27cb04047939ec056f', - hash: '0x9454515ccd8493d2121e60549efd321de96a7322a95e8d537f7b2d0504a03f21', - miner: '0x10f9db11bb1509041909b35be6a3546fe65d22d0', - nonce: '0x611a95000001fe98', - parentHash: '0xf7edf9f6c11ebd4e9c1aa0a2c03203932c0ad79c3fd92cb7540bcf351aa90376', - refereeHashes: [ - '0x4d69e1b945ec2c819bc20bcb0e128e4b161ed28355d42b6d05a6f7cac9ab91f9' - ], - transactionsRoot: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' + difficulty: 368178587115n, + epochNumber: null, + gasLimit: 30000000n, + height: 1118247, + timestamp: 1605005752, + adaptive: false, + blame: 0, + deferredLogsBloomHash: '0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5', + deferredReceiptsRoot: '0x7ae0d5716513206755b6f7c95272b79dbc225759b6e17727e19c2f15c3166bda', + deferredStateRoot: '0x3cf5deba77c8aa9072f1e972d6a97db487a0ce88455f371eb8ac8fa77321cb9d', + hash: '0x194675173abbc5aab50326136008774eea1a289e6722c973dfed12b703ee5f2a', + miner: '0x189121b8f0cdfef0b56eb22d9cb76c97b9c7cfbc', + nonce: '0x799d35f695950fd6', + parentHash: '0x4af3cf8cb358e75acad282ffa4b578b6211ea9eeb7cf87c282f120d8a1c809df', + powQuality: '0xe7ac17feab', + refereeHashes: [], + transactionsRoot: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' } ``` @@ -1390,56 +1393,99 @@ conflux | `Conflux` | true | | Conflux instance. * **Examples** ``` -> const contract = conflux.Contract({ abi, bytecode }); +> const contract = conflux.Contract({ abi, bytecode, address }); { + abi: ContractABI { contract: [Circular *1] }, + address: '0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98', constructor: [Function: bound call], - abi: ContractABI { * }, - address: undefined, - count: [Function: bound call], - inc: [Function: bound call], - 'count()': [Function: bound call], - '0x06661abd': [Function: bound call], - 'inc(uint256)': [Function: bound call], - '0x812600df': [Function: bound call], + name: [Function: bound call], + 'name()': [Function: bound call], + '0x06fdde03': [Function: bound call], + balanceOf: [Function: bound call], + 'balanceOf(address)': [Function: bound call], + '0x70a08231': [Function: bound call], + send: [Function: bound call], + 'send(address,uint256,bytes)': [Function: bound call], + '0x9bd9bbc6': [Function: bound call], + Transfer: [Function: bound call], + 'Transfer(address,address,uint256)': [Function: bound call], + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef': [Function: bound call] } > contract.constructor.bytecode; // input code - "0x6080604052600080..." + "0x6080..." ``` ``` -> const contract = conflux.Contract({ abi, address }); +> const contract = conflux.Contract({ + address: '0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98', + abi: [ + { + type: 'function', + name: 'name', + inputs: [], + outputs: [{ type: 'string' }], + }, + { + type: 'function', + name: 'balanceOf', + inputs: [{ type: 'address' }], + outputs: [{ type: 'uint256' }], + }, + { + name: 'send', + type: 'function', + inputs: [ + { type: 'address', name: 'recipient' }, + { type: 'uint256', name: 'amount' }, + { type: 'bytes', name: 'data' }, + ], + outputs: [{ type: 'bool' }], + }, + ] + }); > contract.address - "0xc3ed1a06471be1d3bcd014051fbe078387ec0ad8" -> await contract.count(); // call a method without parameter, get decoded return value. - "100" -> await contract.inc(1); // call a method with parameters, get decoded return value. - "101" -> await contract.count().options({ from: account }); // call a method from a account. - "100" -> transaction = await conflux.getTransactionByHash('0x8a5f48c2de0f1bdacfe90443810ad650e4b327a0d19ce49a53faffb224883e42'); -> await contract.abi.decodeData(transaction.data) + "0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98" +> await contract.name(); // call a method without parameter, get decoded return value. + "FansCoin" +> await contract.name().call({ to: '0x8b8689c7f3014a4d86e4d1d0daaf74a47f5e0f27' }); // call a method with options + "conflux USDT" +> await contract.balanceOf('0x19c742cec42b9e4eff3b84cdedcde2f58a36f44f'); // call a method with parameters, get decoded return value. + 10000000000000000000n +> transaction = await conflux.getTransactionByHash('0x2055f3287f1a6ce77d91f5dfdf7517a531b3a560fee1265f27dc1ff92314530b'); +> contract.abi.decodeData(transaction.data) { - name: 'inc', - fullName: 'inc(uint256 num)', - type: 'inc(uint256)', - signature: '0x7f98a45e', - array: [ JSBI.BigInt(101) ], - object: { num: JSBI.BigInt(101) } - } -> await contract.count(); // data in block chain changed by transaction. - JSBI.BigInt(101) -> receipt = await conflux.getTransactionReceipt('0x8a5f48c2de0f1bdacfe90443810ad650e4b327a0d19ce49a53faffb224883e42'); -> contract.abi.decodeLog(receipt.logs[0]); + name: 'send', + fullName: 'send(address recipient, uint256 amount, bytes data)', + type: 'send(address,uint256,bytes)', + signature: '0x9bd9bbc6', + array: [ + '0x80bb30efc5683758128b404fe5da03432eb16634', + 60000000000000000000n, + + ], + object: { + recipient: '0x80bb30efc5683758128b404fe5da03432eb16634', + amount: 60000000000000000000n, + data: + } + } +> receipt = await conflux.getTransactionReceipt('0x2055f3287f1a6ce77d91f5dfdf7517a531b3a560fee1265f27dc1ff92314530b'); +> contract.abi.decodeLog(receipt.logs[1]); { - name: 'SelfEvent', - fullName: 'SelfEvent(address indexed sender, uint256 current)', - type: 'SelfEvent(address,uint256))', - signature: '0xc4c01f6de493c58245fb681341f3a76bba9551ce81b11cbbb5d6d297844594df', - array: [ '0xbbd9e9be525ab967e633bcdaeac8bd5723ed4d6b', JSBI.BigInt(100) ], + name: 'Transfer', + fullName: 'Transfer(address indexed from, address indexed to, uint256 value)', + type: 'Transfer(address,address,uint256)', + signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + array: [ + '0x1f3c6b9696604cdc3ce1ca277d4c69a9c2770c9f', + '0x80bb30efc5683758128b404fe5da03432eb16634', + 60000000000000000000n + ], object: { - sender: '0xbbd9e9be525ab967e633bcdaeac8bd5723ed4d6b', - current: JSBI.BigInt(100), - }, + from: '0x1f3c6b9696604cdc3ce1ca277d4c69a9c2770c9f', + to: '0x80bb30efc5683758128b404fe5da03432eb16634', + value: 60000000000000000000n + } } ``` @@ -1928,9 +1974,9 @@ arg | `any` | true | | * **Parameters** -Name | Type | Required | Default | Description ------|------------------------------|----------|---------|------------ -arg | `number,JSBI,string,boolean` | true | | +Name | Type | Required | Default | Description +-----|--------------------------------|----------|---------|------------ +arg | `number,BigInt,string,boolean` | true | | * **Returns** @@ -1940,14 +1986,14 @@ arg | `number,JSBI,string,boolean` | true | | ``` > format.uInt(-3.14) - Error("cannot be converted to a JSBI") + Error("not match uint") > format.uInt(null) - Error("Cannot convert null to a JSBI") + Error("not match number") > format.uInt('0') 0 > format.uInt(1) 1 -> format.uInt(JSBI(100)) +> format.uInt(BigInt(100)) 100 > format.uInt('0x10') 16 @@ -1965,50 +2011,50 @@ arg | `number,JSBI,string,boolean` | true | | * **Parameters** -Name | Type | Required | Default | Description ------|----------------------|----------|---------|------------ -arg | `number,string,JSBI` | true | | +Name | Type | Required | Default | Description +-----|------------------------|----------|---------|------------ +arg | `number,string,BigInt` | true | | * **Returns** -`JSBI` +`BigInt` * **Examples** ``` > format.bigInt(-3.14) - Error("not match bigInt") + Error("Cannot convert -3.14 to a BigInt") > format.bigInt('0.0') - JSBI.BigInt(0) + 0n > format.bigInt('-1') - JSBI.BigInt(-1) + -1n > format.bigInt(1) - JSBI.BigInt(1) -> format.bigInt(JSBI.BigInt(100)) - JSBI.BigInt(100) + 1n +> format.bigInt(BigInt(100)) + 100n > format.bigInt('0x10') - JSBI.BigInt(16) + 16n > format.bigInt(Number.MAX_SAFE_INTEGER + 1) // unsafe integer - Error("not match uint") + 9007199254740992n ``` #### format.bigUInt * **Parameters** -Name | Type | Required | Default | Description ------|----------------------|----------|---------|------------ -arg | `number,string,JSBI` | true | | +Name | Type | Required | Default | Description +-----|------------------------|----------|---------|------------ +arg | `number,string,BigInt` | true | | * **Returns** -`JSBI` +`BigInt` * **Examples** ``` > format.bigUInt('0.0') - JSBI.BigInt(0) + 0n > format.bigUInt('-1') Error("not match bigUInt") ``` @@ -2019,9 +2065,9 @@ When encoding QUANTITIES (integers, numbers): encode as hex, prefix with "0x", t * **Parameters** -Name | Type | Required | Default | Description ------|----------------------|----------|---------|------------ -arg | `number,string,JSBI` | true | | +Name | Type | Required | Default | Description +-----|------------------------|----------|---------|------------ +arg | `number,string,BigInt` | true | | * **Returns** @@ -2042,9 +2088,9 @@ arg | `number,string,JSBI` | true | | * **Parameters** -Name | Type | Required | Default | Description ------|----------------------|----------|---------|------------ -arg | `number,string,JSBI` | true | | +Name | Type | Required | Default | Description +-----|------------------------|----------|---------|------------ +arg | `number,string,BigInt` | true | | * **Returns** @@ -2073,9 +2119,9 @@ arg | `number,string,JSBI` | true | | * **Parameters** -Name | Type | Required | Default | Description ------|--------------------------|----------|---------|------------ -arg | `string,number,JSBI,Big` | true | | +Name | Type | Required | Default | Description +-----|----------------------------|----------|---------|------------ +arg | `string,number,BigInt,Big` | true | | * **Returns** @@ -2119,9 +2165,9 @@ When encoding UNFORMATTED DATA (byte arrays, account addresses, hashes, bytecode * **Parameters** -Name | Type | Required | Default | Description ------|------------------------------------------|----------|---------|------------ -arg | `number,JSBI,string,Buffer,boolean,null` | true | | +Name | Type | Required | Default | Description +-----|--------------------------------------------|----------|---------|------------ +arg | `number,BigInt,string,Buffer,boolean,null` | true | | * **Returns** @@ -2281,9 +2327,9 @@ arg | `string,Buffer` | true | | * **Parameters** -Name | Type | Required | Default | Description ------|------------------------------------------|----------|---------|------------ -arg | `number,string,JSBI,Buffer,boolean,null` | true | | +Name | Type | Required | Default | Description +-----|--------------------------------------------|----------|---------|------------ +arg | `number,string,BigInt,Buffer,boolean,null` | true | | * **Returns** diff --git a/docs/getting_start.md b/docs/getting_start.md index d94b1454..8468e3e6 100644 --- a/docs/getting_start.md +++ b/docs/getting_start.md @@ -7,54 +7,43 @@ Here is a quick start of how to use `js-conflux-sdk` to interact with conflux ne Install the SDK with npm. -```sh -$ npm install js-conflux-sdk +``` +npm install js-conflux-sdk ``` -## Initialize the Conflux object and get balance +## Initialize the Conflux instance and call method To interact with conflux network, we need a RPC endpoint for example: `https://test.confluxrpc.org` which is a conflux testnet RPC endpoint, we can use it directly. ```js // import Conflux Class -const { Conflux } = require('js-conflux-sdk'); +const { Conflux, Drip } = require('js-conflux-sdk'); async function main() { // initialize a Conflux object - const address = '0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b'; - const cfx = new Conflux({ - url: 'https://test.confluxrpc.org', - // for debug: this will log all the RPC request and response to console - logger: console, + const conflux = new Conflux({ + url: 'https://main.confluxrpc.org', // main net endpoint + // url: 'https://test.confluxrpc.org', // test net endpoint + + // timeout: 300 * 1000, // request timeout in ms, default 300*1000 ms === 5 minute + // logger: console, // for debug: this will log all the RPC request and response to console }); - // then we can use cfx to get balance of a conflux account - const balance = await cfx.getBalance(address); - console.log(balance.toString()); + + // then we can use conflux to get balance (in Drip) of a conflux account + const balance = await conflux.getBalance('0x1f323dccb24606b061db9e3a1277b8db99f1c1b2'); + console.log(balance); // 3308889829789826719958034n + console.log(Drip(balance).toCFX()); // 3308889.829789826719958034 } main(); ``` -The cfx object have a lot methods that correspond to Conflux RPC methods, `getBalance` will be the most common used one. The cfx methods will return a promise, you can use `async/await` syntax with it. - -Besides `url` and `logger` Conflux have several other options you can check the [API]() - -## Send a transaction -To send some CFX to another account, your account should have some balance of CFX. And you also need the privateKey of your account. - -```js -// create account instance and add to wallet -const account = conflux.wallet.addPrivateKey(PRIVATE_KEY); -const hash = await conflux.sendTransaction({ - from: account.address, // sender address which added into conflux.wallet - to: ADDRESS, // receiver address - value: Drip.fromCFX(0.1), // 0.1 CFX = 100000000000000000 Drip -}); -``` -That's it, it's very simple. +The conflux instance have a lot methods that correspond to Conflux RPC methods, such as `getBalance` map to RPC `cfx_getBalance`. Call these methods will return a promise or thenable. +Conflux have other methods and options, you can check with [API](../api.md) ## Docs -1. [Official documentation](https://developer.conflux-chain.org/) -2. [RPC methods](https://developer.conflux-chain.org/docs/conflux-doc/docs/json_rpc) -3. [Subscribtion](https://developer.conflux-chain.org/docs/conflux-doc/docs/pubsub) \ No newline at end of file +1. [Official developer documentation](https://developer.conflux-chain.org/) +2. [RPC](https://developer.conflux-chain.org/docs/conflux-doc/docs/json_rpc) +3. [Subscribtion](https://developer.conflux-chain.org/docs/conflux-doc/docs/pubsub) +4. [Conflux Portal](https://portal.conflux-chain.org/) diff --git a/docs/how_to_send_tx.md b/docs/how_to_send_tx.md index 0c024384..3a861f40 100644 --- a/docs/how_to_send_tx.md +++ b/docs/how_to_send_tx.md @@ -1,69 +1,74 @@ # How to send a Conflux Transaction -### A simple CFX transfer +## Send transaction simple It can be very easy to send a simple transaction(transfer some CFX to another address), all you need is `from`, `to`, `value` and `from`'s privateKey. -```javascript -const { Drip } = require('js-conflux-sdk'); +```js +const { Conflux, Drip } = require('js-conflux-sdk'); + +const PRIVATE_KEY = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; // sender private key +const ADDRESS = '0x0123456789012345678901234567890123456789'; async function main() { - // Note: first you need initialize a Conflux object - // create account instance and add to wallet - const PRIVATE_KEY = ""; - const ADDRESS = ""; - const account = cfx.wallet.addPrivateKey(PRIVATE_KEY); + const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); - // This will send a CFX transfer transaction to a RPC endpoint, it will return the tx hash - const txHash = await cfx.sendTransaction({ - from: account.address, // sender address which added into conflux.wallet + const sender = conflux.wallet.addPrivateKey(PRIVATE_KEY); // add private to local wallet + const transactionHash = await conflux.sendTransaction({ + from: sender.address, // account address or instance which added into conflux.wallet to: ADDRESS, // receiver address value: Drip.fromCFX(0.1), // 0.1 CFX = 100000000000000000 Drip - }); - console.log(txHash); + }); + + console.log(transactionHash); // suggest store transactionHash in disk !!! + // 0x22e5ffefe4da995ebcb2847762b7acb1c03fd17c9ab010272965fa63c9590d6e + + // you might need wait seconds here... + await new Promise(resolve => setTimeout(resolve, 60 * 1000)); - // You can get the tx info - const tx = await cfx.getTransactionByHash(txHash); + const transaction = await conflux.getTransactionByHash(txHash); + console.log(transaction); // get transaction from remote /* - { - "nonce": "0", - "value": "1000000000000000000000000000000000", - "gasPrice": "3", - "gas": "16777216", - "v": 1, - "transactionIndex": 0, - "status": 0, - "storageLimit": "65536", - "chainId": 1, - "epochHeight": 454, - "blockHash": "0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7", - "contractCreated": null, - "data": "0x", - "from": "0x1be45681ac6c53d5a40475f7526bac1fe7590fb8", - "hash": "0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8", - "r": "0x85f6729aa1e709202318bd6746c4a232a379eaa4cd9c2ea24c7babdbd09085cd", - "s": "0x7101e1e2ee4ddfcef8879358df0cb0792f34712116f100b76c8e9582625acd2f", - "to": "0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c" - } + { + nonce: 13584n, + gasPrice: 1n, + gas: 75000n, + value: 100000000000000000n, + storageLimit: 2048n, + epochHeight: 1344622, + chainId: 1, + v: 1, + status: 0, + transactionIndex: 3, + blockHash: '0x4ee16b530f6b6951122c1305b262eef5251ebff03498bc510610ed45fb72a014', + contractCreated: null, + data: '0x', + from: '0x1cad0b19bb29d4674531d6f115237e16afce377c', + hash: '0x22e5ffefe4da995ebcb2847762b7acb1c03fd17c9ab010272965fa63c9590d6e', + r: '0x162f2b49022528ba65fa35be2b93b8554d1910f7993201f1e755e5a29c7f8a53', + s: '0x2106ce156aea46ffe8438b8a4057e116b4d1c8551158ae2cf1e4679924e433d8', + to: '0x0123456789012345678901234567890123456789' + } */ - // the receipt will not generate immediately, so wait a while maybe 5s - const receipt = await cfx.getTransactionReceipt(txHash); + const receipt = await conflux.getTransactionReceipt(txHash); + console.log(receipt); // get receipt from remote /* { - "index": 0, - "epochNumber": 455, - "outcomeStatus": 0, - "gasUsed": "21000", - "gasFee": "37748736", - "blockHash": "0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7", - "contractCreated": null, - "from": "0x1be45681ac6c53d5a40475f7526bac1fe7590fb8", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "stateRoot": "0x19d109e6fe9f5a75cc54543af4beab08c0f23fdf95eea33b1afe5a9ef8b770dc", - "to": "0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c", - "transactionHash": "0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8" - } + index: 3, + epochNumber: 1344628, + outcomeStatus: 0, + gasUsed: 54349n, + gasFee: 56250n, + blockHash: '0x4ee16b530f6b6951122c1305b262eef5251ebff03498bc510610ed45fb72a014', + contractCreated: null, + from: '0x1cad0b19bb29d4674531d6f115237e16afce377c', + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + stateRoot: '0xf8d93f9f783605572fb48beb81e7450b25eae2eeb28310429c862a5c1956bd71', + to: '0x0123456789012345678901234567890123456789', + transactionHash: '0x22e5ffefe4da995ebcb2847762b7acb1c03fd17c9ab010272965fa63c9590d6e', + txExecErrorMsg: null + } */ } @@ -72,7 +77,6 @@ main(); If you can get the transaction receipt and it's `outcomeStatus` is `0`, congratulate you have send a transaction successfully. - ### Transaction's stage After sending, a transaction could be in several different states, [here](https://developer.conflux-chain.org/docs/conflux-doc/docs/send_transaction#track-my-transaction) is a detail explanation of transaction life cycle. @@ -90,22 +94,49 @@ Only after a transaction executed, you can get it's receipt. The `receipt.outcom Correspond to transaction stages, the SDK has provide several advanced `sendTransaction` usage: ```js -let txParameters = { - from: account, - to: "0x-a-address", - value: "0x100" -}; -const txHash = await cfx.sendTransaction(txParameters); // send the tx and return a hash -const tx = await cfx.sendTransaction(txParameters).get(); // send the tx and return the tx -const tx = await cfx.sendTransaction(txParameters).mined(); // wait tx mined and return the tx -const receipt = await cfx.sendTransaction(txParameters).executed(); // wait tx executed and return receipt -const receipt = await cfx.sendTransaction(txParameters).confirmed(); // wait tx confirmed and return receipt +const { Conflux, Drip } = require('js-conflux-sdk'); + +const PRIVATE_KEY = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; // sender private key +const ADDRESS = '0x0123456789012345678901234567890123456789'; + +async function main() { + const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); + + const sender = conflux.wallet.addPrivateKey(PRIVATE_KEY); + + const pendingTransaction = conflux.sendTransaction({ + from: sender.address, // account address or instance which added into conflux.wallet + to: ADDRESS, // receiver address + value: Drip.fromCFX(0.1), // 0.1 CFX = 100000000000000000 Drip + }); // NOTE: without await, transaction not send yet + + const transactionHash = await pendingTransaction; // send and await endpoint return transaction hash + console.log(transactionHash); + + // usually wait about 2 seconds + const packedTransaction = await pendingTransaction.get(); // await endpoint packed transaction + console.log(packedTransaction); // `blockHash` might still be `null` + + // usually wait about 5 seconds + const minedTransaction = await pendingTransaction.mined(); // await transaction mined + console.log(minedTransaction); // already have `blockHash` + + // usually wait about 10 seconds + const executedReceipt = await pendingTransaction.executed(); // await transaction executed + console.log(executedReceipt); // if `outcomeStatus` equal 0, return receipt, else throw error + + // usually wait about 50 seconds + const confirmedReceipt = await pendingTransaction.confirmed(); // await transaction confirmed + console.log(confirmedReceipt); // usually same as executedReceipt, but transaction block risk is <= 1e-8 +} + +main(); ``` -Note: the `mined`, `executed`, `confirmed` methods maybe will take a long time, and will be timeout, these methods are not recommended in production. +Note: the `mined`, `executed`, `confirmed` methods maybe will take a long time, and will be timeout. -### A complete transaction +## Send transaction complete Besides `from`, `to`, `value` there are several other fields could be filled with: @@ -124,64 +155,96 @@ Compare with ethereum Conflux transaction have three new field: `storageLimit`, ```js -const txHash = await cfx.sendTransaction({ +const { Conflux, Drip } = require('js-conflux-sdk'); + +const PRIVATE_KEY = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; // sender private key +const ADDRESS = '0x0123456789012345678901234567890123456789'; + +async function main() { + const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); + const account = conflux.wallet.addPrivateKey(PRIVATE_KEY); // create account instance and add to wallet + + const estimate = await conflux.estimateGasAndCollateral({ to, value }); + const status = await conflux.getStatus(); + + const transactionHash = await conflux.sendTransaction({ from: account.address, // sender address which added into conflux.wallet to: ADDRESS, // receiver address value: Drip.fromCFX(0.1), // 0.1 CFX = 100000000000000000 Drip - nonce: 100, - gas: 21000, - gasPrice: new Drip(1), - storageLimit: 0, - epochHeight: await cfx.getEpochNumber(), data: null, - chainId: 1, -}); -console.log(txHash); + gas: estimate.gasUsed, + storageLimit: 0, + chainId: status.chainId, + nonce: await conflux.getNextNonce(account.address), + gasPrice: await conflux.getGasPrice(), + epochHeight: await conflux.getEpochNumber(), + }); + + console.log(transactionHash); +} + +main(); ``` -### How much `gas` and `storageLimit` a transaction need +## How much `gas` and `storageLimit` a transaction need If you are just transfer CFX, the gas should be `21000`, if you are interact with a contract it's a little complicated. Normally you can estimate it by call `estimateGasAndCollateral`. -##### `gasPrice` -When sending transaction if you specify the `gasPrice` it will be used, if not it will try to use `cfx.defaultGasPrice` you can specify it when you initiallize the cfx object. - ```js -const cfx = new Conflux({ +const conflux = new Conflux({ url: 'http://test.confluxrpc.org', logger: console, // for debug - defaultGasPrice: 1 + defaultGasPrice: 1, + defaultGasRatio: 1.1, + defaultStorageRatio: 1.1 }); ``` + +### `gasPrice` +When sending transaction if you specify the `gasPrice` it will be used, if not it will try to use `cfx.defaultGasPrice` you can specify it when you initiallize the cfx object. + If both `gasPrice` and `defaultGasPrice` is not specified, the SDK will fill the result of `getGasPrice()` to it. Currentlly set the gasPrice to `1 Drip` will enough to send most transactions. -##### `gas` +### `gas` First you can specify the tx.`gas`, if you don't it will use the result of `estimateGasAndCollateral.gasUsed`, and this value will be multiply a ratio `defaultGasRatio` (default 1.1), because the estimate result sometimes are not accurate, normally estimated `gasUsed` will not enough. -```js -const cfx = new Conflux({ - url: 'http://test.confluxrpc.org', - logger: console, // for debug - defaultGasRatio: 1.1 -}); -``` - -##### `storageLimit` +### `storageLimit` Same as `gas` you can specify `storageLimit` when you send transaction (unit is Byte), if not +## SendRawTransaction +The `sendTransaction` will use get `from`'s privateKey from wallet, use it sign transaction and invoke `sendRawTransaction` method, if you have a raw transaction you can use it directly. the `sendRawTransaction` method also can use `get`, `mined`, `executed`, `confirmed` method. + ```js -const cfx = new Conflux({ - url: 'http://test.confluxrpc.org', - logger: console, // for debug - defaultStorageRatio: 1.1 -}); -``` +const { Conflux, Transaction } = require('js-conflux-sdk'); -### SendRawTransaction -The `sendTransaction` will use get `from`'s privateKey from wallet, use it sign transaction and invoke `sendRawTransaction` method, if you have a raw transaction you can use it directly. the `sendRawTransaction` method also can use `get`, `mined`, `executed`, `confirmed` method. +const PRIVATE_KEY = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; // sender private key +const ADDRESS = '0x0123456789012345678901234567890123456789'; + +async function main() { + const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); + + const transaction = new Transaction({ + to: ADDRESS, // receiver address + nonce: 1, // sender next nonce + value: 1, + gas: 21000, + gasPrice: 1, + storageLimit: 0, + epochHeight: 100, + chainId: 1, // endpoint status.chainId + data: '0x' + }); + transaction.sign(PRIVATE_KEY); // sender privateKey + + const transactionHash = await conflux.sendRawTransaction(transaction.serialize()); + console.log(transactionHash) +} + +main(); +``` ### Why my transaction is always pending ? If your transaction alway pending in the pool, normally you have use a incorrect `nonce` or your `balance` is not enough. You can get the transaction info by it's hash, and check it's nonce with your account's nonce, and check your balance is enough to cover the value + gasPrice * gas + storageLimit. @@ -197,35 +260,21 @@ If your transaction is failed, you can find reason in below ways: If you want send a transaction with a note, you can specify it through `data`, the tricky is you need convert your message to a hex string. ```js -const hex = require('string-hex'); -let hexString = '0x' + hex("This is the transaction note"); - -let result = await cfx.sendTransaction({ - from: address, - to: '0x1292d4955bb47F5153B88Ca12C7A9E4048f09839', - value: Drip.fromGDrip(0.001), - data: hexString -}); -``` +const { Conflux, format } = require('js-conflux-sdk'); -### How to build a raw transaction -Build a `Transaction`, sign it with privateKey, then you can get a raw transaction. +const PRIVATE_KEY = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; // sender private key -```js -import {Transaction} from 'js-conflux-sdk'; -let tx = new Transaction({ - from: '0x1be45681ac6c53d5a40475f7526bac1fe7590fb8', - nonce: 1, - to: '0x1be45681ac6c53d5a40475f7526bac1fe7590fb8', - value: 1, - gas: 21000, - gasPrice: 1, - storageLimit: 0, - epochHeight: 100, - chainId: 1, - data: "0x" -}); -const privateKey = "...."; -tx.sign(privateKey); -let rawTx = tx.serialize(); +async function main() { + const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); + const account = conflux.wallet.addPrivateKey(PRIVATE_KEY); // create account instance and add to wallet + + const transactionHash = await conflux.sendTransaction({ + from: account.address, + to: account.address, // if data is not contract bytecode, must have `to` address + data: format.bytes('Hello World') + }); + console.log(transactionHash); +} + +main() ``` diff --git a/docs/interact_with_contract.md b/docs/interact_with_contract.md index 328c4205..c1dedafd 100644 --- a/docs/interact_with_contract.md +++ b/docs/interact_with_contract.md @@ -9,6 +9,8 @@ Then compile it with solidity compiler, you will get `bytecode` and `abi`. With const { Conflux } = require('js-conflux-sdk'); const { abi, bytecode } = MINI_ERC20; // see https://github.com/Conflux-Chain/js-conflux-sdk/tree/master/example/contract/miniERC20.json +const PRIVATE_KEY = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; // sender private key + async function main() { const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); const account = conflux.wallet.addPrivateKey(PRIVATE_KEY); @@ -29,8 +31,8 @@ async function main() { "index": 0, "epochNumber": 318456, "outcomeStatus": 0, - "gasUsed": "1054531", - "gasFee": "1054531000000000", + "gasUsed": 1054531n, + "gasFee": 1054531000000000n, "blockHash": "0x4a8b07e2694e358af075f7a9e96e78842b77ac2d511e2ab33f6acfff34a5846c", "contractCreated": "0x8a9c270e1a99c05ca90ef0f0008b8f6444cf1a97", "from": "0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b", @@ -70,12 +72,11 @@ async function main() { // 4. call method with arguments const balance = await contract.balanceOf(account.address); - console.log(balance.toString()); // "10000" JSBI + console.log(balance); // 10000n // 4. change contract state by send a transaction - const txHash = await contract.transfer(ADDRESS, 10).sendTransaction({ from: account }); - console.log(txHash); // 0xb31eb095b62bed1ef6fee6b7b4ee43d4127e4b42411e95f761b1fdab89780f1a - + const transactionHash = await contract.transfer(ADDRESS, 10).sendTransaction({ from: account }); + console.log(transactionHash); // 0xb31eb095b62bed1ef6fee6b7b4ee43d4127e4b42411e95f761b1fdab89780f1a } main(); @@ -84,11 +85,15 @@ main(); ### How to play with InternalContract Conflux network has provide three Internal Contract `AdminControl`, `SponsorWhitelistControl`, `Staking`, these internal contract are very helpful to contract developer, for detail documentation check [official doc](https://developer.conflux-chain.org/docs/conflux-rust/internal_contract/internal_contract). This SDK have fully support for Internal Contract, you can use them like this. -```js +```javascript +const { Conflux } = require('js-conflux-sdk'); + async function main() { + const conflux = new Conflux({ url: 'http://test.confluxrpc.org' }); + // 1. get internal contract through InternalContract method and pass the internal contract name - const sponsor = cfx.InternalContract('SponsorWhitelistControl') + const sponsor = conflux.InternalContract('SponsorWhitelistControl'); const gasSponsor = await sponsor.getSponsorForGas('0x8dc687aef9ee127335434e1a0b6a16a5941d3b67'); } main(); -``` \ No newline at end of file +``` diff --git a/package.json b/package.json index 00039dc3..dea67746 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "types": "./types/index.d.ts", "browser": "dist/js-conflux-sdk.umd.min.js", "browserify-browser": { - "secp256k1": "secp256k1/elliptic" + "secp256k1": "secp256k1/elliptic", + "./src/util/jsbi": "jsbi" }, "files": [ "dist", @@ -25,7 +26,6 @@ "dependencies": { "@babel/runtime": "^7.8.4", "big.js": "^5.2.2", - "jsbi": "^3.1.1", "keccak": "^2.0.0", "lodash": "^4.17.19", "scrypt-js": "^3.0.1", @@ -49,6 +49,7 @@ "exorcist": "^1.0.1", "fs-extra": "^8.1.0", "jest": "26.6.0", + "jsbi": "^3.1.4", "minify-stream": "^2.0.1", "mold-source-map": "^0.4.0", "solc": "^0.6.10" @@ -69,6 +70,7 @@ "build": "node scripts/build-frontend.js", "document": "node scripts/document.js", "prepublishOnly": "npm run build", - "test": "jest --coverage" + "test": "jest --coverage", + "react": "npm run build & cd react & yarn build & yarn start" } } diff --git a/src/CONST.js b/src/CONST.js index fcd1b43c..9a8a0425 100644 --- a/src/CONST.js +++ b/src/CONST.js @@ -1,4 +1,4 @@ -const JSBI = require('jsbi'); +const JSBI = require('./util/jsbi'); JSBI.prototype.toJSON = function () { // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/BigInt diff --git a/src/Conflux.js b/src/Conflux.js index ed2b391f..9bd9a161 100644 --- a/src/Conflux.js +++ b/src/Conflux.js @@ -175,11 +175,11 @@ class Conflux { * @example * > await conflux.getStatus() { - "chainId": 2, - "epochNumber": 324105, - "blockNumber": 426341, - "pendingTxNumber": 40, - "bestHash": "0xef08f2702335f149afc021607511ffae49df8bb56b2afb7f42de02d9cbbf7ef6" + chainId: 1029, + epochNumber: 1117476, + blockNumber: 2230973, + pendingTxNumber: 4531, + bestHash: '0x8d581f13fa0548f2751450a7dabd871777875c9ccdf0d8bd629e07a7a5a7917a' } */ async getStatus() { @@ -194,7 +194,7 @@ class Conflux { * * @example * > await conflux.getGasPrice(); - '1' + 1n */ async getGasPrice() { const result = await this.provider.call('cfx_gasPrice'); @@ -209,7 +209,7 @@ class Conflux { * * @example * > await conflux.getInterestRate(); - "2522880000000" + 2522880000000n */ async getInterestRate(epochNumber) { const result = await this.provider.call('cfx_getInterestRate', @@ -226,7 +226,7 @@ class Conflux { * * @example * > await conflux.getAccumulateInterestRate() - "76269979767787603657181926319926" + 76357297457647044505744908994993n */ async getAccumulateInterestRate(epochNumber) { const result = await this.provider.call('cfx_getAccumulateInterestRate', @@ -251,15 +251,15 @@ class Conflux { * admin `string`: admin of the account. * * @example - > await conflux.getAccount('0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b'); + > await conflux.getAccount('0x1c1e72f0c37968557b3d85a3f32747792798bbde'); { - "accumulatedInterestReturn": "0", - "balance": "0", - "collateralForStorage": "0", - "nonce": "0", - "stakingBalance": "0", - "admin": "0x0000000000000000000000000000000000000000", - "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + accumulatedInterestReturn: 0n, + balance: 824812401057514588670n, + collateralForStorage: 174187500000000000000n, + nonce: 1449n, + stakingBalance: 0n, + admin: '0x0000000000000000000000000000000000000000', + codeHash: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' } */ async getAccount(address, epochNumber) { @@ -278,8 +278,8 @@ class Conflux { * @return {Promise} The balance in Drip. * * @example - * > await conflux.getBalance("0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b"); - '10098788868004995614504' + * > await conflux.getBalance("0x1c1e72f0c37968557b3d85a3f32747792798bbde"); + 824812401057514588670n */ async getBalance(address, epochNumber) { const result = await this.provider.call('cfx_getBalance', @@ -297,8 +297,8 @@ class Conflux { * @return {Promise} The staking balance in Drip. * * @example - * > await conflux.getStakingBalance('0x194770007dda54cF92009BFF0dE90c06F603a09f', 'latest_state'); - '6334100968004995614504' + * > await conflux.getStakingBalance('0x1c1e72f0c37968557b3d85a3f32747792798bbde', 'latest_state'); + 0n */ async getStakingBalance(address, epochNumber) { const result = await this.provider.call('cfx_getStakingBalance', @@ -316,8 +316,8 @@ class Conflux { * @return {Promise} The next nonce should be used by given address. * * @example - * > await conflux.getNextNonce("0x1be45681ac6c53d5a40475f7526bac1fe7590fb8"); - "3" + * > await conflux.getNextNonce("0x1c1e72f0c37968557b3d85a3f32747792798bbde"); + 1449n */ async getNextNonce(address, epochNumber) { const result = await this.provider.call('cfx_getNextNonce', @@ -335,8 +335,8 @@ class Conflux { * @return {Promise} Address to admin, or `null` if the contract does not exist. * * @example - * > conflux.getAdmin('0x8af71f222b6e05b47d8385fe437fe2f2a9ec1f1f') - "0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c" + * > conflux.getAdmin('0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98') + "0x1c1e72f0c37968557b3d85a3f32747792798bbde" */ async getAdmin(address, epochNumber) { return this.provider.call('cfx_getAdmin', @@ -411,21 +411,21 @@ class Conflux { * - txFee `BigInt`: Total gas fee of block transaction * * @example - * > await conflux.getBlockRewardInfo(4060000); + * > await conflux.getBlockRewardInfo(6); [ { - "baseReward": "11295480000000000000", - "totalReward": "11295509726193823715", - "txFee": "0", - "author": "0x13bbe31525cb9ed1461d3277c4413c854d9f8355", - "blockHash": "0x305c0a205af135ffca55a6ffb9569cbf93451ea3b7211b8f0ae39c147f3320e8" + baseReward: 6993700000000000000n, + totalReward: 6993700031741486703n, + txFee: 0n, + author: '0x1f323dccb24606b061db9e3a1277b8db99f1c1b2', + blockHash: '0x73cd891aea310e2c0b8644de91746c7353cebfffb780126bc06101b20689c893' }, { - "baseReward": "11300000000000000000", - "totalReward": "11300029738091185588", - "txFee": "2126250", - "author": "0x1a84009b2f981155b98bb7e10aa0965fbc169be7", - "blockHash": "0xfc75086a3a752d742673859d371061e8a59c85a54e90f13914b62c20364a2150" + baseReward: 6997200000000000000n, + totalReward: 6997200031760371742n, + txFee: 3000000n, + author: '0x1f323dccb24606b061db9e3a1277b8db99f1c1b2', + blockHash: '0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390' } ] */ @@ -477,29 +477,33 @@ class Conflux { * - transactionsRoot `string`: The hash of the transactions of the block. * * @example - * > await conflux.getBlockByHash('0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7'); + * > await conflux.getBlockByHash('0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390'); { - "epochNumber": 455, - "blame": 0, - "height": 455, - "size": 122, - "timestamp": 1594912954, - "gasLimit": "30000000", - "difficulty": "30000", - "transactions": [ - "0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8" + epochNumber: 6, + blame: 0, + height: 6, + size: 352, + timestamp: 1603901780, + gasLimit: 30000000n, + gasUsed: 61118n, + difficulty: 20000000000n, + transactions: [ + '0xaad69c8c814aec3e418b68f60917c607920a531e7082dd2c642323b43ecadb94', + '0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce' ], - "adaptive": false, - "deferredLogsBloomHash": "0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5", - "deferredReceiptsRoot": "0x09f8709ea9f344a810811a373b30861568f5686e649d6177fd92ea2db7477508", - "deferredStateRoot": "0x2124f4f35df1abeb01a43ed25c6b7ea5a56bbc2bdb3ab3feb096e3911e522181", - "hash": "0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7", - "miner": "0x100000000000000000000000000000000000007c", - "nonce": "0xcc2eadd8c5c369ff", - "parentHash": "0x9ced22205ac0fe96ad27be9c0add073ce49582220b8fd1006edf16a402aef9b4", - "powQuality": "0x167d3", - "refereeHashes": [], - "transactionsRoot": "0x5a31184b86d8b88a3860649c17a4b7b4d3c7ef35fea971afb1f44081feff5b60" + adaptive: false, + deferredLogsBloomHash: '0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5', + deferredReceiptsRoot: '0x09f8709ea9f344a810811a373b30861568f5686e649d6177fd92ea2db7477508', + deferredStateRoot: '0x50c0fcbc5bafa7d1dba7b19c87629830106a6be8d0adf505cdc656bb43535d69', + hash: '0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390', + miner: '0x1f323dccb24606b061db9e3a1277b8db99f1c1b2', + nonce: '0x17d86f2f6', + parentHash: '0xc8a412b4b77b48d61f694975f032d109f26bb0f9fc02e4b221d67a382fab386b', + powQuality: '0x5a0f86a6f4', + refereeHashes: [ + '0x73cd891aea310e2c0b8644de91746c7353cebfffb780126bc06101b20689c893' + ], + transactionsRoot: '0xd2f08676484ba2a3738194f44542eb29fb290b8ed74bf007f132fe51d89b2e7c' } */ async getBlockByHash(blockHash, detail = false) { @@ -536,7 +540,7 @@ class Conflux { * @return {Promise} Number >0 and <1 * * @example - * > await conflux.getConfirmationRiskByHash('0x24dcc768132dc7f651d7cb35c52e7bba632eda073d8743f81cfe905ff7e4157a') + * > await conflux.getConfirmationRiskByHash('0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390') 1e-8 */ async getConfirmationRiskByHash(blockHash) { @@ -555,7 +559,7 @@ class Conflux { * - blockHash `string`: hash of the block where this transaction was in and got executed. `null` when its pending. * - contractCreated `string|null`: address of created contract. `null` when it's not a contract creating transaction * - data `string`: the data send along with the transaction. - * - epochHeight `number`: TODO + * - epochHeight `number`: epoch height * - from `string`: address of the sender. * - gas `BigInt`: gas provided by the sender. * - gasPrice `number`: gas price provided by the sender in Drip. @@ -564,35 +568,35 @@ class Conflux { * - r `string`: ECDSA signature r * - s `string`: ECDSA signature s * - status `number`: 0 for success, 1 for error occured, `null` when the transaction is skipped or not packed. - * - storageLimit `BigInt`: TODO - * - chainId `number`: TODO + * - storageLimit `BigInt`: storage limit in bytes + * - chainId `number`: chain id * - to `string`: address of the receiver. null when its a contract creation transaction. * - transactionIndex `number`: integer of the transactions's index position in the block. `null` when its pending. * - v `string`: ECDSA recovery id * - value `BigInt`: value transferred in Drip. * * @example - * > await conflux.getTransactionByHash('0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8'); + * > await conflux.getTransactionByHash('0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce'); { - "nonce": "0", - "value": "1000000000000000000000000000000000", - "gasPrice": "3", - "gas": "16777216", - "v": 1, - "transactionIndex": 0, - "status": 0, - "storageLimit": "65536", - "chainId": 2, - "epochHeight": 454, - "blockHash": "0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7", - "contractCreated": null, - "data": "0x", - "from": "0x1be45681ac6c53d5a40475f7526bac1fe7590fb8", - "hash": "0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8", - "r": "0x85f6729aa1e709202318bd6746c4a232a379eaa4cd9c2ea24c7babdbd09085cd", - "s": "0x7101e1e2ee4ddfcef8879358df0cb0792f34712116f100b76c8e9582625acd2f", - "to": "0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c" - } + nonce: 0n, + gasPrice: 10n, + gas: 200000n, + value: 0n, + storageLimit: 1024n, + epochHeight: 0, + chainId: 1029, + v: 1, + status: 0, + transactionIndex: 1, + blockHash: '0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390', + contractCreated: null, + data: '0xfebe49090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000162788589c8e386863f217faef78840919fb2854', + from: '0x108b8b1333523a79ac363d8f41805e81b085d55d', + hash: '0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce', + r: '0x495da01ae9f445847022a8bc7df0198577ba75f88b26699f61afb435bb9c50bc', + s: '0x2291051b1c53db1d6bfe2fb29be1bf512d063e726dc6b98aaf0f2259b7456be0', + to: '0x83bf953c8b687f0d1b8d2243a3e0654ec1f70d1b' + } */ async getTransactionByHash(transactionHash) { const result = await this.provider.call('cfx_getTransactionByHash', @@ -620,21 +624,22 @@ class Conflux { * - logs `object[]`: Array of log objects, which this transaction generated. * * @example - * > await conflux.getTransactionReceipt('0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8'); + * > await conflux.getTransactionReceipt('0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce'); { - "index": 0, - "epochNumber": 455, - "outcomeStatus": 0, - "gasUsed": "21000", - "gasFee": "37748736", - "blockHash": "0x0909bdb39910d743e7e9b68f24afbbf187349447b161c4716bfd278fd7a0cbc7", - "contractCreated": null, - "from": "0x1be45681ac6c53d5a40475f7526bac1fe7590fb8", - "logs": [], - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "stateRoot": "0x19d109e6fe9f5a75cc54543af4beab08c0f23fdf95eea33b1afe5a9ef8b770dc", - "to": "0x144aa8f554d2ffbc81e0aa0f533f76f5220db09c", - "transactionHash": "0xe6b56ef6a2be1987b0353a316cb02c78493673c31adb847b947d47c3936d89a8" + index: 1, + epochNumber: 6, + outcomeStatus: 0, + gasUsed: 30559n, + gasFee: 1500000n, + blockHash: '0xaf4136d04e9e2cc470703251ec46f5913ab7955d526feed43771705e89c77390', + contractCreated: null, + from: '0x108b8b1333523a79ac363d8f41805e81b085d55d', + logs: [], + logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + stateRoot: '0xd6a7c2c14cb0d1233010acca98e114db5a10e0b94803d23b01a6777b7fd3b2fd', + to: '0x83bf953c8b687f0d1b8d2243a3e0654ec1f70d1b', + transactionHash: '0xbf7110474779ba2404433ef39a24cb5b277186ef1e6cb199b0b60907b029a1ce', + txExecErrorMsg: null } */ async getTransactionReceipt(transactionHash) { @@ -739,14 +744,14 @@ class Conflux { * @example * > packedTx = await conflux.sendTransaction({from:account, to:address, value:0}).get(); // await till transaction packed { - "nonce": "8", - "value": "0", - "gasPrice": "1000000000", - "gas": "21000", + "nonce": 8n, + "value": 0n, + "gasPrice": 1000000000n, + "gas": 21000n, "v": 0, "transactionIndex": null, "status": null, - "storageLimit": "0", + "storageLimit": 0n, "chainId": 1, "epochHeight": 791394, "blockHash": null, @@ -762,14 +767,14 @@ class Conflux { * @example * > minedTx = await conflux.sendTransaction({from:account, to:address, value:0}).mined(); // await till transaction mined { - "nonce": "8", - "value": "0", - "gasPrice": "1000000000", - "gas": "21000", + "nonce": 8n, + "value": 0n, + "gasPrice": 1000000000n, + "gas": 21000n, "v": 0, "transactionIndex": 0, "status": 0, - "storageLimit": "0", + "storageLimit": 0n, "chainId": 1, "epochHeight": 791394, "blockHash": "0xdb2d2d438dcdee8d61c6f495bd363b1afb68cb0fdff16582c08450a9ca487852", @@ -788,8 +793,8 @@ class Conflux { "index": 0, "epochNumber": 791402, "outcomeStatus": 0, - "gasUsed": "21000", - "gasFee": "21000000000000", + "gasUsed": 21000n, + "gasFee": 21000000000000n, "blockHash": "0xdb2d2d438dcdee8d61c6f495bd363b1afb68cb0fdff16582c08450a9ca487852", "contractCreated": null, "from": "0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b", @@ -806,8 +811,8 @@ class Conflux { "index": 0, "epochNumber": 791402, "outcomeStatus": 0, - "gasUsed": "21000", - "gasFee": "21000000000000", + "gasUsed": 21000n, + "gasFee": 21000000000000n, "blockHash": "0xdb2d2d438dcdee8d61c6f495bd363b1afb68cb0fdff16582c08450a9ca487852", "contractCreated": null, "from": "0x1bd9e9be525ab967e633bcdaeac8bd5723ed4d6b", @@ -907,13 +912,13 @@ class Conflux { * - sponsorForGas `string`: the address of the gas sponsor. * * @example - * > await conflux.getSponsorInfo('0x866aca87ff33a0ae05d2164b3d999a804f583222') + * > await conflux.getSponsorInfo('0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98') { - "sponsorBalanceForCollateral": "0", - "sponsorBalanceForGas": "0", - "sponsorGasBound": "0", - "sponsorForCollateral": "0x0000000000000000000000000000000000000000", - "sponsorForGas": "0x0000000000000000000000000000000000000000" + sponsorBalanceForCollateral: 410625000000000000000n, + sponsorBalanceForGas: 9999999993626232440n, + sponsorGasBound: 10000000000n, + sponsorForCollateral: '0x8d5adbcaf5714924830591586f05302bf87f74bd', + sponsorForGas: '0x8d5adbcaf5714924830591586f05302bf87f74bd' } */ async getSponsorInfo(address, epochNumber) { @@ -932,8 +937,8 @@ class Conflux { * @return {Promise} - The collateral storage in Byte. * * @example - * > await conflux.getCollateralForStorage('0xc94770007dda54cf92009bff0de90c06f603a09f') - "158972490234375000" + * > await conflux.getCollateralForStorage('0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98') + 89375000000000000000n */ async getCollateralForStorage(address, epochNumber) { const result = await this.provider.call('cfx_getCollateralForStorage', @@ -1006,29 +1011,29 @@ class Conflux { * * @example * > await conflux.getLogs({ - address: '0x866aca87ff33a0ae05d2164b3d999a804f583222', - fromEpoch: 0, - toEpoch: 'latest_mined', + address: '0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98', + fromEpoch: 39802, + toEpoch: 39802, limit: 1, - topics: ['0x93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db153'] + topics: ['0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d'], }); [ - { - "address": "0x866aca87ff33a0ae05d2164b3d999a804f583222", - "blockHash": "0x0ecbc75aca22cd1566a18c6a7a55f235ae12684c2749b40ac91262d6e8783b0b", - "data": "0x", - "epochNumber": 1504, - "logIndex": 2, - "topics": [ - "0x93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db153", - "0x000000000000000000000000873c4bd4d847bcf7dc066bf4a7cd31dcf182258c", - "0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b", - "0x000000000000000000000000873c4bd4d847bcf7dc066bf4a7cd31dcf182258c" - ], - "transactionHash": "0x2a696f7be50c364333bc145f082e79da3a6e730318b7f7822e3e1fe22e42560b", - "transactionIndex": 0, - "transactionLogIndex": 2 - } + { + epochNumber: 39802, + logIndex: 2, + transactionIndex: 0, + transactionLogIndex: 2, + address: '0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98', + blockHash: '0xca00158a2a508170278d5bdc5ca258b6698306dd8c30fdba32266222c79e57e6', + data: '0x', + topics: [ + '0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d', + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000001c1e72f0c37968557b3d85a3f32747792798bbde', + '0x0000000000000000000000001c1e72f0c37968557b3d85a3f32747792798bbde' + ], + transactionHash: '0xeb75f47002720311f1709e36d7f7e9a91ee4aaa469a1de892839cb1ef66a9939' + } ] */ async getLogs(options) { @@ -1119,25 +1124,23 @@ class Conflux { * > subscription = await conflux.subscribeNewHeads() * > subscription.on('data', data=>console.log(data)) { - difficulty: '19874410', - epochNumber: null, - gasLimit: '30000000', - height: 566239, - powQuality: '39637224', - timestamp: 1602644636, - adaptive: false, - blame: 0, - deferredLogsBloomHash: '0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5', - deferredReceiptsRoot: '0x35182c1c5f1fbb0864758585d94cefcb794619ba8ef4a7adc2e3d48e85a2d4b0', - deferredStateRoot: '0x2cf6ee27ed82e76c585ca46838746907512b86aab04f9f27cb04047939ec056f', - hash: '0x9454515ccd8493d2121e60549efd321de96a7322a95e8d537f7b2d0504a03f21', - miner: '0x10f9db11bb1509041909b35be6a3546fe65d22d0', - nonce: '0x611a95000001fe98', - parentHash: '0xf7edf9f6c11ebd4e9c1aa0a2c03203932c0ad79c3fd92cb7540bcf351aa90376', - refereeHashes: [ - '0x4d69e1b945ec2c819bc20bcb0e128e4b161ed28355d42b6d05a6f7cac9ab91f9' - ], - transactionsRoot: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' + difficulty: 368178587115n, + epochNumber: null, + gasLimit: 30000000n, + height: 1118247, + timestamp: 1605005752, + adaptive: false, + blame: 0, + deferredLogsBloomHash: '0xd397b3b043d87fcd6fad1291ff0bfd16401c274896d8c63a923727f077b8e0b5', + deferredReceiptsRoot: '0x7ae0d5716513206755b6f7c95272b79dbc225759b6e17727e19c2f15c3166bda', + deferredStateRoot: '0x3cf5deba77c8aa9072f1e972d6a97db487a0ce88455f371eb8ac8fa77321cb9d', + hash: '0x194675173abbc5aab50326136008774eea1a289e6722c973dfed12b703ee5f2a', + miner: '0x189121b8f0cdfef0b56eb22d9cb76c97b9c7cfbc', + nonce: '0x799d35f695950fd6', + parentHash: '0x4af3cf8cb358e75acad282ffa4b578b6211ea9eeb7cf87c282f120d8a1c809df', + powQuality: '0xe7ac17feab', + refereeHashes: [], + transactionsRoot: '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' } */ async subscribeNewHeads() { diff --git a/src/contract/Contract.js b/src/contract/Contract.js index f259489b..dccb5076 100644 --- a/src/contract/Contract.js +++ b/src/contract/Contract.js @@ -19,60 +19,102 @@ class Contract { * @return {object} * * @example - * > const contract = conflux.Contract({ abi, bytecode }); + * > const contract = conflux.Contract({ abi, bytecode, address }); { + abi: ContractABI { contract: [Circular *1] }, + address: '0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98', constructor: [Function: bound call], - abi: ContractABI { * }, - address: undefined, - count: [Function: bound call], - inc: [Function: bound call], - 'count()': [Function: bound call], - '0x06661abd': [Function: bound call], - 'inc(uint256)': [Function: bound call], - '0x812600df': [Function: bound call], + name: [Function: bound call], + 'name()': [Function: bound call], + '0x06fdde03': [Function: bound call], + balanceOf: [Function: bound call], + 'balanceOf(address)': [Function: bound call], + '0x70a08231': [Function: bound call], + send: [Function: bound call], + 'send(address,uint256,bytes)': [Function: bound call], + '0x9bd9bbc6': [Function: bound call], + Transfer: [Function: bound call], + 'Transfer(address,address,uint256)': [Function: bound call], + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef': [Function: bound call] } * > contract.constructor.bytecode; // input code - "0x6080604052600080..." + "0x6080..." * @example - * > const contract = conflux.Contract({ abi, address }); + * > const contract = conflux.Contract({ + address: '0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98', + abi: [ + { + type: 'function', + name: 'name', + inputs: [], + outputs: [{ type: 'string' }], + }, + { + type: 'function', + name: 'balanceOf', + inputs: [{ type: 'address' }], + outputs: [{ type: 'uint256' }], + }, + { + name: 'send', + type: 'function', + inputs: [ + { type: 'address', name: 'recipient' }, + { type: 'uint256', name: 'amount' }, + { type: 'bytes', name: 'data' }, + ], + outputs: [{ type: 'bool' }], + }, + ] + }); * > contract.address - "0xc3ed1a06471be1d3bcd014051fbe078387ec0ad8" + "0x8e2f2e68eb75bb8b18caafe9607242d4748f8d98" - * > await contract.count(); // call a method without parameter, get decoded return value. - "100" - * > await contract.inc(1); // call a method with parameters, get decoded return value. - "101" - * > await contract.count().options({ from: account }); // call a method from a account. - "100" + * > await contract.name(); // call a method without parameter, get decoded return value. + "FansCoin" + * > await contract.name().call({ to: '0x8b8689c7f3014a4d86e4d1d0daaf74a47f5e0f27' }); // call a method with options + "conflux USDT" + * > await contract.balanceOf('0x19c742cec42b9e4eff3b84cdedcde2f58a36f44f'); // call a method with parameters, get decoded return value. + 10000000000000000000n - * > transaction = await conflux.getTransactionByHash('0x8a5f48c2de0f1bdacfe90443810ad650e4b327a0d19ce49a53faffb224883e42'); - * > await contract.abi.decodeData(transaction.data) + * > transaction = await conflux.getTransactionByHash('0x2055f3287f1a6ce77d91f5dfdf7517a531b3a560fee1265f27dc1ff92314530b'); + * > contract.abi.decodeData(transaction.data) { - name: 'inc', - fullName: 'inc(uint256 num)', - type: 'inc(uint256)', - signature: '0x7f98a45e', - array: [ JSBI.BigInt(101) ], - object: { num: JSBI.BigInt(101) } - } - - * > await contract.count(); // data in block chain changed by transaction. - JSBI.BigInt(101) + name: 'send', + fullName: 'send(address recipient, uint256 amount, bytes data)', + type: 'send(address,uint256,bytes)', + signature: '0x9bd9bbc6', + array: [ + '0x80bb30efc5683758128b404fe5da03432eb16634', + 60000000000000000000n, + + ], + object: { + recipient: '0x80bb30efc5683758128b404fe5da03432eb16634', + amount: 60000000000000000000n, + data: + } + } - * > receipt = await conflux.getTransactionReceipt('0x8a5f48c2de0f1bdacfe90443810ad650e4b327a0d19ce49a53faffb224883e42'); - * > contract.abi.decodeLog(receipt.logs[0]); + * > receipt = await conflux.getTransactionReceipt('0x2055f3287f1a6ce77d91f5dfdf7517a531b3a560fee1265f27dc1ff92314530b'); + * > contract.abi.decodeLog(receipt.logs[1]); { - name: 'SelfEvent', - fullName: 'SelfEvent(address indexed sender, uint256 current)', - type: 'SelfEvent(address,uint256))', - signature: '0xc4c01f6de493c58245fb681341f3a76bba9551ce81b11cbbb5d6d297844594df', - array: [ '0xbbd9e9be525ab967e633bcdaeac8bd5723ed4d6b', JSBI.BigInt(100) ], + name: 'Transfer', + fullName: 'Transfer(address indexed from, address indexed to, uint256 value)', + type: 'Transfer(address,address,uint256)', + signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + array: [ + '0x1f3c6b9696604cdc3ce1ca277d4c69a9c2770c9f', + '0x80bb30efc5683758128b404fe5da03432eb16634', + 60000000000000000000n + ], object: { - sender: '0xbbd9e9be525ab967e633bcdaeac8bd5723ed4d6b', - current: JSBI.BigInt(100), - }, + from: '0x1f3c6b9696604cdc3ce1ca277d4c69a9c2770c9f', + to: '0x80bb30efc5683758128b404fe5da03432eb16634', + value: 60000000000000000000n + } } */ constructor({ abi, address, bytecode }, conflux) { diff --git a/src/contract/abi/BoolCoder.js b/src/contract/abi/BoolCoder.js index f884d9ff..ea934065 100644 --- a/src/contract/abi/BoolCoder.js +++ b/src/contract/abi/BoolCoder.js @@ -1,6 +1,6 @@ -const JSBI = require('jsbi'); const lodash = require('lodash'); const { assert } = require('../../util'); +const JSBI = require('../../util/jsbi'); const IntegerCoder = require('./IntegerCoder'); class BoolCoder extends IntegerCoder { diff --git a/src/contract/abi/IntegerCoder.js b/src/contract/abi/IntegerCoder.js index 833142cb..0103b70b 100644 --- a/src/contract/abi/IntegerCoder.js +++ b/src/contract/abi/IntegerCoder.js @@ -1,7 +1,7 @@ -const JSBI = require('jsbi'); const { UINT_BOUND } = require('../../CONST'); const { assert, alignBuffer } = require('../../util'); const format = require('../../util/format'); +const JSBI = require('../../util/jsbi'); const BaseCoder = require('./BaseCoder'); class IntegerCoder extends BaseCoder { diff --git a/src/provider/WebSocketProvider.js b/src/provider/WebSocketProvider.js index 73c12a1e..eeb60673 100644 --- a/src/provider/WebSocketProvider.js +++ b/src/provider/WebSocketProvider.js @@ -25,7 +25,7 @@ class WebSocketProvider extends BaseProvider { return new Promise((resolve, reject) => { const client = new Websocket(url); client.onopen = () => resolve(client); - client.onerror = () => reject(new Error(`connect to ${url}, failed`)); + client.onerror = () => reject(new Error(`connect to "${url}" failed`)); client.onmessage = ({ data }) => this.emit('message', data); client.onclose = ({ code, reason }) => this.emit('close', code, reason); }); diff --git a/src/util/format.js b/src/util/format.js index c1d40d33..3a95f341 100644 --- a/src/util/format.js +++ b/src/util/format.js @@ -1,7 +1,7 @@ -const JSBI = require('jsbi'); const Big = require('big.js'); const lodash = require('lodash'); const CONST = require('../CONST'); +const JSBI = require('./jsbi'); const parser = require('./parser'); const sign = require('./sign'); @@ -11,7 +11,7 @@ function toHex(value) { if (lodash.isString(value)) { hex = value.toLowerCase(); // XXX: lower case for support checksum address - } else if (Number.isInteger(value) || (value instanceof JSBI)) { + } else if (Number.isInteger(value) || (typeof value === 'bigint') || (value instanceof JSBI)) { hex = `0x${value.toString(16)}`; } else if (Buffer.isBuffer(value)) { hex = `0x${value.toString('hex')}`; @@ -39,7 +39,7 @@ function toNumber(value) { } function toBigInt(value) { - if (Number.isInteger(value) || (value instanceof JSBI)) { + if (Number.isInteger(value) || (typeof value === 'bigint') || (value instanceof JSBI)) { return JSBI.BigInt(value); } if (lodash.isBoolean(value)) { @@ -74,19 +74,19 @@ const format = {}; format.any = parser(v => v); /** - * @param arg {number|JSBI|string|boolean} + * @param arg {number|BigInt|string|boolean} * @return {Number} * * @example * > format.uInt(-3.14) - Error("cannot be converted to a JSBI") + Error("not match uint") * > format.uInt(null) - Error("Cannot convert null to a JSBI") + Error("not match number") * > format.uInt('0') 0 * > format.uInt(1) 1 - * > format.uInt(JSBI(100)) + * > format.uInt(BigInt(100)) 100 * > format.uInt('0x10') 16 @@ -102,34 +102,34 @@ format.any = parser(v => v); format.uInt = parser(toNumber).$validate(v => Number.isSafeInteger(v) && v >= 0, 'uint'); /** - * @param arg {number|string|JSBI} - * @return {JSBI} + * @param arg {number|string|BigInt} + * @return {BigInt} * * @example * > format.bigInt(-3.14) - Error("not match bigInt") + Error("Cannot convert -3.14 to a BigInt") * > format.bigInt('0.0') - JSBI.BigInt(0) + 0n * > format.bigInt('-1') - JSBI.BigInt(-1) + -1n * > format.bigInt(1) - JSBI.BigInt(1) - * > format.bigInt(JSBI.BigInt(100)) - JSBI.BigInt(100) + 1n + * > format.bigInt(BigInt(100)) + 100n * > format.bigInt('0x10') - JSBI.BigInt(16) + 16n * > format.bigInt(Number.MAX_SAFE_INTEGER + 1) // unsafe integer - Error("not match uint") + 9007199254740992n */ format.bigInt = parser(toBigInt); /** - * @param arg {number|string|JSBI} - * @return {JSBI} + * @param arg {number|string|BigInt} + * @return {BigInt} * * @example * > format.bigUInt('0.0') - JSBI.BigInt(0) + 0n * > format.bigUInt('-1') Error("not match bigUInt") */ @@ -138,7 +138,7 @@ format.bigUInt = format.bigInt.$validate(v => v >= 0, 'bigUInt'); /** * When encoding QUANTITIES (integers, numbers): encode as hex, prefix with "0x", the most compact representation (slight exception: zero should be represented as "0x0") * - * @param arg {number|string|JSBI} + * @param arg {number|string|BigInt} * @return {string} Hex string * * @example @@ -152,7 +152,7 @@ format.bigUInt = format.bigInt.$validate(v => v >= 0, 'bigUInt'); format.bigUIntHex = format.bigUInt.$after(v => `0x${v.toString(16)}`); /** - * @param arg {number|string|JSBI} + * @param arg {number|string|BigInt} * @return {Big} Big instance * * @example @@ -174,7 +174,7 @@ format.bigUIntHex = format.bigUInt.$after(v => `0x${v.toString(16)}`); format.big = parser(toBig); /** - * @param arg {string|number|JSBI|Big} + * @param arg {string|number|BigInt|Big} * @return {Number} * * @example @@ -207,7 +207,7 @@ format.epochNumber = format.bigUIntHex /** * When encoding UNFORMATTED DATA (byte arrays, account addresses, hashes, bytecode arrays): encode as hex, prefix with "0x", two hex digits per byte. * - * @param arg {number|JSBI|string|Buffer|boolean|null} + * @param arg {number|BigInt|string|Buffer|boolean|null} * @return {string} Hex string * * @example @@ -319,7 +319,7 @@ format.privateKey = format.hex64; // alias format.publicKey = format.hex.$validate(v => v.length === 2 + 128, 'publicKey'); /** - * @param arg {number|string|JSBI|Buffer|boolean|null} + * @param arg {number|string|BigInt|Buffer|boolean|null} * @return {Buffer} * * @example diff --git a/src/util/jsbi.js b/src/util/jsbi.js new file mode 100644 index 00000000..64c7368d --- /dev/null +++ b/src/util/jsbi.js @@ -0,0 +1,42 @@ +/** + * support interface of [jsbi](https://github.com/GoogleChromeLabs/jsbi#readme) + * - for node.js using native BigInt as JSBI.BigInt + * - for browser using browserify to replace with jsbi + */ + +/* eslint-disable no-bitwise */ +module.exports = BigInt; +module.exports.BigInt = BigInt; + +module.exports.toNumber = x => Number(x); + +module.exports.unaryMinus = x => -x; +module.exports.bitwiseNot = x => ~x; + +module.exports.exponentiate = (x, y) => x ** y; +module.exports.multiply = (x, y) => x * y; +module.exports.divide = (x, y) => x / y; +module.exports.remainder = (x, y) => x % y; +module.exports.add = (x, y) => x + y; +module.exports.subtract = (x, y) => x - y; +module.exports.leftShift = (x, y) => x << y; +module.exports.signedRightShift = (x, y) => x >> y; + +module.exports.lessThan = (x, y) => x < y; +module.exports.lessThanOrEqual = (x, y) => x <= y; +module.exports.greaterThan = (x, y) => x > y; +module.exports.greaterThanOrEqual = (x, y) => x >= y; +module.exports.equal = (x, y) => x === y; +module.exports.notEqual = (x, y) => x !== y; + +module.exports.bitwiseAnd = (x, y) => x & y; +module.exports.bitwiseXor = (x, y) => x ^ y; +module.exports.bitwiseOr = (x, y) => x | y; + +module.exports.ADD = (x, y) => x + y; +module.exports.LT = (x, y) => x < y; +module.exports.LE = (x, y) => x <= y; +module.exports.GT = (x, y) => x > y; +module.exports.GE = (x, y) => x >= y; +module.exports.EQ = (x, y) => x === y; +module.exports.NE = (x, y) => x !== y; diff --git a/test/conflux/after.test.js b/test/conflux/after.test.js index af78c78b..f2c4b920 100644 --- a/test/conflux/after.test.js +++ b/test/conflux/after.test.js @@ -1,4 +1,3 @@ -const JSBI = require('jsbi'); const lodash = require('lodash'); const { Conflux, format } = require('../../src'); const { MockProvider } = require('../../mock'); @@ -31,30 +30,30 @@ test('getStatus', async () => { test('getGasPrice', async () => { const gasPrice = await conflux.getGasPrice(); - expect(gasPrice).toBeInstanceOf(JSBI); + expect(typeof gasPrice).toEqual('bigint'); }); test('getInterestRate', async () => { const interestRate = await conflux.getInterestRate(); - expect(interestRate).toBeInstanceOf(JSBI); + expect(typeof interestRate).toEqual('bigint'); }); test('getAccumulateInterestRate', async () => { const interestRate = await conflux.getAccumulateInterestRate(); - expect(interestRate).toBeInstanceOf(JSBI); + expect(typeof interestRate).toEqual('bigint'); }); // ------------------------------- address ---------------------------------- test('getAccount', async () => { const account = await conflux.getAccount(ADDRESS); - expect(account.accumulatedInterestReturn).toBeInstanceOf(JSBI); - expect(account.balance).toBeInstanceOf(JSBI); - expect(account.collateralForStorage).toBeInstanceOf(JSBI); - expect(account.nonce).toBeInstanceOf(JSBI); - expect(account.stakingBalance).toBeInstanceOf(JSBI); + expect(typeof account.accumulatedInterestReturn).toEqual('bigint'); + expect(typeof account.balance).toEqual('bigint'); + expect(typeof account.collateralForStorage).toEqual('bigint'); + expect(typeof account.nonce).toEqual('bigint'); + expect(typeof account.stakingBalance).toEqual('bigint'); expect(account.admin.startsWith('0x')).toEqual(true); expect(account.codeHash.startsWith('0x')).toEqual(true); }); @@ -62,19 +61,19 @@ test('getAccount', async () => { test('getBalance', async () => { const balance = await conflux.getBalance(ADDRESS); - expect(balance).toBeInstanceOf(JSBI); + expect(typeof balance).toEqual('bigint'); }); test('getStakingBalance', async () => { const balance = await conflux.getStakingBalance(ADDRESS); - expect(balance).toBeInstanceOf(JSBI); + expect(typeof balance).toEqual('bigint'); }); test('getNextNonce', async () => { const txCount = await conflux.getNextNonce(ADDRESS); - expect(txCount).toBeInstanceOf(JSBI); + expect(typeof txCount).toEqual('bigint'); }); test('getAdmin', async () => { @@ -111,9 +110,9 @@ test('getBlockRewardInfo', async () => { rewardArray.forEach(reward => { expect(reward.blockHash.startsWith('0x')).toEqual(true); expect(reward.author.startsWith('0x')).toEqual(true); - expect(reward.baseReward).toBeInstanceOf(JSBI); - expect(reward.totalReward).toBeInstanceOf(JSBI); - expect(reward.txFee).toBeInstanceOf(JSBI); + expect(typeof reward.baseReward).toEqual('bigint'); + expect(typeof reward.totalReward).toEqual('bigint'); + expect(typeof reward.txFee).toEqual('bigint'); }); }); @@ -141,8 +140,8 @@ test('getBlockByHash', async () => { expect(Number.isInteger(block.height)).toEqual(true); expect(Number.isInteger(block.timestamp)).toEqual(true); expect(block.nonce.startsWith('0x')).toEqual(true); - expect(block.gasLimit).toBeInstanceOf(JSBI); - expect(block.difficulty).toBeInstanceOf(JSBI); + expect(typeof block.gasLimit).toEqual('bigint'); + expect(typeof block.difficulty).toEqual('bigint'); expect(Array.isArray(block.refereeHashes)).toEqual(true); expect(Array.isArray(block.transactions)).toEqual(true); block.transactions.forEach(transactionHash => { @@ -187,13 +186,13 @@ test('getTransactionByHash', async () => { expect(transaction.s.startsWith('0x')).toEqual(true); expect(lodash.isNull(transaction.contractCreated) || transaction.contractCreated.startsWith('0x')).toEqual(true); expect(Number.isInteger(transaction.transactionIndex)).toEqual(true); - expect(transaction.nonce).toBeInstanceOf(JSBI); + expect(typeof transaction.nonce).toEqual('bigint'); expect(lodash.isNull(transaction.status) || Number.isInteger(transaction.status)).toEqual(true); expect(Number.isInteger(transaction.v)).toEqual(true); - expect(transaction.gas).toBeInstanceOf(JSBI); - expect(transaction.gasPrice).toBeInstanceOf(JSBI); - expect(transaction.value).toBeInstanceOf(JSBI); - expect(transaction.storageLimit).toBeInstanceOf(JSBI); + expect(typeof transaction.gas).toEqual('bigint'); + expect(typeof transaction.gasPrice).toEqual('bigint'); + expect(typeof transaction.value).toEqual('bigint'); + expect(typeof transaction.storageLimit).toEqual('bigint'); expect(Number.isInteger(transaction.chainId)).toEqual(true); expect(Number.isInteger(transaction.epochHeight)).toEqual(true); }); @@ -211,8 +210,8 @@ test('getTransactionReceipt', async () => { expect(Number.isInteger(receipt.index)).toEqual(true); expect(Number.isInteger(receipt.epochNumber)).toEqual(true); expect(lodash.isNull(receipt.outcomeStatus) || Number.isInteger(receipt.outcomeStatus)).toEqual(true); - expect(receipt.gasUsed).toBeInstanceOf(JSBI); - expect(receipt.gasFee).toBeInstanceOf(JSBI); + expect(typeof receipt.gasUsed).toEqual('bigint'); + expect(typeof receipt.gasFee).toEqual('bigint'); expect(Array.isArray(receipt.logs)).toEqual(true); }); @@ -267,9 +266,9 @@ test('getStorageRoot', async () => { test('getSponsorInfo', async () => { const info = await conflux.getSponsorInfo(ADDRESS); - expect(info.sponsorBalanceForCollateral).toBeInstanceOf(JSBI); - expect(info.sponsorBalanceForGas).toBeInstanceOf(JSBI); - expect(info.sponsorGasBound).toBeInstanceOf(JSBI); + expect(typeof info.sponsorBalanceForCollateral).toEqual('bigint'); + expect(typeof info.sponsorBalanceForGas).toEqual('bigint'); + expect(typeof info.sponsorGasBound).toEqual('bigint'); expect(info.sponsorForCollateral.startsWith('0x')).toEqual(true); expect(info.sponsorForGas.startsWith('0x')).toEqual(true); }); @@ -277,7 +276,7 @@ test('getSponsorInfo', async () => { test('getCollateralForStorage', async () => { const collateral = await conflux.getCollateralForStorage(ADDRESS); - expect(collateral).toBeInstanceOf(JSBI); + expect(typeof collateral).toEqual('bigint'); }); test('call', async () => { @@ -289,8 +288,8 @@ test('call', async () => { test('estimateGasAndCollateral', async () => { const estimate = await conflux.estimateGasAndCollateral({}); - expect(estimate.gasUsed).toBeInstanceOf(JSBI); - expect(estimate.storageCollateralized).toBeInstanceOf(JSBI); + expect(typeof estimate.gasUsed).toEqual('bigint'); + expect(typeof estimate.storageCollateralized).toEqual('bigint'); }); test('getLogs', async () => { diff --git a/test/contract/EventCoder.test.js b/test/contract/EventCoder.test.js index da605634..54c8612a 100644 --- a/test/contract/EventCoder.test.js +++ b/test/contract/EventCoder.test.js @@ -1,4 +1,4 @@ -const JSBI = require('jsbi'); +const JSBI = require('../../src/util/jsbi'); const EventCoder = require('../../src/contract/event/EventCoder'); test('event', () => { diff --git a/test/contract/FunctionCoder.test.js b/test/contract/FunctionCoder.test.js index f57382da..082bb345 100644 --- a/test/contract/FunctionCoder.test.js +++ b/test/contract/FunctionCoder.test.js @@ -1,4 +1,4 @@ -const JSBI = require('jsbi'); +const JSBI = require('../../src/util/jsbi'); const FunctionCoder = require('../../src/contract/method/FunctionCoder'); test('function', () => { diff --git a/test/contract/contract.test.js b/test/contract/contract.test.js index 0f1bace4..f5106208 100644 --- a/test/contract/contract.test.js +++ b/test/contract/contract.test.js @@ -1,4 +1,4 @@ -const JSBI = require('jsbi'); +const JSBI = require('../../src/util/jsbi'); const { Conflux, format } = require('../../src'); const { MockProvider } = require('../../mock'); const { abi, bytecode, address } = require('./contract.json'); diff --git a/test/contract/valueCoder.test.js b/test/contract/valueCoder.test.js index 9ca025f1..f378f8af 100644 --- a/test/contract/valueCoder.test.js +++ b/test/contract/valueCoder.test.js @@ -1,10 +1,10 @@ /* eslint-disable no-bitwise */ -const JSBI = require('jsbi'); const lodash = require('lodash'); const { format, CONST } = require('../../src'); const BaseCoder = require('../../src/contract/abi/BaseCoder'); const { valueCoder } = require('../../src/contract/abi'); +const JSBI = require('../../src/util/jsbi'); const HexStream = require('../../src/util/HexStream'); function testEncode(coder, value, string) { diff --git a/test/util/format.test.js b/test/util/format.test.js index 6d7efb01..1dd6d658 100644 --- a/test/util/format.test.js +++ b/test/util/format.test.js @@ -1,6 +1,6 @@ -const JSBI = require('jsbi'); const Big = require('big.js'); const { format } = require('../../src'); +const JSBI = require('../../src/util/jsbi'); const HEX_64 = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'; const HEX_40 = '0x0123456789012345678901234567890123456789'; diff --git a/test/util/jsbi.test.js b/test/util/jsbi.test.js new file mode 100644 index 00000000..df858fc1 --- /dev/null +++ b/test/util/jsbi.test.js @@ -0,0 +1,126 @@ +/* eslint-disable no-bitwise,no-self-compare */ + +const JSBI = require('jsbi'); +const NodeBI = require('../../src/util/jsbi'); + +JSBI.prototype.toJSON = function () { + return this.toString(); +}; + +NodeBI.prototype.toJSON = function () { + return this.toString(); +}; + +const jsbi = JSBI.BigInt(10); +const bi = NodeBI.BigInt(10); + +test('constructor', () => { + expect(jsbi).toBeInstanceOf(JSBI); + expect(typeof bi).toEqual('bigint'); + + expect(JSBI.toNumber(jsbi)).toEqual(10); + expect(NodeBI.toNumber(bi)).toEqual(10); + + expect(JSON.stringify(jsbi)).toEqual('"10"'); + expect(JSON.stringify(bi)).toEqual('"10"'); +}); + +test('toString', () => { + expect(jsbi.toString()).toEqual('10'); + expect(bi.toString()).toEqual('10'); + + expect(jsbi.toString(2)).toEqual('1010'); + expect(bi.toString(2)).toEqual('1010'); + + expect(jsbi.toString(8)).toEqual('12'); + expect(bi.toString(8)).toEqual('12'); + + expect(jsbi.toString(10)).toEqual('10'); + expect(bi.toString(10)).toEqual('10'); + + expect(jsbi.toString(16)).toEqual('a'); + expect(bi.toString(16)).toEqual('a'); +}); + +test('operator', () => { + expect(JSBI.unaryMinus(jsbi)).toEqual(JSBI.BigInt(-jsbi)); + expect(NodeBI.unaryMinus(bi)).toEqual(BigInt(-bi)); + + expect(JSBI.bitwiseNot(jsbi)).toEqual(JSBI.BigInt(~jsbi)); + expect(NodeBI.bitwiseNot(bi)).toEqual(BigInt(~bi)); + + expect(JSBI.asIntN(4, JSBI.BigInt(0xff))).toEqual(JSBI.BigInt(-1)); + expect(NodeBI.asIntN(4, NodeBI.BigInt(0xff))).toEqual(BigInt(-1)); + + expect(JSBI.asUintN(4, JSBI.BigInt(0xff))).toEqual(JSBI.BigInt(15)); + expect(NodeBI.asUintN(4, NodeBI.BigInt(0xff))).toEqual(BigInt(15)); + + expect(JSBI.exponentiate(jsbi, JSBI.BigInt(2))).toEqual(JSBI.BigInt(10 ** 2)); + expect(NodeBI.exponentiate(bi, NodeBI.BigInt(2))).toEqual(BigInt(10 ** 2)); + expect(() => JSBI.exponentiate(jsbi, 2)).toThrow('b.__unsignedDigit is not a function'); + expect(() => NodeBI.exponentiate(bi, 2)).toThrow('Cannot mix BigInt and other types, use explicit conversions'); + + expect(JSBI.multiply(jsbi, JSBI.BigInt(2))).toEqual(JSBI.BigInt(10 * 2)); + expect(NodeBI.multiply(bi, NodeBI.BigInt(2))).toEqual(BigInt(10 * 2)); + + expect(JSBI.divide(jsbi, JSBI.BigInt(3))).toEqual(JSBI.BigInt(Math.floor(10 / 3))); + expect(NodeBI.divide(bi, NodeBI.BigInt(3))).toEqual(BigInt(Math.floor(10 / 3))); + expect(JSBI.divide(jsbi, JSBI.BigInt(11))).toEqual(JSBI.BigInt(Math.floor(10 / 11))); + expect(NodeBI.divide(bi, NodeBI.BigInt(11))).toEqual(BigInt(Math.floor(10 / 11))); + + expect(JSBI.remainder(jsbi, JSBI.BigInt(3))).toEqual(JSBI.BigInt(10 % 3)); + expect(NodeBI.remainder(bi, NodeBI.BigInt(3))).toEqual(BigInt(10 % 3)); + + expect(JSBI.add(jsbi, JSBI.BigInt(1))).toEqual(JSBI.BigInt(11)); + expect(NodeBI.add(bi, NodeBI.BigInt(1))).toEqual(BigInt(11)); + expect(JSBI.ADD(jsbi, JSBI.BigInt(1))).toEqual(JSBI.BigInt(11)); + expect(NodeBI.ADD(bi, NodeBI.BigInt(1))).toEqual(BigInt(11)); + + expect(JSBI.subtract(jsbi, JSBI.BigInt(20))).toEqual(JSBI.BigInt(-10)); + expect(NodeBI.subtract(bi, NodeBI.BigInt(20))).toEqual(BigInt(-10)); + + expect(JSBI.leftShift(jsbi, JSBI.BigInt(2))).toEqual(JSBI.BigInt(10 << 2)); + expect(NodeBI.leftShift(bi, NodeBI.BigInt(2))).toEqual(BigInt(10 << 2)); + + expect(JSBI.signedRightShift(jsbi, JSBI.BigInt(2))).toEqual(JSBI.BigInt(10 >> 2)); + expect(NodeBI.signedRightShift(bi, NodeBI.BigInt(2))).toEqual(BigInt(10 >> 2)); + + expect(JSBI.lessThan(jsbi, JSBI.BigInt(11))).toEqual(10 < 11); + expect(NodeBI.lessThan(bi, NodeBI.BigInt(11))).toEqual(10 < 11); + expect(JSBI.LT(jsbi, JSBI.BigInt(11))).toEqual(10 < 11); + expect(NodeBI.LT(bi, NodeBI.BigInt(11))).toEqual(10 < 11); + + expect(JSBI.lessThanOrEqual(jsbi, JSBI.BigInt(10))).toEqual(10 <= 10); + expect(NodeBI.lessThanOrEqual(bi, NodeBI.BigInt(10))).toEqual(10 <= 10); + expect(JSBI.LE(jsbi, JSBI.BigInt(10))).toEqual(10 <= 10); + expect(NodeBI.LE(bi, NodeBI.BigInt(10))).toEqual(10 <= 10); + + expect(JSBI.greaterThan(jsbi, JSBI.BigInt(11))).toEqual(10 > 11); + expect(NodeBI.greaterThan(bi, NodeBI.BigInt(11))).toEqual(10 > 11); + expect(JSBI.GT(jsbi, JSBI.BigInt(11))).toEqual(10 > 11); + expect(NodeBI.GT(bi, NodeBI.BigInt(11))).toEqual(10 > 11); + + expect(JSBI.greaterThanOrEqual(jsbi, JSBI.BigInt(10))).toEqual(10 >= 10); + expect(NodeBI.greaterThanOrEqual(bi, NodeBI.BigInt(10))).toEqual(10 >= 10); + expect(JSBI.GE(jsbi, JSBI.BigInt(10))).toEqual(10 >= 10); + expect(NodeBI.GE(bi, NodeBI.BigInt(10))).toEqual(10 >= 10); + + expect(JSBI.equal(jsbi, JSBI.BigInt(10))).toEqual(10 === 10); + expect(NodeBI.equal(bi, NodeBI.BigInt(10))).toEqual(10 === 10); + expect(JSBI.EQ(jsbi, JSBI.BigInt(10))).toEqual(10 === 10); + expect(NodeBI.EQ(bi, NodeBI.BigInt(10))).toEqual(10 === 10); + + expect(JSBI.notEqual(jsbi, JSBI.BigInt(10))).toEqual(10 !== 10); + expect(NodeBI.notEqual(bi, NodeBI.BigInt(10))).toEqual(10 !== 10); + expect(JSBI.NE(jsbi, JSBI.BigInt(10))).toEqual(10 !== 10); + expect(NodeBI.NE(bi, NodeBI.BigInt(10))).toEqual(10 !== 10); + + expect(JSBI.bitwiseAnd(jsbi, JSBI.BigInt(11))).toEqual(JSBI.BigInt(10 & 11)); + expect(NodeBI.bitwiseAnd(bi, NodeBI.BigInt(11))).toEqual(BigInt(10 & 11)); + + expect(JSBI.bitwiseXor(jsbi, JSBI.BigInt(11))).toEqual(JSBI.BigInt(10 ^ 11)); + expect(NodeBI.bitwiseXor(bi, NodeBI.BigInt(11))).toEqual(BigInt(10 ^ 11)); + + expect(JSBI.bitwiseOr(jsbi, JSBI.BigInt(11))).toEqual(JSBI.BigInt(10 | 11)); + expect(NodeBI.bitwiseOr(bi, NodeBI.BigInt(11))).toEqual(BigInt(10 | 11)); +}); diff --git a/yarn.lock b/yarn.lock index c3ec5b7e..cac4820e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4035,7 +4035,7 @@ js2xmlparser@^4.0.1: dependencies: xmlcreate "^2.0.3" -jsbi@^3.1.1: +jsbi@^3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.1.4.tgz#9654dd02207a66a4911b4e4bb74265bc2cbc9dd0" integrity sha512-52QRRFSsi9impURE8ZUbzAMCLjPm4THO7H2fcuIvaaeFTbSysvkodbQQXIVsNgq/ypDbq6dJiuGKL0vZ/i9hUg==