Compare commits

...

154 Commits

Author SHA1 Message Date
Richard Moore
dad3829c2e Updated dist files. 2021-05-17 16:19:36 -04:00
Richard Moore
de4d683f6d admin: moved some changelog links around 2021-05-17 16:13:35 -04:00
Richard Moore
ebe4cc90f5 admin: updated Changelog 2021-05-13 23:51:01 -04:00
Richard Moore
35e3bf9d11 admin: dependency security audit updates 2021-05-13 23:50:24 -04:00
Richard Moore
2d717dcef8 docs: updated banner version. 2021-05-13 23:49:30 -04:00
Richard Moore
3316468e3e More aggresively check for mempool transactions sent from JsonRpcSigner. 2021-05-13 23:29:59 -04:00
Richard Moore
5144acf456 Added initial support for detecting replacement transactions (#1477). 2021-05-13 23:28:47 -04:00
Richard Moore
aadc5cd3d6 Added convenience method for HD path derivation. 2021-05-13 23:02:00 -04:00
Richard Moore
6e088099ad Added mnemonicPath option to cli. 2021-05-13 22:59:16 -04:00
Richard Moore
b6370f1360 Added some popular Ethereum-compatible chains to networks. 2021-05-13 22:58:16 -04:00
Richard Moore
26464c5425 Added debug event to Web3Provider. 2021-05-13 22:27:13 -04:00
Richard Moore
37a9c77ab2 Abstracted EtherscanProivder to more easily fascilitate other Etherscan-supported chains (#1204, #1473). 2021-05-07 00:31:15 -04:00
Richard Moore
483d67f55c Added EIP-838 error name as well as error signature (#1498). 2021-04-26 17:46:16 -04:00
Richard Moore
987bec87af Added new error for replaced transactions (#1477). 2021-04-26 12:06:37 -04:00
Richard Moore
a9cdbe1238 More flexible FixedNumber input and output for strings with no decimals (#1019, #1291, #1463). 2021-04-23 18:41:00 -04:00
Richard Moore
4e9abfdee4 Added hex support for bigint (#1472). 2021-04-23 17:44:22 -04:00
Richard Moore
3bb5fbf533 Added support for null entries in EventFilter (#1499). 2021-04-23 17:43:27 -04:00
Richard Moore
cadccc3060 Add bigint to allowed BigNumberish types (#1472). 2021-04-22 22:34:06 -04:00
Richard Moore
65196097f6 Support for EIP-838 custom contract errors (#1498). 2021-04-22 22:29:30 -04:00
Richard Moore
8e22e0260e Minor version bump. 2021-04-22 22:10:56 -04:00
Richard Moore
de7da421b3 docs: updated versions and dates 2021-04-22 06:34:44 -04:00
Richard Moore
a9f7957550 Updated dist files. 2021-04-22 06:34:02 -04:00
Richard Moore
bd2d44eecf docs: updated script links in README. 2021-04-22 06:28:46 -04:00
Richard Moore
bd05aed070 Do not throw on ABI _error_ type (#1493, #1497). 2021-04-22 06:26:56 -04:00
Richard Moore
ce8f1e4015 Updated dist files. 2021-04-19 21:30:28 -04:00
Richard Moore
58488e78f9 Fixed JsonRpcProvider event-loop caching when using any network (#1484). 2021-04-19 20:56:18 -04:00
Richard Moore
29116593ba Updated experimental Eip1193Bridge to support final EIP-1193 API. 2021-04-19 20:52:50 -04:00
Richard Moore
51f0e1a52f Fail early for ABI decoding that will obviously run out of data (#1486). 2021-04-19 20:26:05 -04:00
Richard Moore
c086962302 Fixed BigNumber toBigInt return type (#1485). 2021-04-19 20:09:39 -04:00
Richard Moore
c0daf437f7 Updated dist files. 2021-04-18 19:33:26 -04:00
Richard Moore
8eaeba35f5 Increase provider tests gas price for sending a transaction. 2021-04-18 19:26:39 -04:00
Richard Moore
4a44865a8c Fixed run-checking non-filter Contract events (#1458). 2021-04-18 19:23:27 -04:00
Richard Moore
725fe0aa32 Updated dist files. 2021-04-18 02:48:05 -04:00
Richard Moore
08adc18a68 Increased sendTransaction timeout to 15 minutes and pull Pocket from tx tests. 2021-04-18 02:42:20 -04:00
Richard Moore
1fcf4b6ce6 Export Eip1193Bridge in experimental package. 2021-04-18 02:40:26 -04:00
Richard Moore
7c8ae9cfcb Merge branch 'master' of github.com:ethers-io/ethers.js 2021-04-17 22:41:31 -04:00
Richard Moore
0cd5fccfad Updated dist files. 2021-04-17 22:41:09 -04:00
Richard Moore
53ee187443 admin: updated spell-check data 2021-04-17 22:37:04 -04:00
Richard Moore
4577444c44 Prevent non-typed transactions from unsafely ignoring specified access lists (#1364). 2021-04-17 22:35:40 -04:00
Richard Moore
1cb3199e5c Update tests for current EIP-2930 support across backends (#1364). 2021-04-17 22:23:18 -04:00
Richard Moore
25c3024a89 docs: added AccessLists details (#1364). 2021-04-17 22:09:50 -04:00
Richard Moore
ae0d5eb7c2 Removed underscore from the JsonRpcBatchProvider name (#62, #656, #892). 2021-04-17 18:12:08 -04:00
Richard Moore
b8df000c8f Added better error detection when pre-EIP-155 transactions are disabled. 2021-04-17 18:10:27 -04:00
Richard Moore
eb1ec2f231 Fix Android React Native environment shims which crash on normalizing Korean test (#1298). 2021-04-17 18:08:00 -04:00
Richard Moore
b65508995c Fixed EIP-2930 transactions for EtherscanProvider (#1364). 2021-04-14 15:04:24 -04:00
Richard Moore
2a7dbf0571 Update issue templates 2021-04-12 20:50:14 -04:00
Richard Moore
0dc6f4a45b Update issue templates 2021-04-12 20:43:44 -04:00
Richard Moore
2534b1b3b2 docs: fixed typo in signature (#1411). 2021-04-10 19:58:20 -04:00
Richard Moore
a11602d066 docs: fixed typo (#1450). 2021-04-10 19:56:40 -04:00
Richard Moore
bec066bcb5 Re-enable AlchemyProvider Berlin tests. 2021-04-02 19:10:16 -04:00
Richard Moore
ef5a2b4baa docs: added details for reverted calls. 2021-04-02 03:55:53 -04:00
Richard Moore
9e273220b6 docs: Fixed typo in getting-started (#1423). 2021-04-02 03:55:06 -04:00
Richard Moore
d55ab6d4e6 Added experimental _JsonRpcBatchProvider (#62, #656, #892). 2021-04-02 03:53:48 -04:00
Richard Moore
1a7c4e89ef Cache JsonRpcProvider requests for certain methods per event loop (#1371). 2021-04-02 03:45:47 -04:00
Richard Moore
c84a5e62f5 admin: updated admin dist files 2021-03-30 19:59:47 -04:00
Richard Moore
6978cca17d admin: fixed rats nest linking on Windows (#1345, #1346) 2021-03-30 19:59:28 -04:00
Richard Moore
0e3016bfae admin: updated admin dist files 2021-03-30 19:55:25 -04:00
Richard Moore
d50b2d7e65 admin: updated spell check words 2021-03-30 19:54:52 -04:00
Richard Moore
941e4210c6 admin: added minor version bumping 2021-03-30 19:54:20 -04:00
Richard Moore
3b1d3fcee6 Update dist files. 2021-03-30 15:22:45 -04:00
Richard Moore
81fd628292 Added BigNumber.toBigInt method (#1415). 2021-03-30 14:28:43 -04:00
Richard Moore
f9dd0996ca docs: fixed typo (#1387). 2021-03-27 00:46:04 -04:00
Richard Moore
87ceaed4be Abstracted Contract with BaseContract without meta-class properties for easier extensions (#1384). 2021-03-26 17:32:36 -04:00
Richard Moore
0e1721b130 Fixed Contract properties that collide with null member properties (#1393). 2021-03-26 16:37:08 -04:00
Richard Moore
c47d2eba4d Added EIP-2930 support (#1364). 2021-03-26 16:16:56 -04:00
Richard Moore
1db4ce12d4 Added abstraction for EIP-2718 support. 2021-03-09 15:26:20 -05:00
Richard Moore
6c43e20e7a Updated dist files. 2021-03-07 18:24:04 -05:00
Richard Moore
b2ecffb0c8 Bumped TypeScript to 4.2.2 (#1288). 2021-03-07 18:12:39 -05:00
Richard Moore
a953f71752 Fixed shims from not displaying debug information. 2021-03-07 17:37:49 -05:00
Richard Moore
c5a53d6911 Force TypedData numbers to be in decimal (#1193). 2021-02-25 00:46:10 -05:00
Richard Moore
bcda16df1d Updated dist files. 2021-02-12 19:06:01 -05:00
Richard Moore
d937668dc1 Prevent unhandled rejections when passing nullish into Contract constructor (#1234). 2021-02-12 18:58:28 -05:00
Richard Moore
8279120e0a Better error messaging when provider backends give bogus responses (#1243). 2021-02-12 18:52:44 -05:00
Richard Moore
243beffa4f Prevent unconfigured ENS names from making an init tx (#1290). 2021-02-12 18:25:25 -05:00
Richard Moore
3a76d69a16 admin: small updates to build scripts. 2021-02-08 15:27:05 -05:00
Richard Moore
5b41675f33 docs: commit built docs 2021-02-08 15:26:10 -05:00
Richard Moore
80cde06bcc Updated dist files 2021-02-08 15:24:45 -05:00
Richard Moore
7d0b33dc42 docs: more details on various APIs. 2021-02-08 14:52:31 -05:00
Richard Moore
173f4d44bf docs: update links in README (#1281). 2021-02-08 14:48:30 -05:00
Richard Moore
73e94349de When in Status trigger personal_sign instead of eth_sign (#1285). 2021-02-08 14:46:04 -05:00
Richard Moore
796954f880 Bump elliptic version for CVE-2020-28498 (#1284). 2021-02-08 14:38:24 -05:00
Richard Moore
f0a88f551f docs: better linking to errors in docs 2021-02-04 18:59:51 -05:00
Richard Moore
f4b97c00ed docs: added more on contributing (#1153). 2021-02-04 18:54:43 -05:00
Richard Moore
38eccc8b9d docs: more descriptions for logs and events. 2021-02-04 18:54:10 -05:00
Richard Moore
a3b5f7132c docs: typo 2021-02-04 18:48:07 -05:00
Richard Moore
a1e7db4abe docs: added links 2021-02-04 18:46:27 -05:00
Richard Moore
689459c1fd docs: added social profile assets 2021-02-04 18:45:09 -05:00
Richard Moore
755fc72094 docs: added other resources. 2021-02-04 18:44:37 -05:00
Richard Moore
620b7b91a1 docs: added some info on contract overrides (#1199). 2021-02-04 17:29:21 -05:00
Richard Moore
fb9eea6c7e docs: typos and corrected priority order (#1252, #1255). 2021-02-04 17:23:23 -05:00
Richard Moore
d83c583412 docs: updated NonceManager method name (#1271). 2021-02-04 17:22:26 -05:00
Richard Moore
3f97b94d15 docs: typos (#1189, #1261) 2021-02-04 17:21:11 -05:00
Richard Moore
0ae9ac6f98 docs: added details on URL for JsonRpcProvider regarding ConnectionInfo support (#1266). 2021-02-04 17:17:55 -05:00
Richard Moore
2333b6cfd2 Updated dist files. 2021-02-03 14:44:48 -05:00
Richard Moore
73b31b371f Fixed typos in JSON ABI formatting (#1275). 2021-02-03 14:26:10 -05:00
Richard Moore
fd0cf2cc54 Updated dist files. 2021-02-02 17:32:11 -05:00
Richard Moore
27a981c84b Added load balancer support to PocketProvider (#1052). 2021-02-02 17:05:47 -05:00
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
2787 changed files with 23315 additions and 13088 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' ]

22
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,22 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: investigate
assignees: ''
---
Note: Not all sections may be relevant, but please be as thorough while remaining concise as possible. Remove this Notice and any sections that don't feel pertinent.
**Describe the bug**
A clear and concise description of what the bug is.
**Reproduction steps**
Please include code snippets, with console.log output, any contract ABI, contract address, network and the full error.
**Environment:**
Please include anything that may be useful in diagnosing the issue. Node vs Browser? Geth vs Parity vs Ganache? Third Party tools, like Hardhat? Mobile vs. Desktop?
**Search Terms**
Often similar issues have come up before. Include any search terms you have tried in this repository's Issues (including closed issues) and Discussions, so if there are matching issues, we can be sure to add those keywords to make it easier for people to find in the future.

View File

@@ -0,0 +1,22 @@
---
name: Feature Request
about: Suggest a new feature for ethers
title: ''
labels: ''
assignees: ''
---
Note: The best place to start a Feature Request is usually in the Discussions, to mull through the desired feature, current options and think through the impact on the library overall.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

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

2
.gitignore vendored
View File

@@ -25,3 +25,5 @@ packages/testcases/input/nameprep/**
.nyc_output/**
output/**
misc/testing/**

View File

@@ -3,6 +3,145 @@ Changelog
This change log is managed by `admin/cmds/update-versions` but may be manually updated.
ethers/v5.2.0 (2021-05-17 16:18)
--------------------------------
- More aggresively check for mempool transactions sent from JsonRpcSigner. ([3316468](https://github.com/ethers-io/ethers.js/commit/3316468e3e0a5925cbecad85d894cc7d622394e7))
- Added initial support for detecting replacement transactions. ([#1477](https://github.com/ethers-io/ethers.js/issues/1477); [987bec8](https://github.com/ethers-io/ethers.js/commit/987bec87afaa365f291290a0136cedbc2b1992f2), [5144acf](https://github.com/ethers-io/ethers.js/commit/5144acf456b51c95bbe3950bd37609abecc7ebc7))
- Added convenience method for HD path derivation. ([aadc5cd](https://github.com/ethers-io/ethers.js/commit/aadc5cd3d65421e13ebd4e4d7c293ac3ece5e178))
- Added mnemonicPath option to cli. ([6e08809](https://github.com/ethers-io/ethers.js/commit/6e088099adabd7c5d2e6710062ebc62b316ba0f1))
- Added some popular Ethereum-compatible chains to networks. ([b6370f1](https://github.com/ethers-io/ethers.js/commit/b6370f13600a0c444342cbf16a83f010a929976b))
- Added debug event to Web3Provider. ([26464c5](https://github.com/ethers-io/ethers.js/commit/26464c54258f98c321638475d6cf11595186e76d))
- Abstracted EtherscanProivder to more easily fascilitate other Etherscan-supported chains. ([#1204](https://github.com/ethers-io/ethers.js/issues/1204), [#1473](https://github.com/ethers-io/ethers.js/issues/1473); [37a9c77](https://github.com/ethers-io/ethers.js/commit/37a9c77ab2acb7f75e1fc4cc918810d2fe59dd76))
- Added Custom Contract Errors. ([#1498](https://github.com/ethers-io/ethers.js/issues/1498); [6519609](https://github.com/ethers-io/ethers.js/commit/65196097f6626401638d85cf19e3d628a6223d5d), [483d67f](https://github.com/ethers-io/ethers.js/commit/483d67f55c15a76bcd853e889a0e35815d9850f7))
- More flexible FixedNumber input and output for strings with no decimals. ([#1019](https://github.com/ethers-io/ethers.js/issues/1019), [#1291](https://github.com/ethers-io/ethers.js/issues/1291), [#1463](https://github.com/ethers-io/ethers.js/issues/1463); [a9cdbe1](https://github.com/ethers-io/ethers.js/commit/a9cdbe1238c149a7167c6bb1a78f314805b52755))
- Added hex support for bigint. ([#1472](https://github.com/ethers-io/ethers.js/issues/1472); [4e9abfd](https://github.com/ethers-io/ethers.js/commit/4e9abfdee478a8423da4d55feea8c1aae78a8eb4))
- Added support for null entries in EventFilter. ([#1499](https://github.com/ethers-io/ethers.js/issues/1499); [3bb5fbf](https://github.com/ethers-io/ethers.js/commit/3bb5fbf533107e880377ecc14f30f314a5028e56))
- Add bigint to allowed BigNumberish types. ([#1472](https://github.com/ethers-io/ethers.js/issues/1472); [cadccc3](https://github.com/ethers-io/ethers.js/commit/cadccc3060b88ab2ca64aeb302717d2d1c95a897))
- Minor version bump. ([8e22e02](https://github.com/ethers-io/ethers.js/commit/8e22e0260eb70713c943c9e99ee8d66d71ebe56d))
ethers/v5.1.4 (2021-04-22 06:33)
--------------------------------
- Do not throw on ABI "error" type. ([#1493](https://github.com/ethers-io/ethers.js/issues/1493), [#1497](https://github.com/ethers-io/ethers.js/issues/1497); [bd05aed](https://github.com/ethers-io/ethers.js/commit/bd05aed070ac9e1421a3e2bff2ceea150bedf9b7))
ethers/v5.1.3 (2021-04-19 21:01)
--------------------------------
- Fixed JsonRpcProvider event-loop caching when using any network. ([#1484](https://github.com/ethers-io/ethers.js/issues/1484); [58488e7](https://github.com/ethers-io/ethers.js/commit/58488e78f9ef79715693e19b42663335aad88c03))
- Updated experimental Eip1193Bridge to support final EIP-1193 API. ([2911659](https://github.com/ethers-io/ethers.js/commit/29116593ba6c9c0fa491b13787cca8b233d4218c))
- Fail early for ABI decoding that will obviously run out of data. ([#1486](https://github.com/ethers-io/ethers.js/issues/1486); [51f0e1a](https://github.com/ethers-io/ethers.js/commit/51f0e1a52fb885e6f146f7b3b70ed487fd1c8f5a))
- Fixed BigNumber toBigInt return type. ([#1485](https://github.com/ethers-io/ethers.js/issues/1485); [c086962](https://github.com/ethers-io/ethers.js/commit/c0869623024bbf3671938dad03b131ff2ac54345))
ethers/v5.1.2 (2021-04-18 19:31)
--------------------------------
- Increase provider tests gas price for sending a transaction. ([8eaeba3](https://github.com/ethers-io/ethers.js/commit/8eaeba35f550c3d9aa1ae62eb8d8e0c912818f7f))
- Fixed run-checking non-filter Contract events. ([#1458](https://github.com/ethers-io/ethers.js/issues/1458); [4a44865](https://github.com/ethers-io/ethers.js/commit/4a44865a8c22adb9c55d5c37a81ee46ebc68228c))
ethers/v5.1.1 (2021-04-18 02:47)
--------------------------------
- Increased sendTransaction timeout to 15 minutes and pull Pocket from tx tests. ([08adc18](https://github.com/ethers-io/ethers.js/commit/08adc18a68bdc730633bdaaf2329014a84c12b2b))
- Export Eip1193Bridge in experimental package. ([1fcf4b6](https://github.com/ethers-io/ethers.js/commit/1fcf4b6ce6922d2bcb245375c967da3072f113ed))
- Prevent non-typed transactions from unsafely ignoring specified access lists. ([#1364](https://github.com/ethers-io/ethers.js/issues/1364); [4577444](https://github.com/ethers-io/ethers.js/commit/4577444c448f41114263077c5b54fbe6af749fd4))
- Update tests for current EIP-2930 support across backends. ([#1364](https://github.com/ethers-io/ethers.js/issues/1364); [1cb3199](https://github.com/ethers-io/ethers.js/commit/1cb3199e5cb01f5a55eb00ab6c7904606d7ea1dd))
- Removed underscore from the JsonRpcBatchProvider name. ([#62](https://github.com/ethers-io/ethers.js/issues/62), [#656](https://github.com/ethers-io/ethers.js/issues/656), [#892](https://github.com/ethers-io/ethers.js/issues/892); [ae0d5eb](https://github.com/ethers-io/ethers.js/commit/ae0d5eb7c2e37a003d893671db59c2d5719aea0f))
- Added better error detection when pre-EIP-155 transactions are disabled. ([b8df000](https://github.com/ethers-io/ethers.js/commit/b8df000c8f0ccd252b6049ac5a32a986d5a8e08d))
- Fix Android React Native environment shims which crash on normalizing Korean test. ([#1298](https://github.com/ethers-io/ethers.js/issues/1298); [eb1ec2f](https://github.com/ethers-io/ethers.js/commit/eb1ec2f2318e2851073ea1634e5003cdb53f1c1b))
- Fixed EIP-2930 transactions for EtherscanProvider. ([#1364](https://github.com/ethers-io/ethers.js/issues/1364); [b655089](https://github.com/ethers-io/ethers.js/commit/b65508995ce7d02f109a970ebeb625819beb915a))
- Re-enable AlchemyProvider Berlin tests. ([bec066b](https://github.com/ethers-io/ethers.js/commit/bec066bcb5ab8b95a7e7ce4848d7b76d7f248ccc))
- Added experimental _JsonRpcBatchProvider. ([#62](https://github.com/ethers-io/ethers.js/issues/62), [#656](https://github.com/ethers-io/ethers.js/issues/656), [#892](https://github.com/ethers-io/ethers.js/issues/892); [d55ab6d](https://github.com/ethers-io/ethers.js/commit/d55ab6d4e6025c484cc7e64486d927bd54a0772b))
- Cache JsonRpcProvider requests for certain methods per event loop. ([#1371](https://github.com/ethers-io/ethers.js/issues/1371); [1a7c4e8](https://github.com/ethers-io/ethers.js/commit/1a7c4e89efecc2b8afc8bea4c1f8f75fdaac08c5))
ethers/v5.1.0 (2021-03-30 14:44)
--------------------------------
- Added BigNumber.toBigInt method. ([#1415](https://github.com/ethers-io/ethers.js/issues/1415); [81fd628](https://github.com/ethers-io/ethers.js/commit/81fd628292b7dde90fe5115074fa68476a872dbf))
- Abstracted Contract with BaseContract without meta-class properties for easier extensions. ([#1384](https://github.com/ethers-io/ethers.js/issues/1384); [87ceaed](https://github.com/ethers-io/ethers.js/commit/87ceaed4be21283619da74678cf371c228c918b7))
- Fixed Contract properties that collide with null member properties. ([#1393](https://github.com/ethers-io/ethers.js/issues/1393); [0e1721b](https://github.com/ethers-io/ethers.js/commit/0e1721b13084dacf63089e47116f7d5331be4f36))
- Added EIP-2930 support. ([#1364](https://github.com/ethers-io/ethers.js/issues/1364); [c47d2eb](https://github.com/ethers-io/ethers.js/commit/c47d2eba4dc741eb5cb754c3ef5064b8ea7ac7cc))
- Added abstraction for EIP-2718 support. ([1db4ce1](https://github.com/ethers-io/ethers.js/commit/1db4ce12d49e235a7155de24ee153f409e7e7370))
ethers/v5.0.32 (2021-03-07 18:17)
---------------------------------
- Bumped TypeScript to 4.2.2. ([#1288](https://github.com/ethers-io/ethers.js/issues/1288); [b2ecffb](https://github.com/ethers-io/ethers.js/commit/b2ecffb0c8d44c8ee65199e7866dc744abae4e6e))
- Fixed shims from not displaying debug information. ([a953f71](https://github.com/ethers-io/ethers.js/commit/a953f717523a844a3a45810a5acc6630383884d3))
- Force TypedData numbers to be in decimal. ([#1193](https://github.com/ethers-io/ethers.js/issues/1193); [c5a53d6](https://github.com/ethers-io/ethers.js/commit/c5a53d6911d7c41dd03a290b550e80f2919e9379))
ethers/v5.0.31 (2021-02-12 19:04)
---------------------------------
- Prevent unhandled rejections when passing nullish into Contract constructor. ([#1234](https://github.com/ethers-io/ethers.js/issues/1234); [d937668](https://github.com/ethers-io/ethers.js/commit/d937668dc1d39cc293f64bbd30b99b29614d1607))
- Better error messaging when provider backends give bogus responses. ([#1243](https://github.com/ethers-io/ethers.js/issues/1243); [8279120](https://github.com/ethers-io/ethers.js/commit/8279120e0ad1cbb7aeabd32c08e168a4228abbec))
- Prevent unconfigured ENS names from making an init tx. ([#1290](https://github.com/ethers-io/ethers.js/issues/1290); [243beff](https://github.com/ethers-io/ethers.js/commit/243beffa4f83c910f5f1c5e0554531e5dcf3ab93))
ethers/v5.0.30 (2021-02-08 15:22)
---------------------------------
- When in Status trigger personal_sign instead of eth_sign. ([#1285](https://github.com/ethers-io/ethers.js/issues/1285); [73e9434](https://github.com/ethers-io/ethers.js/commit/73e94349de94d2969ccb21c834119525ddfcb961))
- Bump elliptic version for CVE-2020-28498. ([#1284](https://github.com/ethers-io/ethers.js/issues/1284); [796954f](https://github.com/ethers-io/ethers.js/commit/796954f8807b0c464c7baa8f7ff299e22685e192))
ethers/v5.0.29 (2021-02-03 14:36)
---------------------------------
- Fixed typos in JSON ABI formatting. ([#1275](https://github.com/ethers-io/ethers.js/issues/1275); [73b31b3](https://github.com/ethers-io/ethers.js/commit/73b31b371fa47bacc4f5f6bed01d0d1e5d66fa2c))
ethers/v5.0.28 (2021-02-02 17:12)
---------------------------------
- Added load balancer support to PocketProvider. ([#1052](https://github.com/ethers-io/ethers.js/issues/1052); [27a981c](https://github.com/ethers-io/ethers.js/commit/27a981c84b578feb762fdb37dd5325d9c335bd59))
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)
---------------------------------

View File

@@ -44,7 +44,7 @@ Installing
**browser (UMD)**
```
<script src="https://cdn.ethers.io/lib/ethers-5.0.umd.min.js" type="text/javascript">
<script src="https://cdn.ethers.io/lib/ethers-5.1.umd.min.js" type="text/javascript">
</script>
```
@@ -52,7 +52,7 @@ Installing
```
<script type="module">
import { ethers } from "https://cdn.ethers.io/lib/ethers-5.0.umd.min.js";
import { ethers } from "https://cdn.ethers.io/lib/ethers-5.1.esm.min.js";
</script>
```
@@ -80,9 +80,9 @@ everyone else with packages they do not need.
We will keep a list of useful packages here.
- `@ethersproject/experimental` ([documentation](https://docs.ethers.io))
- `@ethersproject/cli` ([documentation](https://docs.ethers.io))
- `@ethersproject/hardware-wallets` ([documentation](https://docs.ethers.io))
- `@ethersproject/experimental` ([documentation](https://docs.ethers.io/v5/api/experimental/))
- `@ethersproject/cli` ([documentation](https://docs.ethers.io/v5/cli/))
- `@ethersproject/hardware-wallets` ([documentation](https://docs.ethers.io/v5/api/other/hardware/))
License

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 @@

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

@@ -1,18 +1,22 @@
_section: Contract @<Contract> @SRC<contracts:class.Contract>
Explain contract here...
A **Contract** is an abstraction of code that has been deployed
to the blockchain.
A Contract may be sent transactions, which will trigger its code
to be run with the input of the transaction data.
_subsection: Creating Instances @<Contract--creating>
_property: new ethers.Contract(address, abi, signerOrProvider) @src<contracts:constructor.Contract>
_property: new ethers.Contract(address, abi, signerOrProvider) @src<contracts:class.Contract>
_property: contract.attach(addressOrName) => [[Contract]] @<Contract-attach> @SRC<contracts:Contract.attach>
_property: contract.attach(addressOrName) => [[Contract]] @<Contract-attach> @SRC<contracts:BaseContract.attach>
Returns a new instance of the **Contract** attached to a new
address. This is useful if there are multiple similar or identical
copies of a Contract on the network and you wish to interact with
each of them.
_property: contract.connect(providerOrSigner) => [[Contract]] @<Contract-connect> @SRC<contracts:Contract.connect>
_property: contract.connect(providerOrSigner) => [[Contract]] @<Contract-connect> @SRC<contracts:BaseContract.connect>
Returns a new instance of the Contract, but connected to
//providerOrSigner//.
@@ -61,11 +65,11 @@ _subsection: Events @<Contract--events>
_property: contract.queryFilter(event [ , fromBlockOrBlockHash [ , toBlock ]) => Promise<Array<Event>> @<Contract-queryFilter> @SRC<contracts>
Return Events that match the //event//.
_property: contract.listenerCount([ event ]) => number @<Contract-listenerCount> @SRC<contracts:Contract.listenerCount>
_property: contract.listenerCount([ event ]) => number @<Contract-listenerCount> @SRC<contracts:BaseContract.listenerCount>
Return the number of listeners that are subscribed to //event//. If
no event is provided, returns the total count of all events.
_property: contract.listeners(event) => Array<Listener> @<Contract-listeners> @SRC<contracts:Contract.listeners>
_property: contract.listeners(event) => Array<Listener> @<Contract-listeners> @SRC<contracts:BaseContract.listeners>
Return a list of listeners that are subscribed to //event//.
_property: contract.off(event, listener) => this @<Contract-off> @SRC<contracts>
@@ -78,7 +82,7 @@ _property: contract.once(event, listener) => this @<Contract-once> @SRC<contrac
Subscribe once to //event// calling //listener// when the event
occurs.
_property: contract.removeAllListeners([ event ]) => this @<Contract-removeAllListeners> @SRC<contracts:Contract.removeAllListeners>
_property: contract.removeAllListeners([ event ]) => this @<Contract-removeAllListeners> @SRC<contracts:BaseContract.removeAllListeners>
Unsubscribe all listeners for //event//. If no event is provided,
all events are unsubscribed.
@@ -101,7 +105,10 @@ free and does not require any ether, but **cannot make changes** to
the blockchain state..
_property: contract.METHOD_NAME(...args [, overrides ]) => Promise<any> @<Contract-functionsCall>
The type of the result depends on the ABI.
The type of the result depends on the ABI. If the method returns a single
value, it will be returned directly, otherwise a [[Result]] object will
be returned with each parameter available positionally and if the parameter
is named, it will also be available by its name.
For values that have a simple meaning in JavaScript, the types are fairly
straight forward; strings and booleans are returned as JavaScript strings
@@ -113,6 +120,32 @@ number is used. Otherwise a [[BigNumber]] is returned.
For bytes (both fixed length and dynamic), a [[DataHexString]] is returned.
If the call reverts (or runs out of gas), a [CALL_EXCEPTION](errors--call-exception)
will be thrown which will include:
- ``error.address`` - the contract address
- ``error.args`` - the arguments passed into the method
- ``error.transaction`` - the transaction
The //overrides// object for a read-only method may include any of:
- ``overrides.from`` - the ``msg.sender`` (or ``CALLER``) to use during the
execution of the code
- ``overrides.value`` - the ``msg.value`` (or ``CALLVALUE``) to use during the
exectuiont of the code
- ``overrides.gasPrice`` - the price to pay per gas (theoretically); since there
is no transaction, there is not going to be any fee charged, but the EVM still
requires a value to report to ``tx.gasprice`` (or ``GASPRICE``);
//most developers will not require this//
- ``overrides.gasLimit`` - the amount of gas (theoretically) to allow a node
to use during the execution of the code; since there is no transaction, there
is not going to be any fee charged, but the EVM still processes gas metering
so calls like ``gasleft`` (or ``GAS``) report meaningful values
- ``overrides.blockTag`` - a block tag to simulate the execution at, which
can be used for hypothetical historic analysis; note that many backends
do not support this, or may require paid plans to access as the node database
storage and processing requirements are much higher
_property: contract.functions.METHOD_NAME(...args [, overrides ]) => Promise<[[Result]]>
The result will always be a [[Result]], even if there is only a single
@@ -130,6 +163,8 @@ allowing an alternate UTF-8 error strategy to be used.
Most developers should not require this.
The //overrides// are identical to the read-only operations above.
_heading: Write Methods (non-constant) @<Contract--write>
A non-constant method requires a transaction to be signed and requires
@@ -147,6 +182,32 @@ Returns a [[providers-TransactionResponse]] for the transaction after
it is sent to the network. This requires the **Contract** has a
signer.
The //overrides// object for write methods may include any of:
- ``overrides.gasPrice`` - the price to pay per gas
- ``overrides.gasLimit`` - the limit on the amount of gas to allow the transaction
to consume; any unused gas is returned at the gasPrice
- ``overrides.value`` - the amount of ether (in wei) to forward with the call
- ``overrides.nonce`` - the nonce to use for the [[Signer]]
If the ``wait()`` method on the returned [[providers-TransactionResponse]]
is called, there will be additional properties on the receipt:
- ``receipt.events`` - an array of the logs, with additional properties
(if the ABI included a description for the events)
- ``receipt.events[n].args`` - the parsed arguments
- ``receipt.events[n].decode`` - a method that can be used to parse the
log topics and data (this was used to compute ``args``)
- ``receipt.events[n].event`` - the name of the event
- ``receipt.events[n].eventSignature`` - the full signature of the event
- ``receipt.removeListener()`` - a method to remove the listener that trigger
this event
- ``receipt.getBlock()`` - a method to return the [Block](providers-Block) this event occurred in
- ``receipt.getTransaction()`` - a method to return the
[Transaction](providers-TransactionResponse) this event occurred in
- ``receipt.getTransactionReceipt()`` - a method to return the
[Transaction Receipt](providers-TransactionReceipt) this event occurred in
_heading: Write Methods Analysis @<Contract--check>
@@ -157,11 +218,17 @@ _property: contract.estimateGas.METHOD_NAME(...args [ , overrides ]) => Promise<
Returns the estimate units of gas that would be required to
execute the //METHOD_NAME// with //args// and //overrides//.
The //overrides// are identical to the overrides above for read-only
or write methods, depending on the type of call of //METHOD_NAME//.
_property: contract.populateTransaction.METHOD_NAME(...args [ , overrides ]) => Promise<[UnsignedTx](UnsignedTransaction)> @<contract-populateTransaction>
Returns an [[UnsignedTransaction]] which represents the transaction
that would need to be signed and submitted to the network to execute
//METHOD_NAME// with //args// and //overrides//.
The //overrides// are identical to the overrides above for read-only
or write methods, depending on the type of call of //METHOD_NAME//.
_property: contract.callStatic.METHOD_NAME(...args [ , overrides ]) => Promise<any> @<contract-callStatic>
Rather than executing the state-change of a transaction, it is possible
to ask a node to //pretend// that a call is not state-changing and
@@ -172,6 +239,8 @@ can be used to determine if a transaction will fail or succeed.
This otherwise functions the same as a [Read-Only Method](Contract--readonly).
The //overrides// are identical to the read-only operations above.
_heading: Event Filters @<Contract--filters>
An event filter is made up of topics, which are values logged in a
[[link-wiki-bloomfilter]], allowing efficient searching for entries

View File

@@ -136,7 +136,7 @@ Returns the number of decimal places used by this ERC-20 token. This can be
used with [parseUnits](utils-parseUnits) when taking input from the user or
[formatUnits](utils-formatunits] when displaying the token amounts in the UI.
_property: erc20.getBalance(owner [, overrides ]) => Promise<[[BigNumber]]>
_property: erc20.balanceOf(owner [, overrides ]) => Promise<[[BigNumber]]>
Returns the balance of //owner// for this ERC-20 token.
_property: erc20.symbol([ overrides ]) => Promise<string>

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
_property: nonceManager.incrementTransactionCount( [ 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

@@ -5,11 +5,13 @@ with Ethereum and is available in all major Ethereum node implementations
(e.g. [[link-geth]] and [[link-parity]]) as well as many
third-party web services (e.g. [[link-infura]])
_property: new ethers.providers.JsonRpcProvider([ url [ , aNetworkish ] ]) @SRC<providers:constructor.JsonRpcProvider>
Connect to a JSON-RPC API located at //url// using the //aNetworkish// network.
If //url// is not specified, the default (i.e. ``http:/\/localhost:8545``) is used
and if no network is specified, it will be determined automatically by
querying the node.
_property: new ethers.providers.JsonRpcProvider([ urlOrConnectionInfo [ , networkish ] ]) @SRC<providers:constructor.JsonRpcProvider>
Connect to a JSON-RPC HTTP API using the URL or [[ConnectionInfo]] //urlOrConnectionInfo//
connected to the //networkish// network.
If //urlOrConnectionInfo// is not specified, the default (i.e. ``http:/\/localhost:8545``)
is used and if no network is specified, it will be determined automatically by querying the
node using ``eth_chaindId`` and falling back on ``eth_networkId``.
_note: Note: Connecting to a Local Node
Each node implementation is slightly different and may require specific

View File

@@ -1,7 +1,5 @@
_section: Other Providers
Others...
_subsection: FallbackProvider @<FallbackProvider> @INHERIT<[[Provider]]> @SRC<providers/fallback-provider:class.FallbackProvider>
The **FallbackProvider** is the most advanced [[Provider]] available in
@@ -11,7 +9,7 @@ It uses a quorum and connects to multiple [Providers](Provider) as backends,
each configured with a //priority// and a //weight// .
When a request is made, the request is dispatched to multiple backends, randomly
chosen (higher priority backends are always selected first) and the results from
chosen (lower-value priority backends are always selected first) and the results from
each are compared against the others. Only once the quorum has been reached will that
result be accepted and returned to the caller.
@@ -40,9 +38,9 @@ _property: fallbackProviderConfig.provider => [[Provider]]
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
at random.
The priority used for the provider. Lower-value priorities are favoured over
higher-value priorities. If multiple providers share the same priority, they
are chosen at random.
_property: fallbackProviderConfig.stallTimeout => number
The timeout (in ms) after which another [[Provider]] will be attempted. This
@@ -152,11 +150,11 @@ 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.
_property: new ethers.provider.WebSocketProvider([ url [ , network ] ])
_property: new ethers.providers.WebSocketProvider([ url [ , network ] ])
Returns a new [[WebSocketProvider]] connected to //url// as the //network//.
If //url// is unspecified, the default ``"ws:/\/localhost:8546"`` will be used.

View File

@@ -1,7 +1,20 @@
_section: Provider @<Provider>
Explain what a provider is...
A **Provider** in ethers is a read-only abstraction to
access the blockchain data.
_note: Coming from Web3.js?
If you are coming from Web3.js, this is one of the biggest
differences you will encounter using ethers.
The ethers library creates a strong division between the
operation a **Provider** can perform and those of a [[Signer]],
which Web3.js lumps together.
This separation of concerns and a stricted subset of Provider
operations allows for a larger variety of backends, a more
consistent API and ensures other libraries to operate without
being able to rely on any underlying assumption.
_subsection: Accounts Methods @<Provider--account-methods>
@@ -73,6 +86,10 @@ reading and debugging much simpler.
The provider offers some basic operations to help resolve and
work with ENS names.
_property: provider.getResolver(name) => Promise<[[EnsResolver]]>
Returns an EnsResolver instance which can be used to further inquire
about specific entries for an ENS name.
_property: provider.lookupAddress(address) => Promise<string> @<Provider-lookupAddress> @SRC<providers/base-provider>
Performs a reverse lookup of the //address// in ENS using the
//Reverse Registrar//. If the name does not exist, or the
@@ -94,6 +111,25 @@ provider.resolveName("ricmoo.firefly.eth");
//!
_subsection: EnsResolver @<EnsResolver>
_property: resolver.name => string
The name of this resolver.
_property: resolver.address => string<[[address]]>
The address of the Resolver.
_property: resolver.getAddress([ cointType = 60 ]) => Promise<string>
Returns a Promise which resolves to the [[link-eip-2304]] multicoin address
stored for the //coinType//. By default an Ethereum [[address]]
(``coinType = 60``) will be returned.
_property: resolver.getContentHash() => Promise<string>
Returns a Promise which resolves to any stored [[link-eip-1577]] content hash.
_property: resolver.getText(key) => Promise<string>
Returns a Promise which resolves to any stored [[link-eip-634]] text entry for //key//.
_subsection: Logs Methods @<Provider--log-methods>
_property: provider.getLogs(filter) => Promise<Array<[[providers-Log]]>> @<Provider-getLogs> @SRC<providers/base-provider>
@@ -115,6 +151,13 @@ Returns the block number (or height) of the most recently mined block.
_property: provider.getGasPrice() => Promise<[[BigNumber]]> @<Provider-getGasPrice> @SRC<providers/base-provider>
Returns a //best guess// of the [[gas-price]] to use in a transaction.
_property: provider.ready => Promise<[[providers-Network]]> @<Provider-ready> @src<providers/base-provider>
Returns a Promise which will stall until the network has heen established,
ignoring errors due to the target node not being active yet.
This can be used for testing or attaching scripts to wait until the node is
up and running smoothly.
_code: Network Status Examples @lang<javascript>
// The network information
@@ -146,7 +189,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//
@@ -156,6 +199,21 @@ An estimate may not be accurate since there could be another transaction
on the network that was not accounted for, but after being mined affected
relevant state.
_property: provider.getTransaction(hash) => Promise<[[providers-TransactionResponse]]> @<Provider-getTransaction> @src<providers/base-provider>
Returns the transaction with //hash// or null if the transaction is unknown.
If a transaction has not been mined, this method will search the transaction
pool. Various backends may have more restrictive transaction pool access (e.g.
if the gas price is too low or the transaction was only recently sent and not
yet indexed) in which case this method may also return null.
_property: provider.getTransactionReceipt(hash) => Promise<[[providers-TransactionReceipt]]> @<Provider-getTransactionReceipt> @src<providers/base-provider>
Returns the transaction receipt for //hash// or null if the transaction
has not been mined.
To stall until the transaction has been mined, consider the ``waitForTransaction``
method below.
_property: provider.sendTransaction(transaction) => Promise<[[providers-TransactionResponse]]> @<Provider-sendTransaction> @SRC<providers/base-provider>
Submits //transaction// to the network to be mined. The //transaction// **must** be signed,
and be valid (i.e. the nonce is correct and the account has sufficient balance to pay
@@ -164,36 +222,47 @@ for the transaction).
_property: provider.waitForTransaction(hash [ , confirms = 1 [ , timeout ] ]) => Promise<[TxReceipt](providers-TransactionReceipt)> @<Provider-waitForTransaction> @SRC<providers/base-provider>
Returns a Promise which will not resolve until //transactionHash// is mined.
If //confirms// is 0, this method is non-blocking and if the
transaction has not been mined returns null. Otherwise,
this method will block until the transaction has //confirms//
blocks mined on top of the block in which is was mined.
_subsection: Event Emitter Methods @<Provider--event-methods>
Explain events here...
The EventEmitter API allows applications to use an
[[link-wiki-observer-pattern]] to register callbacks for when
various events occur.
This closely follows the Event Emitter provided by other JavaScript
libraries with the exception that event names support some more
[complex objects](Provider--events), not only strings. The objects
are normalized internally.
_property: provider.on(eventName, listener) => this @<Provider-on> @SRC<providers/base-provider>
Add a //listener// to be triggered for each //eventName//.
Add a //listener// to be triggered for each //eventName// [event](Provider--events).
_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.
Add a //listener// to be triggered for only the next
//eventName// [event](Provider--events), 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
is generally only used internally.
Notify all listeners of the //eventName// [event](Provider--events),
passing //args// to each listener. This is generally only used internally.
_property: provider.off(eventName [ , listener ]) => this @<Provider-off> @SRC<providers/base-provider>
Remove a //listener// for //eventName//. If no //listener// is provided,
all listeners for //eventName// are removed.
Remove a //listener// for the //eventName// [event](Provider--events).
If no //listener// is provided, all listeners for //eventName// are removed.
_property: provider.removeAllListeners([ eventName ]) => this @<Provider-removeAllListeners> @SRC<providers/base-provider>
Remove all the listeners for //eventName//. If no //eventName// is provided,
**all** events are removed.
Remove all the listeners for the //eventName// [events](Provider--events).
If no //eventName// is provided, **all** events are removed.
_property: provider.listenerCount([ eventName ]) => number @<Provider-listenerCount> @SRC<providers/base-provider>
Returns the number of listeners for //eventName//. If no //eventName// is
provided, the total number of listeners is returned.
Returns the number of listeners for the //eventName// [events](Provider--events).
If no //eventName// is provided, the total number of listeners is returned.
_property: provider.listeners(eventName) => Array<Listener> @<Provider-listeners> @SRC<providers/base-provider>
Returns the list of Listeners for //eventName//.
Returns the list of Listeners for the //eventName// [events](Provider--events).
_heading: Events @<Provider--events>
@@ -207,7 +276,7 @@ properties ``address`` (the source contract) and ``topics`` (a topic-set to matc
If ``address`` is unspecified, the filter matches any contract address.
See events for more information on how to specify topic-sets.
See [EventFilters](providers-EventFilter) for more information on filtering events.
_definition: **Topic-Set Filter**
@@ -216,6 +285,8 @@ The value of a **Topic-Set Filter** is a array of Topic-Sets.
This event is identical to a //Log Filter// with the address omitted (i.e. from
any contract).
See [EventFilters](providers-EventFilter) for more information on filtering events.
_definition: **Transaction Filter**
The value of a **Transaction Filter** is any transaction hash.

View File

@@ -1,23 +1,15 @@
_section: Types
_subsection: BlockTag @<providers-BlockTag>
A **BlockTag** specifies a specific location in the Blockchain.
A **BlockTag** specifies a specific block location in the Blockchain.
- **``"latest"``** -- The most recently mined block
- **``"earliest"``** -- Block #0
- **``"pending"``** -- The block currently being prepared for mining; not all
- **``"latest"``** - The most recently mined block
- **``"earliest"``** - Block #0
- **``"pending"``** - The block currently being prepared for mining; not all
operations and backends support this BlockTag
- **//number//** -- The block at this height
- **//a negative number//** -- The block this many blocks ago
_heading: EventType @<providers-EventType>
And **EventType** can be any of the following.
- **//string//** -- TODO...
- **//Array<string<[[DataHexString]]<32>> | Array<string<[[DataHexString]]<32>>>>//** -- TODO...
- **//[[providers-EventFilter]]//** -- TODO...
- **//number//** - The block at this height
- **//a negative number//** - The block this many blocks ago
- **//hex string//** - The block at this height (as a hexidecimal value)
_subsection: Networkish @<providers-Networkish>
A **Networkish** may be any of the following:
@@ -59,19 +51,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 +75,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)
@@ -111,10 +103,15 @@ _heading: EventFilter @<providers-EventFilter>
_property: filter.address => string<[[address]]>
The address to filter by, or ``null`` to match any address.
_property: filter.topics => Array<string<[[DataHexString]]<32>> | Array<string<[[DataHexString]]<32>>>>
The topics to filter by, or ``null`` to match any topics. Each entry represents an
**AND** condition that must match, or may be ``null`` to match anything. If a given
entry is an Array, then that entry is treated as an **OR** for any value in the entry.
_property: filter.topics => Array<string<[Data](DataHexString)<32>> | Array<string<[Data](DataHexString)<32>>>>
The topics to filter by or ``null`` to match any topics.
Each entry represents an **AND** condition that must match, or may
be ``null`` to match anything. If a given entry is an Array, then
that entry is treated as an **OR** for any value in the entry.
See [Filters](events--filters) for more details and examples
on specifying complex filters.
_heading: Filter @<providers-Filter> @INHERIT<[[providers-EventFilter]]>
@@ -205,7 +202,18 @@ The chain ID this transaction is authorized on, as specified by
If the chain ID is 0 will disable EIP-155 and the transaction will be valid
on any network. This can be **dangerous** and care should be taken, since it
allows transactions to be replayed on networks that were possibly not
intended.
intended. Intentionally-replayable transactions are also disabled by default
on recent versions of Geth and require configuration to enable.
_property: transactionRequest.type => null | number
The [[link-eip-2718]] type of this transaction envelope, or ``null``
for legacy transactions that do not have an envelope.
_property: transactionRequest.accessList => [[providers-AccessListish]]
The [[providers-AccessList]] to include in an [[link-eip-2930]] transaction, which will
include a ``type`` of ``1``.
_heading: TransactionResponse @<providers-TransactionResponse> @INHERIT<[[Transaction]]>
@@ -231,14 +239,33 @@ transaction was mined.
_property: transaction.raw => string<[[DataHexString]]>
The serialized transaction.
_property: transaction.wait([ confirmations = 1 ]) => Promise<[[providers-TransactionReceipt]]>
Wait for //confirmations//. If 0, and the transaction has not been mined,
``null`` is returned.
_property: transaction.wait([ confirms = 1 ]) => Promise<[[providers-TransactionReceipt]]>
Resolves to the [[providers-TransactionReceipt]] once the transaction
has been included in the chain for //confirms// blocks. If //confirms//
is 0, and the transaction has not been mined, ``null`` is returned.
If the transaction execution failed (i.e. the receipt status is ``0``),
a [CALL_EXCEPTION](errors--call-exception) Error will be rejected with
the following properties:
- ``error.transaction`` - the original transaction
- ``error.transactionHash`` - the hash of the transaction
- ``error.receipt`` - the actual receipt, with the status of ``0``
_property: transactionRequest.type => null | number
The [[link-eip-2718]] type of this transaction envelope, or ``null``
for legacy transactions that do not have an envelope.
_property: transactionRequest.accessList => [[providers-AccessList]]
The [[providers-AccessList]] included in an [[link-eip-2930]] transaction, which will
also have its ``type`` equal to ``1``.
_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 +322,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.
@@ -308,3 +335,110 @@ _property: receipt.status => boolean
The status of a transaction is 1 is successful or 0 if it was
reverted. Only transactions included in blocks [post-Byzantium Hard Fork](link-eip-609)
have this property.
_subsection: Access Lists
An Access List is optional an includes a list of addresses and storage
slots for that address which should be //warmed// or pre-fetched for
use within the execution of this transaction. A //warmed// value has an
additional upfront cost to access, but is discounted throughout the code
execution for reading and writing.
_heading: AccessListish @<providers-AccessListish>
A looser description of an [[providers-AccessList]], which will be
converted internally using [accessListify](utils-accessListify).
It may be any of:
- any [[providers-AccessList]]
- an Array of 2-element Arrays, where the first element is the address
and second array is an array of storage keys
- an object, whose keys represent the addresses and each value is an
array of storage keys
When using the object form (the last option), the addresses and storage
slots will be sorted. If an explicit order for the access list is
required, one of the other forms must be used. Most developers
**do not** require explicit order.
_code: equivalent to the AccessList example below @lang<javascript>
// Option 1:
// AccessList
// see below
// Option 2:
// Array< [ Address, Array<Bytes32> ] >
[
[
"0x0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
[
"0x0000000000000000000000000000000000000000000000000000000000000004",
"0x0bcad17ecf260d6506c6b97768bdc2acfb6694445d27ffd3f9c1cfbee4a9bd6d"
]
],
[
"0x5FfC014343cd971B7eb70732021E26C35B744cc4",
[
"0x0000000000000000000000000000000000000000000000000000000000000001"
]
]
]
// <hide>
;
// </hide>
// Option 3:
// Record<Address, Array<Bytes32>>
// <hide>
(
// </hide>
{
"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e": [
"0x0000000000000000000000000000000000000000000000000000000000000004",
"0x0bcad17ecf260d6506c6b97768bdc2acfb6694445d27ffd3f9c1cfbee4a9bd6d"
],
"0x5FfC014343cd971B7eb70732021E26C35B744cc4": [
"0x0000000000000000000000000000000000000000000000000000000000000001"
]
}
// <hide>
)
// </hide>
_heading: AccessList @<providers-AccessList>
An [[link-eip-2930]] transaction allows an optional **AccessList**
which causes a transaction to //warm// (i.e. pre-cache) another
addresses state and the specified storage keys.
This incurs an increased intrinsic cost for the transaction, but provides
discounts for storage and state access throughout the execution of the
transaction.
_code: example access list
// Array of objects with the form:
// {
// address: Address,
// storageKey: Array< DataHexString< 32 > >
// }
[
{
address: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
storageKeys: [
"0x0000000000000000000000000000000000000000000000000000000000000004",
"0x0bcad17ecf260d6506c6b97768bdc2acfb6694445d27ffd3f9c1cfbee4a9bd6d"
]
},
{
address: "0x5FfC014343cd971B7eb70732021E26C35B744cc4",
storageKeys: [
"0x0000000000000000000000000000000000000000000000000000000000000001"
]
}
]

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

@@ -45,13 +45,13 @@ _property: ethers.utils.getAddress(address) => string<[[address]]> @<utils-getA
Returns //address// as a Checksum Address.
If //address// is an invalid 40-nibble [[HexString]] or if it contains mixed case and
the checksum is invalid, an InvalidArgument Error is thrown.
the checksum is invalid, an [INVALID_ARGUMENT](errors--invalid-argument) Error is thrown.
The value of //address// may be any supported address format.
_property: ethers.utils.getIcapAddress(address) => string<[IcapAddress](address-icap)> @<utils-getIcapAddress> @SRC<address>
Returns //address// as an [ICAP address](link-icap).
Supports the same restrictions as [utils.getAddress](utils-getAddress).
Supports the same restrictions as [getAddress](utils-getAddress).
_property: ethers.utils.isAddress(address) => boolean @<utils-isAddress> @SRC<address>
Returns true if //address// is valid (in any supported format).

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

@@ -1,6 +1,13 @@
_section: Byte Manipulation
Tra la la...
While there are many high-level APIs for interacting with
Ethereum, such as [Contracts](Contract) and [Providers](Provider),
a lot of the low level access requires byte manipulation
operations.
Many of these operations are used internally, but can also be
used to help normalize binary data representations from the
output of various functions and methods.
_subsection: Types
@@ -155,7 +162,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

@@ -1,6 +1,16 @@
_section: HD Wallet @<hdnodes>
TODO: Explain [BIP32](link-bip-32) [BIP-39](link-bip-39) and whatnot here...
The Hierarchal Desterministic (HD) Wallet was a standard
created for Bitcoin, but lends itself well to a wide variety of
Blockchains which rely on secp256k1 private keys.
For a more detailed technical understanding:
- [BIP-32](link-bip-32) - the hierarchal deterministic description
- [BIP-39](link-bip-39) - the method used to derive the BIP-32 seed
from human-readable sequences of words (i.e. a mnemonic)
- [BIP-44](link-bip-44) - a standard defined to make BIP-32 easy
to adapt to any future compatible blockchain
_subsection: Types

View File

@@ -48,39 +48,38 @@ Throw an Error with //message// and an optional //code// and
additional //params// set.
_property: logger.throwArgumentError(message, name, value) => never @SRC<logger>
Throw an [INVALID_ARGUMENT](errors-InvalidArgument) Error with //name// and //value//.
Throw an [INVALID_ARGUMENT](errors--invalid-argument) Error with //name// and //value//.
_heading: Usage Validation
There can be used to ensure various properties and actions are safe.
_property: logger.checkAbstract(target, kind) => void @SRC<logger>
Checks that //target// is not //kind// and performs the same operations
as ``checkNew``. This is useful for ensuring abstract classes are not
being instantiated.
_property: logger.checkAbstract(target, kind) => void @<Logger-checkAbstract> @SRC<logger>
If //target// is //kind//, throws a [UNSUPPORTED_OPERATION](errors--unsupported-operation) error
otherwise performs the same operations as [checkNew](Logger-checkNew).
_property: logger.checkArgumentCount(count, expectedCount [ , message) => void @SRC<logger>
If //count// is not equal to //expectedCount//, throws a [MISSING_ARGUMENT](errors-MissingArgument)
or [UNEXPECTED_ARGUMENT](errors-UnexpectedArgument) error.
This is useful for ensuring abstract classes are not being instantiated.
_property: logger.checkNew(target, kind) => void @SRC<logger>
_property: logger.checkArgumentCount(count, expectedCount [ , message) => void @<Logger-checkArgumentCount> @SRC<logger>
If //count// is not equal to //expectedCount//, throws a [MISSING_ARGUMENT](errors--missing-argument)
or [UNEXPECTED_ARGUMENT](errors--unexpected-argument) error.
_property: logger.checkNew(target, kind) => void @<Logger-checkNew> @SRC<logger>
If //target// is not a valid ``this`` or ``target`` value, throw a
[MISSING_NEW](errors-MissingNew) error. This is useful to ensure
[MISSING_NEW](errors--missing-new) error. This is useful to ensure
callers of a Class are using ``new``.
_property: logger.checkNormalize(message) => void @SRC<logger>
_property: logger.checkNormalize(message) => void @<Logger-checkNoralize> @SRC<logger>
Check that the environment has a correctly functioning [[link-js-normalize]]. If not, a
[UNSUPPORTED_OPERATION](errors-UnsupportedOperation) error is thrown.
[UNSUPPORTED_OPERATION](errors--unsupported-operation) error is thrown.
_property: logger.checkSafeUint53(value [, message ]) => void @SRC<logger>
_property: logger.checkSafeUint53(value [, message ]) => void @<Logger-checkSafeUint53> @SRC<logger>
If //value// is not safe as a [JavaScript number](link-wiki-ieee754), throws a
[NUMERIC_FAULT](errors-NumericFault) error.
[NUMERIC_FAULT](errors--numeric-fault) error.
_heading: Censorship @<Logger--censorship>
_property: Logger.setCensorship(censor [ , permanent = false ]) => void @SRC<logger>
_property: Logger.setCensorship(censor [ , permanent = false ]) => void @<Logger-setCensorship> @SRC<logger>
Set error censorship, optionally preventing errors from being uncensored.
In production applications, this prevents any error from leaking information
@@ -88,7 +87,7 @@ by masking the message and values of errors.
This can impact debugging, making it substantially more difficult.
_property: Logger.setLogLevel(logLevel) => void @SRC<logger>
_property: Logger.setLogLevel(logLevel) => void @<Logger-setLogLevel> @SRC<logger>
Set the log level, to suppress logging output below a [particular log level](Logger-levels).
@@ -98,76 +97,113 @@ Every error in Ethers has a ``code`` value, which is a string that will
match one of the following error codes.
_heading: Generic Error Codes
_heading: Generic Error Codes @<errors-generic>
_property: Logger.errors.NOT_IMPLEMENTED
The operation is not implemented.
_property: Logger.errors.NOT_IMPLEMENTED @<errors--not-implemented>
The operation is not implemented. This may occur when calling a method
on a sub-class that has not fully implemented its abstract superclass.
_property: Logger.errors.SERVER_ERROR
_property: Logger.errors.SERVER_ERROR @<errors--server-error>
There was an error communicating with a server.
_property: Logger.errors.TIMEOUT @<errors-Timeout>
This may occur for a number of reasons, for example:
- a [CORS](link-cors) issue; this is quite often the problem and also the
hardest to diagnose and fix, so it is very beneficial to familiarize
yourself with CORS; some backends allow you configure your CORS, such as
the geth command-line or conifguration files or the INFURA and Alchemy
dashboards by specifing allowed Origins, methods, etc.
- an SSL issue; for example, if you are trying to connect to a local node via
HTTP but are serving the content from a secure HTTPS website
- a link issue; a firewall is preventing the traffic from reaching the server
- a server issue; the server is down, or is returning 500 error codes
- a backend DDoS mitigation proxy; for example, Etherscan operates behind a
Cloudflare proxy, which will block traffic if the request is sent via
specific User Agents or the client fingerprint is detected as a bot in some
cases
_property: Logger.errors.TIMEOUT @<errors--timeout>
A timeout occurred.
_property: Logger.errors.UNKNOWN_ERROR @<errors-UnknownError>
_property: Logger.errors.UNKNOWN_ERROR @<errors--unknown-error>
A generic unknown error.
_property: Logger.errors.UNSUPPORTED_OPERATION @<errors-UnsupportedOperation>
_property: Logger.errors.UNSUPPORTED_OPERATION @<errors--unsupported-operation>
The operation is not supported.
This can happen for a variety reasons, for example:
_heading: Safety Error Codes
- Some backends do not support certain operations; such as passing a blockTag
to an [[EtherscanProvider]] for [call](Provider-call)
- A [[Contract]] object connected to [[Provider]] (instead of a [[Signer]]) cannot
[sign](Signer-signTransaction) or [send](Signer-sendTransaction) transactions
- a [[Contract]] connected to a [[Signer]] without a [[Provider]] is write-only
and cannot estimate gas or execute static calls
_property: Logger.errors.BUFFER_OVERRUN
_heading: Safety Error Codes @<errors-safety>
_property: Logger.errors.BUFFER_OVERRUN @<errors--buffer-overrun>
The amount of data needed is more than the amount of data required,
which would cause the data buffer to read past its end.
_property: Logger.errors.NUMERIC_FAULT @<errors-NumericFault>
This can occur if a contract erroneously returns invalid ABI-encoded
data or RLP data is malformed.
_property: Logger.errors.NUMERIC_FAULT @<errors--numeric-fault>
There was an invalid operation done on numeric values.
Common cases of this occur when there is [[link-wiki-overflow]],
[[link-wiki-underflow]] in fixed numeric types or division by zero.
_heading: Usage Error Codes
_heading: Usage Error Codes @<errors-usage>
_property: Logger.errors.INVALID_ARGUMENT @<errors-InvalidArgument>
_property: Logger.errors.INVALID_ARGUMENT @<errors--invalid-argument>
The type or value of an argument is invalid. This will generally also
include the ``name`` and ``value`` of the argument. Any function which
accepts sensitive data (such as a private key) will include the string
``[\[REDACTED]\]`` instead of the value passed in.
``"[\[REDACTED]\]"`` instead of the value passed in.
_property: Logger.errors.MISSING_ARGUMENT @<errors-MissingArgument>
_property: Logger.errors.MISSING_ARGUMENT @<errors--missing-argument>
An expected parameter was not specified.
_property: Logger.errors.MISSING_NEW @<errors-MissingNew>
An object is a Class, but is now being called with ``new``.
_property: Logger.errors.MISSING_NEW @<errors--missing-new>
An object is a Class, but is not being called with ``new``.
_property: Logger.errors.UNEXPECTED_ARGUMENT @<errors-UnexpectedArgument>
_property: Logger.errors.UNEXPECTED_ARGUMENT @<errors--unexpected-argument>
Too many parameters we passed into a function.
_heading: Ethereum Error Codes
_heading: Ethereum Error Codes @<errors-ethereum>
_property: Logger.errors.CALL_EXCEPTION
_property: Logger.errors.CALL_EXCEPTION @<errors--call-exception>
An attempt to call a blockchain contract (getter) resulted in a
revert or other error.
revert or other error, such as insufficient gas (out-of-gas) or an
invalid opcode. This can also occur during gas estimation or if
waiting for a [[providers-TransactionReceipt]] which failed during execution.
_property: Logger.errors.INSUFFICIENT_FUNDS
Consult the contract to determine the cause, such as a failed condition
in a ``require`` statement. The ``reason`` property may provide more
context for the cause of this error.
_property: Logger.errors.INSUFFICIENT_FUNDS @<errors--insufficient-funds>
The account is attempting to make a transaction which costs more than is
available.
A sending account must have enough ether to pay for the value, the gas limit
(at the gas price) as well as the intrinsic cost of data. The intrinsic cost
of data is 4 gas for each zero byte and 68 gas for each non-zero byte.
of data is 4 gas for each zero byte and 68 gas for each non-zero byte, as well
as 35000 gas if a transaction contains no ``to`` property and is therefore
expected to create a new account.
_property: Logger.errors.NETWORK_ERROR
_property: Logger.errors.NETWORK_ERROR @<errors--network>
An Ethereum network validation error, such as an invalid chain ID.
_property: Logger.errors.NONCE_EXPIRED
_property: Logger.errors.NONCE_EXPIRED @<errors--nonce-expired>
The nonce being specified has already been used in a mined transaction.
_property: Logger.errors.REPLACEMENT_UNDERPRICED
_property: Logger.errors.REPLACEMENT_UNDERPRICED @<errors--replacement-underpriced>
When replacing a transaction, by using a nonce which has already been sent to
the network, but which has not been mined yet the new transaction must specify
a higher gas price.
@@ -175,9 +211,12 @@ a higher gas price.
This error occurs when the gas price is insufficient to //bribe// the transaction
pool to prefer the new transaction over the old one. Generally, the new gas price
should be about 50% + 1 wei more, so if a gas price of 10 gwei was used, the
replacement should be 15.000000001 gwei.
replacement should be 15.000000001 gwei. This is not enforced by the protocol, as
it deals with unmined transactions, and can be configured by each node, however
to ensure a transaction is propagated to a miner it is best practice to follow
the defaults most nodes have enabled.
_property: Logger.errors.UNPREDICTABLE_GAS_LIMIT
_property: Logger.errors.UNPREDICTABLE_GAS_LIMIT @<errors--unpredicatable-gas-limit>
When estimating the required amount of gas for a transaction, a node is queried for
its best guess.
@@ -196,7 +235,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

@@ -1,9 +1,40 @@
_section: Property Utilities
_property: ethers.utils.checkProperties() => void
This is a collection of utility functions used for handling
properties in a platform-safe way.
The next major version of ethers will no longer be compatible
with ES3, so many of these will be removed in favor of the
built-in options available in ES2015 and above.
_property: ethers.utils.checkProperties(object, check) => void
Checks that //object// only contains properties included
in //check//, and throws [INVALID_ARGUMENT](errors--invalid-argument) if not.
_property: ethers.utils.deepCopy(anObject) => any
Creates a recursive copy of //anObject//. Frozen (i.e. and other known
immutable) objects are copied by reference.
_property: ethers.utils.defineReadOnly(anObject, name, value) => void
Uses the ``Object.defineProperty`` method to set a read-only property
on an object.
_property: ethers.utils.getStatic(aConstructor, key) => any
Recursively check for a static method //key// on an inheritance chain
from //aConstructor// to all ancestors.
This is used to mimic behaviour in other languages where ``this`` in
a static method will also search ancestors.
_property: ethers.utils.resolveProperties(anObject) => Promise<any> @<utils-resolveproperties> @SRC<properties>
Retruns a Promise which resolves all child values on //anObject//.
_property: ethers.utils.shallowCopy(anObject) => any
Returns a shallow copy of //anObject//. This is the same as
using ``Object.assign({ }, anObject)``.

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

@@ -1,7 +1,11 @@
_section: Strings @<strings>
Tra la la
A **String** is a representation of a human-readable input of output,
which are often taken for granted.
When dealing with blockchains, properly handling human-readable and
human-provided data is important to prevent loss of funds, assets,
incorrect permissions, etc.
_subsection: Bytes32String @<Bytes32String>

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.
@@ -97,8 +97,17 @@ used to encode the chain ID into the serialized transaction.
_subsection: Functions @<transactions--functions>
_property: ethers.utils.accessListify(anAcceslistish) => [[providers-AccessList]] @<utils-accessListify> @SRC<transactions:accessListify>
Normalizes the [[providers-AccessListish]] //anAccessListish// into
an [[providers-AccessList]].
This is useful for other utility functions which wish to remain
flexible as to the input parameter for access lists, such as
when creating a [[Signer]] which needs to manipulate a possibly
typed transaction envelope.
_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

@@ -1,34 +1,40 @@
_section: Events
Explain how topics and such work
_subsection: Solidity Topics
How to compute the topic...
_section: Events @<events>
_subsection: Logs and Filtering
Example hog logs are used.
Logs and filtering are used quite often in blockchain applications,
since they allow for efficient queries of indexed data and provide
lower-cost data storage when the data is not required to be
accessed on-chain.
Link to provider.getLogs and contract.on
These can be used in conjunction with the [Provider Events API](Provider--event-methods)
and with the [Contract Events API](Contract--events).
_heading: Filters
The Contract Events API also provides [higher-level methods](Contract--filters)
to compute and query this data, which should be preferred over the lower-level filter.
Filter are used as a way to query ... efficient, explain bloom filters lightly
_heading: Filters @<events--filters>
A filter may have up to 4 topic-sets, where each topic-set refers
to a condition that must match the log topic in that position (i.e. each
condition is ``AND``-ed together).
When a Contract creates a log, it can include up to 4 pieces of
data to be indexed by. The indexed data is hashed and included in
a [[link-wiki-bloomfilter]], which is a data structure that allows
for efficient filtering.
If a topic-set is ``null``, a log topic in that position is not filtered
So, a filter may correspondingly have up to 4 topic-sets, where each
topic-set refers to a condition that must match the indexed log topic
in that position (i.e. each condition is ``AND``-ed together).
If a topic-set is ``null``, a log topic in that position is **not filtered**
at all and **any value** matches.
If a topic-set is a single topic, a log topic in that position must match
If a topic-set is a single topic, a log topic in that position **must** match
**that topic**.
If a topic-set is an array of topics, a log topic in that position must
match any **one** of the topics (i.e. the topic in this position are ``OR``-ed).
match **any one** of the topics (i.e. the topic in this position are ``OR``-ed).
This may sound complicated at first, but is more easily understood with
some examples.
_table: Example Log Matching @style<full>
@@ -152,6 +158,56 @@ contract.filters.Transfer(myAddress, otherAddress)
contract.filters.Transfer(null, [ myAddress, otherAddress ])
//!
_subsection: Solidity Topics @<events-solidity>
This is a quick (and non-comprehensive) overview of how events are computed
in Solidity.
This is likely out of the scope for most developers, but may be interesting
to those who want to learn a bit more about the underlying technology.
Solidity provides two types of events, anonymous and non-anonymous. The
default is non-anonymous, and most developers will not need to worry about
anonymous events.
For non-anonymous events, up to 3 topics may be indexed (instead of 4), since
the first topic is reserved to specify the event signature. This allows
non-anonymous events to always be filtered by their event signature.
This topic hash is always in the first slot of the indexed data, and is
computed by normalizing the Event signature and taking the keccak256 hash
of it.
For anonymous events, up to 4 topics may be indexed, and there is no
signature topic hash, so the events cannot be filtered by the event
signature.
Each additional indexed property is processed depending on whether its
length is fixed or dynamic.
For fixed length types (e.g. ``uint``, ``bytes5``), all of which are
internally exactly 32 bytes (shorter types are padded with zeros;
numeric values are padded on the left, data values padded on the right),
these are included directly by their actual value, 32 bytes of data.
For dynamic types (e.g. ``string``, ``uint256[]``) , the value is hashed
using keccak256 and this hash is used.
Because dynamic types are hashed, there are important consequences in
parsing events that should be kept in mind. Mainly that the original
value is lost in the event. So, it is possible to tell is a topic is
equal to a given string, but if they do not match, there is no way
to determine what the value was.
If a developer requires that a string value is required to be both
able to be filtered and also able to be read, the value must be included
in the signature twice, once indexed and once non-indexed (e.g.
``someEvent(string indexed searchBy, string clearText)``).
For a more detailed description, please refer to the
[Solidity Event Documentation](link-solidity-events).
_heading: Other Things? TODO
Explain what happens to strings and bytes, how to filter and retain the value

View File

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

View File

@@ -43,6 +43,8 @@ function getDefinitions(source) {
if (depth === 3) {
add("var", node.name.escapedText, node.name.end);
}
} else if (ts.isGetAccessorDeclaration(node)) {
add("getter", (lastClass + "." + node.name.text), node.name.end);
}
ts.forEachChild(node, (node) => { return visit(node, depth + 1); });
}
@@ -127,7 +129,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 +151,7 @@ function codeContextify(context) {
//return JSON.stringify(value);
return inspect(value, {
compact: false,
depth: null,
breakLength: Infinity,
sorted: true,
});
@@ -151,9 +161,12 @@ function codeContextify(context) {
module.exports = {
title: "ethers",
subtitle: "v5.0",
subtitle: "v5.2",
description: "Documentation for ethers, a complete, tiny and simple Ethereum library.",
logo: "logo.svg",
socialImage: "social.jpg",
prefix: "/v5",
link: "https:/\/docs.ethers.io",
@@ -170,6 +183,7 @@ module.exports = {
codeRoot: "../",
externalLinks: {
"link-mail": "mailto:me@ricmoo.com",
"link-alchemy": { name: "Alchemy", url: "https:/\/alchemyapi.io" },
"link-cloudflare": { name: "Cloudflare", url: "https:/\/developers.cloudflare.com/distributed-web/ethereum-gateway/" },
"link-ens": { name: "ENS", url: "https:/\/ens.domains/" },
@@ -185,16 +199,20 @@ 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" },
"link-solidity": { name: "Solidity" , url: "https:/\/solidity.readthedocs.io/en/v0.6.2/" },
"link-solidity": { name: "Solidity" , url: "https:/\/solidity.readthedocs.io/" },
"link-solidity-errors": "https:/\/docs.soliditylang.org/en/v0.8.4/abi-spec.html#errors",
"link-solidity-events": "https:/\/docs.soliditylang.org/en/v0.8.4/abi-spec.html#events",
"link-sphinx": { name: "Sphinx", url: "https:/\/www.sphinx-doc.org/" },
"link-alchemy-signup": "https:/\/dashboard.alchemyapi.io/signup?referral=55a35117-028e-4b7c-9e47-e275ad0acc6d",
"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",
@@ -229,25 +247,32 @@ module.exports = {
"link-ethersio": "https:/\/ethers.io/",
"link-ethers-docs": "https:/\/docs.ethers.io/",
"link-ethers-js": "https:/\/cdn.ethers.io/lib/ethers-5.0.esm.min.js",
"link-ethers-js": "https:/\/cdn.ethers.io/lib/ethers-5.1.esm.min.js",
"link-ethers-npm": "https:/\/www.npmjs.com/search?q=%40ethersproject%2F",
"link-ethers-asm-grammar": "https:/\/github.com/ethers-io/ethers.js/blob/master/packages/asm/grammar.jison",
"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-634": { name: "EIP-634", url: "https:/\/eips.ethereum.org/EIPS/eip-634" },
"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-1577": { name: "EIP-1577", url: "https:/\/eips.ethereum.org/EIPS/eip-1577" },
"link-eip-2098": { name: "EIP-2098", url: "https:/\/eips.ethereum.org/EIPS/eip-2098" },
"link-eip-2304": { name: "EIP-2304", url: "https:/\/eips.ethereum.org/EIPS/eip-2304" },
"link-eip-2718": { name: "EIP-2718", url: "https:/\/eips.ethereum.org/EIPS/eip-2718" },
"link-eip-2930": { name: "EIP-2930", url: "https:/\/eips.ethereum.org/EIPS/eip-2930" },
"link-bip-39": { name: "BIP-39", url: "https:/\/en.bitcoin.it/wiki/BIP_0039" },
"link-bip-32": { name: "BIP-32", url: "https:/\/github.com/bitcoin/bips/blob/master/bip-0032.mediawiki" },
"link-bip-44": { name: "BIP-44", url: "https:/\/en.bitcoin.it/wiki/BIP_0044" },
"link-npm-elliptic": { name: "elliptic", url: "https:/\/www.npmjs.com/package/elliptic" },
"link-npm-ethersproject-shims": { name: "Shims", url: "https:/\/www.npmjs.com/package/@ethersproject/shims" },
"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",
@@ -256,8 +281,12 @@ module.exports = {
"link-js-proxy": "https:/\/developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy",
"link-js-typedarray": "https:/\/developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray",
"link-cors": { name: "CORS", url: "https:/\/developer.mozilla.org/en-US/docs/Web/HTTP/CORS" },
"link-ricmoo-humanreadableabi": "https:/\/blog.ricmoo.com/human-readable-contract-abis-in-ethers-js-141902f4d917",
"link-other-ethereum-dev-docs": "https:/\/ethereum.org/en/developers/docs/",
"link-wiki-basicauth": { name: "Basic Authentication", url: "https:/\/en.wikipedia.org/wiki/Basic_access_authentication" },
"link-wiki-backoff": { name: "Exponential Backoff", url: "https:/\/en.wikipedia.org/wiki/Exponential_backoff" },
"link-wiki-bloomfilter": { name: "Bloom Filter", url: "https:/\/en.wikipedia.org/wiki/Bloom_filter" },
@@ -268,6 +297,7 @@ module.exports = {
"link-wiki-hmac": "https:/\/en.wikipedia.org/wiki/HMAC",
"link-wiki-iban": "https:/\/en.wikipedia.org/wiki/International_Bank_Account_Number",
"link-wiki-ieee754": "https:/\/en.wikipedia.org/wiki/Double-precision_floating-point_format",
"link-wiki-observer-pattern": { name: "Obeserver Pattern", url: "https:/\/en.wikipedia.org/wiki/Observer_pattern" },
"link-wiki-ripemd": "https:/\/en.m.wikipedia.org/wiki/RIPEMD",
"link-wiki-sha2": "https:/\/en.wikipedia.org/wiki/SHA-2",
"link-wiki-twoscomplement": "https:/\/en.wikipedia.org/wiki/Two%27s_complement",

View File

@@ -7,7 +7,7 @@ Many things are the way they are for good (at the time, at least) reasons,
but I always welcome criticism, and am completely willing to have my mind
changed on things.
So, pull requests are always welcome, but please keep a few points in mind:
Pull requests are always welcome, but please keep a few points in mind:
- Backwards-compatibility-breaking changes will not be accepted; they may be
considered for the next major version
@@ -15,72 +15,150 @@ So, pull requests are always welcome, but please keep a few points in mind:
arguments as to why
- The library aims to be lean, so keep an eye on the dist/ethers.min.js
file size before and after your changes
- Keep the PR simple and readable; only modify files in the ``docs.wrm/``
and ``packages/*/src.ts/`` folders, as this allows the changes to be easily
verified
- Add test cases for both expected and unexpected input
- Any new features need to be supported by me (future issues, documentation,
testing, migration), so anything that is overly complicated or specific
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.
**:)**
_subsection: Building @<contributing--building>
If you wish to modify the source code, there are a few steps involved in
setting up your environment.
The build process for ethers is unfortunatly not super trivial, but
I have attempted to make it as straight-forward as possible.
Since the library uses a monorepo, you must install an initial required
set of libraries, which can then be used to install the remaining libraries
used within each package, as well as link all the packages within the repo
with each other.
It is a mono-repo which attempts to be compatibile with a large
number of environments, build tools and platforms, which is why
there are a some weird things it must do.
_code: Preparing for builds @lang<shell>
There are several custom scripts in the ``misc/admin`` folder
to help manage the monorepo. Developers working on contributing
to ethers should not generally need to worry about those, since
they are wrapped up behind ``npm run SCRIPT`` operations.
_code: Installing @lang<shell>
# Clone the repository
/home/ricmoo> git clone git@github.com:ethers-io/ethers.js.git
/home/ricmoo> git clone https://github.com/ethers-io/ethers.js.git
/home/ricmoo> cd ethers.js
# Install the base dependencies
# Install all dependencies:
# - Hoists all sub-package dependencies in the package.json (preinstall)
# - Installs all the (hoisted) dependencies and devDependencies (install)
# - Build the rat-nests (in .package_node_modules) (postinstall)
# - Create a dependency graph for the TypeScript (postinstall)
# - Link the rat-nets into each project (postinstall)
/home/ricmoo/ethers.js> npm install
# Install each module's dependencies and link the libraries
# internally, so they reference each other
/home/ricmoo/ethers.js> npm run bootstrap
_heading: Making Changes @<contributing--updating>
_subsection: Making your changes @<contributing--updating>
TODO: Add more information here.
Once your environment is set up, you should be able to simply
start the ``auto-build`` feature, and make changes to the
TypeScript source.
_code: Watching and Building @lang<shell>
# Begin watching the files and re-building whenever they change
/home/ricmoo/ethers.js> npm run auto-build
# Or if you do not want to watch and just build
/home/ricmoo/ethers.js> npm run build
# Sometimes the issue only affects the ESM modules
/home/ricmoo/ethers.js> npm run auto-build-esm
_heading: Creating Browser-Ready Files
To create files for use directly in a browser, the distribution
files (located in ``packages/ethers/dist``) need to be built
which requires several intermediate builds, scripts and for
various rollup scripts to execute.
# Or if you only need to run a single build
/home/ricmoo/ethers.js> npm run _build-cjs
/home/ricmoo/ethers.js> npm run _build-esm
_code: Building Distribution Files @lang<shell>
# If you need to rebuild all the libs (esm + cjs) and dist files
# Note: this requires node 10 or newer
/home/ricmoo/ethers.js> npm run build-all
_heading: Testing
_code: Testing @lang<shell>
# Rebuilds all files and bundles testcases up for testing
# Rebuilds all files (npm run build-all) and bundles testcases up for testing
/home/ricmoo/ethers.js> npm test
# Often you don't need the full CI experience
/home/ricmoo/ethers.js> npm run _test-node
/home/ricmoo/ethers.js> npm run test-node
_heading: Distribution
Most developers should not ever require this step, but for people
forking ethers and creating alternates (for example if you have
a non-EVM compatible chain but are trying to reuse this package).
This script will rebuild the entire ethers project, compare it
against npm, re-write package versions, update internal hashes,
re-write various TypeScript files (to get around some ES+TS
limitations for Tree Shaking and linking), re-write map files,
bundle stripped versions of dependencies and basically just a
whole bunch of stuff.
If you use this and get stuck, [message me](link-mail).
_code: Preparing the Distribution @lang<shell>
# Prepare all the distribution files
# - Remove all generated files (i.e. npm run clean)
# - Re-install all dependencies, hoisting, etc. (npm install)
# - Spell check all strings in every TypeScript files
# - Build everything from scratch with this clean install
# - Compare local with npm, bumping the version if changed
# - Build everything again (with the updated versions)
# - Update the CHANGELOG.md with the git history since the last change
/home/ricmoo/ethers.js> npm run update-version
_note: Do NOT check in dist files in a PR
For Pull Requests, please ONLY commit files in the ``docs.wrm/`` and
``packages/*/src.ts/`` folders. I will prepare the distribution builds
myself and keeping the PR relevant makes it easier to verify the changes.
_heading: Publishing
Again, this should not be necessary for most developers. This step
requires using the ``misc/admin/cmds/config-set`` script for a number
of values, including private keys, NPM session keys, AWS access keys,
GitHub API tokens, etc.
The config file is encrypted with about 30 seconds of scrypt password-based
key derivation function, so brute-forcing the file is quite expensive.
The config file also contains a plain-text mnemonic. This is a money-pot.
Place a tempting amount of ether or Bitcoin on this account and set up an
e-mail alert for this account.
If any attacker happens across your encrypted config, they will have instant
access to the plain-text mnemonic, so they have the option to immediately
steal the ether (i.e. the responsible-disclosure bond).
If you ever see this ether taken, your encrypted file is compromised! Rotate
all your AWS keys, NPM session keys, etc. immedately.
@TODO: document all the keys that need to be set for each step
_code: Preparing the Distribution @lang<shell>
# Publish
# - Update any changed packages to NPM
# - Create a release on GitHub with the latest CHANGELOG.md description
# - Upload the bundled files the the CDN
# - Flush the CDN edge caches
/home/ricmoo/ethers.js> npm run publish-all
_subsection: Documentation @<contributing--documentation>
@@ -95,7 +173,7 @@ Style Guide (this section will have much more coming):
- Prefix external links with ``link-``
- Changing an anchor name must be well justified, as it will break all existing links
to that section; flatworm will support symlinks in the future
- In general, I aim for xonsistency; look to similar situations throughout the documentation
- In general, I aim for consistency; look to similar situations throughout the documentation
_heading: Building

View File

@@ -17,7 +17,7 @@ _subsection: Installing @<cookbook-reactnative-shims>
To use ethers in React Native, you must either provide shims for the needed
missing functionality, or use the ethers.js shim.
It is **HIGHLY RECOMMENDED** you check out the [security section](cookbook-reactnative-security>
It is **HIGHLY RECOMMENDED** you check out the [security section](cookbook-reactnative-security)
below for instructions on installing packages which can affect the security
of your application.
@@ -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.

BIN
docs.wrm/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -101,7 +101,7 @@ with Ethereum and is available in all major Ethereum node implementations
third-party web services (e.g. [[link-infura]]). It typically provides:
- A connection to the Ethereum network (a [[Provider]])
- Holds your private key and can sign thing (a [[Signer]])
- Holds your private key and can sign things (a [[Signer]])
_code: Connecting to an RPC client @lang<script>
@@ -165,7 +165,7 @@ If you are familiar with Databases, this is similar to an //Object Relational Ma
In order to communicate with the Contract on-chain, this class
needs to know what methods are available and how to encode and
decode the data, which is what the //Application Binary Interface// (API)
decode the data, which is what the //Application Binary Interface// (ABI)
provides.
This class is a //meta-class//, which means its methods are constructed
@@ -311,14 +311,14 @@ const daiContract = new ethers.Contract("dai.tokens.ethers.eth", daiAbi, provide
myAddress = await signer.getAddress()
//! async myAddress
// Filter for all token transfers to me
// Filter for all token transfers from me
filterFrom = daiContract.filters.Transfer(myAddress, null);
// <hide>
filterFrom
// </hide>
//!
// Filter for all token transfers from me
// Filter for all token transfers to me
filterTo = daiContract.filters.Transfer(null, myAddress);
// <hide>
filterTo

View File

@@ -45,6 +45,7 @@ _toc:
migration
testing
contributing
other-resources
documentation
license

View File

@@ -7,7 +7,7 @@ of uses.
_heading: MIT License
//Copyright &copy; 2019 [Richard Moore](mailto:me@ricmoo.com).//
//Copyright &copy; 2019-2021 [Richard Moore](mailto:me@ricmoo.com).//
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

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

@@ -0,0 +1,17 @@
_section: Other Resources
There is a lot of documentation on the internet to help you get started,
learn more or cover advanced topics. Here are a few resources to check out.
_subsection: Ethereum Overview
- Official [Ethereum Developer Documentations](link-other-ethereum-dev-docs)
- The [Solidity Documentation](link-solidity), the defactor language for smart
contracts as well as a resource for some of the core concepts of Ethereum
_subsection: Tutorials
I do not manage or maintain these tutorials, but have happened across them.
If a link is dead or outdated, please [let me know](link-mail) and I'll update it.
- No links yet; send me some

BIN
docs.wrm/social.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

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

@@ -0,0 +1 @@
index.html => /v5/api-keys

View File

@@ -0,0 +1,9 @@
server-error => /v5/api/utils/logger/#errors--server-error
unsupported-operation => /v5/api/utils/logger/#errors--unsupported-operation
numeric-fault => /v5/api/utils/logger/#errors--numeric-fault
call-exception => /v5/api/utils/logger/#errors--numeric-fault
insufficient-funds => /v5/api/utils/logger/#errors--insufficient-funds
nonce-expired => /v5/api/utils/logger/#errors--nonce-expired
replacement-underpriced => /v5/api/utils/logger/#errors--replacement-underpriced
unpredicatable-gas-limit => /v5/api/utils/logger/#errors--unpredicatable-gas-limit

BIN
docs/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -26,17 +26,20 @@ Developer Documentation
* [Signing Messages](getting-started)
* [Ethereum Basics](concepts)
* [Events](concepts/events)
* [Solidity Topics](concepts/events)
* [Logs and Filtering](concepts/events)
* [Solidity Topics](concepts/events)
* [Gas](concepts/gas)
* [Gas Price](concepts/gas)
* [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)
@@ -44,6 +47,7 @@ Developer Documentation
* [Accounts Methods](api/providers/provider)
* [Blocks Methods](api/providers/provider)
* [Ethereum Naming Service (ENS) Methods](api/providers/provider)
* [EnsResolver](api/providers/provider)
* [Logs Methods](api/providers/provider)
* [Network Status Methods](api/providers/provider)
* [Transactions Methods](api/providers/provider)
@@ -193,7 +197,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)
@@ -250,8 +254,10 @@ Developer Documentation
* [Schemas](testing)
* [Contributing and Hacking](contributing)
* [Building](contributing)
* [Making your changes](contributing)
* [Documentation](contributing)
* [Other Resources](other-resources)
* [Ethereum Overview](other-resources)
* [Tutorials](other-resources)
* [Flatworm Docs](documentation)
* [Fragments](documentation)
* [Markdown](documentation)

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

@@ -12,6 +12,7 @@ Application Programming Interface
* [Accounts Methods](providers/provider)
* [Blocks Methods](providers/provider)
* [Ethereum Naming Service (ENS) Methods](providers/provider)
* [EnsResolver](providers/provider)
* [Logs Methods](providers/provider)
* [Network Status Methods](providers/provider)
* [Transactions Methods](providers/provider)
@@ -161,7 +162,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

@@ -12,14 +12,17 @@ Creating Instances
#### **new ***ethers* . **ContractFactory**( interface , bytecode [ , signer ] )
Creates a new instance of a **ContractFactory** for the contract described by the *interface* and *bytecode* initcode.
#### *ContractFactory* . **fromSolidity**( compilerOutput [ , signer ] ) => *[ContractFactory](/v5/api/contract/contract-factory/)*
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.
#### *contractFactory* . **connect**( signer ) => *[Contract](/v5/api/contract/contract/)*
Returns a **new instance** of the ContractFactory with the same *interface* and *bytecode*, but with a different *signer*.
Properties
@@ -27,14 +30,17 @@ Properties
#### *contractFactory* . **interface** => *[Interface](/v5/api/utils/abi/interface/)*
The [Contract](/v5/api/contract/contract/) interface.
#### *contractFactory* . **bytecode** => *string< [DataHexString](/v5/api/utils/bytes/#DataHexString) >*
The bytecode (i.e. initcode) that this **ContractFactory** will use to deploy the Contract.
#### *contractFactory* . **signer** => *[Signer](/v5/api/signer/#Signer)*
The [Signer](/v5/api/signer/#Signer) (if any) this ContractFactory will use to deploy instances of the Contract to the Blockchain.
Methods
@@ -42,52 +48,90 @@ 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)*
#### *contractFactory* . **getDeployTransaction**( ...args [ , overrides ] ) => *[UnsignedTransaction](/v5/api/utils/transactions/#UnsignedTransaction)*
Returns the unsigned transaction which would deploy this Contract with *args* passed to the Contract's constructor.
If the optional *overrides* is specified, they can be used to override the endowment `value`, transaction `nonce`, `gasLimit` or `gasPrice`.
#### *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.
#### *contractFactory* . **deploy**( ...args [ , overrides ] ) => *Promise< [Contract](/v5/api/contract/contract/) >*
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.
If the optional *overrides* is specified, they can be used to override the endowment `value`, transaction `nonce`, `gasLimit` or `gasPrice`.
```
// <hide>
const signer = ethers.LocalSigner();
const ContractFactory = ethers.ContractFactory;
// </hide>
```javascript
// 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);
// The address is available immediately, but the contract
// is NOT deployed yet
contract.address
//!
// '0x26E9685C018Bf3A401DFA632827e7e6C7D96b1C0'
// The transaction that the signer sent to deploy
contract.deployTransaction
//!
// {
// blockHash: null,
// blockNumber: null,
// chainId: 1337,
// confirmations: 0,
// creates: '0x26E9685C018Bf3A401DFA632827e7e6C7D96b1C0',
// data: '0x608060405234801561001057600080fd5b5060405161012e38038061012e8339818101604052604081101561003357600080fd5b81019080805190602001909291908051906020019092919050505081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060008190555050506088806100a66000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633fa4f24514602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000805490509056fea2646970667358221220926465385af0e8706644e1ff3db7161af699dc063beaadd55405f2ccd6478d7564736f6c63430007040033000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c000000000000000000000000000000000000000000000000000000000000002a',
// from: '0xf3e6942b256A60B596B24F633caE8aDB4983fCA6',
// gasLimit: { BigNumber: "126462" },
// gasPrice: { BigNumber: "1" },
// hash: '0x4037630fdadbbe0aac0bf90eba61118e35ee5fc28329e2134bb2bad0bfc12684',
// nonce: 1,
// r: '0xc3bb79ea4600864cd110fe74d31d38bb3702c327fd5aef9feddf66903cc87a4f',
// s: '0x35cc2ffe352c02b5fcfbbcd2e348001af670f64438d7a9b2c34756ec293a0784',
// to: null,
// transactionIndex: null,
// v: 2709,
// value: { BigNumber: "0" },
// wait: [Function]
// }
// 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()
//!
// { Promise: {
// blockHash: '0x1715de2bdfec15a7f64fb79a8254699274be6776df244d24a04945a3218543e6',
// blockNumber: 2,
// byzantium: true,
// confirmations: 1,
// contractAddress: '0x26E9685C018Bf3A401DFA632827e7e6C7D96b1C0',
// cumulativeGasUsed: { BigNumber: "126462" },
// from: '0xf3e6942b256A60B596B24F633caE8aDB4983fCA6',
// gasUsed: { BigNumber: "126462" },
// logs: [],
// logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
// status: 1,
// to: null,
// transactionHash: '0x4037630fdadbbe0aac0bf90eba61118e35ee5fc28329e2134bb2bad0bfc12684',
// transactionIndex: 0
// } }
// Now the contract is safe to interact with
contract.value()
//!
// { Promise: { BigNumber: "42" } }
```

File diff suppressed because one or more lines are too long

View File

@@ -117,7 +117,7 @@ Meta-Class
#### *contract* . **METHOD_NAME**( ...args [ , overrides ] ) => *Promise< any >*
The type of the result depends on the ABI.
The type of the result depends on the ABI. If the method returns a single value, it will be returned directly, otherwise a [Result](/v5/api/utils/abi/interface/#Result) object will be returned with each parameter available positionally and if the parameter is named, it will also be available by its name.
For values that have a simple meaning in JavaScript, the types are fairly straight forward; strings and booleans are returned as JavaScript strings and booleans.
@@ -125,6 +125,16 @@ For numbers, if the **type** is in the JavaScript safe range (i.e. less than 53
For bytes (both fixed length and dynamic), a [DataHexString](/v5/api/utils/bytes/#DataHexString) is returned.
The *overrides* object for a read-only method may include any of:
- `overrides.from` - the `msg.sender` (or `CALLER`) to use during the execution of the code
- `overrides.value` - the `msg.value` (or `CALLVALUE`) to use during the exectuiont of the code
- `overrides.gasPrice` - the price to pay per gas (theoretically); since there is no transaction, there is not going to be any fee charged, but the EVM still requires a value to report to `tx.gasprice` (or `GASPRICE`); *most developers will not require this*
- `overrides.gasLimit` - the amount of gas (theoretically) to allow a node to use during the execution of the code; since there is no transaction, there is not going to be any fee charged, but the EVM still processes gas metering so calls like `gasleft` (or `GAS`) report meaningful values
- `overrides.blockTag` - a block tag to simulate the execution at, which can be used for hypothetical historic analysis; note that many backends do not support this, or may require paid plans to access as the node database storage and processing requirements are much higher
#### *contract* . *functions* . **METHOD_NAME**( ...args [ , overrides ] ) => *Promise< [Result](/v5/api/utils/abi/interface/#Result) >*
@@ -136,6 +146,8 @@ Another use for this method is for error recovery. For example, if a function re
Most developers should not require this.
The *overrides* are identical to the read-only operations above.
### Write Methods (non-constant)
@@ -143,6 +155,29 @@ Most developers should not require this.
Returns a [TransactionResponse](/v5/api/providers/types/#providers-TransactionResponse) for the transaction after it is sent to the network. This requires the **Contract** has a signer.
The *overrides* object for write methods may include any of:
- `overrides.gasPrice` - the price to pay per gas
- `overrides.gasLimit` - the limit on the amount of gas to allow the transaction to consume; any unused gas is returned at the gasPrice
- `overrides.value` - the amount of ether (in wei) to forward with the call
- `overrides.nonce` - the nonce to use for the [Signer](/v5/api/signer/#Signer)
If the `wait()` method on the returned [TransactionResponse](/v5/api/providers/types/#providers-TransactionResponse) is called, there will be additional properties on the receipt:
- `receipt.events` - an array of the logs, with additional properties (if the ABI included a description for the events)
- `receipt.events[n].args` - the parsed arguments
- `receipt.events[n].decode` - a method that can be used to parse the log topics and data (this was used to compute `args`)
- `receipt.events[n].event` - the name of the event
- `receipt.events[n].eventSignature` - the full signature of the event
- `receipt.removeListener()` - a method to remove the listener that trigger this event
- `receipt.getBlock()` - a method to return the [Block](/v5/api/providers/types/#providers-Block) this event occurred in
- `receipt.getTransaction()` - a method to return the [Transaction](/v5/api/providers/types/#providers-TransactionResponse) this event occurred in
- `receipt.getTransactionReceipt()` - a method to return the [Transaction Receipt](/v5/api/providers/types/#providers-TransactionReceipt) this event occurred in
### Write Methods Analysis
@@ -150,11 +185,15 @@ Returns a [TransactionResponse](/v5/api/providers/types/#providers-TransactionRe
Returns the estimate units of gas that would be required to execute the *METHOD_NAME* with *args* and *overrides*.
The *overrides* are identical to the overrides above for read-only or write methods, depending on the type of call of *METHOD_NAME*.
#### *contract* . *populateTransaction* . **METHOD_NAME**( ...args [ , overrides ] ) => *Promise< [UnsignedTx](/v5/api/utils/transactions/#UnsignedTransaction) >*
Returns an [UnsignedTransaction](/v5/api/utils/transactions/#UnsignedTransaction) which represents the transaction that would need to be signed and submitted to the network to execute *METHOD_NAME* with *args* and *overrides*.
The *overrides* are identical to the overrides above for read-only or write methods, depending on the type of call of *METHOD_NAME*.
#### *contract* . *callStatic* . **METHOD_NAME**( ...args [ , overrides ] ) => *Promise< any >*
@@ -164,6 +203,8 @@ This does not actually change any state, but is free. This in some cases can be
This otherwise functions the same as a [Read-Only Method](/v5/api/contract/contract/#Contract--readonly).
The *overrides* are identical to the read-only operations above.
### Event Filters

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*
#### *nonceManager* . **incrementTransactionCount**( [ 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

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