Compare commits

...

86 Commits

Author SHA1 Message Date
Richard Moore
29be1e37bc Updated dist files. 2021-02-01 15:56:47 -05:00
Richard Moore
e727efc33e Added support for networks with slightly incorrect EIP-658 implementations (#952, #1251). 2021-02-01 15:50:27 -05:00
Richard Moore
4af2c19f45 Added Pocket network to the default provider (#1030, #1052). 2021-02-01 14:40:02 -05:00
Richard Moore
4f67ecdf62 Updated dist files. 2021-01-31 21:12:58 -05:00
Richard Moore
3396846a30 Added TypeScript declaration maps (#401). 2021-01-19 05:22:54 -05:00
Richard Moore
5c27b45ac9 Updated dist files. 2021-01-13 14:49:25 -05:00
Richard Moore
20f6e16394 Better provider internal block management (#1084, #1208, #1221, #1235). 2021-01-13 14:42:15 -05:00
Richard Moore
2df9dd1120 Updated dist files. 2021-01-13 03:41:29 -05:00
Richard Moore
74470defda Fixed abundant UnhandledRejectErrors in provider polling (#1084, #1208, #1221, #1235). 2021-01-13 03:16:27 -05:00
Richard Moore
8175c83026 Fixed non-checksum address comparisons in abstract Signer (#1236). 2021-01-12 21:43:49 -05:00
Richard Moore
e0ccafb140 Updated dist files. 2021-01-08 03:32:59 -05:00
Richard Moore
20335e96c2 Safety check on digest length for signing. 2020-12-19 15:26:16 -05:00
Richard Moore
a56a0a3336 Fixed listenerCount for contract when requesting for all events (#1205). 2020-12-18 03:56:14 -05:00
Richard Moore
4ad47b1b43 admin: added lock-versions script. 2020-12-14 01:26:05 -05:00
Richard Moore
0e6cc9a9a8 Lock package versions for the ESM builds (#1009). 2020-12-14 01:25:31 -05:00
Richard Moore
21c6c7ddb6 docs: use local dev node for exampels during build. 2020-12-08 18:30:34 -05:00
Richard Moore
8efbfc6afa docs: Filled in ContractFactory and examples. 2020-12-08 18:29:56 -05:00
Richard Moore
8e3cfd8517 Updated dist files. 2020-12-08 01:44:36 -05:00
Richard Moore
0a6c15e691 admin: Added TypeScript-migrated admin scripts. 2020-12-08 01:38:32 -05:00
Richard Moore
d3b1ac046a Fixed EIP-712 getPayload dropping EIP712Domain from types for JSON-RPC calls (#687). 2020-12-08 01:37:44 -05:00
Richard Moore
86b413750d admin: sync github issues. 2020-12-08 01:23:40 -05:00
Richard Moore
70c2b1b300 Remvoed dead files. 2020-12-08 01:22:09 -05:00
Richard Moore
5cb418cf7d Fixed typos in CHANGELOG. 2020-11-25 20:03:27 -05:00
Richard Moore
8e4ee887b9 build: added testing folder to git ignore. 2020-11-25 15:35:12 -05:00
Richard Moore
ef09361539 build: updated build scripts. 2020-11-25 15:34:05 -05:00
Richard Moore
6e36447aa0 Merge branch 'master' of github.com:ethers-io/ethers.js 2020-11-25 15:32:20 -05:00
Richard Moore
1c4259881a Updated dist files. 2020-11-25 15:30:58 -05:00
Richard Moore
ba00df1ab7 build: Added updated admin scripts 2020-11-25 15:29:58 -05:00
Richard Moore
45a2902874 Fix BigNumber when passed something with a length property (#1172). 2020-11-25 15:07:34 -05:00
Richard Moore
211defa27f Upddated dist files. 2020-11-23 19:23:11 -05:00
Richard Moore
bdc6df4b8b ci: Use macOS for coverage to fix libudev issue with ubuntu. 2020-11-23 19:10:17 -05:00
Richard Moore
799896ac13 Added directory to repo field for each package. 2020-11-23 18:44:11 -05:00
Richard Moore
8b54f7ff23 CI: use macos for tests. 2020-11-23 18:22:31 -05:00
Richard Moore
2cf462c571 ci: break ubuntu pacakge into its own step. 2020-11-23 18:12:21 -05:00
Richard Moore
1f6646e131 CI: attempting custom package repo. 2020-11-23 18:08:05 -05:00
Richard Moore
e6a52b309b CI: change linux version back to ubuntu-latest. 2020-11-23 13:09:00 -05:00
Richard Moore
fb808d1362 Updated dist files. 2020-11-23 03:43:28 -05:00
Richard Moore
fd2882d088 Temporary fix for GitHub actions being down. 2020-11-23 03:36:02 -05:00
Richard Moore
a8e3380ed5 Add ABI coder function to compute default values (#1101). 2020-11-23 00:59:44 -05:00
Richard Moore
7f775f7ad6 docs: updated generated docs. 2020-11-22 23:07:13 -05:00
Richard Moore
d122d18cfa docs: fixed source search link 2020-11-22 23:06:27 -05:00
Richard Moore
34488cd7d8 docs: updates and fixes (#1122). 2020-11-22 23:03:50 -05:00
Richard Moore
95e2871966 Updated dist files. 2020-11-22 22:44:33 -05:00
Richard Moore
4a8d579dca Fix for new versions of Geth which return formatted data on revert rather than standard data (#949). 2020-11-22 17:43:32 -05:00
Richard Moore
fbbe4ad638 Fixed typo in BigNumber error (#1164). 2020-11-22 16:38:28 -05:00
Richard Moore
20defec9f1 Addd missing sideEffects flag to some packages. 2020-11-22 16:35:27 -05:00
Richard Moore
c8bb77d8af Allow base-10 to be passed into BigNumbner.toString and improve errors for other radices (#1164). 2020-11-22 16:34:07 -05:00
Richard Moore
29f6c34343 Allow private keys to Wallet to omit the 0x prefix (#1166). 2020-11-20 17:30:36 -05:00
Richard Moore
a185e89181 Updated dist files. 2020-11-19 18:54:50 -05:00
Richard Moore
c9e548071e Force address to use bignumber package with base36 private functions (#1163). 2020-11-19 18:45:10 -05:00
Richard Moore
62c7195ed6 Updated dist files. 2020-11-19 17:44:10 -05:00
Richard Moore
cc63e61f73 Remove stray console.log in hardware wallets (#1136). 2020-11-19 17:24:37 -05:00
Richard Moore
2816850716 Added some funding links for the sponsor button. 2020-11-19 17:20:46 -05:00
Richard Moore
4b7028a661 docs: Typo in BigNumber source (#1100). 2020-11-18 17:25:58 -05:00
Richard Moore
0382faebb1 docs: Typo in BigNumber (#1127). 2020-11-18 17:22:22 -05:00
Richard Moore
97efeba8dc docs: fixed typo in contracts readme (#1128). 2020-11-18 17:20:24 -05:00
Richard Moore
cddc258c96 Remove invalid pkg.module reference (#1133). 2020-11-18 17:13:23 -05:00
Richard Moore
3abfdffffa Updated dist files. 2020-11-17 20:36:19 -05:00
Richard Moore
02546b9401 Fix browser ws alias. 2020-11-17 20:07:22 -05:00
Richard Moore
fff72ef369 Use faux-registry to better simulate real world React Native apps. 2020-11-17 18:48:02 -05:00
Richard Moore
f10977ab35 Fixing React Native tests. 2020-11-17 13:41:43 -05:00
Richard Moore
1729f804fb Prevent node 8 from using rollup (contains incompatible syntax). 2020-11-17 02:51:54 -05:00
Richard Moore
8933467c01 Updated dist build. 2020-11-16 23:07:24 -05:00
Richard Moore
22bd0c76dd Use dist files in browser tests. 2020-11-16 21:20:35 -05:00
Richard Moore
4809325bee Refactoring dist build process. 2020-11-14 17:42:36 -05:00
Richard Moore
e0b1d0e1e0 Updated dist files. 2020-10-22 21:55:40 -04:00
Richard Moore
fe17a29581 Allow 0x as a numeric value for 0 in Provider formatter (#1104). 2020-10-22 21:03:51 -04:00
Richard Moore
d8cdd0e94c admin: Updated spell checker and mime-types. 2020-10-22 20:01:57 -04:00
Richard Moore
5a9bc30336 Updated dist files. 2020-10-22 20:01:18 -04:00
Richard Moore
28f60d5ef8 Use POST for long requests in EtherscanProvider (#1093). 2020-10-22 19:46:52 -04:00
Richard Moore
a21202c66b Export verifyTypedData in utils (#687). 2020-10-20 00:17:43 -04:00
Richard Moore
116cc89686 admin: updated publish script to allow forcing publish 2020-10-20 00:17:02 -04:00
Richard Moore
550ecf2f25 Added verifyTypedData for EIP-712 typed data (#687). 2020-10-20 00:15:55 -04:00
Richard Moore
7b19fdfeed Updated dist files. 2020-10-19 01:27:15 -04:00
Richard Moore
15a90af5be Fix signTypedData call for JsonRpcSigner (#687). 2020-10-19 01:17:36 -04:00
Richard Moore
86146650d8 Updated dist files. 2020-10-18 23:19:16 -04:00
Richard Moore
7fcae25a78 Refactoring test case generation scripts. 2020-10-18 21:55:12 -04:00
Richard Moore
15893537c3 Added EIP-712 test cases (#687). 2020-10-18 21:54:21 -04:00
Richard Moore
be4e2164e6 Initial Signer support for EIP-712 signed typed data (#687). 2020-10-18 21:52:25 -04:00
Richard Moore
3e676f21b0 Split hash library files up. 2020-10-18 21:45:32 -04:00
Richard Moore
5a4dd5a703 Added EIP-712 multi-dimensional array support (#687). 2020-10-12 00:58:04 -04:00
Richard Moore
345a830dc4 Consolidated TypedDataEncoder methods (#687). 2020-10-10 04:44:17 -04:00
Richard Moore
cfa6dec293 Initial EIP-712 utilities (#687). 2020-10-10 04:12:52 -04:00
Richard Moore
5a6d9a3a38 Added test cases for PocketProvider. 2020-10-08 21:29:14 -04:00
Richard Moore
a62d20d86f Added initial PocketProvider (#1052). 2020-10-08 20:21:32 -04:00
Richard Moore
5e0e3de52e Admin: Upddated spell-check script. 2020-10-07 20:11:34 -04:00
2773 changed files with 21825 additions and 31005 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
custom: [ 'https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2', 'https://www.buymeacoffee.com/ricmoo' ]

View File

@@ -9,7 +9,8 @@ jobs:
test-node:
runs-on: ubuntu-latest
# runs-on: ubuntu-latest
runs-on: macos-latest
strategy:
fail-fast: false
@@ -25,8 +26,8 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install node-hid requirements
run: sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev libudev-dev
# - name: Install node-hid requirements
# run: sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev libudev-dev
- name: Install dependencies (and link per package)
run: npm ci
@@ -40,7 +41,8 @@ jobs:
test-browser:
runs-on: ubuntu-latest
# runs-on: ubuntu-latest
runs-on: macos-latest
strategy:
fail-fast: false
@@ -55,8 +57,8 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install node-hid requirements
run: sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev libudev-dev
# - name: Install node-hid requirements
# run: sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev libudev-dev
- name: Install dependencies (and link per package)
run: npm ci
@@ -100,7 +102,8 @@ jobs:
name: Coverage
runs-on: ubuntu-latest
# runs-on: ubuntu-latest
runs-on: macos-latest
continue-on-error: true
@@ -112,8 +115,8 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install node-hid requirements
run: sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev libudev-dev
# - name: Install node-hid requirements
# run: sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev libudev-dev
- name: Install dependencies (and link per package)
run: npm ci

3
.gitignore vendored
View File

@@ -1,5 +1,6 @@
node_modules/
packages/*/node_modules
packages/*/lib._esm
.package_node_modules/
obsolete/
.DS_Store
@@ -24,3 +25,5 @@ packages/testcases/input/nameprep/**
.nyc_output/**
output/**
misc/testing/**

View File

@@ -3,6 +3,81 @@ Changelog
This change log is managed by `admin/cmds/update-versions` but may be manually updated.
ethers/v5.0.27 (2021-02-01 15:55)
---------------------------------
- Added support for networks with slightly incorrect EIP-658 implementations. ([#952](https://github.com/ethers-io/ethers.js/issues/952), [#1251](https://github.com/ethers-io/ethers.js/issues/1251); [e727efc](https://github.com/ethers-io/ethers.js/commit/e727efc33eaa31c3af6adbb64a893caf354d0ba7))
- Added Pocket network to the default provider. ([#1030](https://github.com/ethers-io/ethers.js/issues/1030), [#1052](https://github.com/ethers-io/ethers.js/issues/1052); [4af2c19](https://github.com/ethers-io/ethers.js/commit/4af2c19f455bb43406d3cc5421c3b3fdda75f78f))
- Added TypeScript declaration maps. ([#401](https://github.com/ethers-io/ethers.js/issues/401); [3396846](https://github.com/ethers-io/ethers.js/commit/3396846a30a4be0ed58fe449589e7e4e54f3d32e))
ethers/v5.0.26 (2021-01-13 14:47)
---------------------------------
- Fixed abundant UnhandledRejectErrors in provider polling. ([#1084](https://github.com/ethers-io/ethers.js/issues/1084), [#1208](https://github.com/ethers-io/ethers.js/issues/1208), [#1221](https://github.com/ethers-io/ethers.js/issues/1221), [#1235](https://github.com/ethers-io/ethers.js/issues/1235); [74470de](https://github.com/ethers-io/ethers.js/commit/74470defda5170338735bbbe676c207cdd5cc1cf), [20f6e16](https://github.com/ethers-io/ethers.js/commit/20f6e16394909a43498c1ac6c73152957bd121bd))
- Fixed non-checksum address comparisons in abstract Signer. ([#1236](https://github.com/ethers-io/ethers.js/issues/1236); [8175c83](https://github.com/ethers-io/ethers.js/commit/8175c83026436b6335800780ca12b7257e1b490f))
ethers/v5.0.25 (2021-01-08 03:31)
---------------------------------
- Safety check on digest length for signing. ([20335e9](https://github.com/ethers-io/ethers.js/commit/20335e96c2429e851081b72031ea3fd4cd677904))
- Fixed listenerCount for contract when requesting for all events. ([#1205](https://github.com/ethers-io/ethers.js/issues/1205); [a56a0a3](https://github.com/ethers-io/ethers.js/commit/a56a0a33366ea9276fba5bc45f1e4678dd723fa6))
- Lock package versions for the ESM builds. ([#1009](https://github.com/ethers-io/ethers.js/issues/1009); [0e6cc9a](https://github.com/ethers-io/ethers.js/commit/0e6cc9a9a8ebceae4529ccbb7c107618eb54490a))
ethers/v5.0.24 (2020-12-08 01:43)
---------------------------------
- Fixed EIP-712 getPayload dropping EIP712Domain from types for JSON-RPC calls. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [d3b1ac0](https://github.com/ethers-io/ethers.js/commit/d3b1ac046aaf2a46f6c3efbd93c55adb0cb8f16d))
- Remvoed dead files. ([70c2b1b](https://github.com/ethers-io/ethers.js/commit/70c2b1b3002f44c39f4fd87fc2cfc3f5dc6555ed))
ethers/v5.0.23 (2020-11-25 15:25)
---------------------------------
- Fix BigNumber when passed something with a length property. ([#1172](https://github.com/ethers-io/ethers.js/issues/1172); [45a2902](https://github.com/ethers-io/ethers.js/commit/45a2902874e828a16396a253548bcb00bceccf95))
ethers/v5.0.22 (2020-11-23 19:16)
---------------------------------
- Added directory to repo field for each package. ([799896a](https://github.com/ethers-io/ethers.js/commit/799896ac13cce857ce0124d2fb480f5d1eed114c))
- Add ABI coder function to compute default values. ([#1101](https://github.com/ethers-io/ethers.js/issues/1101); [a8e3380](https://github.com/ethers-io/ethers.js/commit/a8e3380ed547b6368be5fe40b48be6e31b5cdd93))
- Fix for new versions of Geth which return formatted data on revert rather than standard data. ([#949](https://github.com/ethers-io/ethers.js/issues/949); [4a8d579](https://github.com/ethers-io/ethers.js/commit/4a8d579dcaf026d0c232e20176605d34cba4767d))
- Addd missing sideEffects flag to some packages. ([20defec](https://github.com/ethers-io/ethers.js/commit/20defec9f1683487b6ea9c8730d2ab7b3745bfa5))
- Allow base-10 to be passed into BigNumbner.toString and improve errors for other radices. ([#1164](https://github.com/ethers-io/ethers.js/issues/1164); [c8bb77d](https://github.com/ethers-io/ethers.js/commit/c8bb77d8af85d2f9f9df82f1afbe7516ab296e98), [fbbe4ad](https://github.com/ethers-io/ethers.js/commit/fbbe4ad638e06089cdd976a7f4ffd51b85a31558))
- Allow private keys to Wallet to omit the 0x prefix. ([#1166](https://github.com/ethers-io/ethers.js/issues/1166); [29f6c34](https://github.com/ethers-io/ethers.js/commit/29f6c34343d75fa42023bdcd07632f49a450570c))
ethers/v5.0.21 (2020-11-19 18:52)
---------------------------------
- Force address to use bignumber package with base36 private functions. ([#1163](https://github.com/ethers-io/ethers.js/issues/1163); [c9e5480](https://github.com/ethers-io/ethers.js/commit/c9e548071e9ed03e3b12f40f0be779c16422a73f))
- Remove stray console.log in hardware wallets. ([#1136](https://github.com/ethers-io/ethers.js/issues/1136); [cc63e61](https://github.com/ethers-io/ethers.js/commit/cc63e61f73d530c28655f9421506a25fc0a49df0))
- Added some funding links for the sponsor button. ([2816850](https://github.com/ethers-io/ethers.js/commit/2816850716d4bf2b458f1db4e0c7a5dc09fb14f7))
- Remove invalid pkg.module reference. ([#1133](https://github.com/ethers-io/ethers.js/issues/1133); [cddc258](https://github.com/ethers-io/ethers.js/commit/cddc258c963ab63de426b89ef190b83aefe6f6cd))
ethers/v5.0.20 (2020-11-17 20:32)
---------------------------------
- Fix browser ws alias for WebSockets. ([02546b9](https://github.com/ethers-io/ethers.js/commit/02546b9401d8066135b4453da917f7ef49c95ad8))
- Fixing React Native tests. ([f10977a](https://github.com/ethers-io/ethers.js/commit/f10977ab35f953c3148d99b61799788f47d2a5a2), [fff72ef](https://github.com/ethers-io/ethers.js/commit/fff72ef369f5420bf8283b0808e8fec71f26dd2b))
- Refactoring dist build process. ([4809325](https://github.com/ethers-io/ethers.js/commit/4809325bee9cbdd269b099d7b12b218f441ac840), [22bd0c7](https://github.com/ethers-io/ethers.js/commit/22bd0c76dddef7134618ec70ac1b084a054e616e), [8933467](https://github.com/ethers-io/ethers.js/commit/8933467c01b64ead547d7c136f22f3c05c85ca1f))
ethers/v5.0.19 (2020-10-22 21:55)
---------------------------------
- Allow 0x as a numeric value for 0 in Provider formatter. ([#1104](https://github.com/ethers-io/ethers.js/issues/1104); [fe17a29](https://github.com/ethers-io/ethers.js/commit/fe17a295816214d063f3d6bd4f3273e0ce0c3eac))
- Use POST for long requests in EtherscanProvider. ([#1093](https://github.com/ethers-io/ethers.js/issues/1093); [28f60d5](https://github.com/ethers-io/ethers.js/commit/28f60d5ef83665541c8c1b432f8e173d73cb8227))
- Added verifyTypedData for EIP-712 typed data. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [550ecf2](https://github.com/ethers-io/ethers.js/commit/550ecf2f25b90f6d8996583489a218dbf2306ebc), [a21202c](https://github.com/ethers-io/ethers.js/commit/a21202c66b392ec6f91296d66551dffca742cf0a))
ethers/v5.0.18 (2020-10-19 01:26)
---------------------------------
- Fix signTypedData call for JsonRpcSigner. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [15a90af](https://github.com/ethers-io/ethers.js/commit/15a90af5be75806e26f589f0a3f3687c0fb1c672))
- Added EIP-712 test cases. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [1589353](https://github.com/ethers-io/ethers.js/commit/15893537c3d9c92fe8748a3e9617d133d1d5d6a7))
- Initial Signer support for EIP-712 signed typed data. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [be4e216](https://github.com/ethers-io/ethers.js/commit/be4e2164e64dfa0697561763e8079120a485a566))
- Split hash library files up. ([3e676f2](https://github.com/ethers-io/ethers.js/commit/3e676f21b00931ed966f4561e4f28792a1f8f154))
- Added EIP-712 multi-dimensional array support. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [5a4dd5a](https://github.com/ethers-io/ethers.js/commit/5a4dd5a70377d3e86823d279d6ff466d03767644))
- Consolidated TypedDataEncoder methods. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [345a830](https://github.com/ethers-io/ethers.js/commit/345a830dc4bc869d5f3edfdc27465797e7663055))
- Initial EIP-712 utilities. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [cfa6dec](https://github.com/ethers-io/ethers.js/commit/cfa6dec29314fe485df283974612d40550bc4179))
- Added initial PocketProvider. ([#1052](https://github.com/ethers-io/ethers.js/issues/1052); [a62d20d](https://github.com/ethers-io/ethers.js/commit/a62d20d86f2d545b9a7bcda5418993790b7db91c))
ethers/v5.0.17 (2020-10-07 20:08)
---------------------------------

View File

@@ -1,59 +0,0 @@
Admin Tool
==========
This tool is meant for admin tasks related to ethers.js.
Workflow
--------
After a new series of changes have been made and tested:
1. Run `npm run update-versions` to update and build all packages
2. Make any human-necessary changes to the automatically updated `CHANGELOG.md`
3. Run `git add .`
4. Run `git commit -S -m "Updated dist files."`
5. Run `git push`
6. Wait for TravisCI to complete running test cases
7. Run `npm run publish-all` to publish changed packages to NPM and tag GitHub
Update Dependency Graph: admin/cmds/update-depgraph
---------------------------------------------------
This is run as part of `npm run bootstrap` before running lerna bootstrap.
It recomputes the dependency graph and writes out the ordered
**tsconfig.project.json**
Update Versions: admin/cmds/update-versions
-------------------------------------------
Run using the `npm run update-versions`, which also cleans, bootstraps and
rebuilds the project before running the script.
For each package that has changed from the version in NPM (the published
tarballs are compared):
- Update the `version` in the **package.json**
- Update the `src.ts/_version.ts` (matches the **package.json**)
- Updates the `tarballHash` in the **package.json**
- Compiles the TypeScript (which updates the `_version.js` and `_version.d.js`)
- Lists all changed files (highlighting src.ts files)
Then:
- Generate the distribution files
- Update the `CHANGELOG.md`
Publish: admin/cmds/publish
---------------------------
Run using `npm run publish-all`. This requires a password for the secure
local config and the OTP for NPM.
- Publish (in dependency order) changed files to NPM
- The `gitHead` is updated in **only** the NPM **package.json**
- @TODO: Cut a release on GitHub including the relevant CHANGELOG entry

View File

@@ -1,111 +0,0 @@
"use strict";
const fs = require("fs");
const resolve = require("path").resolve;
const spawn = require("child_process").spawn;
const { dirnames } = require("./local");
const { loadPackage, savePackage } = require("./local");
const { loadJson, saveJson } = require("./utils");
function run(progname, args, ignoreErrorStream) {
return new Promise((resolve, reject) => {
const proc = spawn(progname, args);
let stdout = Buffer.from([]);
let stderr = Buffer.from([]);
proc.stdout.on("data", (data) => {
stdout = Buffer.concat([ stdout, data ]);
});
proc.stderr.on("data", (data) => {
stderr = Buffer.concat([ stdout, data ]);
});
proc.on("error", (error) => {
console.log("ERROR");
console.log(stderr.toString());
error.stderr = stderr.toString();
error.stdout = stdout.toString();
reject(error);
});
proc.on("close", (code) => {
if ((stderr.length && !ignoreErrorStream) || code !== 0) {
console.log("ERROR");
console.log(stderr.toString());
let error = new Error(`stderr not empty: ${ progname } ${ JSON.stringify(args) }`);
error.stderr = stderr.toString();
error.stdout = stdout.toString();
error.statusCode = code;
reject(error);
} else {
resolve(stdout.toString());
}
});
});
}
function setupConfig(outDir, moduleType, targetType) {
// Configure the tsconfit.package.json...
const path = resolve(__dirname, "../tsconfig.package.json");
const content = loadJson(path);
content.compilerOptions.module = moduleType;
content.compilerOptions.target = targetType;
saveJson(path, content);
// Configure the browser field for every pacakge, copying the
// browser.umd filed for UMD and browser.esm for ESM
dirnames.forEach((dirname) => {
let info = loadPackage(dirname);
if (info._ethers_nobuild) { return; }
if (targetType === "es2015") {
if (info["browser.esm"]) {
info.browser = info["browser.esm"];
}
} else if (targetType === "es5") {
if (info["browser.umd"]) {
info.browser = info["browser.umd"];
}
} else {
throw new Error("unsupported target");
}
savePackage(dirname, info);
let path = resolve(__dirname, "../packages", dirname, "tsconfig.json");
let content = loadJson(path);
content.compilerOptions.outDir = outDir;
saveJson(path, content);
});
}
function setupBuild(buildModule) {
if (buildModule) {
setupConfig("./lib.esm/", "es2015", "es2015");
} else {
setupConfig("./lib/", "commonjs", "es5");
}
}
function runBuild(buildModule) {
setupBuild(buildModule);
// Compile
return run("npx", [ "tsc", "--build", resolve(__dirname, "../tsconfig.project.json"), "--force" ]);
}
function runDist() {
return run("npm", [ "run", "_dist" ], true);
}
module.exports = {
run: run,
runDist: runDist,
runBuild: runBuild,
setupBuild: setupBuild
};

View File

@@ -1,145 +0,0 @@
"use strict";
const fs = require("fs");
const resolve = require("path").resolve;
const git = require("./git");
const local = require("./local");
const npm = require("./npm");
const utils = require("./utils");
const ChangelogPath = resolve(__dirname, "../CHANGELOG.md");
async function generate() {
// Get each section of the Changelog
let existing = fs.readFileSync(ChangelogPath).toString().split("\n");
let sections = [ ];
let lastLine = existing[0];
existing.slice(1).forEach((line) => {
if (line.substring(0, 5) === "=====" || line.substring(0, 5) === "-----") {
sections.push({
title: lastLine,
underline: line.substring(0, 1),
body: [ ]
});
lastLine = null;
return;
} else if (lastLine) {
sections[sections.length - 1].body.push(lastLine);
}
lastLine = line;
});
sections[sections.length - 1].body.push(lastLine);
let lastVersion = await npm.getPackageVersion("ethers");
let logs = await git.run([ "log", (lastVersion.gitHead + "..") ]);
let changes = [ ];
logs.split("\n").forEach((line) => {
if (line.toLowerCase().substring(0, 6) === "commit") {
changes.push({
commit: line.substring(6).trim(),
body: [ ]
});
} else if (line.toLowerCase().substring(0, 5) === "date:") {
changes[changes.length - 1].date = utils.getDateTime(new Date(line.substring(5).trim()));
} else if (line.substring(0, 1) === " ") {
line = line.trim();
if (line === "") { return; }
changes[changes.length - 1].body += line + " ";
}
});
// @TODO:
// ethers/version ([date](tag))
let newSection = {
title: `ethers/v${ local.loadPackage("ethers").version } (${utils.getDateTime(new Date())})`,
underline: "-",
body: [ ]
}
// Delete duplicate sections for the same version (ran update multiple times)
while (sections[1].title === newSection.title) {
sections.splice(1, 1);
}
changes.forEach((change) => {
let body = change.body.trim();
let link = body.match(/(\((.*#.*)\))/)
let commit = `[${ change.commit.substring(0, 7) }](https://github.com/ethers-io/ethers.js/commit/${ change.commit })`;
if (link) {
body = body.replace(/ *(\(.*#.*)\) */, "");
link = link[2].replace(/#([0-9]+)/g, (all, issue) => {
return `[#${ issue }](https://github.com/ethers-io/ethers.js/issues/${ issue })`;
}) + "; " + commit;
} else {
link = commit;
}
newSection.body.push(` - ${ body } (${ link })`);
});
sections.splice(1, 0, newSection);
let formatted = [ ];
sections.forEach((section) => {
formatted.push(section.title);
formatted.push(utils.repeat(section.underline, section.title.length));
formatted.push("");
section.body.forEach((line) => {
line = line.trim();
if (line === "") { return; }
if (line.substring(0, 1) === "-") {
line = "- " + line.substring(1).trim();
}
if (section.underline === "-") {
line = " " + line;
}
formatted.push(line);
});
formatted.push("");
});
return formatted.join("\n") + "\n";
}
function getChanges() {
const changes = [ ];
let lastLine = null;
fs.readFileSync(ChangelogPath).toString().split("\n").forEach((line) => {
line = line.trim();
if (line === "") { return; }
if (line.substring(0, 5) === "-----") {
changes.push({ title: lastLine, lines: [ ] });
} else if (line.substring(0, 1) === "-" && changes.length) {
changes[changes.length - 1].lines.push(line);
}
lastLine = line;
});
return changes;
}
function latestChange() {
const recent = getChanges()[0];
const match = recent.title.match(/ethers\/([^\(]*)\(([^\)]*)\)/);
return {
title: recent.title,
version: match[1].trim(),
data: match[2].trim(),
content: recent.lines.join("\n")
};
}
module.exports = {
generate: generate,
latestChange: latestChange,
ChangelogPath: ChangelogPath,
}

View File

@@ -1,142 +0,0 @@
"use strict";
const { colorify } = require("../log");
const { getIssues } = require("../github");
const { repeat } = require("../utils");
const Options = {
"body": 1,
"end": 1,
"issue": 1,
"start": 1,
"title": 1,
"user": 1,
};
const Flags = {
"open": 1,
"match-case": 1,
};
(async function() {
const options = { };
for (let i = 2; i < process.argv.length; i++) {
const option = process.argv[i];
if (option.substring(0, 2) === "--") {
const comps = option.substring(2).split(/=/);
if (Flags[comps[0]]) {
if (comps[1] != null) { throw new Error("Invalid flag: " + option); }
options[comps[0]] = true;
} else if (Options[comps[0]]) {
if (comps[1] == null) {
options[comps[0]] = process.argv[++i];
if (options[comps[0]] == null) {
throw new Error("Missing option value: " + option);
}
} else {
options[comps[0]] = comps[1];
}
} else {
throw new Error("Unexpected option: " + option);
}
} else {
throw new Error("Unexpected argument: " + option);
}
}
if (options["title"]) { options.title = new RegExp(options.title, (options["match-case"] ? "": "i")); }
if (options["body"]) { options.body = new RegExp(options.title, (options["match-case"] ? "": "i")); }
if (options["start"]) {
if (options["start"].match(/^[0-9]{4}-[0-9]{2}-[0-9{2}]$/)) {
throw new Error("Expected YYYY-MM-DD");
}
}
if (options["end"]) {
if (options["end"].match(/^[0-9]{4}-[0-9]{2}-[0-9{2}]$/)) {
throw new Error("Expected YYYY-MM-DD");
}
}
const count = { issues: 0, comments: 0, code: 0, responses: 0 };
const issues = await getIssues();
issues.forEach((issue) => {
const info = issue.issue;
const comments = issue.comments;
if (options.issue && parseInt(options.issue) != info.number) { return; }
if (options.open && info.state !== "open") { return; }
if (options.title && !info.title.match(options.title)) { return; }
if (options.body) {
const body = info.body + "\n" + comments.map((c) => (c.body)).join("\n");
if (!body.match(options.body)) {
return;
}
}
if (options.user) {
const users = comments.map((c) => (c.user.login));
users.push(info.user.login);
if (users.indexOf(options.user) === -1) {
return;
}
}
const dates = comments.map((c) => (c.created_at.split("T")[0]));
dates.push(info.created_at.split("T")[0]);
if (options.start) {
if (dates.filter((d) => (d >= options.start)).length === 0) { return; }
}
if (options.end) {
if (dates.filter((d) => (d <= options.start)).length === 0) { return; }
}
count.issues++;
console.log(colorify(repeat("=", 70), "bold"))
console.log(colorify("Issue:", "bold"), info.title, ` (#${ info.number })`);
console.log(colorify("User:","bold"), colorify(info.user.login, "blue"));
console.log(colorify("State:", "bold"), info.state);
if (info.created_at === info.updated_at) {
console.log(colorify("Created:", "bold"), info.created_at);
} else {
console.log(colorify("Created:", "bold"), info.created_at, ` (updated: ${ info.updated_at })`);
}
info.body.trim().split("\n").forEach((line) => {
console.log(" " + line);
});
if (comments.length) {
comments.forEach((info) => {
if (options.start && info.created_at < options.start) { return ; }
if (options.end && info.created_at > options.end) { return; }
count.comments++;
if (options.user && info.user.login !== options.user) { return; }
count.responses++;
if (info.body.indexOf("`") >= 0) { count.code++; }
console.log(colorify(repeat("-", 70), "bold"));
console.log(colorify("User:", "bold"), colorify(info.user.login, "green"));
if (info.created_at === info.updated_at) {
console.log(colorify("Created:", "bold"), info.created_at);
} else {
console.log(colorify("Created:", "bold"), info.created_at, ` (updated: ${ info.updated_at })`);
}
info.body.trim().split("\n").forEach((line) => {
console.log(" " + line);
});
});
}
});
console.log(colorify(repeat("=", 70), "bold"))
// @TODO: Add stats on new/closed issues
//if (options.user) {
// console.log(`${ count.responses } responses (${ count.code } w/ code) on ${ count.comments } comments across ${ count.issues } issues.`);
//} else {
console.log(`${ count.comments } comment${ (count.comments !== 1) ? "s": "" } across ${ count.issues } issue${ (count.issues !== 1) ? "s": ""}.`);
//}
})().catch((error) => {
console.log("Error: " + error.message);
});

View File

@@ -1,49 +0,0 @@
"use strict";
const { getOrdered, loadPackage } = require("../depgraph");
const { savePackage } = require("../local");
const { log } = require("../log");
(async function() {
let versions = { };
const dirnames = getOrdered();
dirnames.forEach((dirname) => {
let info = loadPackage(dirname);
if (info.name.split("/")[0] === "@ethersproject" || info.name === "ethers") {
versions[info.name] = info.version;
}
});
dirnames.forEach((dirname) => {
const info = loadPackage(dirname);
let shown = false;
["dependencies", "devDependencies"].forEach((key) => {
const deps = info[key];
if (!deps) { return; }
Object.keys(deps).forEach((name) => {
// Not a package in this monorepoa
const version = versions[name];
if (version == null) { return; }
const value = ((version.indexOf("beta") !== -1) ? ">=": "^") + version;
// No change
if (value === deps[name]) { return; }
// Show a header for the first change
if (!shown) {
log(`<bold:Locking ${ info.name }:>`);
shown = true;
}
// Show the locked version
log(` <green:${ name }>: ${ deps[name] } => <bold:${ value.replace(">", "&gt;") }>`);
deps[name] = value;
});
});
savePackage(dirname, info);
});
})();

View File

@@ -1,210 +0,0 @@
"use strict";
const { basename, resolve } = require("path");
const fs = require("fs");
const AWS = require('aws-sdk');
const config = require("../config");
const { ChangelogPath, latestChange } = require("../changelog");
const { getOrdered, loadPackage } = require("../depgraph");
const { getGitTag } = require("../git");
const { createRelease } = require("../github");
const { getPackageVersion, publish } = require("../npm");
const { log } = require("../log");
const USER_AGENT = "ethers-dist@0.0.0";
const TAG = "latest";
let dirnames = getOrdered();
// Only publish specific packages
if (process.argv.length > 2) {
let filter = process.argv.slice(2);
// Verify all named packages exist
filter.forEach((dirname) => {
try {
loadPackage(dirname);
} catch (error) {
console.log("Package not found: " + dirname);
process.exit(1);
}
});
// Filter out pacakges we don't care about
dirnames = dirnames.filter((dirname) => (filter.indexOf(dirname) >= 0));
}
function putObject(s3, info) {
return new Promise(function(resolve, reject) {
s3.putObject(info, function(error, data) {
if (error) {
reject(error);
} else {
resolve({
name: info.Key,
hash: data.ETag.replace(/"/g, '')
});
}
});
});
}
function invalidate(cloudfront, distributionId) {
return new Promise((resolve, reject) => {
cloudfront.createInvalidation({
DistributionId: distributionId,
InvalidationBatch: {
CallerReference: `${ USER_AGENT }-${ parseInt(((new Date()).getTime()) / 1000) }`,
Paths: {
Quantity: "1",
Items: [
"/\*"
]
}
}
}, function(error, data) {
if (error) {
console.log(error);
return;
}
resolve(data.Invalidation.Id);
});
});
}
(async function() {
let token = null;
const gitCommit = await getGitTag(ChangelogPath);
let includeEthers = false;
// @TODO: Fail if there are any untracked files or unchecked in files
// Load the token from the encrypted store
try {
token = await config.get("npm-token");
} catch (error) {
switch (error.message) {
case "wrong password":
log("<bold:Wrong password>");
break;
case "cancelled":
break;
default:
console.log(error);
}
log("<red:Aborting.>");
return;
}
token = token.trim().split("=");
let options = {
npmVersion: USER_AGENT,
tag: TAG
};
// Set the authentication token
options[token[0]] = token[1];
for (let i = 0; i < dirnames.length; i++) {
let dirname = dirnames[i];
if (dirname === "ethers") {
includeEthers = true;
}
let info = loadPackage(dirname);
let npmInfo = await getPackageVersion(info.name);
if (!npmInfo) { npmInfo = { version: "NEW" }; }
if (info.tarballHash === npmInfo.tarballHash) { continue; }
log(`<bold:Publishing:> ${info.name}...`);
log(` <blue:Version:> ${npmInfo.version} <bold:=\\>> ${info.version}`);
let success = await publish(dirname, options);
if (!success) {
log(" <red:FAILED! Aborting.>");
return;
}
log(" <green:Done.>");
}
// Publish the GitHub release
const beta = false;
if (includeEthers) {
// Get the latest change from the changelog
const change = latestChange();
// Publish the release to GitHub
{
// The password above already succeeded
const username = await config.get("github-user");
const password = await config.get("github-release");
// Publish the release
const link = await createRelease(username, password, change.version, change.title, change.content, beta, gitCommit);
log(`<bold:Published Release:> ${ link }`);
}
// Upload the scripts to the CDN and refresh the edge caches
{
const awsAccessId = await config.get("aws-upload-scripts-accesskey");
const awsSecretKey = await config.get("aws-upload-scripts-secretkey");
const bucketName = await config.get("aws-upload-scripts-bucket");
const originRoot = await config.get("aws-upload-scripts-root");
const distributionId = await config.get("aws-upload-scripts-distribution-id");
const s3 = new AWS.S3({
apiVersion: '2006-03-01',
accessKeyId: awsAccessId,
secretAccessKey: awsSecretKey
});
// Upload the libs to ethers-v5.0 and ethers-5.0.x
const fileInfos = [
{ filename: "packages/ethers/dist/ethers.esm.min.js", key: `ethers-${ change.version.substring(1) }.esm.min.js` },
{ filename: "packages/ethers/dist/ethers.umd.min.js", key: `ethers-${ change.version.substring(1) }.umd.min.js` },
{ filename: "packages/ethers/dist/ethers.esm.min.js", key: `ethers-5.0.esm.min.js` },
{ filename: "packages/ethers/dist/ethers.umd.min.js", key: `ethers-5.0.umd.min.js` },
];
for (let i = 0; i < fileInfos.length; i++) {
const fileInfo = fileInfos[i];
const status = await putObject(s3, {
ACL: 'public-read',
Body: fs.readFileSync(resolve(__dirname, "../../", fileInfo.filename)),
Bucket: bucketName,
ContentType: "application/javascript; charset=utf-8",
Key: (originRoot + fileInfo.key)
});
log(`<bold:Uploaded :> https://cdn.ethers.io/lib/${ fileInfo.key }`);
}
// Flush the edge caches
{
const cloudfront = new AWS.CloudFront({
//apiVersion: '2006-03-01',
accessKeyId: awsAccessId,
secretAccessKey: awsSecretKey
});
const invalidationId = await invalidate(cloudfront, distributionId);
log(`<bold:Invalidated Cache :> ${ invalidationId }`);
}
}
}
})();

View File

@@ -1,100 +0,0 @@
const fs = require("fs");
const http = require("http");
const path = require("path");
function getMime(filename) {
const comps = filename.split('.');
const ext = comps[comps.length - 1];
switch (ext.toLowerCase()) {
case 'css': return 'text/css';
case 'doctree': return 'application/x-doctree';
case 'eot': return 'application/vnd.ms-fontobject';
case 'gif': return 'image/gif';
case 'html': return 'text/html';
case 'js': return 'application/javascript';
case 'jpg': return 'image/jpeg';
case 'jpeg': return 'image/jpeg';
case 'md': return 'text/markdown';
case 'pickle': return 'application/x-pickle';
case 'png': return 'image/png';
case 'svg': return 'image/svg+xml';
case 'ttf': return 'application/x-font-ttf';
case 'txt': return 'text/plain';
case 'woff': return 'application/font-woff';
}
console.log('NO MIME', filename);
return undefined;
}
function start(root, options) {
if (root == null) { throw new Error("root required"); }
if (options == null) { options = { }; }
if (options.port == null) { options.port = 8000; }
root = path.resolve(root);
const server = http.createServer((req, resp) => {
// Follow redirects in options
if (options.redirects && options.redirects[req.url]) {
resp.writeHead(301, { Location: options.redirects[req.url] });
resp.end();
return;
}
let filename = path.resolve(root, "." + req.url);
// Make sure we aren't crawling out of our sandbox
if (req.url[0] !== "/" || filename.substring(0, filename.length) !== filename) {
resp.writeHead(403);
resp.end();
return;
}
try {
const stat = fs.statSync(filename);
if (stat.isDirectory()) {
// Redirect bare directory to its path (i.e. "/foo" => "/foo/")
if (req.url[req.url.length - 1] !== "/") {
resp.writeHead(301, { Location: req.url + "/" });
resp.end();
return;
}
filename += "/index.html";
}
const content = fs.readFileSync(filename);
resp.writeHead(200, {
"Content-Length": content.length,
"Content-Type": getMime(filename)
});
resp.end(content);
return;
} catch (error) {
if (error.code === "ENOENT") {
resp.writeHead(404, { });
resp.end();
return;
}
resp.writeHead(500, { });
resp.end();
return;
}
});
server.listen(options.port, () => {
console.log(`Server running on: http://localhost:${ options.port }`);
});
return server;
}
start(path.resolve(__dirname, "../../docs"), {
redirects: {
"/": "/v5/"
}
});

View File

@@ -1,16 +0,0 @@
"use strict";
const { prompt } = require("../../packages/cli");
const config = require("../config");
if (process.argv.length !== 3) {
console.log("Usage: set-config KEY");
process.exit(1);
}
const key = process.argv[2];
(async function() {
const value = await prompt.getPassword("Value: ");
await config.set(key, value);
})();

View File

@@ -1,146 +0,0 @@
"use strict";
// Expected this to be run after
// - npm run clean
// - npm run bootstrap
// - npm run build
const fs = require("fs");
const semver = require("semver");
const { runBuild, runDist } = require("../build");
const { ChangelogPath, generate } = require("../changelog");
const { getOrdered, loadPackage } = require("../depgraph");
const { getDiff, getStatus, getGitTag } = require("../git");
const { updatePackage } = require("../local");
const { getPackageVersion } = require("../npm");
const { resolve } = require("../utils");
const { colorify, log } = require("../log");
const { prompt } = require("../../packages/cli");
let dirnames = getOrdered();
// Only publish specific packages
if (process.argv.length > 2) {
let filter = process.argv.slice(2);
// Verify all named packages exist
filter.forEach((dirname) => {
try {
loadPackage(dirname);
} catch (error) {
console.log("Package not found: " + dirname);
process.exit(1);
}
});
// Filter out pacakges we don't care about
dirnames = dirnames.filter((dirname) => (filter.indexOf(dirname) >= 0));
}
(async function() {
let progress = prompt.getProgressBar(colorify("Updating versions", "bold"));
for (let i = 0; i < dirnames.length; i++) {
progress(i / dirnames.length);
let dirname = dirnames[i];
let path = resolve("packages", dirname);
// Get local package.json (update the tarballHash)
let info = await updatePackage(dirname);
// Get the remote package.json (or sub in a placeholder for new pacakges)
let npmInfo = await getPackageVersion(info.name);
if (!npmInfo) { npmInfo = { version: "NEW" }; }
if (info.tarballHash === npmInfo.tarballHash) { continue; }
// Bump the version if necessary
if (info.version === npmInfo.version) {
let newVersion = semver.inc(info.version, "patch");
// Write out the _version.ts
if (!info._ethers_nobuild) {
let code = "export const version = " + JSON.stringify(dirname + "/" + newVersion) + ";\n";
fs.writeFileSync(resolve(path, "src.ts/_version.ts"), code);
}
// Update the package.json (we do this after _version, so if we fail,
// this remains old; which is what triggers the version bump)
info = await updatePackage(dirname, { version: newVersion });
}
}
progress(1);
try {
log("<bold:Building TypeScript source (es6)...>");
await runBuild(true);
log("<bold:Building TypeScript source (commonjs)...>");
await runBuild(false);
log("<bold:Building distribution files...>");
let content = await runDist();
console.log(content);
} catch (error) {
console.log(error);
log("<red:Aborting.>");
return;
}
// Update the tarball hash now that _version and package.json may have changed.
progress = prompt.getProgressBar(colorify("Updating tarballHash", "bold"));
for (let i = 0; i < dirnames.length; i++) {
progress(i / dirnames.length);
await updatePackage(dirnames[i]);
}
progress(1);
// Show the changed files (compared to npm)
for (let i = 0; i < dirnames.length; i++) {
let dirname = dirnames[i];
// Get local package.json
let info = await loadPackage(dirname);
let path = resolve("packages/", dirname);
// Get the remote package.json (or sub in a placeholder for new pacakges)
let npmInfo = await getPackageVersion(info.name);
if (!npmInfo) { npmInfo = { version: "NEW" }; }
// No change
if (info.tarballHash === npmInfo.tarballHash) { continue; }
let gitHead = await getGitTag(path);
log(`<bold:Package>: ${info.name}`);
log(` <green:Tarball Changed:> (bumping version)`);
log(` ${npmInfo.version} => ${info.version}`)
log(` <blue:Changed:>`);
let filenames = await getDiff(path, npmInfo.gitHead, true);
filenames.forEach((filename) => {
let short = filename.split("/").slice(1).join("/");
if (short.indexOf("/src.ts/") >= 0 || short.indexOf("/dist/") >= 0) {
log(` <bold:${short}>`);
} else {
log(` ${short}`);
}
});
log("");
}
let existing = fs.readFileSync(ChangelogPath).toString();
let changelog = await generate();
if (existing !== changelog) {
let changelogStatus = await getStatus(ChangelogPath);
if (changelogStatus !== "unmodified") {
log("<bold:WARNING:> There are local changes to the CHANGELOG (they will be discarded)");
console.log(existing);
}
log("<bold:Updating CHANGELOG>...");
fs.writeFileSync(ChangelogPath, changelog);
}
})();

View File

@@ -1,120 +0,0 @@
"use strict";
const fs = require("fs");
const os = require("os");
const resolve = require("path").resolve;
const AES = require("aes-js");
const scrypt = require("scrypt-js");
const { prompt } = require("../packages/cli");
const randomBytes = require("../packages/random").randomBytes;
const computeHmac = require("../packages/sha2").computeHmac;
const colorify = require("./log").colorify;
function getScrypt(message, password, salt) {
let progressBar = prompt.getProgressBar(message);
return scrypt.scrypt(Buffer.from(password), Buffer.from(salt), (1 << 17), 8, 1, 64, progressBar);
}
function Config(filename) {
this.salt = null;
this.dkey = null;
this.values = { };
this.canary = "";
this.filename = filename;
}
Config.prototype.load = async function() {
if (this.dkey) { return; }
let data = null;
if (fs.existsSync(this.filename)) {
data = JSON.parse(fs.readFileSync(this.filename));
} else {
data = {
salt: Buffer.from(randomBytes(32)).toString("hex")
};
}
this.canary = data.canary || "";
this.salt = data.salt;
const password = await prompt.getPassword(colorify("Password (config-store): ", "bold"));
this.dkey = await getScrypt(colorify("Unlocking config", "bold"), password, this.salt);
if (data.ciphertext) {
const ciphertext = Buffer.from(data.ciphertext, "base64");
const iv = Buffer.from(data.iv, "base64");
const aes = new AES.ModeOfOperation.ctr(this.dkey.slice(0, 32), new AES.Counter(iv));
const plaintext = aes.decrypt(ciphertext);
const hmac = computeHmac("sha512", this.dkey.slice(32, 64), plaintext);
if (hmac !== data.hmac) {
throw new Error("wrong password");
}
this.values = JSON.parse(Buffer.from(plaintext).toString());
}
};
Config.prototype.keys = async function() {
await this.load();
return Object.keys(this.values);
}
Config.prototype.save = function() {
this.values._junk = Buffer.from(randomBytes(16 + parseInt(Math.random() * 48))).toString("base64")
const plaintext = Buffer.from(JSON.stringify(this.values));
const iv = Buffer.from(randomBytes(16));
const hmac = computeHmac("sha512", this.dkey.slice(32, 64), plaintext);
const aes = new AES.ModeOfOperation.ctr(this.dkey.slice(0, 32), new AES.Counter(iv));
const ciphertext = Buffer.from(aes.encrypt(plaintext));
const data = {
ciphertext: ciphertext.toString("base64"),
iv: iv.toString("base64"),
salt: this.salt,
hmac: hmac,
canary: this.canary
};
fs.writeFileSync(this.filename, JSON.stringify(data, null, 2));
}
Config.prototype.get = async function(key) {
await this.load();
return this.values[key];
};
Config.prototype.set = async function(key, value) {
await this.load();
this.values[key] = value;
this.save();
};
Config.prototype.lock = function() {
this.salt = this.dkey = null;
}
const config = new Config(resolve(os.homedir(), ".ethers-dist"));
module.exports = {
get: function(key) {
return config.get(key);
},
set: function(key, value) {
config.set(key, value);
},
keys: function() {
return config.keys();
},
lock: function() {
config.lock();
}
}

View File

@@ -1,94 +0,0 @@
"use strict";
const fs = require("fs");
const { loadJson, resolve } = require("./utils");
const ROOT = resolve("packages");
const dirnames = fs.readdirSync(ROOT);
function loadPackage(dirname) {
return loadJson(resolve("packages", dirname, "package.json"));
}
function getOrdered(skipNobuild) {
let packages = { };
let filenames = { };
let addDeps = (name, depends) => {
Object.keys(depends).forEach((dep) => {
// Not a package we manage
if (packages[dep] == null) { return; }
deps[name][dep] = true;
});
}
for (let i = 0; i < dirnames.length; i++) {
let dirname = dirnames[i];
let info = loadPackage(dirname);
if (skipNobuild && info._ethers_nobuild) { continue; }
packages[info.name] = info;
filenames[info.name] = dirname;
}
// Maps names to list of dependencies; { [ name:string]: Array<name: string> }
let deps = { };
let depGraph = { };
Object.keys(packages).forEach((name) => {
let info = packages[name];
deps[info.name] = { };
addDeps(info.name, info.dependencies || { });
addDeps(info.name, info.devDependencies || { });
deps[info.name] = Object.keys(deps[info.name]);
deps[info.name].sort();
});
let ordered = [ ];
let remaining = Object.keys(deps);
let isSatisfied = (name) => {
for (let i = 0; i < deps[name].length; i++) {
if (ordered.indexOf(deps[name][i]) === -1) { return false; }
}
return true;
}
while (remaining.length) {
let bail = true;
for (let i = 0; i < remaining.length; i++) {
if (!isSatisfied(remaining[i])) { continue; }
bail = false;
ordered.push(remaining[i]);
remaining.splice(i, 1);
break;
}
if (bail) {
throw new Error("Nothing processed; circular dependencies...");
}
}
return ordered.map((name) => filenames[name]);
}
function sort(dirnames) {
let ordered = getOrdered();
dirnames.sort((a, b) => {
let ai = ordered.indexOf(local.loadPackage(a).name);
let bi = ordered.indexOf(local.loadPackage(b).name);
if (ai === -1 || bi === -1) {
throw new Error("unknown dirname - " + [a, b].join(", "));
}
return ai - bi;
});
}
module.exports = {
dirnames: dirnames,
getOrdered: getOrdered,
loadPackage: loadPackage,
ROOT: ROOT,
sort: sort
}

View File

@@ -1,186 +0,0 @@
"use strict";
const resolve = require("path").resolve;
const spawn = require("child_process").spawn;
const semver = require("semver");
const { run } = require("./build");
const { loadPackage } = require("./local");
function git(args) {
return run("git", args);
}
function getStatus(filename) {
return git([ "status", "-s", resolve(__dirname, "..", filename) ]).then((result) => {
result = result.trim();
if (result === "") { return "unmodified"; }
switch (result.substring(0, 2)) {
case 'M ': return "modified";
case 'A ': return "added";
case 'D ': return "deleted";
case 'R ': return "renamed";
case 'C ': return "copied";
case 'U ': return "updated";
case '??': return "untracked";
}
console.log(result);
return "unknown";
});
}
async function getChanges(latest) {
let diff = await git(["diff", "--name-only", latest ]);
// Map dirname => { dist: [ ], src: [ ] }
let changes = { "_": { filename: "_", dist: [], src: [] } };
diff.split("\n").forEach((line) => {
// e.g. packages/constants/index.d.ts
let comps = line.trim().split("/");
// Track non-packages as dist
if (comps.length < 2 || comps[0] !== "packages") {
let filename = comps.join("/").trim();
if (filename === "") { return; }
changes._.dist.push(filename);
return;
}
let name = loadPackage(comps[1]).name;
let change = changes[name];
if (!change) {
change = { filename: comps[1], dist: [ ], src: [ ] }
changes[name] = change;
}
// Split changes into source changes (src.ts/) or dist changes (output of TypeScript)
if (comps[2] === "src.ts") {
change.src.push(comps.join("/"));
} else {
change.dist.push(comps.join("/"));
}
});
return changes;
}
function getLatestTag() {
let seq = Promise.resolve();
// @TODO: Pull
if (false) {
seq = seq.then(() => {
console.log("Pulling remote changes...");
return git([ "pull" ]);
});
}
seq = seq.then(() => {
return git([ "tag" ]).then((tags) => {
tags = tags.split("\n").filter(tag => (tag.match(/^v[0-9]+\.[0-9]+\.[0-9]+\-/)));
tags.sort(semver.compare)
return tags.pop();
});
});
return seq;
}
function findChanges(latest) {
let seq = Promise.resolve();
seq = seq.then(() => {
return git(["diff", "--name-only", latest, "HEAD" ]).then((result) => {
let filenames = { };
result.split("\n").forEach((line) => {
// e.g. packages/constants/index.d.ts
let comps = line.trim().split("/");
if (comps.length < 2) { return; }
filenames[comps[1]] = true;
});
return Object.keys(filenames);
});
});
seq = seq.then((filenames) => {
return filenames.map((filename) => {
let name = packages[filename].name;
return {
filename: filename,
name: name,
localVersion: getLocalVersion(name),
}
});
});
seq = seq.then((packages) => {
let seq = Promise.resolve();
packages.forEach((p) => {
seq = seq.then(() => {
return getNpmVersion(p.name).then((version) => {
p.npmVersion = version;
});
});
});
return seq.then(() => packages);
});
return seq;
}
async function getGitTag(filename) {
let result = await git([ "log", "-n", "1", "--", filename ]);
result = result.trim();
if (!result) { return null; }
result = result.match(/^commit\s+([0-9a-f]{40})\n/i);
if (!result) { return null; }
return result[1];
}
async function getDiff(filename, tag, nameOnly) {
if (tag == null) { tag = "HEAD"; }
let cmd = [ "diff", "--name-only", tag, "--", filename ]
if (!nameOnly) { cmd.splice(1, 1); }
try {
let result = await git(cmd);
result = result.trim();
if (result === "") { return [ ]; }
return result.split("\n");
} catch (error) {
// This tag does not exist, so compare against beginning of time
// This happens when there is a new history (like an orphan branch)
if (error.stderr.trim().match(/^fatal: bad object/)) {
console.log("Could not find history; showing all");
let cmd = [ "rev-list", "--max-parents=0", "HEAD" ];
let tag = await git(cmd);
return getDiff(filename, tag.trim(), nameOnly);
}
throw error;
}
}
async function getUntracked(filename) {
let cmd = [ "ls-files", "-o", "--exclude-standard"];
if (filename) {
cmd.push("--");
cmd.push(filename);
}
let result = await git(cmd);
result = result.trim();
if (result === "") { return [ ]; }
return result.split("\n");
}
module.exports = {
findChanges: findChanges,
getChanges: getChanges,
getDiff: getDiff,
getGitTag: getGitTag,
getLatestTag: getLatestTag,
getStatus: getStatus,
getUntracked: getUntracked,
run: git,
}

View File

@@ -1,162 +0,0 @@
"use strict";
const fs = require("fs");
const { resolve } = require("path");
const zlib = require("zlib");
const { id } = require("../packages/hash");
const { fetchJson } = require("../packages/web");
const CacheDir = resolve(__dirname, "../github-cache/");
function addResponse(result, response) {
return { result, response };
}
function loadFile(filename) {
return JSON.parse(zlib.gunzipSync(fs.readFileSync(filename)).toString());
//return JSON.parse(fs.readFileSync(filename).toString());
}
// @TODO: atomic
function saveFile(filename, content) {
fs.writeFileSync(filename, zlib.gzipSync(JSON.stringify(content)));
//fs.writeFileSync(filename, JSON.stringify(content));
}
function mockFetchJson(url, body, headers) {
return {
result: null,
response: {
statusCode: 304
}
}
}
async function _fetchGitHub(user, password, fetchJson, url) {
const result = [ ];
while (true) {
const filename = resolve(CacheDir, id(url).substring(2, 14));
const headers = {
"User-Agent": "ethers-io",
};
let items = null;
let link = null;
try {
const data = loadFile(filename);
headers["if-none-match"] = data.etag;
items = data.items;
link = data.link;
} catch (error) {
if (error.code !== "ENOENT") { throw error; }
}
const fetch = await fetchJson({
url: url,
user: user,
password: password,
headers: headers
}, null, addResponse);
// Cached response is good; use it!
if (fetch.response.statusCode !== 304) {
items = fetch.result;
if (fetch.response.headers) {
link = (fetch.response.headers.link || null);
}
if (fetch.response.headers.etag){
saveFile(filename, {
timestamp: (new Date()).getTime(),
url: url,
link: link,
etag: fetch.response.headers.etag,
items: items,
version: 1
});
}
}
items.forEach((item) => { result.push(item)});
url = null;
(link || "").split(",").forEach((item) => {
if (item.indexOf('rel="next"') >= 0) {
const match = item.match(/<([^>]*)>/);
if (match) { url = match[1]; }
}
});
if (!url) { break; }
}
return result;
}
async function fetchGitHub(user, password, url, cacheOnly) {
if (cacheOnly) {
return await _fetchGitHub("none", "none", mockFetchJson, url);
}
const results = await _fetchGitHub(user, password, fetchJson, url);
return results;
}
async function _getIssues(user, password) {
const cacheOnly = (user == null);
let issues = await fetchGitHub(user, password, "https:/\/api.github.com/repos/ethers-io/ethers.js/issues?state=all&per_page=100", cacheOnly)
if (!cacheOnly) { console.log(`Found ${ issues.length } issues`); }
const result = [ ];
for (let i = 0; i < issues.length; i++) {
const issue = issues[i];
let comments = await fetchGitHub(user, password, issue.comments_url, cacheOnly);
result.push({ issue, comments});
if (!cacheOnly) { console.log(` Issue ${ issue.number }: ${ comments.length } comments`); }
}
result.sort((a, b) => (a.issue.number - b.issue.number));
return result;
}
function getIssues() {
return _getIssues();
}
function syncIssues(user, password) {
return _getIssues(user, password);
}
async function createRelease(user, password, tagName, title, body, prerelease, commit) {
const payload = {
tag_name: tagName,
target_commitish: (commit || "master"),
name: title,
body: body,
//draft: true,
draft: false,
prerelease: !!prerelease
};
const headers = {
"User-Agent": "ethers-io",
};
const result = await fetchJson({
url: "https://api.github.com/repos/ethers-io/ethers.js/releases",
user: user,
password: password,
headers: headers
}, JSON.stringify(payload));
return result.html_url;
}
module.exports = {
getIssues,
syncIssues,
createRelease,
}

View File

@@ -1,401 +0,0 @@
"use strict";
const fs = require("fs");
const resolve = require("path").resolve;
const diff = require("diff");
const semver = require("semver");
const { prompt } = require("../packages/cli");
const build = require("./build");
const changelog = require("./changelog");
const depgraph = require("./depgraph");
const { colorify, colorifyStatus, log } = require("./log");
const config = require("./config")
const git = require("./git");
const local = require("./local");
const npm = require("./npm");
const utils = require("./utils");
/*
async function runChanged(dirnames, callback) {
try {
await callback(dirname, info, npmInfo);
} catch (error) {
console.log(error);
console.log(colorify("Aborting! " + error.message));
return;
}
}
}
}
*/
/*
if (diff) {
} else {
*/
async function runDiff(dirnames) {
// Default to all packages
if (dirnames == null || dirnames.length === 0) { dirnames = local.dirnames; }
for (let i = 0; i < dirnames.length; i++) {
let dirname = dirnames[i];
// Get local (update the tarballHash) and remote package.json
let info = await local.loadPackage(dirname);
let npmInfo = await npm.getPackageVersion(info.name);
if (!npmInfo) { npmInfo = { gitHead: "HEAD", version: "NEW" }; }
let delta = await git.getDiff(resolve(__dirname, "../packages", dirname), npmInfo.gitHead);
if (delta.length === 0) { continue; }
// Bump the version if necessary
if (info.version === npmInfo.version) {
info.version = semver.inc(info.version, "patch");
}
console.log(colorify("<bold:Package>: ") + info.name);
console.log(colorify(" <green:Git Head Changed:> (run update to bump version)"));
console.log(" " + npmInfo.gitHead)
console.log(" " + npmInfo.version + colorify(" => ", "bold") + info.version)
console.log(colorify(" Diff", "bold"));
delta.forEach((line) => {
let color = "blue";
switch (line.substring(0, 1)) {
case '+':
color = "green";
break;
case '-':
color = "red";
break;
case ' ':
color = "normal";
break;
}
console.log(" " + colorify(line, color));
});
console.log("");
}
console.log("");
}
async function updateChangelog() {
let filename = resolve(local.ROOT, "../CHANGELOG.md");
let lastVersion = await git.getLatestTag();
let newVersion = "v" + local.getVersion("ethers");
let current = fs.readFileSync(filename).toString();
let log = await changelog.generate();
if (log === current) { return; }
let changes = diff.createTwoFilesPatch("CHANGELOG-old.md", "CHANGELOG.md", current, log, lastVersion, newVersion);
console.log(changes);
try {
let response = await prompt.getChoice(colorify("Accept changes?", "bold"), "yn", "n");
if (response === "n") { throw new Error("Not changing."); }
} catch (error) {
console.log("Abort: " + error.message);
return;
}
fs.writeFileSync(filename, log);
}
// Updates the dependency-graph (tsconfig.project.json) so the build order is correct
async function runUpdateDepgraph() {
log(`<bold:Updating dependency-graph build order (tsconfig.project.json)...>`);
let ordered = depgraph.getOrdered();
let path = resolve(local.ROOT, "../tsconfig.project.json")
let projectConfig = local.loadJson(path);
projectConfig.references = ordered.map((name) => ({ path: ("./packages/" + name) }));
local.saveJson(path, projectConfig);
}
async function runUpdate(dirnames) {
// Check for untracked files...
let untracked = [ ];
if (dirnames == null || dirnames.length === 0) {
dirnames = local.dirnames;
let filenames = await git.getUntracked(resolve(__dirname, ".."));
for (let i = 0; i < filenames.length; i++) {
untracked.push(filenames[i]);
}
} else {
for (let i = 0; i < dirnames.length; i++) {
let filenames = await git.getUntracked(resolve(local.ROOT, dirnames[i]));
for (let j = 0; j < filenames.length; j++) {
untracked.push(filenames[j]);
}
}
}
// Untracked files! Abort.
if (untracked.length) {
log("<bold:Untracked Files:>");
untracked.forEach((filename) => {
console.log(" " + filename);
});
log("<red:Aborting.>");
return;
}
log(`<bold:Run TypeScript build...>`);
await build.runBuild()
log("");
// @TODO: Root
// Update all the package.json and _version.ts
let progress = prompt.getProgressBar(colorify("Updating versions", "bold"));
for (let i = 0; i < dirnames.length; i++) {
progress(i / dirnames.length);
let dirname = dirnames[i];
let path = resolve(__dirname, "../packages/", dirname);
// Get local package.json (update the tarballHash)
let info = await local.updatePackage(dirname);
// Get the remote package.json (or sub in a placeholder for new pacakges)
let npmInfo = await npm.getPackageVersion(info.name);
if (!npmInfo) { npmInfo = { version: "NEW" }; }
if (info.tarballHash === npmInfo.tarballHash) { continue; }
// Bump the version if necessary
if (info.version === npmInfo.version) {
let newVersion = semver.inc(info.version, "patch");
// Write out the _version.ts
if (!info._ethers_skipPrepare) {
let code = "export const version = " + JSON.stringify(newVersion) + ";\n";
fs.writeFileSync(resolve(path, "src.ts/_version.ts"), code);
}
// Update the package.json (we do this after _version, so if we fail,
// this remains old; which is what triggers the version bump)
info = await local.updatePackage(dirname, { version: newVersion });
}
}
progress(1);
// Build the TypeScript sources
log("<bold:Runing TypeScript build...>");
try {
await build.runTsc();
} catch (error) {
console.log(error);
log("<red:Aborting.>");
return;
}
// Run the dist
// @TODO:
// Update the tarball hash now that _version and package.json may have changed.
progress = prompt.getProgressBar(colorify("Updating tarballHash", "bold"));
for (let i = 0; i < dirnames.length; i++) {
progress(i / dirnames.length);
await local.updatePackage(dirnames[i]);
}
progress(1);
// Show the changed files (compared to npm)
for (let i = 0; i < dirnames.length; i++) {
let dirname = dirnames[i];
// Get local package.json
let info = await local.loadPackage(dirname);
let path = resolve(__dirname, "../packages/", dirname);
// Get the remote package.json (or sub in a placeholder for new pacakges)
let npmInfo = await npm.getPackageVersion(info.name);
if (!npmInfo) { npmInfo = { version: "NEW" }; }
// No change
if (info.tarballHash === npmInfo.tarballHash) { continue; }
let gitHead = await git.getGitTag(path);
log(`<bold:Package>: ${info.name}`);
log(` <green:Tarball Changed:> (bumping version)`);
log(` ${npmInfo.version} => ${info.version}`)
log(` <blue:Changed:>`);
let filenames = await git.getDiff(resolve(__dirname, "../packages", dirname), npmInfo.gitHead, true);
filenames.forEach((filename) => {
let short = filename.split("/").slice(1).join("/");
if (short.indexOf("/src.ts/") >= 0) {
log(` <bold:${short}>`);
} else {
log(` ${short}`);
}
});
log("");
}
// @TODO: Changelog
await updateChangelog();
}
async function runAdd(type, names) {
let latest = await git.getLatestTag();
console.log("");
console.log(colorify("<bold:Latest Published>: ") + latest);
console.log("");
let changes = await git.getChanges("HEAD");
if (!names || names.length === 0) {
names = Object.keys(changes);
}
let filenames = [ ];
for (let i = 0; i < names.length; i++) {
let name = names[i];
let change = changes[name] || changes[(packages[name] || {}).name];
if (!change) { return; }
change[type].forEach((filename) => {
filenames.push(filename);
});
}
if (filenames.length === 0) {
console.log(colorify("<bold:Nothing to add.>"));
console.log("");
return;
}
for (let i = 0; i < filenames.length; i++) {
let filename = filenames[i];
let status = await git.getStatus(filename);
console.log(" " + colorifyStatus(status) + ": " + utils.repeat(" ", 10 - status.length) + filename);
}
console.log("");
try {
let response = await prompt.getChoice(colorify("Add these files?", "bold"), "yn", "n");
if (response === "n") { throw new Error("Not adding."); }
} catch (error) {
console.log("Abort: " + error.message);
return;
}
let params = filenames.map((f) => f); //resolve(ROOT, f));
params.unshift("--");
params.unshift("add");
console.log("git " + params.join(" "));
try {
await git.run(params);
} catch (error) {
console.log("Error: (status: " + error.code + ")");
console.log(" " + error.stderr);
return;
}
console.log("Added.");
}
function runDist() {
// Run npm dist
// Generate changelog
// run status to update all the package
// add dist files?
}
async function runPublish(dirnames) {
// @TODO: Make sure there are no staged files
// @TODO: Make sure the repo has been pushed
// @TODO: Run the publish in the correct order
// Get the authentication token from our encrypted store
let token = await config.get("token");
token = token.trim().split("=");
let options = {
npmVersion: "ethers-dist@0.0.0",
tag: "next"
};
// Set the authentication token
options[token[0]] = token[1];
if (dirnames == null || dirnames.length === 0) { dirnames = local.dirnames; }
depgraph.sort(dirnames);
await runChanged(dirnames, async (dirname, info, npmInfo) => {
console.log(colorify("<bold:Publishing:> ") + info.name + "...")
console.log(colorify(" Version: ", "blue") + npmInfo.version + colorify(" => ", "bold") + info.version);
let success = await npm.publish(dirname, options);
if (!success) {
console.log(colorify(" <red:FAILED! Aborting.>"));
throw new Error("");
}
console.log(colorify(" <green:Done.>"));
});
}
async function runTest() {
let r = await git([ "tag", "--porcelain", "-a", "-m", "Title of Release\n\nHello\n-----\n\nTesting 4 **bold** #1\nHello World", "test6", "HEAD" ]);
console.log(r);
try {
r = await git([ "push", "--tags" ])
} catch(e) { console.log(e); }
console.log(r);
}
(function() {
let args = process.argv.slice(2);
switch (args[0]) {
// Compare published to current stage
case "diff":
return runDiff(args.slice(1));
// Add unchecked-in source files
case "add-source":
return runAdd("src", args.slice(1));
// Update all package.json. the changelog and dist files
case "update":
return runUpdate(args.slice(1));
// Update dependency graph (./tsconfig-project.json)
case "update-depgraph":
return runUpdateDepgraph();
// Add unchecked-in dist files
case "add-dist":
return runAdd("dist", args.slice(1));
// Add unchecked-in source files
case "changelog":
return updateChangelog();
// Add unchecked-in source files
case "publish":
return runPublish(args.slice(1));
case "test":
return runTest();
}
})();

View File

@@ -1,101 +0,0 @@
"use strict";
const packlist = require("npm-packlist");
const tar = require("tar");
const keccak256 = (function() {
try {
return require("../packages/keccak256").keccak256;
} catch (error) {
console.log("Cannot load Keccak256 (maybe not built yet? Not really a problem for most things)");
return null;
}
})();
const { dirnames, loadPackage, ROOT } = require("./depgraph");
const { resolve, saveJson } = require("./utils");
function sorted(obj) {
if (Array.isArray(obj)) { return obj.map(sorted); }
if (obj == null || typeof(obj) !== "object") { return obj; }
const keys = Object.keys(obj);
keys.sort();
const result = { };
keys.forEach((key) => { result[key] = sorted(obj[key]); });
return result;
}
function savePackage(dirname, info) {
return saveJson(resolve(ROOT, dirname, "package.json"), sorted(info));
}
async function createTarball(dirname) {
let base = resolve(ROOT, dirname);
// From NPM publish, create the packed version
let files = await packlist({ path: base });
files = files.map((f) => ("./" + f));
let options = {
cwd: base,
prefix: 'package/',
portable: true,
sync: true,
// Provide a specific date in the 1980s for the benefit of zip,
// which is confounded by files dated at the Unix epoch 0.
mtime: new Date('1985-10-26T08:15:00.000Z'),
gzip: true
};
// Take the hash of the package sans
return tar.create(options, files).read();
}
async function updatePackage(dirname, values) {
let info = loadPackage(dirname);
if (values) {
for (let key in values) {
info[key] = values[key];
}
}
/*
["dependencies", "devDependencies"].forEach((key) => {
let deps = info[key] || [];
for (let name in deps) {
if (name.substring(0, "@ethersproject".length) === "@ethersproject" || name === "ethers") {
deps[name] = ">5.0.0-beta.0";
}
}
});
*/
//if (dirname !== "ethers") {
// delete info.publishConfig.tag;
//}
// Create a normalized version sans tarballHash to compute the tarballHash
delete info.tarballHash;
savePackage(dirname, info);
// Compute the tarballHash
let tarball = await createTarball(dirname);
info.tarballHash = keccak256(tarball);
// Save the updated package.json to disk
savePackage(dirname, info);
return info;
}
module.exports = {
ROOT: ROOT,
createTarball: createTarball,
dirnames: dirnames,
getVersion: function(dirname) { return ((loadPackage(dirname) || {}).version || null); },
loadPackage: loadPackage,
savePackage: savePackage,
updatePackage: updatePackage,
}

View File

@@ -1,53 +0,0 @@
"use strict";
function getColor(color) {
if (!color || color === "normal") { return "\x1b[0m"; }
return "\x1b[1m" + ({
blue: "\x1b[34m",
cyan: "\x1b[36m",
green: "\x1b[32m",
magenta: "\x1b[35m",
red: "\x1b[31m",
yellow: "\x1b[33m",
bold: ""
})[color];
}
// See: https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color
let disableColor = !(process.stdout.isTTY);
function colorify(message, color) {
if (color) {
if (disableColor) { return message; }
return getColor(color) + message + getColor();
}
return message.replace(/<([^:]*):((?:[^<>\\]|\\.)*)>/g, (all, color, message) => {
message = message.replace("\\>", ">");
if (disableColor) { return message; }
return getColor(color) + message + getColor();
});
}
function colorifyStatus(status) {
switch (status) {
case "modified": return colorify("<blue:" + status + ">");
case "added": return colorify("<green:" + status + ">");
case "deleted": return colorify("<red:" + status + ">");
case "unmodified": return colorify("<magenta:" + status + ">");
}
return status;
}
function log(message, color) {
if (color) {
console.log(colorify(message, color));
} else {
console.log(colorify(message));
}
}
module.exports = {
colorify: colorify,
colorifyStatus: colorifyStatus,
log: log
}

View File

@@ -1,104 +0,0 @@
"use strict";
const resolve = require("path").resolve;
const npmpub = require("libnpmpublish");
const semver = require("semver");
const local = require("./local");
const keccak256 = require("../packages/keccak256").keccak256;
const fetchJson = require("../packages/web").fetchJson;
const { prompt } = require("../packages/cli");
const colorify = require("./log").colorify;
const git = require("./git");
let cache = { };
async function getPackage(name) {
if (cache[name]) { return cache[name]; }
return fetchJson("http:/" + "/registry.npmjs.org/" + name).then((result) => {
cache[name] = result;
return result;
}, (error) => {
if (error.status === 404) {
return null;
}
throw error;
});
}
async function getVersion(name) {
return getPackage(name).then((result) => {
if (!result) { return null; }
let versions = Object.keys(result.versions);
versions.sort(semver.compare)
return versions.pop();
});
}
async function getPackageVersion(name, version) {
let info = await getPackage(name)
if (!info) { return null; }
if (version == null) {
let versions = Object.keys(info.versions);
versions.sort(semver.compare);
version = versions.pop();
}
return info.versions[version] || null;
}
async function getTarballHash(name, version) {
let info = await getPackageVersion(name, version);
return (info || {}).tarballHash;
}
async function _publish(info, tarball, options) {
try {
let result = await npmpub.publish(info, tarball, options);
return result;
} catch (error) {
// We need an OTP
if (error.code === "EOTP") {
try {
let otp = await prompt.getMessage(colorify("Enter OTP: ", "bold"));
options.otp = otp.replace(" ", "");
} catch (error) {
// CTRL-C
if (error.message === "cancelled") {
return false;
}
// Something unexpected...
throw error;
}
// Retry with the new OTP
return _publish(info, tarball, options);
}
throw error;
}
}
async function publish(dirname, options) {
let info = local.loadPackage(dirname);
info.gitHead = await git.getGitTag(resolve(__dirname, "../packages/", dirname));
if (info.gitHead == null) { throw new Error("no git tag found - " + dirname); }
let tarball = await local.createTarball(dirname);
return _publish(info, tarball, options);
}
module.exports = {
getPackage: getPackage,
getPackageVersion: getPackageVersion,
getTarballHash: getTarballHash,
getVersion: getVersion,
publish: publish,
};

View File

@@ -1,50 +0,0 @@
{
"name": "DevelopmentChain",
"engine": {
"instantSeal": null
},
"params": {
"gasLimitBoundDivisor": "0x0400",
"accountStartNonce": "0x0",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x11",
"registrar" : "0x0000000000000000000000000000000000001337",
"maxCodeSize": 24576,
"maxCodeSizeTransition": "0x0",
"eip98Transition": "0x7fffffffffffff",
"eip140Transition": "0x0",
"eip145Transition": "0x0",
"eip150Transition": "0x0",
"eip155Transition": "0x0",
"eip160Transition": "0x0",
"eip161abcTransition": "0x0",
"eip161dTransition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
"eip658Transition": "0x0",
"wasmActivationTransition": "0x0"
},
"genesis": {
"seal": {
"generic": "0x0"
},
"difficulty": "0x20000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x7A1200"
},
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
"0x7454a8f5a7c7555d79b172c89d20e1f4e4cc226c": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
}
}

View File

@@ -1 +0,0 @@
{"id":"24d70b97-fff9-d322-e760-4b8cc2e21751","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"45d392cd16dbbd5c0f5b2d145c112da9"},"ciphertext":"b001ccd09fc5431dc055975b58ee61f86e85529245506c04182c902716e750e5","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"028594da27a0e864105f33b912e5dc6ce7c75ecd13c81bfc158fe963d30c93bb"},"mac":"374bf2e9144b74b889708abc19e9ebc164f90bc27e83fd9f01da4571a9f81a70"},"address":"7454a8f5a7c7555d79b172c89d20e1f4e4cc226c","name":"","meta":"{}"}

View File

@@ -1,64 +0,0 @@
"use strict";
const fs = require("fs");
const _resolve = require("path").resolve;
function repeat(chr, length) {
let result = chr;
while (result.length < length) { result += chr; }
return result;
}
function zpad(value) {
value = String(value);
while (value.length < 2) { value = "0" + value; }
return value;
}
function getDate(date) {
return [
date.getFullYear(),
zpad(date.getMonth() + 1),
zpad(date.getDate())
].join("-");
}
function getDateTime(date) {
return getDate(date) + " " + [
zpad(date.getHours()) ,
zpad(date.getMinutes() + 1)
].join(":");
}
function today() {
return getDate(new Date());
}
function loadJson(filename) {
return JSON.parse(fs.readFileSync(filename).toString());
}
// @TODO: atomic write
function saveJson(filename, json) {
fs.writeFileSync(filename, JSON.stringify(json, null, 2) + "\n");
}
function resolve(...args) {
args = args.slice();
args.unshift("..");
args.unshift(__dirname);
return _resolve.apply(null, args);
}
module.exports = {
resolve: resolve,
loadJson: loadJson,
saveJson: saveJson,
repeat: repeat,
today: today,
getDate: getDate,
getDateTime: getDateTime
}

View File

@@ -10,7 +10,7 @@ permissions.
The ethers library offers default API keys for each service, so that each
[[Provider]] works out-of-the-box.
These API keys are a provided as a community resource by the backend services
These API keys are provided as a community resource by the backend services
for low-traffic projects and for early prototyping.
Since these API keys are shared by all users (that have not acquired their
@@ -43,7 +43,7 @@ operations required to interact with the Ethereum Blockchain.
_subsection: INFURA @<api-keys--infura>
The INFURA service has been around for quite some time and is very robust
and reliable and highly recommend.
and reliable and highly recommended.
They offer a standard JSON-RPC interface and a WebSocket interface, which makes
interaction with standard tools versatile, simple and straight forward.
@@ -74,6 +74,18 @@ with debugging.
- access to advanced token balance and metadata APIs
- access to advanced debugging trace and revert reason APIs
_subsection: Pocket Gateway@<api-keys--pocket-gateway>
[Sign up for a free API key on Pocket](link-pocket-signup)
**Benefits:**
- customer usage metrics
- decentralized Access to Blockchain Infrastructure
- Stake as opposed to paying a monthly fee
- Highly redundant global set of nodes incentivized by cryptoeconomic incentives
_subsection: Creating a Default Provider @<api-keys--getDefaultProvider>
@@ -99,5 +111,16 @@ const network = "homestead";
const provider = ethers.getDefaultProvider(network, {
etherscan: YOUR_ETHERSCAN_API_KEY,
infura: YOUR_INFURA_PROJECT_ID,
alchemy: YOUR_ALCHEMY_API_KEY
// Or if using a project secret:
// infura: {
// projectId: YOUR_INFURA_PROJECT_ID,
// projectSecret: YOUR_INFURA_PROJECT_SECRET,
// },
alchemy: YOUR_ALCHEMY_API_KEY,
pocket: YOUR_POCKET_APPLICATION_KEY
// Or if using an application secret key:
// pocket: {
// applicationId: ,
// applicationSecretKey:
// }
});

View File

@@ -1,24 +1,49 @@
_section: ContractFactory @<ContractFactory> @SRC<contracts:class.ContractFactory>
@TODO: Fill this in, including @SRC links
To deploy a [[Contract]], additional information is needed
that is not available on a Contract object itself.
Mainly, the bytecode (more specifically the initcode) of a contract is required.
The **Contract Factory** sends a special type of transaction, an initcode
transaction (i.e. the ``to`` field is null, and the ``data`` field is the
initcode) where the initcode will be evaluated and the result becomes the
new code to be deployed as a new contract.
_subsection: Creating Instances @<ContractFactory--creating>
_property: new ethers.ContractFactory(interface, bytecode [ , signer ]) @SRC<contracts:constructor.ContractFactory>
Creates a new instance of a **ContractFactory** for the contract described
by the //interface// and //bytecode// initcode.
_property: ContractFactory.fromSolidity(compilerOutput [ , signer ]) => [[ContractFactory]]
Consumes the output of the Solidity compiler, extracting the ABI
and bytecode from it, allowing for the various formats the solc
compiler has emitted over its life.
_property: contractFactory.connect(signer) => [[Contract]] @<ContractFactory-connect>
Returns a **new instance** of the ContractFactory with the same //interface//
and //bytecode//, but with a different //signer//.
_subsection: Properties @<ContractFactory--properties>
_property: contractFactory.interface => [[Interface]]
The [[Contract]] interface.
_property: contractFactory.bytecode => string<[[DataHexString]]>
The bytecode (i.e. initcode) that this **ContractFactory** will
use to deploy the Contract.
_property: contractFactory.signer => [[Signer]]
The [[Signer]] (if any) this ContractFactory will use to deploy instances
of the Contract to the Blockchain.
_subsection: Methods @<ContractFactory--methods>
@@ -26,39 +51,55 @@ _property: contractFactory.attach(address) => [[Contract]] @<ContractFactory-att
Return an instance of a [[Contract]] attached to //address//. This is the
same as using the [Contract constructor](Contract--creating) with
//address// and this the the //interface// and //signerOrProvider// passed
//address// and this the //interface// and //signerOrProvider// passed
in when creating the ContractFactory.
_property: contractFactory.getDeployTransaction(...args) => [[UnsignedTransaction]]
_property: contractFactory.getDeployTransaction(...args [ , overrides ]) => [[UnsignedTransaction]]
Returns the unsigned transaction which would deploy this Contract with //args// passed
to the Contract's constructor.
_property: contractFactory.deploy(...args) => Promise<[[Contract]]> @<ContractFactory-deploy>
If the optional //overrides// is specified, they can be used to
override the endowment ``value``, transaction ``nonce``, ``gasLimit`` or
``gasPrice``.
_property: contractFactory.deploy(...args [ , overrides ]) => Promise<[[Contract]]> @<ContractFactory-deploy>
Uses the signer to deploy the Contract with //args// passed into the constructor and
returns a Contract which is attached to the address where this contract **will** be
returns a Contract which is attached to the address where this contract **will** be
deployed once the transaction is mined.
The transaction can be found at ``contract.deployTransaction``, and no interactions
should be made until the transaction is mined.
_code: Deploying a Contract
If the optional //overrides// is specified, they can be used to
override the endowment ``value``, transaction ``nonce``, ``gasLimit`` or
``gasPrice``.
_code: Deploying a Contract @lang<javascript>
// <hide>
const signer = ethers.LocalSigner();
const signer = localSigner;
const ContractFactory = ethers.ContractFactory;
const bytecode = "608060405234801561001057600080fd5b5060405161012e38038061012e8339818101604052604081101561003357600080fd5b81019080805190602001909291908051906020019092919050505081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060008190555050506088806100a66000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633fa4f24514602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000805490509056fea2646970667358221220926465385af0e8706644e1ff3db7161af699dc063beaadd55405f2ccd6478d7564736f6c63430007040033";
// </hide>
// If your contract constructor requires parameters, the ABI
// must include the constructor
const abi = [
"constructor(address owner, uint256 initialValue)"
"constructor(address owner, uint256 initialValue)",
"function value() view returns (uint)"
];
const factory = new ContractFactory(abi, bytecode, signer)
// The factory we use for deploying contracts
factory = new ContractFactory(abi, bytecode, signer)
const contract = await factory.deploy("ricmoo.eth", 42);
// Deploy an instance of the contract
contract = await factory.deploy("ricmoo.eth", 42);
//<hide>
//! async contract
//</hide>
// The address is available immediately, but the contract
// is NOT deployed yet
@@ -69,7 +110,9 @@ contract.address
contract.deployTransaction
//!
// Wait until the transaction is mined
// Wait until the transaction is mined (i.e. contract is deployed)
// - returns the receipt
// - throws on failure (the reciept is on the error)
contract.deployTransaction.wait()
//!

View File

@@ -55,11 +55,11 @@ The provider associated with the signer.
_property: nonceManager.setTransactionCount(count) => void
Set the current transaction count (nonce) for the signer.
This may be useful it interacting with the signer outside of using
This may be useful in interacting with the signer outside of using
this class.
_property: nonceManager.increaseTransactionCount( [ count = 1 ]) => void
Bump the current transaction count (nonce) by //count//.
This may be useful it interacting with the signer outside of using
This may be useful in interacting with the signer outside of using
this class.

View File

@@ -57,7 +57,7 @@ _heading: PopNode @<asm-popnode> @INHERIT<[[asm-valuenode]]> @SRC<asm:class.PopN
A **PopNode** is used to store a place-holder for an implicit pop from the
stack. It represents the code for an implicit place-holder (i.e. ``$$``) or an
explicit place-holder (e.g. ``$1``), which indicates the expect stack position
explicit place-holder (e.g. ``$1``), which indicates the expected stack position
to consume.
_property: literalNode.index => number
@@ -72,7 +72,7 @@ A **LinkNode** represents a link to another [[asm-node]]'s data,
for example ``$foo`` or ``#bar``.
_property: linkNode.label => string
Te name of the target node.
The name of the target node.
_property: linkNode.type => "offset" | "length"
Whether this node is for an offset or a length value of the
@@ -115,7 +115,7 @@ The code to execute. Any result is ignored.
_heading: LabelledNode @<asm-labellednode> @INHERIT<[[asm-node]]> @SRC<asm:class.LabelledNode>
A **LabelledNode** is used for any Node that has a name, and can therefore
be targetted by a [[asm-linknode]].
be targeted by a [[asm-linknode]].
_property: labelledNode.name => string
The name of this node.

View File

@@ -76,7 +76,7 @@ A scope may access the offset of any child [[asm-dialect-datasegment]] or
child [[asm-dialect-scope]] (with respect to itself) and may access the length
of any [[asm-dialect-datasegment]] or [[asm-dialect-scope]] anywhere in the program.
Every program in the **Ethers ASM Dialect** has a top-leve scope named ``_``.
Every program in the **Ethers ASM Dialect** has a top-level scope named ``_``.
_subsection: Data Segment @<asm-dialect-datasegment>

View File

@@ -6,7 +6,7 @@ to them, which simplifies development, since you do not need
to run your own instance or cluster of Ethereum nodes.
However, this reliance on third-party services can reduce
resiliance, security and increase the amount of required trust.
resilience, security and increase the amount of required trust.
To mitigate these issues, it is recommended you use a
[Default Provider](providers-getDefaultProvider).
@@ -20,7 +20,7 @@ _property: new ethers.providers.EtherscanProvider([ network = "homestead", [ api
Create a new **EtherscanProvider** connected to //network// with the
optional //apiKey//.
The //network// may be specified as **string** for a common
The //network// may be specified as a **string** for a common
network name, a **number** for a common chain ID or a
[Network Object]provider-(network).
@@ -86,7 +86,7 @@ _property: new ethers.providers.InfuraProvider([ network = "homestead", [ apiKey
Create a new **InfuraProvider** connected to //network// with
the optional //apiKey//.
The //network// may be specified as **string** for a common
The //network// may be specified as a **string** for a common
network name, a **number** for a common chain ID or a
[Network Object]provider-(network).
@@ -157,7 +157,7 @@ _property: new ethers.providers.AlchemyProvider([ network = "homestead", [ apiKe
Create a new **AlchemyProvider** connected to //network// with
the optional //apiKey//.
The //network// may be specified as **string** for a common
The //network// may be specified as a **string** for a common
network name, a **number** for a common chain ID or a
[Network Object](providers-Network).

View File

@@ -20,7 +20,7 @@ for use in production.
It creates a [[FallbackProvider]] connected to as many backend
services as possible. When a request is made, it is sent to
multiple backends simulatenously. As responses from each backend
multiple backends simultaneously. As responses from each backend
are returned, they are checked that they agree. Once a quorum
has been reached (i.e. enough of the backends agree), the response
is provided to your application.
@@ -31,7 +31,7 @@ responses that match the majority.
_property: ethers.getDefaultProvider([ network, [ options ] ]) => [[Provider]]
Returns a new Provider, backed by multiple services, connected
to //network//. Is no //network// is provided, **homestead**
to //network//. If no //network// is provided, **homestead**
(i.e. mainnet) is used.
The //network// may also be a URL to connect to, such as ``http:/\/localhost:8545``
@@ -43,20 +43,22 @@ _table: Option Properties
$Alchemy: [[link-alchemy]] API Token
$Etherscan: [[link-etherscan]] API Token
$Infura: [[link-infura]] Project ID or ProjectID and Project Secret
$Infura: [[link-infura]] Project ID or ``{ projectId, projectSecret }``
$Pocket: [[link-pocket]] Application ID or ``{ applicationId, applicationSecretKey }``
$Quorum: The number of backends that must agree
//(default: 2 for mainnet, 1 for testnets)//
| **Property** | **Description** |
| //alchemy// | $Alchemy |
| //etherscan// | $Etherscan |
| //infura// | $Infura |
| //pocket// | $Pocket |
| //quorum// | $Quorum |
_note: Note: API Keys
It is highly recommended for production services that to acquire
and specify an API Key for each sercice.
It is highly recommended for production services to acquire
and specify an API Key for each service.
The default API Keys used by ethers are shared across all users,
so services may throttle all services that are using the default

View File

@@ -41,7 +41,7 @@ The provider for this configuration.
_property: fallbackProviderConfig.priority => number
The priority used for the provider. Higher priorities are favoured over lower
priorities. If multiple providers share the same prioirty, they are chosen
priorities. If multiple providers share the same priority, they are chosen
at random.
_property: fallbackProviderConfig.stallTimeout => number
@@ -152,7 +152,7 @@ which allows for a persistent connection, multiplexing requests and pub-sub
events for a more immediate event dispatching.
The WebSocket API is newer, and if running your own infrastructure, note that
WebSockets are much more intensive on your server resourses, as they must manage
WebSockets are much more intensive on your server resources, as they must manage
and maintain the state for each client. For this reason, many services may also
charge additional fees for using their WebSocket endpoints.

View File

@@ -146,7 +146,7 @@ _subsection: Transactions Methods @<Provider--transaction-methods>
_property: provider.call(transaction [ , blockTag = latest ]) => Promise<string<[[DataHexString]]>> @<Provider-call> @SRC<providers/base-provider>
Returns the result of executing the //transaction//, using //call//. A call
does not require any ether, but cannot change any state. This is useful
for calling gettings on Contracts.
for calling getters on Contracts.
_property: provider.estimateGas(transaction) => Promise<[[BigNumber]]> @<Provider-estimateGas> @SRC<providers/base-provider>
Returns an estimate of the amount of gas that would be required to submit //transaction//
@@ -174,7 +174,7 @@ Add a //listener// to be triggered for each //eventName//.
_property: provider.once(eventName, listener) => this @<Provider-once> @SRC<providers/base-provider>
Add a //listener// to be triggered for only the next //eventName//,
at which time it be removed.
at which time it will be removed.
_property: provider.emit(eventName, ...args) => boolean @<Provider-emit> @SRC<providers/base-provider>
Notify all listeners of //eventName//, passing //args// to each listener. This

View File

@@ -59,19 +59,19 @@ The timestamp of this block.
_property: block.nonce => string<[[DataHexString]]>
The nonce used as part of the proof-of-work to mine this block.
This property is generally of little interest developers.
This property is generally of little interest to developers.
_property: block.difficulty => number
The difficulty target required to be met by the miner of the block.
This property is generally of little interest developers.
This property is generally of little interest to developers.
_property: block.gasLimit => [[BigNumber]]
The maximum amount of gas that this block was permitted to use. This
is a value that can be voted up or voted down by miners and is used
to automatically adjust the bandwidth requirements of the network.
This property is generally of little interest developers.
This property is generally of little interest to developers.
_property: block.gasUsed => [[BigNumber]]
The total amount of gas used by all transactions in this block.
@@ -83,7 +83,7 @@ miner that mined this block would like the subsidy reward to go to.
_property: block.extraData => string
This is extra data a miner may choose to include when mining a block.
This property is generally of little interest developers.
This property is generally of little interest to developers.
_heading: Block (with transaction hashes)
@@ -238,7 +238,7 @@ Wait for //confirmations//. If 0, and the transaction has not been mined,
_heading: TransactionReceipt @<providers-TransactionReceipt>
_property: receipt.to => string<[[address]]>
The address this transaction is to. This is ``null`` if the the
The address this transaction is to. This is ``null`` if the
transaction was an **init transaction**, used to deploy a contract.
_property: receipt.from => string<[[address]]>
@@ -295,7 +295,7 @@ including the actual block it was mined in.
_property: receipt.cumulativeGasUsed => [[BigNumber]]
For the block this transaction was included in, this is the sum of the
gas used used by each transaction in the ordered list of transactions
gas used by each transaction in the ordered list of transactions
up to (and including) this transaction.
This is generally of little interest to developers.

View File

@@ -6,7 +6,7 @@ which can be used to sign messages and transactions and send
signed transactions to the Ethereum Network to execute state
changing operations.
The available operations depends largely on the sub-class used.
The available operations depend largely on the sub-class used.
For example, a Signer from MetaMask can send transactions and sign
messages but cannot sign a transaction (without broadcasting it).
@@ -20,9 +20,9 @@ The most common Signers you will encounter are:
_subsection: Signer @<Signer> @SRC<abstract-signer:class.Signer>
The **Signer** class is abstract and cannot be directly instaniated.
The **Signer** class is abstract and cannot be directly instantiated.
Instead use one of the concreate sub-classes, such as the [[Wallet]],
Instead use one of the concrete sub-classes, such as the [[Wallet]],
[[VoidSigner]] or [[JsonRpcSigner]].
_property: signer.connect(provider) => [[Signer]] @<Signer-connect>
@@ -112,6 +112,63 @@ Sub-classes **must** implement this, however they may throw if sending a
transaction is not supported, such as the [[VoidSigner]] or if the
Wallet is offline and not connected to a [[Provider]].
_property: signer._signTypedData(domain, types, value) => Promise<string<[RawSignature](signature-raw)>> @<Signer-signTypedData>
Signs the typed data //value// with //types// data structure for //domain// using
the [[link-eip-712]] specification.
_warning: Experimental feature (this method name will change)
This is still an experimental feature. If using it, please specify the **exact**
version of ethers you are using (e.g. spcify ``"5.0.18"``, **not** ``"^5.0.18"``) as
the method name will be renamed from ``_signTypedData`` to ``signTypedData`` once
it has been used in the field a bit.
_code: Typed Data Example @lang<javascript>
// <hide>
signer = new Wallet("0x1234567890123456789012345678901234567890123456789012345678901234");
// </hide>
// All properties on a domain are optional
const domain = {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
};
// The named list of all type definitions
const types = {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' }
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' }
]
};
// The data to sign
const value = {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
},
contents: 'Hello, Bob!'
};
const signature = await signer._signTypedData(domain, types, value);
//! async signature
_heading: Sub-Classes @<Signer--subclassing>
It is very important that all important properties of a **Signer** are
@@ -124,20 +181,20 @@ and libraries make this assumption.
A sub-class **must** extend Signer and **must** call ``super()``.
_property: signer.checkTransaction(transactionRequest) => [[providers-TransactionRequest]] @<Signer-checkTransaction> @SRC<abstract-signer>
This is generally not required to be overridden, but may needed to provide
This is generally not required to be overridden, but may be needed to provide
custom behaviour in sub-classes.
This should return a **copy** of the //transactionRequest//, with any properties
needed by ``call``, ``estimateGas`` and ``populateTransaction`` (which is used
by sendTransaction). It should also throw an error if any unknown key is specified.
The default implementation checks only valid [[providers-TransactionRequest]] properties
The default implementation checks only if valid [[providers-TransactionRequest]] properties
exist and adds ``from`` to the transaction if it does not exist.
If there is a ``from`` field it **must** be verified to be equal to the Signer's address.
_property: signer.populateTransaction(transactionRequest) => Promise<[[providers-TransactionRequest]]> @<Signer-populateTransaction> @SRC<abstract-signer>
This is generally not required to be overridden, but may needed to provide
This is generally not required to be overridden, but may be needed to provide
custom behaviour in sub-classes.
This should return a **copy** of //transactionRequest//, follow the same procedure
@@ -193,7 +250,7 @@ _property: wallet.address => string<[[address]]>
The address for the account this Wallet represents.
_property: wallet.provider => [[Provider]]
The provider this wallet is connected to, which will ge used for any [[Signer--blockchain-methods]]
The provider this wallet is connected to, which will be used for any [[Signer--blockchain-methods]]
methods. This can be null.
_note: Note
@@ -352,5 +409,5 @@ The privateKey of this EOA
_property: eoa.mnemonic => [[Mnemonic]]
//Optional//. The account HD mnemonic, if it has one and can be
determined. Some sources do not encode the mnemonic, such as an
determined. Some sources do not encode the mnemonic, such as
HD extended keys.

View File

@@ -39,7 +39,7 @@ _subsection: Coding Methods @<AbiCoder--methods>
_property: abiCoder.encode(types, values) => string<[[DataHexString]]> @<AbiCoder-encode> @SRC<abi/abi-coder>
Encode the array //values// according the array of //types//, each of which may be a
Encode the array //values// according to the array of //types//, each of which may be a
string or a [[ParamType]].
_property: abiCoder.decode(types, data) => [[Result]] @<AbiCoder-decode> @SRC<abi/abi-coder>

View File

@@ -31,7 +31,7 @@ _property: ethers.utils.FragmentTypes.full => string
This is a full human-readable string, including all parameter names, any
optional modifiers (e.g. ``indexed``, ``public``, etc) and white-space
to aid in human readabiliy.
to aid in human readability.
_property: ethers.utils.FragmentTypes.minimal => string
@@ -81,7 +81,7 @@ will be one of:
_property: fragment.inputs => Array<[[ParamType]]>
This is an array of of each [[ParamType]] for the input parameters to
This is an array of each [[ParamType]] for the input parameters to
the Constructor, Event of Function.
_heading: Methods
@@ -211,13 +211,13 @@ to parameters which are part of an [[EventFragment]].
_property: paramType.arrayChildren => [[ParamType]] @<ParamType-arrayChildren>
The type of children of the array. This is null for for any parameter
The type of children of the array. This is null for any parameter
which is not an array.
_property: paramType.arrayLength => number @<ParamType-arrayLength>
The length of the array, or ``-1`` for dynamic-length arrays. This is
null for parameters which is not arrays.
null for parameters which are not arrays.
_property: paramType.components => Array<[[ParamType]]> @<ParamType-components>

View File

@@ -4,7 +4,7 @@ Many operations in Ethereum operation on numbers which are
[outside the range of safe values](BigNumber--notes-safenumbers) to use
in JavaScript.
A **BigNumber** is an object which safely allows mathematic operations
A **BigNumber** is an object which safely allows mathematical operations
on numbers of any magnitude.
Most operations which need to return a value will return a **BigNumber**
@@ -126,7 +126,7 @@ _heading: Two's Complement
[Two's Complement](link-wiki-twoscomplement)
is an elegant method used to encode and decode fixed-width signed values
while efficiently preserving mathematic operations.
while efficiently preserving mathematical operations.
Most users will not need to interact with these.
_property: BigNumber.fromTwos(bitwidth) => [[BigNumber]] @SRC<bignumber>
@@ -175,7 +175,7 @@ Returns the value of //BigNumber// as a base-16, ``0x``-prefixed [[DataHexString
_heading: Inspection
_property: ethers.BigNumnber.isBigNumber(object) => boolean @SRC<bignumber>
_property: ethers.BigNumber.isBigNumber(object) => boolean @SRC<bignumber>
Returns true if and only if the //object// is a BigNumber object.
@@ -270,7 +270,7 @@ various purposes.
_heading: Allow us to set a global Big Number library?
Another comment that comes up frequently is tha desire to specify a
Another comment that comes up frequently is the desire to specify a
global user-defined Big Number library, which all functions would
return.

View File

@@ -155,7 +155,7 @@ Any missing properties will be computed.
_subsection: Random Bytes
_property: ethers.utils.randomBytes(length) => Uint8Array @<utils-randomBytes> @SRC<random/index>
_property: ethers.utils.randomBytes(length) => Uint8Array @<utils-randomBytes> @SRC<random/random>
Return a new Uint8Array of //length// random bytes.
_property: ethers.utils.shuffled(array) => Array<any> @<utils-shuffled> @SRC<random>

View File

@@ -1,4 +1,4 @@
_section: Display Logic and Input
_section: Display Logic and Input @<display-logic>
When creating an Application, it is useful to convert between
user-friendly strings (usually displaying **ether**) and the
@@ -17,11 +17,11 @@ The [formatUnits](unit-conversion) will format a [BigNumberish](BigNumberish)
into a string, which is useful when displaying a balance.
_subsection: Units
_subsection: Units @<display-logic--units>
_heading: Decimal Count
A **Unit** can be specified as an number, which indicates the
A **Unit** can be specified as a number, which indicates the
number of decimal places that should be used.
**Examples:**
@@ -29,7 +29,7 @@ number of decimal places that should be used.
- 1 ether in wei, has **18** decimal places (i.e. 1 ether represents 10^^18^^ wei)
- 1 bitcoin in Satoshi, has **8** decimal places (i.e. 1 bitcoin represents 10^^8^^ satoshi)
_heading: Named Units
_heading: Named Units @<display-logic--named-units>
There are also several common **Named Units**, in which case their name (as
a string) may be used.
@@ -46,9 +46,9 @@ _table: @STYLE<compact>
| //ether// | 18 |
_subsection: Functions
_subsection: Functions @<display-logic--functions>
_heading: Formatting
_heading: Formatting @<display-logic--formatting>
_property: ethers.utils.commify(value) => string @<utils-commify> @SRC<units>
Returns a string with value grouped by 3 digits, separated by ``,``.

View File

@@ -28,7 +28,7 @@ structures of Arrays and data.
_property: ethers.utils.RLP.encode(dataObject) => string<[[DataHexString]]> @<utils-rlpEncode> @SRC<rlp>
Encode a structured Data Object into its RLP-encoded representation.
Each Data component may be an valid [[BytesLike]].
Each Data component may be a valid [[BytesLike]].
_property: ethers.utils.RLP.decode(aBytesLike) => [DataObject](rlp--dataobject) @<utils.rlpDecode> @SRC<rlp>
Decode an RLP-encoded //aBytesLike// into its structured Data Object.

View File

@@ -81,7 +81,7 @@ _subsection: FixedFormat @<FixedFormat>
A **FixedFormat** is a simple object which represents a decimal
(base-10) Fixed-Point data representation. Usually using this
class directly is uneccessary, as passing in a [[FixedFormat--strings]]
class directly is unnecessary, as passing in a [[FixedFormat--strings]]
directly into the [[FixedNumber]] will automatically create this.
_heading: Format Strings @<FixedFormat--strings>

View File

@@ -1,6 +1,8 @@
_section: Hashing Algorithms @<hashing-algorithms>
Explain what hash functions are?
There are many hashing algorithms used throughout the blockchain
space as well as some more complex usages which require utilities
to facilitate these common operations.
_subsection: Cryptographic Hash Functions @<cryptographic-hash-functions>
@@ -66,7 +68,7 @@ utils.keccak256("0x1234")
utils.keccak256([ 0x12, 0x34 ])
//!
const bytes = utils.toUtf8Bytes("0x1234");
const bytes = utils.toUtf8Bytes("0x1234")
// <hide>
bytes
// </hide>
@@ -119,8 +121,8 @@ Use the [SHA2-512](link-wiki-sha2) hash algorithm.
_code: HMAC @lang<javascript>
const key = "0x0102";
const data = "0x1234";
const key = "0x0102"
const data = "0x1234"
utils.computeHmac("sha256", key, data)
//!
@@ -132,13 +134,39 @@ Computes the [[link-eip-191]] personal message digest of //message//. Personal m
converted to UTF-8 bytes and prefixed with ``\\x19Ethereum Signed Message:``
and the length of //message//.
_property: ethers.utils.namehash(name) => string<[[DataHexString]]<32>> @<utils-namehash> @SRC<hash>
Returns the [ENS Namehash](link-namehash) of //name//.
_code: Hashing Messages @lang<javascript>
// @TODO: include examples of hashMessage; it can be complex. :)
// Hashing a string message
utils.hashMessage("Hello World")
//!
// Hashing binary data (also "Hello World", but as bytes)
utils.hashMessage( [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 ])
//!
// NOTE: It is important to understand how strings and binary
// data is handled differently. A string is ALWAYS processed
// as the bytes of the string, so a hexstring MUST be
// converted to an ArrayLike object first.
// Hashing a hex string is the same as hashing a STRING
// Note: this is the hash of the 4 characters [ '0', 'x', '4', '2' ]
utils.hashMessage("0x42")
//!
// Hashing the binary data
// Note: this is the hash of the 1 byte [ 0x42 ]
utils.hashMessage([ 0x42 ])
//!
// Hashing the binary data
// Note: similarly, this is the hash of the 1 byte [ 0x42 ]
utils.hashMessage(utils.arrayify("0x42"))
//!
_property: ethers.utils.namehash(name) => string<[[DataHexString]]<32>> @<utils-namehash> @SRC<hash>
Returns the [ENS Namehash](link-namehash) of //name//.
_code: Namehash @lang<javascript>
@@ -154,6 +182,121 @@ utils.namehash("ricmoo.firefly.eth")
utils.namehash("ricmoo.xyz")
//!
_heading: Typed Data Encoder @<TypedDataEncoder> @SRC<hash:class.TypedDataEncoder>
The **TypedDataEncoder** is used to compute the various encoded data required
for [[link-eip-712]] signed data.
Signed data requires a domain, list of structures and their members and the data
itself.
The **domain** is an object with values for any of the standard domain
properties.
The **types** is an object with each property being the name of a structure, mapping
to an array of field descriptions. It should **not** include the ``EIP712Domain``
property unless it is required as a child structure of another.
_note: Experimental Feature (this exported class name will change)
This is still an experimental feature. If using it, please specify the **exact**
version of ethers you are using (e.g. spcify ``"5.0.18"``, **not** ``"^5.0.18"``) as
the exported class name will be renamed from ``_TypedDataEncoder`` to ``TypedDataEncoder`` once
it has been used in the field a bit.
_property: ethers.utils._TypedDataEncoder.from(types) => [TypedDataEncoder] @<TypedDataEncoder-from> @SRC<hash:TypedDataEncoder.from>
Creates a new **TypedDataEncoder** for //types//. This object is a fairly
low-level object that most developers should not require using instances
directly.
Most developers will find the static class methods below the most useful.
_property: TypedDataEncoder.encode(domain, types, values) => string @<TypedDataEncoder-encode> @SRC<hash:staticmethod.TypedDataEncoder.encode>
Encodes the Returns the hashed [[link-eip-712]] domain.
_property: TypedDataEncoder.getPayload(domain, types, value) => any @<TypedDataEncoder-getPayload> @SRC<hash:TypedDataEncoder.getPayload>
Returns the standard payload used by various JSON-RPC ``eth_signTypedData*``
calls.
All domain values and entries in value are normalized and the types are
verified.
_property: TypedDataEncoder.getPrimaryType(types) => string @<TypedDataEncoder-getPrimaryType> @SRC<hash:TypedDataEncoder.getPrimaryType>
Constructs a directed acyclic graph of the types and returns the
root type, which can be used as the **primaryType** for [[link-eip-712]]
payloads.
_property: TypedDataEncoder.hash(domain, types, values) => string<[[DataHexString]]<32>> @<TypedDataEncoder-hash> @SRC<hash:staticmethod.TypedDataEncoder.hash>
Returns the computed [[link-eip-712]] hash.
_property: TypedDataEncoder.hashDomain(domain) => string<[[DataHexString]]<32>> @<TypedDataEncoder-hashDomain> @SRC<hash:TypedDataEncoder.hashDomain>
Returns the hashed [[link-eip-712]] domain.
_property: TypedDataEncoder.resolveNames(domain, types, value, resolveName) => Promise<any> @<TypedDataEncoder-resolveNames> @SRC<hash:TypedDataEncoder.resolveNames>
Returns a copy of value, where any leaf value with a type of ``address`` will have
been recursively replacedwith the value of calling //resolveName// with that value.
_code: Typed Data Example @lang<javascript>
// <hide>
TypedDataEncoder = ethers.utils._TypedDataEncoder
// </hide>
const domain = {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
}
// The named list of all type definitions
const types = {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' }
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' }
]
}
// The data to sign
const value = {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
},
contents: 'Hello, Bob!'
}
TypedDataEncoder.encode(domain, types, value)
//!
TypedDataEncoder.getPayload(domain, types, value)
//!
TypedDataEncoder.getPrimaryType(types)
//!
TypedDataEncoder.hash(domain, types, value)
//!
TypedDataEncoder.hashDomain(domain)
//!
_subsection: Solidity Hashing Algorithms @<utils--solidity-hashing>
@@ -187,3 +330,20 @@ utils.solidityKeccak256([ "int16", "uint48" ], [ -1, 12 ])
utils.soliditySha256([ "int16", "uint48" ], [ -1, 12 ])
//!
// As a short example of the non-distinguished nature of
// Solidity tight-packing (which is why it is inappropriate
// for many things from a security point of view), consider
// the following examples are all equal, despite representing
// very different values and layouts.
utils.solidityPack([ "string", "string" ], [ "hello", "world01" ])
//!
utils.solidityPack([ "string", "string" ], [ "helloworld", "01" ])
//!
utils.solidityPack([ "string", "string", "uint16" ], [ "hell", "oworld", 0x3031 ])
//!
utils.solidityPack([ "uint96" ], [ "32309054545061485574011236401" ])
//!

View File

@@ -196,7 +196,7 @@ _property: Logger.levels.DEBUG
Log all output, including debugging information.
_property: Logger.levels.INFO
Only log output for infomational, warnings and errors.
Only log output for informational, warnings and errors.
_property: Logger.levels.WARNING
Only log output for warnings and errors.

View File

@@ -39,7 +39,13 @@ will then be used to compute the address; this allows systems which use
the v to encode additional data (such as [EIP-155](link-eip-155))
to be used since the v parameter is still completely non-ambiguous.
_property: ethers.utils.verifyTypedData(domain, types, value, signature) => string<[[address]]> @<utils-verifyTypedData> @SRC<wallet>
Returns the address that signed the [[link-eip-712]] //value// for the //domain//
and //types// to produce the signature.
_property: ethers.utils.recoverPublicKey(digest, signature) => string<[[DataHexString]]<65>> @<utils-recoverPublicKey>
Returns the uncompressed public key (i.e. the first byte will be ``0x04``)
of the private key that was used to sign //digest// which gave the //signature//.
_property: ethers.utils.computePublicKey(key [, compressed = false ]) => string<[[DataHexString]]> @<utils-computePublicKey>
Computes the public key of //key//, optionally compressing it. The //key//

View File

@@ -7,7 +7,7 @@ An unsigned transaction represents a transaction that has not been
signed and its values are flexible as long as they are not ambiguous.
_property: unsignedTransaction.to => string<[Address](address)>
The addres this transaction is to.
The address this transaction is to.
_property: unsignedTransaction.nonce => number
The nonce of this transaction.
@@ -98,7 +98,7 @@ used to encode the chain ID into the serialized transaction.
_subsection: Functions @<transactions--functions>
_property: ethers.utils.parseTransaction(aBytesLike) => [[Transaction]] @<utils-parseTransaction> @SRC<transactions:parse>
Parses the transaction properties from a serialized transactions.
Parses the transaction properties from a serialized transaction.
_property: ethers.utils.serializeTransaction(tx [ , signature ]) => string<[[DataHexString]]> @<utils-serializeTransaction> @SRC<transactions:serialize>
Computes the serialized //transaction//, optionally serialized with

View File

@@ -3,7 +3,7 @@ _section: Web Utilities @<web>
_property: ethers.utils.fetchJson(urlOrConnectionInfo [, json [ , processFunc ] ]) => Promise<any> @<utils-fetchJson>
Fetch and parse the JSON content from //urlOrConnectionInfo//, with the
optiona body //json// and optionally processing the result with //processFun//
optional body //json// and optionally processing the result with //processFun//
before returning it.
_property: ethers.utils.poll(pollFunc [, options ]) => Promise<any> @<utils-poll>

View File

@@ -30,7 +30,7 @@ the registered //name//.
_subsection: Languages @<wordlists--languages>
The [official wordlists](link-bip39-wordlists) available in at
The [official wordlists](link-bip39-wordlists) available at
`ethers.wordlists`. In the browser, only the english language is
available by default; to include the others (which increases the
size of the library), see the dist files in the `ethers` package.

View File

@@ -104,8 +104,8 @@ bytecode by running multiple passes of an assemble stage, each pass
more closely approximating the final result.
This allows small portions of the bytecode to be massaged and tweaked
until the bytecode stablizes. This allows for more compact jump
destinations and for code to be include more advanced meta-programming
until the bytecode stabilizes. This allows for more compact jump
destinations and for code to include more advanced meta-programming
techniques.
_code: @lang<shell>

View File

@@ -47,8 +47,8 @@ for a given option is invalid or some combination of options and flags is not
allowed.
Once the prepareOptions is complete (the returned promise is resolved), the ``prepareArguments``
is called. This should validate the number of arguments is expected and throw
and error if there are too many or too few arguments or if any arguments do not
is called. This should validate the number of arguments expected and throw
an error if there are too many or too few arguments or if any arguments do not
make sense.
Once the prepareArguments is complete (the returned promise is resolved), the ``run``

View File

@@ -11,3 +11,4 @@ _toc:
events
gas
security
best-practices

View File

@@ -127,7 +127,14 @@ function codeContextify(context) {
context.hexlify = ethers.utils.hexlify;
context.hexValue = ethers.utils.hexValue;
context.Wallet = ethers.Wallet;
context.provider = new ethers.providers.InfuraProvider();
context.provider = new ethers.providers.InfuraProvider("mainnet", "49a0efa3aaee4fd99797bfa94d8ce2f1");
// We use a local dev node for some signing examples, but want to
// resolve ENS names against mainnet; super hacky but makes the
// docs nicer
context.localProvider = new ethers.providers.JsonRpcProvider();
context.localSigner = context.localProvider.getSigner();
context.localProvider.resolveName = context.provider.resolveName.bind(context.provider);
context.BigNumber.prototype[inspect.custom] = function(depth, options) {
return `{ BigNumber: ${JSON.stringify(this.toString()) } }`;
@@ -142,6 +149,7 @@ function codeContextify(context) {
//return JSON.stringify(value);
return inspect(value, {
compact: false,
depth: null,
breakLength: Infinity,
sorted: true,
});
@@ -185,6 +193,7 @@ module.exports = {
"link-metamask": { name: "Metamask", url: "https:/\/metamask.io/" },
"link-otto": "https:/\/github.com/robertkrimen/otto",
"link-parity": { name: "Parity", url: "https:/\/www.parity.io" },
"link-pocket": { name: "Pocket Network", url: "https:/\/pokt.network" },
"link-react-native": { name: "React Native", url: "https:/\/reactnative.dev" },
"link-rtd": "https:/\/github.com/readthedocs/sphinx_rtd_theme",
"link-semver": { name: "semver", url: "https:/\/semver.org" },
@@ -195,6 +204,7 @@ module.exports = {
"link-etherscan-signup": "https:/\/etherscan.io/apis",
"link-etherscan-ratelimit": "https:/\/info.etherscan.com/api-return-errors/",
"link-infura-signup": "https:/\/infura.io/register",
"link-pocket-signup": "https:/\/pokt.network/pocket-gateway-ethereum-mainnet/",
"link-json-rpc": "https:/\/github.com/ethereum/wiki/wiki/JSON-RPC",
"link-web3-send": "https:/\/github.com/ethereum/web3.js/blob/1.x/packages/web3-providers-http/types/index.d.ts#L57",
@@ -236,6 +246,7 @@ module.exports = {
"link-eip-155": { name: "EIP-155", url: "https:/\/eips.ethereum.org/EIPS/eip-155" },
"link-eip-191": { name: "EIP-191", url: "https:/\/eips.ethereum.org/EIPS/eip-191" },
"link-eip-609": { name: "EIP-609", url: "https:/\/eips.ethereum.org/EIPS/eip-609" },
"link-eip-712": { name: "EIP-712", url: "https:/\/eips.ethereum.org/EIPS/eip-712" },
"link-eip-1014": { name: "EIP-1014", url: "https:/\/eips.ethereum.org/EIPS/eip-1014" },
"link-eip-1193": { name: "EIP-1193", url: "https:/\/eips.ethereum.org/EIPS/eip-1193" },
"link-eip-2098": { name: "EIP-2098", url: "https:/\/eips.ethereum.org/EIPS/eip-2098" },
@@ -247,7 +258,7 @@ module.exports = {
"link-npm-events": { name: "EventEmitter", url: "https:/\/nodejs.org/dist/latest-v13.x/docs/api/events.html#events_class_eventemitter" },
"link-npm-bnjs": { name: "BN.js", url: "https:/\/www.npmjs.com/package/bn.js" },
"link-npm-query-bignumber": "https:/\/www.npmjs.com/search?q=bignumber",
"link-npm-react-native-crypto": { name: "React Native Crypto", url: "https:/\/www.npmjs.com/package/react-native-crypto" },
"link-npm-react-native-get-random-values": { name: "React Native get-random-values", url: "https:/\/www.npmjs.com/package/react-native-get-random-values" },
"link-js-array": "https:/\/developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array",
"link-js-bigint": "https:/\/developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt",

View File

@@ -21,7 +21,7 @@ So, pull requests are always welcome, but please keep a few points in mind:
may not be accepted
In general, **please start an issue //before// beginning a pull request**, so we can
have a public discussion and figure out the best way to address to problem/feature.
have a public discussion and figure out the best way to address the problem/feature.
**:)**

View File

@@ -40,8 +40,21 @@ _subsection: Security @<cookbook-reactnative-security>
The React Native environment does not contain a secure random source, which
is used when computing random private keys. This could result in private
keys that others could guess, allowing the funds to be stolen.
keys that others could possibly guess, allowing funds to be stolen and assets
manipulated.
For this reason, it is **HIGHLY RECOMMENDED** to get either the
[[link-npm-react-native-crypto]] module working or some equivalent.
For this reason, it is **HIGHLY RECOMMENDED** to also install the
[[link-npm-react-native-get-random-values]], which **must** be included
before the shims. If it worked correctly you should not receive any
warning in the console regarding missing secure random sources.
_code: Importing with Secure Random Sources @lang<script>
// Import the crypto getRandomValues shim (**BEFORE** the shims)
import "react-native-get-random-values"
// Import the the ethers shims (**BEFORE** ethers)
import "@ethersproject/shims"
// Import the ethers library
import { ethers } from "ethers";

View File

@@ -380,7 +380,7 @@ _heading: Variables @<flatworm--table-variable>
Often the layout of a table is easier to express and maintain without
uneven or changing content within it. So the content can be defined
separately within a table directive using **variables**. A variable
name must being with a letter and must only contain letters and numbers.
name must begin with a letter and must only contain letters and numbers.
Variables are also useful when content is repeated throughout a table.

View File

@@ -151,7 +151,7 @@ All errors now belong to the [[Logger]] class and the related functions
have been moved to [[Logger]] instances, which can include a per-package
version string.
Global error functions have been moved [[Logger]] class methods.
Global error functions have been moved to [[Logger]] class methods.
_code: @lang<script>

View File

@@ -61,7 +61,7 @@ _subsection: Test Suites @<testing-suites>
The test suites are available as gzipped JSON files in the
``@ethersproject/testcases``, which makes it easy to install and import
(both GZIP and JSON are quite easy to consume from most langauges). Each
(both GZIP and JSON are quite easy to consume from most languages). Each
test suite also has its schema available in this package.
_table: Test Suites @style<full>
@@ -126,7 +126,7 @@ _heading: Deterministic Random Numbers (DRNG)
When creating test cases, often we want want random data from the perspective
we do not case what values are used, however we want the values to be consistent
accross runs. Otherwise it becomes difficult to reproduce an issue.
across runs. Otherwise it becomes difficult to reproduce an issue.
In each of the following the seed is used to control the random value returned. Be
sure to tweak the seed properly, for example on each iteration change the value and

View File

@@ -33,10 +33,13 @@ Developer Documentation
* [Gas Limit](concepts/gas)
* [Security](concepts/security)
* [Key Derivation Functions](concepts/security)
* [Best Practices](concepts/best-practices)
* [Network Changes](concepts/best-practices)
* [Provider API Keys](api-keys)
* [Etherscan](api-keys)
* [INFURA](api-keys)
* [Alchemy](api-keys)
* [Pocket Gateway](api-keys)
* [Creating a Default Provider](api-keys)
* [Application Programming Interface](api)
* [Providers](api/providers)
@@ -193,7 +196,7 @@ Developer Documentation
* [Data Segment](api/other/assembly/dialect)
* [Links](api/other/assembly/dialect)
* [Stack Placeholders](api/other/assembly/dialect)
* [Evaluation and Excution](api/other/assembly/dialect)
* [Evaluation and Execution](api/other/assembly/dialect)
* [Utilities](api/other/assembly/api)
* [Assembler](api/other/assembly/api)
* [Disassembler](api/other/assembly/api)

View File

@@ -16,6 +16,9 @@ INFURA
Alchemy
-------
Pocket Gateway
--------------
Creating a Default Provider
---------------------------
@@ -29,7 +32,18 @@ const network = "homestead";
const provider = ethers.getDefaultProvider(network, {
etherscan: YOUR_ETHERSCAN_API_KEY,
infura: YOUR_INFURA_PROJECT_ID,
alchemy: YOUR_ALCHEMY_API_KEY
// Or if using a project secret:
// infura: {
// projectId: YOUR_INFURA_PROJECT_ID,
// projectSecret: YOUR_INFURA_PROJECT_SECRET,
// },
alchemy: YOUR_ALCHEMY_API_KEY,
pocket: YOUR_POCKET_APPLICATION_KEY
// Or if using an application secret key:
// pocket: {
// applicationId: ,
// applicationSecretKey:
// }
});
```

File diff suppressed because one or more lines are too long

View File

@@ -161,7 +161,7 @@ Application Programming Interface
* [Data Segment](other/assembly/dialect)
* [Links](other/assembly/dialect)
* [Stack Placeholders](other/assembly/dialect)
* [Evaluation and Excution](other/assembly/dialect)
* [Evaluation and Execution](other/assembly/dialect)
* [Utilities](other/assembly/api)
* [Assembler](other/assembly/api)
* [Disassembler](other/assembly/api)

View File

@@ -42,7 +42,7 @@ Methods
#### *contractFactory* . **attach**( address ) => *[Contract](/v5/api/contract/contract/)*
Return an instance of a [Contract](/v5/api/contract/contract/) attched to *address*. This is the same as using the [Contract constructor](/v5/api/contract/contract/#Contract--creating) with *address* and this the the *interface* and *signerOrProvider* passed in when creating the ContractFactory.
Return an instance of a [Contract](/v5/api/contract/contract/) attached to *address*. This is the same as using the [Contract constructor](/v5/api/contract/contract/#Contract--creating) with *address* and this the *interface* and *signerOrProvider* passed in when creating the ContractFactory.
#### *contractFactory* . **getDeployTransaction**( ...args ) => *[UnsignedTransaction](/v5/api/utils/transactions/#UnsignedTransaction)*
@@ -52,7 +52,7 @@ Returns the unsigned transaction which would deploy this Contract with *args* pa
#### *contractFactory* . **deploy**( ...args ) => *Promise< [Contract](/v5/api/contract/contract/) >*
Uses the signer to deploy the Contract with *args* passed into the constructor and retruns a Contract which is attached to the address where this contract **will** be deployed once the transaction is mined.
Uses the signer to deploy the Contract with *args* passed into the constructor and returns a Contract which is attached to the address where this contract **will** be deployed once the transaction is mined.
The transaction can be found at `contract.deployTransaction`, and no interactions should be made until the transaction is mined.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -17,7 +17,7 @@ Generates a brain wallet, with a slightly improved experience, in which the gene
#### *BrainWallet* . **generateLegacy**( username , password [ , progressCallback ] ) => *[BrainWallet](/v5/api/experimental/#experimental-brainwallet)*
Generate a brain wallet which is compatibile with the ethers v3 and earlier.
Generate a brain wallet which is compatible with the ethers v3 and earlier.
EIP1193Bridge
@@ -45,13 +45,13 @@ The provider associated with the signer.
Set the current transaction count (nonce) for the signer.
This may be useful it interacting with the signer outside of using this class.
This may be useful in interacting with the signer outside of using this class.
#### *nonceManager* . **increaseTransactionCount**( [ count = 1 ] ) => *void*
Bump the current transaction count (nonce) by *count*.
This may be useful it interacting with the signer outside of using this class.
This may be useful in interacting with the signer outside of using this class.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -17,7 +17,7 @@ Other Libraries
* [Data Segment](assembly/dialect)
* [Links](assembly/dialect)
* [Stack Placeholders](assembly/dialect)
* [Evaluation and Excution](assembly/dialect)
* [Evaluation and Execution](assembly/dialect)
* [Utilities](assembly/api)
* [Assembler](assembly/api)
* [Disassembler](assembly/api)

View File

@@ -16,7 +16,7 @@ Assembly
* [Data Segment](dialect)
* [Links](dialect)
* [Stack Placeholders](dialect)
* [Evaluation and Excution](dialect)
* [Evaluation and Execution](dialect)
* [Utilities](api)
* [Assembler](api)
* [Disassembler](api)

View File

@@ -62,7 +62,7 @@ Opcode
#### *asm* . *Opcode* . **from**( valueOrMnemonic ) => *[Opcode](/v5/api/other/assembly/api/#asm-opcode)*
Create a new instnace of an Opcode for a given numeric value (e.g. 0x60 is PUSH1) or mnemonic string (e.g. "PUSH1").
Create a new instance of an Opcode for a given numeric value (e.g. 0x60 is PUSH1) or mnemonic string (e.g. "PUSH1").
### Properties

File diff suppressed because one or more lines are too long

View File

@@ -53,7 +53,7 @@ The literal value of this node, which may be a [DataHexString](/v5/api/utils/byt
#### *literalNode* . **verbatim** => *boolean*
This is true in a [DataNode](/v5/api/other/assembly/ast/#asm-datanode) context, since in that case the value should be taken verbatim and no `PUSH` operation shoud be added, otherwise false.
This is true in a [DataNode](/v5/api/other/assembly/ast/#asm-datanode) context, since in that case the value should be taken verbatim and no `PUSH` operation should be added, otherwise false.
### PopNode
@@ -67,7 +67,7 @@ The index this **PopNode** is representing. For an implicit place-holder this is
#### *linkNode* . **label** => *string*
Te name of the target node.
The name of the target node.
#### *linkNode* . **type** => *"offset" | "length"*
@@ -91,7 +91,7 @@ A list of all operands passed into this Node.
#### *literalNode* . **verbatim** => *boolean*
This is true in a [DataNode](/v5/api/other/assembly/ast/#asm-datanode) context, since in that case the value should be taken verbatim and no `PUSH` operation shoud be added, otherwise false.
This is true in a [DataNode](/v5/api/other/assembly/ast/#asm-datanode) context, since in that case the value should be taken verbatim and no `PUSH` operation should be added, otherwise false.
#### *evaluationNode* . **script** => *string*

File diff suppressed because one or more lines are too long

View File

@@ -31,6 +31,6 @@ Links
Stack Placeholders
------------------
Evaluation and Excution
-----------------------
Evaluation and Execution
------------------------

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -12,7 +12,7 @@ Default Provider
#### *ethers* . **getDefaultProvider**( [ network , [ options ] ] ) => *[Provider](/v5/api/providers/provider/)*
Returns a new Provider, backed by multiple services, connected to *network*. Is no *network* is provided, **homestead** (i.e. mainnet) is used.
Returns a new Provider, backed by multiple services, connected to *network*. If no *network* is provided, **homestead** (i.e. mainnet) is used.
The *network* may also be a URL to connect to, such as `http://localhost:8545` or `wss://example.com`.
@@ -25,7 +25,7 @@ Option Properties
#### Note: API Keys
It is highly recommended for production services that to acquire and specify an API Key for each sercice.
It is highly recommended for production services to acquire and specify an API Key for each service.
The default API Keys used by ethers are shared across all users, so services may throttle all services that are using the default API Keys during periods of load without realizing it.

View File

@@ -14,7 +14,7 @@ EtherscanProvider
Create a new **EtherscanProvider** connected to *network* with the optional *apiKey*.
The *network* may be specified as **string** for a common network name, a **number** for a common chain ID or a [Network Object]provider-(network).
The *network* may be specified as a **string** for a common network name, a **number** for a common chain ID or a [Network Object]provider-(network).
If no *apiKey* is provided, a shared API key will be used, which may result in reduced performance and throttled requests. It is highly recommended for production, you register with [Etherscan](https://etherscan.io) for your own API key.
@@ -71,7 +71,7 @@ InfuraProvider
Create a new **InfuraProvider** connected to *network* with the optional *apiKey*.
The *network* may be specified as **string** for a common network name, a **number** for a common chain ID or a [Network Object]provider-(network).
The *network* may be specified as a **string** for a common network name, a **number** for a common chain ID or a [Network Object]provider-(network).
The *apiKey* can be a **string** Project ID or an **object** with the properties `projectId` and `projectSecret` to specify a [Project Secret](https://infura.io/docs/gettingStarted/authentication) which can be used on non-public sources (like on a server) to further secure your API access and quotas.
@@ -130,7 +130,7 @@ AlchemyProvider
Create a new **AlchemyProvider** connected to *network* with the optional *apiKey*.
The *network* may be specified as **string** for a common network name, a **number** for a common chain ID or a [Network Object](/v5/api/providers/types/#providers-Network).
The *network* may be specified as a **string** for a common network name, a **number** for a common chain ID or a [Network Object](/v5/api/providers/types/#providers-Network).
#### Note: Default API keys

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -36,7 +36,7 @@ The provider for this configuration.
#### *fallbackProviderConfig* . **priority** => *number*
The priority used for the provider. Higher priorities are favoured over lower priorities. If multiple providers share the same prioirty, they are choosen at random.
The priority used for the provider. Higher priorities are favoured over lower priorities. If multiple providers share the same priority, they are chosen at random.
#### *fallbackProviderConfig* . **stallTimeout** => *number*

File diff suppressed because one or more lines are too long

View File

@@ -33,7 +33,7 @@ Returns the number of transactions *address* has ever **sent**, as of *blockTag*
```javascript
// Get the balance for an account...
provider.getBalance("ricmoo.firefly.eth");
// { Promise: { BigNumber: "1492974808274631213" } }
// { Promise: { BigNumber: "284831012276355695" } }
// Get the code for a contract...
provider.getCode("registrar.firefly.eth");
@@ -45,7 +45,7 @@ provider.getStorageAt("registrar.firefly.eth", 0)
// Get transaction count of an account...
provider.getTransactionCount("ricmoo.firefly.eth");
// { Promise: 679 }
// { Promise: 689 }
```
Blocks Methods
@@ -96,7 +96,7 @@ provider.getBlockWithTransactions(100004)
// blockHash: '0xf93283571ae16dcecbe1816adc126954a739350cd1523a1559eabeae155fbb63',
// blockNumber: 100004,
// chainId: 0,
// confirmations: 10719007,
// confirmations: 11212224,
// creates: null,
// data: '0x',
// from: '0xcf00A85f3826941e7A25BFcF9Aac575d40410852',
@@ -177,16 +177,16 @@ provider.getNetwork()
// The current block number
provider.getBlockNumber()
// { Promise: 10819010 }
// { Promise: 11312227 }
// Get the current suggested gas price (in wei)...
gasPrice = await provider.getGasPrice()
// { BigNumber: "69000000000" }
// { BigNumber: "46200000000" }
// ...often this gas price is easier to understand or
// display to the user in gwei (giga-wei, or 1e9 wei)
utils.formatUnits(gasPrice, "gwei")
// '69.0'
// '46.2'
```
Transactions Methods
@@ -194,7 +194,7 @@ Transactions Methods
#### *provider* . **call**( transaction [ , blockTag = latest ] ) => *Promise< string< [DataHexString](/v5/api/utils/bytes/#DataHexString) > >*
Returns the result of executing the *transaction*, using *call*. A call does not require any ether, but cannot change any state. This is useful for calling gettings on Contracts.
Returns the result of executing the *transaction*, using *call*. A call does not require any ether, but cannot change any state. This is useful for calling getters on Contracts.
#### *provider* . **estimateGas**( transaction ) => *Promise< [BigNumber](/v5/api/utils/bignumber/) >*
@@ -224,7 +224,7 @@ Add a *listener* to be triggered for each *eventName*.
#### *provider* . **once**( eventName , listener ) => *this*
Add a *listener* to be triggered for only the next *eventName*, at which time it be removed.
Add a *listener* to be triggered for only the next *eventName*, at which time it will be removed.
#### *provider* . **emit**( eventName , ...args ) => *boolean*

File diff suppressed because one or more lines are too long

View File

@@ -60,21 +60,21 @@ The timestamp of this block.
The nonce used as part of the proof-of-work to mine this block.
This property is generally of little interest developers.
This property is generally of little interest to developers.
#### *block* . **difficulty** => *number*
The difficulty target required to be met by the miner of the block.
This property is generally of little interest developers.
This property is generally of little interest to developers.
#### *block* . **gasLimit** => *[BigNumber](/v5/api/utils/bignumber/)*
The maximum amount of gas that this block was permitted to use. This is a value that can be voted up or voted down by miners and is used to automatically adjust the bandwidth requirements of the network.
This property is generally of little interest developers.
This property is generally of little interest to developers.
#### *block* . **gasUsed** => *[BigNumber](/v5/api/utils/bignumber/)*
@@ -91,7 +91,7 @@ The coinbase address of this block, which indicates the address the miner that m
This is extra data a miner may choose to include when mining a block.
This property is generally of little interest developers.
This property is generally of little interest to developers.
### Block (with transaction hashes)
@@ -277,7 +277,7 @@ Wait for *confirmations*. If 0, and the transaction has not been mined, `null` i
#### *receipt* . **to** => *string< [Address](/v5/api/utils/address/#address) >*
The address this transaction is to. This is `null` if the the transaction was an **init transaction**, used to deploy a contract.
The address this transaction is to. This is `null` if the transaction was an **init transaction**, used to deploy a contract.
#### *receipt* . **from** => *string< [Address](/v5/api/utils/address/#address) >*
@@ -313,7 +313,7 @@ The amount of gas actually used by this transaction.
#### *receipt* . **logsBloom** => *string< [DataHexString](/v5/api/utils/bytes/#DataHexString) >*
A [bloom-filter](https://en.wikipedia.org/wiki/Bloom_filter), which incldues all the addresses and topics included in any log in this transaction.
A [bloom-filter](https://en.wikipedia.org/wiki/Bloom_filter), which includes all the addresses and topics included in any log in this transaction.
#### *receipt* . **blockHash** => *string< [DataHexString](/v5/api/utils/bytes/#DataHexString)< 32 > >*
@@ -343,7 +343,7 @@ The number of blocks that have been mined since this transaction, including the
#### *receipt* . **cumulativeGasUsed** => *[BigNumber](/v5/api/utils/bignumber/)*
For the block this transaction was included in, this is the sum of the gas used used by each transaction in the ordered list of transactions up to (and including) this transaction.
For the block this transaction was included in, this is the sum of the gas used by each transaction in the ordered list of transactions up to (and including) this transaction.
This is generally of little interest to developers.

File diff suppressed because one or more lines are too long

View File

@@ -103,22 +103,72 @@ This method populates the transactionRequest with missing fields, using [populat
Sub-classes **must** implement this, however they may throw if sending a transaction is not supported, such as the [VoidSigner](/v5/api/signer/#VoidSigner) or if the Wallet is offline and not connected to a [Provider](/v5/api/providers/provider/).
#### *signer* . **_signTypedData**( domain , types , value ) => *Promise< string< [RawSignature](/v5/api/utils/bytes/#signature-raw) > >*
Signs the typed data *value* with *types* data structure for *domain* using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) specification.
#### Experimental feature (this method name will change)
This is still an experimental feature. If using it, please specify the **exact** version of ethers you are using (e.g. spcify `"5.0.18"`, **not** `"^5.0.18"`) as the method name will be renamed from `_signTypedData` to `signTypedData` once it has been used in the field a bit.
```javascript
// All properties on a domain are optional
const domain = {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
};
// The named list of all type definitions
const types = {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' }
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' }
]
};
// The data to sign
const value = {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
},
contents: 'Hello, Bob!'
};
const signature = await signer._signTypedData(domain, types, value);
// '0x463b9c9971d1a144507d2e905f4e98becd159139421a4bb8d3c9c2ed04eb401057dd0698d504fd6ca48829a3c8a7a98c1c961eae617096cb54264bbdd082e13d1c'
```
### Sub-Classes
#### *signer* . **checkTransaction**( transactionRequest ) => *[TransactionRequest](/v5/api/providers/types/#providers-TransactionRequest)*
This is generally not required to be overridden, but may needed to provide custom behaviour in sub-classes.
This is generally not required to be overridden, but may be needed to provide custom behaviour in sub-classes.
This should return a **copy** of the *transactionRequest*, with any properties needed by `call`, `estimateGas` and `populateTransaction` (which is used by sendTransaction). It should also throw an error if any unknown key is specified.
The default implementation checks only valid [TransactionRequest](/v5/api/providers/types/#providers-TransactionRequest) properties exist and adds `from` to the transaction if it does not exist.
The default implementation checks only if valid [TransactionRequest](/v5/api/providers/types/#providers-TransactionRequest) properties exist and adds `from` to the transaction if it does not exist.
If there is a `from` field it **must** be verified to be equal to the Signer's address.
#### *signer* . **populateTransaction**( transactionRequest ) => *Promise< [TransactionRequest](/v5/api/providers/types/#providers-TransactionRequest) >*
This is generally not required to be overridden, but may needed to provide custom behaviour in sub-classes.
This is generally not required to be overridden, but may be needed to provide custom behaviour in sub-classes.
This should return a **copy** of *transactionRequest*, follow the same procedure as `checkTransaction` and fill in any properties required for sending a transaction. The result should have all promises resolved; if needed the [resolveProperties](/v5/api/utils/properties/#utils-resolveproperties) utility function can be used for this.
@@ -172,7 +222,7 @@ The address for the account this Wallet represents.
#### *wallet* . **provider** => *[Provider](/v5/api/providers/provider/)*
The provider this wallet is connected to, which will ge used for any [Blockchain Methods](/v5/api/signer/#Signer--blockchain-methods) methods. This can be null.
The provider this wallet is connected to, which will be used for any [Blockchain Methods](/v5/api/signer/#Signer--blockchain-methods) methods. This can be null.
#### Note
@@ -285,7 +335,7 @@ contract = new ethers.Contract("dai.tokens.ethers.eth", abi, signer)
// Get the number of tokens for this account
tokens = await contract.balanceOf(signer.getAddress())
// { BigNumber: "11386855832278858351495" }
// { BigNumber: "15923148775162018481031" }
//
// Pre-flight (check for revert) on DAI from the signer
@@ -302,7 +352,7 @@ contract.callStatic.transfer("donations.ethers.eth", tokens)
// This will fail since it is greater than the token balance
contract.callStatic.transfer("donations.ethers.eth", tokens.add(1))
// Error: call revert exception (method="transfer(address,uint256)", errorSignature="Error(string)", errorArgs=["Dai/insufficient-balance"], reason="Dai/insufficient-balance", code=CALL_EXCEPTION, version=abi/5.0.4)
// Error: call revert exception (method="transfer(address,uint256)", errorSignature="Error(string)", errorArgs=["Dai/insufficient-balance"], reason="Dai/insufficient-balance", code=CALL_EXCEPTION, version=abi/5.0.9)
```
ExternallyOwnedAccount
@@ -320,6 +370,6 @@ The privateKey of this EOA
#### *eoa* . **mnemonic** => *[Mnemonic](/v5/api/utils/hdnode/#Mnemonic)*
*Optional*. The account HD mnemonic, if it has one and can be determined. Some sources do not encode the mnemonic, such as an HD extended keys.
*Optional*. The account HD mnemonic, if it has one and can be determined. Some sources do not encode the mnemonic, such as HD extended keys.

File diff suppressed because one or more lines are too long

View File

@@ -29,7 +29,7 @@ Coding Methods
#### *abiCoder* . **encode**( types , values ) => *string< [DataHexString](/v5/api/utils/bytes/#DataHexString) >*
Encode the array *values* according the array of *types*, each of which may be a string or a [ParamType](/v5/api/utils/abi/fragments/#ParamType).
Encode the array *values* according to the array of *types*, each of which may be a string or a [ParamType](/v5/api/utils/abi/fragments/#ParamType).
#### *abiCoder* . **decode**( types , data ) => *[Result](/v5/api/utils/abi/interface/#Result)*

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -18,7 +18,7 @@ Formats
#### *ethers* . *utils* . *FragmentTypes* . **full** => *string*
This is a full human-readable string, including all parameter names, any optional modifiers (e.g. `indexed`, `public`, etc) and white-space to aid in human readabiliy.
This is a full human-readable string, including all parameter names, any optional modifiers (e.g. `indexed`, `public`, etc) and white-space to aid in human readability.
#### *ethers* . *utils* . *FragmentTypes* . **minimal** => *string*
@@ -64,7 +64,7 @@ This is a string which indicates the type of the [Fragment](/v5/api/utils/abi/fr
#### *fragment* . **inputs** => *Array< [ParamType](/v5/api/utils/abi/fragments/#ParamType) >*
This is an array of of each [ParamType](/v5/api/utils/abi/fragments/#ParamType) for the input parameters to the Constructor, Event of Function.
This is an array of each [ParamType](/v5/api/utils/abi/fragments/#ParamType) for the input parameters to the Constructor, Event of Function.
### Methods
@@ -204,12 +204,12 @@ Whether the parameter has been marked as indexed. This **only** applies to param
#### *paramType* . **arrayChildren** => *[ParamType](/v5/api/utils/abi/fragments/#ParamType)*
The type of children of the array. This is null for for any parameter wjhich is not an array.
The type of children of the array. This is null for any parameter which is not an array.
#### *paramType* . **arrayLength** => *number*
The length of the array, or `-1` for dynamic-length arrays. This is null for parameters which is not arrays.
The length of the array, or `-1` for dynamic-length arrays. This is null for parameters which are not arrays.
#### *paramType* . **components** => *Array< [ParamType](/v5/api/utils/abi/fragments/#ParamType) >*

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More