Compare commits

...

368 Commits

Author SHA1 Message Date
Richard Moore
71b7547f10 Update dist files. 2021-06-26 01:55:19 -04:00
Richard Moore
4970385e7b Fixing up testcases for non-eip-1559 ready platforms (#1610). 2021-06-26 01:44:12 -04:00
Richard Moore
0364dd9368 Added some provider-specific adjustments to deal with eip-1559 (#1610). 2021-06-25 22:58:55 -04:00
Richard Moore
e95708eedc Updated gasPrice to be optional for eip-1559 (#1610). 2021-06-25 22:58:01 -04:00
Richard Moore
ba6854bdd5 Added effectiveGasPrice to receipt. 2021-06-25 22:57:05 -04:00
Richard Moore
1e31b34a5a Fixed ENS names for JsonRpcSigner. 2021-06-25 00:02:08 -04:00
Richard Moore
7deb4c174a Added EIP-2930 and EIP-1559 transaction tests. 2021-06-24 23:49:59 -04:00
Richard Moore
f053a7ad58 Renamed Interface error coding methods. 2021-06-24 19:34:27 -04:00
Richard Moore
b1affdbc10 Fixed documentation on FallbackProvider priority (#1713). 2021-06-24 18:07:33 -04:00
Richard Moore
c2c0ce7503 Updated dist files. 2021-06-24 02:13:06 -04:00
Richard Moore
7efc36df29 Added ConstructorFragment to exports. 2021-06-24 01:29:13 -04:00
Richard Moore
720bde7719 Added error utilities to Interface. 2021-06-24 01:25:31 -04:00
Richard Moore
319987ec3e Fixed EIP-1559 from address calculation bug (#1610). 2021-06-24 00:46:53 -04:00
Richard Moore
2a7ce0e72a merged master including transaction type 0 legacy constant (#1610). 2021-06-24 00:02:50 -04:00
Richard Moore
8ba64af29f admin: updated Flatworm version 2021-06-23 23:42:00 -04:00
Richard Moore
17af9f812f docs: fixed typos and updated examples 2021-06-23 23:40:50 -04:00
Richard Moore
d001901c8c Added type to TransactionResponse and TrnsactionReceipt (#1687). 2021-06-23 23:39:57 -04:00
Richard Moore
91951dc825 Trap CALL_EXCEPTION errors when resolving ENS entries (#1690). 2021-06-21 23:25:37 -04:00
Richard Moore
8277f5a62a Fixed transaction serialization with explicit null type (#1628). 2021-06-21 21:21:35 -04:00
Richard Moore
e615e51fbf admin: updated spell check dictionary 2021-06-21 21:15:39 -04:00
Richard Moore
99422c1c7c admin: fixed typo in docs (#1686). 2021-06-21 21:15:01 -04:00
Richard Moore
e8a0144b7a Fix issue with loading JSON ABI with internalType property (#728). 2021-06-21 21:12:25 -04:00
Richard Moore
f9d09645e7 docs: Added info on signMessage (#1343). 2021-06-18 16:17:26 -04:00
Richard Moore
91fff1449d Better baseFee calculation (#1610). 2021-06-14 23:42:11 -04:00
Richard Moore
c5bca7767e Refactored eip-1559 logic (#1610). 2021-06-14 22:24:14 -04:00
Richard Moore
79c5bf6bcb docs: added more examples 2021-06-11 17:13:46 -04:00
Richard Moore
412bbe2939 Updated dist files. 2021-06-10 18:29:05 -04:00
Richard Moore
ee82e86ccc Fixed replacement transaction detection for JsonRpcSigner (#1658). 2021-06-10 18:22:02 -04:00
Richard Moore
376cf3cdbf Added Matic testnet info to networks (#1546). 2021-06-10 18:01:23 -04:00
Richard Moore
89bae3bd63 docs: grammar fix (#1594). 2021-06-10 17:48:55 -04:00
Richard Moore
a6e128f5cc Match Solidity identifier regex (#1657). 2021-06-10 17:47:17 -04:00
Richard Moore
5456c35924 Added EIP-1559 overrides to contracts (#1610). 2021-06-10 17:42:20 -04:00
Richard Moore
be20e28de1 docs: adding more examples 2021-06-10 17:38:38 -04:00
Richard Moore
30c0c97270 docs: added more examples and moved to new flatworm evaler format. 2021-06-04 01:17:56 -04:00
Richard Moore
4e6d121fb8 Updated dist files. 2021-05-31 19:06:24 -04:00
Richard Moore
bfcd05fcbb Added MinInt256 and MaxInt256 constants (#1576). 2021-05-31 18:32:33 -04:00
Richard Moore
819b1ace5c Version bumps for bn.js and hash.js to match elliptic and fix some build tools (#1478). 2021-05-31 18:29:26 -04:00
Richard Moore
4b331148d9 Removed Hangul checks in shims which crashes Android (#1519). 2021-05-31 18:20:32 -04:00
Richard Moore
7adcf3b154 Fixed ENS namehash with leading and trailing dots (#1605). 2021-05-31 18:16:30 -04:00
Richard Moore
630656e949 Fixed broken variable in template string (#1624, #1626). 2021-05-31 17:40:32 -04:00
Richard Moore
8681cd5969 Fixed FixedNumber rounding for non-default formats (#1629). 2021-05-31 17:37:56 -04:00
Richard Moore
470551e4ee Update ws dependency version to fix security (#1633, #1634). 2021-05-31 15:46:47 -04:00
Richard Moore
7a12216cfb Initial EIP-1559 support (#1610). 2021-05-30 17:47:04 -04:00
Richard Moore
d395d16fa3 admin: flags for karma to prevent timeout 2021-05-19 01:30:12 -04:00
Richard Moore
8077ce0aae Updated dist files. 2021-05-19 00:05:36 -04:00
Richard Moore
2fe78ad7e3 ci: Removing Pocket network from the default provider and tests as it is not currently reliable 2021-05-19 00:00:10 -04:00
Richard Moore
5f1f2c5e2c Updated dist files 2021-05-18 16:02:27 -04:00
Richard Moore
3c79ee8cef admin: added words to spellcheck 2021-05-18 15:56:01 -04:00
Richard Moore
772067a3c9 admin: added words to spellchecker 2021-05-18 15:53:15 -04:00
Richard Moore
621897f249 More resiliant testing. 2021-05-18 15:52:32 -04:00
Richard Moore
d3b7130ed6 Merge branch 'master' of github.com:ethers-io/ethers.js 2021-05-17 16:29:33 -04:00
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
4898e7baac admin: update issue templates 2021-04-27 18:43:54 -04:00
Richard Moore
c71bbbe7db admin: fixed config.yml filename 2021-04-27 18:40:44 -04:00
Richard Moore
c8fecbbc29 admin: fixed duplicate files GitHub UI created. 2021-04-27 18:38:22 -04:00
Richard Moore
b4df28dddd Update issue templates 2021-04-27 18:32:06 -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
Richard Moore
3abfdffffa Updated dist files. 2020-11-17 20:36:19 -05:00
Richard Moore
02546b9401 Fix browser ws alias. 2020-11-17 20:07:22 -05:00
Richard Moore
fff72ef369 Use faux-registry to better simulate real world React Native apps. 2020-11-17 18:48:02 -05:00
Richard Moore
f10977ab35 Fixing React Native tests. 2020-11-17 13:41:43 -05:00
Richard Moore
1729f804fb Prevent node 8 from using rollup (contains incompatible syntax). 2020-11-17 02:51:54 -05:00
Richard Moore
8933467c01 Updated dist build. 2020-11-16 23:07:24 -05:00
Richard Moore
22bd0c76dd Use dist files in browser tests. 2020-11-16 21:20:35 -05:00
Richard Moore
4809325bee Refactoring dist build process. 2020-11-14 17:42:36 -05:00
Richard Moore
e0b1d0e1e0 Updated dist files. 2020-10-22 21:55:40 -04:00
Richard Moore
fe17a29581 Allow 0x as a numeric value for 0 in Provider formatter (#1104). 2020-10-22 21:03:51 -04:00
Richard Moore
d8cdd0e94c admin: Updated spell checker and mime-types. 2020-10-22 20:01:57 -04:00
Richard Moore
5a9bc30336 Updated dist files. 2020-10-22 20:01:18 -04:00
Richard Moore
28f60d5ef8 Use POST for long requests in EtherscanProvider (#1093). 2020-10-22 19:46:52 -04:00
Richard Moore
a21202c66b Export verifyTypedData in utils (#687). 2020-10-20 00:17:43 -04:00
Richard Moore
116cc89686 admin: updated publish script to allow forcing publish 2020-10-20 00:17:02 -04:00
Richard Moore
550ecf2f25 Added verifyTypedData for EIP-712 typed data (#687). 2020-10-20 00:15:55 -04:00
Richard Moore
7b19fdfeed Updated dist files. 2020-10-19 01:27:15 -04:00
Richard Moore
15a90af5be Fix signTypedData call for JsonRpcSigner (#687). 2020-10-19 01:17:36 -04:00
Richard Moore
86146650d8 Updated dist files. 2020-10-18 23:19:16 -04:00
Richard Moore
7fcae25a78 Refactoring test case generation scripts. 2020-10-18 21:55:12 -04:00
Richard Moore
15893537c3 Added EIP-712 test cases (#687). 2020-10-18 21:54:21 -04:00
Richard Moore
be4e2164e6 Initial Signer support for EIP-712 signed typed data (#687). 2020-10-18 21:52:25 -04:00
Richard Moore
3e676f21b0 Split hash library files up. 2020-10-18 21:45:32 -04:00
Richard Moore
5a4dd5a703 Added EIP-712 multi-dimensional array support (#687). 2020-10-12 00:58:04 -04:00
Richard Moore
345a830dc4 Consolidated TypedDataEncoder methods (#687). 2020-10-10 04:44:17 -04:00
Richard Moore
cfa6dec293 Initial EIP-712 utilities (#687). 2020-10-10 04:12:52 -04:00
Richard Moore
5a6d9a3a38 Added test cases for PocketProvider. 2020-10-08 21:29:14 -04:00
Richard Moore
a62d20d86f Added initial PocketProvider (#1052). 2020-10-08 20:21:32 -04:00
Richard Moore
5e0e3de52e Admin: Upddated spell-check script. 2020-10-07 20:11:34 -04:00
Richard Moore
d78b7a3998 Updated dist files. 2020-10-07 20:10:50 -04:00
Richard Moore
5abc2f36e2 Better error message for parseUnits of non-strings (#981). 2020-10-07 19:50:27 -04:00
Richard Moore
38a068bcea Add gzip support to AlchemyProivder and InfuraProvider fetching (#1085). 2020-10-07 19:43:20 -04:00
Richard Moore
65772a8e1a Add gzip support to getUrl in node (#1085). 2020-10-07 19:40:28 -04:00
Richard Moore
a022093ce0 Added CommunityResourcable to mark Providers as highly throttled. 2020-10-07 17:28:18 -04:00
Richard Moore
50f84b3c57 Updated dist files. 2020-10-07 00:25:28 -04:00
Richard Moore
df21d5326a Admin: Added retry logic, fixed version exports and removed unnecessary logging. 2020-10-07 00:11:47 -04:00
Richard Moore
e65fa8fc00 Docs: Added referral link to Alchemy. 2020-10-07 00:09:10 -04:00
Richard Moore
8e682cc848 Added debug event info to WebSocketProvider (#1018). 2020-10-06 21:12:49 -04:00
Richard Moore
ef8e4330d3 Docs: Merge typos fixes (#1082). 2020-10-06 17:20:25 -04:00
Richard Moore
a0278615a4 Merge branch 'fix-doc-typos' of git://github.com/yuetloo/ethers.js into yuetloo-fix-doc-typos 2020-10-06 17:20:07 -04:00
Richard Moore
d8821d7317 Docs: Fixed typo (#1087). 2020-10-06 17:18:09 -04:00
Richard Moore
78a82d9ff2 CI: Force INFURA for provider and contract tests. 2020-10-06 16:58:52 -04:00
Richard Moore
1ac7decd89 CI: Removed solc tests to try fixing Promise issues. 2020-10-06 14:51:55 -04:00
Richard Moore
4fa7276cc1 CI: Updated provider tests. 2020-10-06 01:46:23 -04:00
Richard Moore
6ae222d55c CI: Temporarily remove Cloudflare from tests. 2020-10-05 23:51:14 -04:00
Richard Moore
efeeda5e5c CI: Updated dist files. 2020-10-05 23:27:03 -04:00
Richard Moore
c75c937b13 Updated dist files. 2020-10-05 22:17:15 -04:00
Richard Moore
d1ee596292 CI: Fix provider timeout. 2020-10-05 21:25:37 -04:00
Richard Moore
b61e2cc96a Updated dist files. 2020-10-05 16:49:47 -04:00
Richard Moore
ca94445f0f Added custom API key for Alchemy in test suite. 2020-10-05 16:44:40 -04:00
Richard Moore
4d95fe925d Updated dist files. 2020-10-05 15:46:12 -04:00
Richard Moore
f3e5b0ded1 ABI encoding performance additions (#1012). 2020-10-05 15:34:00 -04:00
Yuet Loo Wong
8ce9761bad fix typo begine to begins 2020-10-03 14:24:47 -03:00
Richard Moore
3d051e454d Export hexConcat in utils (#1079). 2020-10-03 13:18:56 -04:00
Yuet Loo Wong
c48ad4421f fix typos in documentation 2020-10-03 13:30:15 -03:00
Richard Moore
40264ff900 Cache chain ID for WebSocketProvider (#1054). 2020-10-03 02:54:03 -04:00
Richard Moore
e86f83b9c0 Docs: Fixed typo (#1074). 2020-10-03 02:23:32 -04:00
Richard Moore
e986b09e58 Build: Added new publish script. 2020-10-03 02:20:50 -04:00
Richard Moore
22dee96f51 Updated dist files. 2020-09-26 03:27:47 -04:00
Richard Moore
0c614b7097 CI: Refactored changelog admin script. 2020-09-26 03:25:54 -04:00
Richard Moore
f0a5869c53 Add more accurate intrinsic gas cost to ABI calls with specified gas property (#1058). 2020-09-26 02:17:05 -04:00
Richard Moore
5cd1668e0d Better errors for unconfigured ENS names (#1066). 2020-09-26 01:23:43 -04:00
Richard Moore
0b061d68cc CI: Fixed reaxct-native tests with new scripts. 2020-09-23 15:53:42 -04:00
Richard Moore
ffa4a2d054 CI: Fix test cases. 2020-09-23 01:00:30 -04:00
Richard Moore
f8072a8004 Build: Added node 8 support. 2020-09-23 00:23:02 -04:00
Richard Moore
4306b3563a Updated CLI solc to versin 0.7.1. 2020-09-23 00:00:21 -04:00
Richard Moore
c4de88af6f Docs: Fix typo (#1044). 2020-09-22 23:51:59 -04:00
Richard Moore
9486185ceb Updated dist files. 2020-09-22 23:18:45 -04:00
Richard Moore
261eb04e97 Ignore metadata files in each package. 2020-09-22 22:57:17 -04:00
Richard Moore
832bd6c908 Refactored admin scripts. 2020-09-22 22:54:48 -04:00
Richard Moore
05844caf85 Extended Karma testing timeout managed by tests. 2020-09-21 22:44:37 -04:00
Richard Moore
f7e82fcb46 Started refactoring admin scripts into TypeScript. 2020-09-21 01:14:06 -04:00
Richard Moore
27b3af0a7b Removed dead files. 2020-09-17 17:17:15 -04:00
Richard Moore
f733fac875 Custom API key for Etherscan during tests (#824). 2020-09-17 03:44:29 -04:00
Richard Moore
1097a1b020 Replaced lerna with admin hoist and link scripts. 2020-09-17 03:40:55 -04:00
Richard Moore
ea422d63b3 Replaced lerna with admin hoist and link scripts. 2020-09-17 03:39:25 -04:00
Richard Moore
a3821f6c4b Updated dist files. 2020-09-16 19:44:55 -04:00
Richard Moore
de8a717b4c Refactored provider test cases to more reliable CI. 2020-09-16 19:38:01 -04:00
Richard Moore
86e0269a86 Extend Karma timeout for new provider tests. 2020-09-16 11:00:29 -04:00
Richard Moore
d15c097dba Updated dist files. 2020-09-16 03:08:36 -04:00
Richard Moore
49f71574f4 More robust blockchain error detection (#1047) 2020-09-16 02:19:28 -04:00
Richard Moore
9ee685df46 Forward blockchain errors from Signer during gas estimation (#1047). 2020-09-15 22:14:22 -04:00
Richard Moore
263bfe5ce6 Improve fetch errors with looser mime-type detection (#1047). 2020-09-15 22:12:56 -04:00
Richard Moore
e8a9eea493 CI: Add node-hid requirements to all jobs. 2020-09-12 01:31:17 -04:00
Richard Moore
1c499c9f42 CI: Add node-hid requirements. 2020-09-12 01:18:28 -04:00
Richard Moore
c1a297db99 Updated dist files. 2020-09-11 02:10:58 -04:00
Richard Moore
be92339696 Force content-length in web fetching. 2020-09-11 01:10:53 -04:00
Richard Moore
bc3eeeca39 Better error forwarding from FallbackProvider (#1021). 2020-09-11 01:10:15 -04:00
Richard Moore
042b74e6ee Add clamping functions to FixedNumber (#1037). 2020-09-10 01:16:28 -04:00
Richard Moore
6e10675adf Docs: updated dist files. 2020-09-08 01:12:15 -04:00
Richard Moore
2b83feb6bd Docs: fixed markdown. 2020-09-08 01:11:29 -04:00
Richard Moore
19fd55e935 Docs: add example for custom ENS address (#911). 2020-09-08 01:10:08 -04:00
Richard Moore
710998b19a Docs: Added link to React-Native. 2020-09-08 00:36:44 -04:00
Richard Moore
828a35fdca Merge branch 'ChrisChinchilla-ethereum-basics' 2020-09-08 00:30:09 -04:00
Richard Moore
95bcda0d8a Merge branch 'ethereum-basics' of git://github.com/ChrisChinchilla/ethers.js into ChrisChinchilla-ethereum-basics 2020-09-08 00:29:14 -04:00
Richard Moore
ccfe205db8 Merge branch 'ChrisChinchilla-master' 2020-09-08 00:27:57 -04:00
Richard Moore
f9684aeec2 Merge branch 'master' of git://github.com/ChrisChinchilla/ethers.js into ChrisChinchilla-master 2020-09-08 00:26:54 -04:00
Richard Moore
9d5de46c84 Updated dist files. 2020-09-07 19:55:52 -04:00
Richard Moore
28ee745211 Docs: added React Native and fixed typos. 2020-09-07 19:40:50 -04:00
Richard Moore
4e394fc680 Allow events to use compact bytes ABI coded data for Solidity 0.4 external events (#891, #992). 2020-09-07 19:35:37 -04:00
Richard Moore
97acaa1129 Docs: fixed typo (#1026). 2020-09-06 01:57:06 -04:00
Richard Moore
fe280c8458 Updated dist files. 2020-09-05 23:57:15 -04:00
Richard Moore
bdccf7b8d3 Synced unorm in shims to most recent version. 2020-09-05 23:45:25 -04:00
Richard Moore
0234cfbbef Updated dist files. 2020-09-05 23:35:35 -04:00
Richard Moore
cadb28d6b3 Fixed LedgerSigner sendTransaction (#936). 2020-09-05 04:37:47 -04:00
Richard Moore
72385c2287 Added BrainWallet to experimental exports. 2020-09-05 04:29:53 -04:00
Richard Moore
201e5ced9c More readable server errors. 2020-09-05 04:29:08 -04:00
Richard Moore
bf481f4bbf Updated dist files. 2020-09-05 01:23:16 -04:00
Richard Moore
681f2a50b2 Fixed test retry in browsers. 2020-09-05 01:14:25 -04:00
Richard Moore
18fdb96fe1 Updated dist files. 2020-09-04 03:21:51 -04:00
Richard Moore
35b64b9a65 Add test retry support to reporter. 2020-09-04 03:15:07 -04:00
Richard Moore
4ca98825d4 Updated dist files. 2020-09-04 02:11:49 -04:00
Richard Moore
0558bba8eb Added retry logic to provider tests. 2020-09-04 02:06:04 -04:00
Richard Moore
a440317594 Updated dist files. 2020-09-04 01:37:14 -04:00
Richard Moore
2359a98641 Fixed link in docs (#1028). 2020-09-04 01:26:29 -04:00
Richard Moore
a32fbd835d Ignore coverage build folder. 2020-09-04 01:24:54 -04:00
Richard Moore
6fd3bb62d1 Added memory-like support and new opcodes to asm. 2020-09-04 01:20:35 -04:00
Richard Moore
83db8a6bd1 Added basic ENS resolver functions for contenthash, text and multi-coin addresses (#1003). 2020-09-04 01:18:57 -04:00
Richard Moore
f24240eddf Updated dist files. 2020-08-27 22:04:58 -04:00
Richard Moore
d01d0c8448 Added support for changing Reporter logging function. 2020-08-27 21:58:34 -04:00
Richard Moore
d3b473e7c7 Added test-react script. 2020-08-27 21:56:40 -04:00
Richard Moore
57eb5b777e Initial React Native test harness (#993). 2020-08-27 21:54:16 -04:00
Richard Moore
240aac5683 Updating shims for constrained environments (#944, #993). 2020-08-27 14:23:23 -04:00
Richard Moore
8abdbbbf63 Updating shims for constrained environments (#944, #993). 2020-08-27 14:22:58 -04:00
Richard Moore
5fcd03f27e Updated dist files. 2020-08-25 01:53:48 -04:00
Richard Moore
cb8f4a3a4e Updated docs for all packages on npm pages (#1013). 2020-08-25 01:09:48 -04:00
Richard Moore
8facc1a530 Added JSON support to BigNumber (#1010). 2020-08-24 23:15:03 -04:00
Richard Moore
17fdca8994 CI: added dummy file to preserve output folder. 2020-08-23 20:00:39 -04:00
Richard Moore
df0caab5d6 CI: added coverage artifacts. 2020-08-23 19:44:43 -04:00
Richard Moore
9733927f82 CI: added coverage artifacts. 2020-08-23 19:42:49 -04:00
Richard Moore
28dbcfc38c CI: added coverage artifacts. 2020-08-23 19:39:57 -04:00
Richard Moore
bb8e77dc70 Updated admin scripts. 2020-08-23 16:37:24 -04:00
Richard Moore
ae619bcfc7 CI: do not build dist files in node 8 (dependency syntax issues). 2020-08-23 16:35:15 -04:00
Richard Moore
5b5904ea99 Updated packages for security audit. 2020-08-20 17:22:41 -04:00
Richard Moore
8f4b3027ef Run bootstrap in postinstall for better testing UX (#1001). 2020-08-20 17:09:30 -04:00
Richard Moore
e9009631d5 Fixed typo in docs (#976). 2020-08-20 16:51:41 -04:00
Richard Moore
be273f26e9 Fixed typos in readme (#996). 2020-08-20 16:49:34 -04:00
Richard Moore
b0c082d728 Fix emitted error for ABI code array count mismatch (#1004). 2020-08-20 15:33:16 -04:00
Richard Moore
9640e864a6 Updated dist files. 2020-08-04 20:55:55 -04:00
Richard Moore
e1bbb064a1 Do not mutate connection in fetchJson. 2020-08-04 20:49:40 -04:00
Richard Moore
d38ebaeb23 Updated dist files. 2020-08-04 20:33:21 -04:00
Richard Moore
39a16260a7 Updated dist files. 2020-07-31 01:32:26 -04:00
Richard Moore
2c49a52a41 Renamed and documented experimental fetchData function. 2020-07-31 01:15:22 -04:00
Richard Moore
c414a45825 Updated dist files. 2020-07-30 17:04:53 -04:00
Richard Moore
e2d6f281d5 Abstract fetchJson for data. 2020-07-30 17:03:36 -04:00
Richard Moore
ba404ffb0b Updated dist files. 2020-07-20 02:27:26 -04:00
Richard Moore
af10705632 Add testcases for setLogLevel (#947). 2020-07-20 01:43:47 -04:00
Richard Moore
5443363de4 Fix Logger setLogLevel with enum case mismatch (#947). 2020-07-20 01:43:02 -04:00
Richard Moore
e3f7426af4 Removed UUID dependency from json-wallets (#966). 2020-07-20 01:33:15 -04:00
Richard Moore
8b907d5f5f Added link to Chrome CLI switches for Karma Browser Tests. 2020-07-19 01:19:38 -04:00
Richard Moore
771190202f Fixed typo in DAI docs example (#958). 2020-07-18 06:08:45 -04:00
Chris Chinchilla
32de4f1930 Minor typo changes 2020-07-14 14:12:22 +02:00
Chris Chinchilla
232c7a895b Further review 2020-07-14 14:08:59 +02:00
Chris Chinchilla
c443a8bd9d Further review 2020-07-14 14:08:59 +02:00
Chris Chinchilla
0940944048 Start review of getting started guide 2020-07-14 14:08:59 +02:00
Chris Chinchilla
3ac0aeaac6 Further review 2020-07-14 14:05:55 +02:00
Chris Chinchilla
8557285da6 Merge branch 'master' of github.com:ethers-io/ethers.js 2020-07-14 13:14:08 +02:00
Chris Chinchilla
fb46e0fd79 Further review 2020-07-14 13:13:52 +02:00
Chris Chinchilla
84d6fdfc37 Start review of getting started guide 2020-07-07 14:41:23 +02:00
3326 changed files with 60925 additions and 43365 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' ]

24
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@@ -0,0 +1,24 @@
---
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.
If you are unsure if something is a bug, start a thread in the *"discussions"* tab above..
**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 and link this issue to it, making it easier for people to find in the future.

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

16
.github/ISSUE_TEMPLATE/documentation.md vendored Normal file
View File

@@ -0,0 +1,16 @@
---
name: Documentation
about: Documentation request or suggestion
title: ''
labels: documentation
assignees: ''
---
Please include anything about the [documentation](https://docs.ethers.io) you would like to see improved.
- Missing information or details?
- Wrong Information?
- Dead or wrong links?
- Something needs code examples?
- General feedback or anything else?

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.

16
.github/ISSUE_TEMPLATE/other.md vendored Normal file
View File

@@ -0,0 +1,16 @@
---
name: Other
about: Something else
title: ''
labels: ''
assignees: ''
---
Generally this issue template should be used.
If your issue is **not** a **Feature Request**, a **Bug Report** or problem with the **Documentation** you should probably be using the *"Discussion"* tab at the top.
But for truly exceptional issues, please include the details here.
Please also include any search terms you used when searching issues and discussions, so we can better tag those in the future.

View File

@@ -9,28 +9,40 @@ jobs:
test-node:
runs-on: ubuntu-latest
# runs-on: ubuntu-latest
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
node-version: [8.x, 10.x, 12.x, 13.x ]
node-version: [ 8.x, 10.x, 12.x, 13.x ]
steps:
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- uses: actions/checkout@v2
- run: npm ci
- run: npm run bootstrap
- run: npm run build-all
- run: npm run test-node
- 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 dependencies (and link per package)
run: npm ci
- name: Build CommonJS and ESM (from TypeScript)
run: npm run build-all
- name: Run tests
run: npm run test-node
test-browser:
runs-on: ubuntu-latest
# runs-on: ubuntu-latest
runs-on: macos-latest
strategy:
fail-fast: false
@@ -41,18 +53,57 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: 12.x
- uses: actions/checkout@v2
- run: npm ci
- run: npm run bootstrap
- run: npm run build-all
- run: npm run test-browser-${{ matrix.module }}
- 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 dependencies (and link per package)
run: npm ci
- name: Build CommonJS and ESM (from TypeScript)
run: npm run build-all
- name: Run tests
run: npm run test-browser-${{ matrix.module }}
test-react-native:
runs-on: macos-latest
# Temporary for testing CI
continue-on-error: true
strategy:
fail-fast: false
steps:
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: Checkout repository
uses: actions/checkout@v2
- name: Install dependencies (and link per package)
run: npm ci
- name: Build CommonJS and ESM (from TypeScript)
run: npm run build-all
- name: Run tests
run: npm run test-react
coverage:
name: Coverage
runs-on: ubuntu-latest
# runs-on: ubuntu-latest
runs-on: macos-latest
continue-on-error: true
@@ -60,8 +111,33 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: 12.x
- uses: actions/checkout@v2
- run: npm ci
- run: npm run bootstrap
- run: npm run build-all
- run: npm run test-coverage
- 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 dependencies (and link per package)
run: npm ci
- name: Build CommonJS and ESM (from TypeScript)
run: npm run build-all
- name: Run tests
run: npm run test-coverage
- name: Upload coverage summary
uses: actions/upload-artifact@v2
with:
name: coverage-summary
path: ./output/summary.txt
- name: Tar files
run: tar -cvf ./output/coverage.tar ./output/lcov-report/
- name: Upload coverage
uses: actions/upload-artifact@v2
with:
name: coverage-complete
path: ./output/coverage.tar

9
.gitignore vendored
View File

@@ -1,4 +1,7 @@
node_modules/
packages/*/node_modules
packages/*/lib._esm
.package_node_modules/
obsolete/
.DS_Store
.tmp/
@@ -18,3 +21,9 @@ lerna-debug.log
packages/*/tsconfig.tsbuildinfo
packages/testcases/input/nameprep/**
.nyc_output/**
output/**
misc/testing/**

View File

@@ -1,7 +1,286 @@
Changelog
=========
This change log is managed by `scripts/cmds/update-versions` but may be manually updated.
This change log is managed by `admin/cmds/update-versions` but may be manually updated.
ethers/v5.4.0 (2021-06-26 01:50)
--------------------------------
- Added EIP-1559 support. ([#1610](https://github.com/ethers-io/ethers.js/issues/1610); [319987e](https://github.com/ethers-io/ethers.js/commit/319987ec3e1d0e8787f98f525e5fc07875bf5570), [91fff14](https://github.com/ethers-io/ethers.js/commit/91fff1449df5e337fd3b4681b5a04b151d92f5a1), [c5bca77](https://github.com/ethers-io/ethers.js/commit/c5bca7767e3f3d43e3d0bd3c9e9420321ee9907a), [5456c35](https://github.com/ethers-io/ethers.js/commit/5456c359245d9eef5d2abdc05ccedb5269576c94), [7a12216](https://github.com/ethers-io/ethers.js/commit/7a12216cfbd3f86b917451924957471b8be21a8b), [e95708e](https://github.com/ethers-io/ethers.js/commit/e95708eedc130aeb92820a2234398970a987c507))
- Added effectiveGasPrice to receipt. ([ba6854b](https://github.com/ethers-io/ethers.js/commit/ba6854bdd5a912fe873d5da494cb5c62c190adde))
- Fixed ENS names for JsonRpcSigner. ([1e31b34](https://github.com/ethers-io/ethers.js/commit/1e31b34a5a3a269867a45b519662db85f0c86654))
- Added EIP-2930 and EIP-1559 transaction tests. ([7deb4c1](https://github.com/ethers-io/ethers.js/commit/7deb4c174a30b75f8419b8661829add4e5cb69d6))
- Added ConstructorFragment to exports. ([7efc36d](https://github.com/ethers-io/ethers.js/commit/7efc36df294ddd333e37793cad712cbd587bc686))
- Added error utilities to Interface. ([720bde7](https://github.com/ethers-io/ethers.js/commit/720bde7719d9a2fbc7e859f8952b7918e7164b87), [f053a7a](https://github.com/ethers-io/ethers.js/commit/f053a7ad58866c8192a64e1e335a2613358385be))
- merged master including transaction type 0 legacy constant. ([#1610](https://github.com/ethers-io/ethers.js/issues/1610); [2a7ce0e](https://github.com/ethers-io/ethers.js/commit/2a7ce0e72a1e0c9469e10392b0329e75e341cf18))
- Added type to TransactionResponse and TrnsactionReceipt. ([#1687](https://github.com/ethers-io/ethers.js/issues/1687); [d001901](https://github.com/ethers-io/ethers.js/commit/d001901c8c0541c823eb9638b9b309a316b00757))
- Trap CALL_EXCEPTION errors when resolving ENS entries. ([#1690](https://github.com/ethers-io/ethers.js/issues/1690); [91951dc](https://github.com/ethers-io/ethers.js/commit/91951dc825af42d4440d2d3b43cfa7a601b20342))
- Fixed transaction serialization with explicit null type. ([#1628](https://github.com/ethers-io/ethers.js/issues/1628); [8277f5a](https://github.com/ethers-io/ethers.js/commit/8277f5a62a6739a05ae6682da6956fb490b81e4a))
- Fix issue with loading JSON ABI with internalType property. ([#728](https://github.com/ethers-io/ethers.js/issues/728); [e8a0144](https://github.com/ethers-io/ethers.js/commit/e8a0144b7aa95add967578d9629d70bf01fc55cf))
ethers/v5.3.1 (2021-06-10 18:28)
--------------------------------
- Fixed replacement transaction detection for JsonRpcSigner. ([#1658](https://github.com/ethers-io/ethers.js/issues/1658); [ee82e86](https://github.com/ethers-io/ethers.js/commit/ee82e86ccc439825259d20825a00050217890ad3))
- Added Matic testnet info to networks. ([#1546](https://github.com/ethers-io/ethers.js/issues/1546); [376cf3c](https://github.com/ethers-io/ethers.js/commit/376cf3cdbf6d2281331d36c5742414a425927318))
- Match Solidity identifier regex. ([#1657](https://github.com/ethers-io/ethers.js/issues/1657); [a6e128f](https://github.com/ethers-io/ethers.js/commit/a6e128f5cc566d291b722cca1734ba41aae6c548))
ethers/v5.3.0 (2021-05-31 18:41)
--------------------------------
- Added MinInt256 and MaxInt256 constants. ([#1576](https://github.com/ethers-io/ethers.js/issues/1576); [bfcd05f](https://github.com/ethers-io/ethers.js/commit/bfcd05fcbb132d456d6f22f70c8ac9cf5b1826f7))
- Version bumps for bn.js and hash.js to match elliptic and fix some build tools. ([#1478](https://github.com/ethers-io/ethers.js/issues/1478); [819b1ac](https://github.com/ethers-io/ethers.js/commit/819b1ace5c9b16e29dc354ad80e0e5b71ac63c52))
- Removed Hangul checks in shims which crashes Android. ([#1519](https://github.com/ethers-io/ethers.js/issues/1519); [4b33114](https://github.com/ethers-io/ethers.js/commit/4b331148d980e3056ceaabdcd6e50a2aa1beb40d))
- Fixed ENS namehash with leading and trailing dots. ([#1605](https://github.com/ethers-io/ethers.js/issues/1605); [7adcf3b](https://github.com/ethers-io/ethers.js/commit/7adcf3b154669d9d1a0a66d5e15dabfbf6618180))
- Fixed broken variable in template string. ([#1624](https://github.com/ethers-io/ethers.js/issues/1624), [#1626](https://github.com/ethers-io/ethers.js/issues/1626); [630656e](https://github.com/ethers-io/ethers.js/commit/630656e949a8ffd940e4b66ec93ec07cd6ec2634))
- Fixed FixedNumber rounding for non-default formats. ([#1629](https://github.com/ethers-io/ethers.js/issues/1629); [8681cd5](https://github.com/ethers-io/ethers.js/commit/8681cd59698d02d040871aa889fc6ccc8550df98))
- Update ws dependency version to fix security. ([#1633](https://github.com/ethers-io/ethers.js/issues/1633), [#1634](https://github.com/ethers-io/ethers.js/issues/1634); [470551e](https://github.com/ethers-io/ethers.js/commit/470551e4ee3f1e343a26fc0775f9d9f7489129f8))
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)
---------------------------------
- Fix browser ws alias for WebSockets. ([02546b9](https://github.com/ethers-io/ethers.js/commit/02546b9401d8066135b4453da917f7ef49c95ad8))
- Fixing React Native tests. ([f10977a](https://github.com/ethers-io/ethers.js/commit/f10977ab35f953c3148d99b61799788f47d2a5a2), [fff72ef](https://github.com/ethers-io/ethers.js/commit/fff72ef369f5420bf8283b0808e8fec71f26dd2b))
- Refactoring dist build process. ([4809325](https://github.com/ethers-io/ethers.js/commit/4809325bee9cbdd269b099d7b12b218f441ac840), [22bd0c7](https://github.com/ethers-io/ethers.js/commit/22bd0c76dddef7134618ec70ac1b084a054e616e), [8933467](https://github.com/ethers-io/ethers.js/commit/8933467c01b64ead547d7c136f22f3c05c85ca1f))
ethers/v5.0.19 (2020-10-22 21:55)
---------------------------------
- Allow 0x as a numeric value for 0 in Provider formatter. ([#1104](https://github.com/ethers-io/ethers.js/issues/1104); [fe17a29](https://github.com/ethers-io/ethers.js/commit/fe17a295816214d063f3d6bd4f3273e0ce0c3eac))
- Use POST for long requests in EtherscanProvider. ([#1093](https://github.com/ethers-io/ethers.js/issues/1093); [28f60d5](https://github.com/ethers-io/ethers.js/commit/28f60d5ef83665541c8c1b432f8e173d73cb8227))
- Added verifyTypedData for EIP-712 typed data. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [550ecf2](https://github.com/ethers-io/ethers.js/commit/550ecf2f25b90f6d8996583489a218dbf2306ebc), [a21202c](https://github.com/ethers-io/ethers.js/commit/a21202c66b392ec6f91296d66551dffca742cf0a))
ethers/v5.0.18 (2020-10-19 01:26)
---------------------------------
- Fix signTypedData call for JsonRpcSigner. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [15a90af](https://github.com/ethers-io/ethers.js/commit/15a90af5be75806e26f589f0a3f3687c0fb1c672))
- Added EIP-712 test cases. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [1589353](https://github.com/ethers-io/ethers.js/commit/15893537c3d9c92fe8748a3e9617d133d1d5d6a7))
- Initial Signer support for EIP-712 signed typed data. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [be4e216](https://github.com/ethers-io/ethers.js/commit/be4e2164e64dfa0697561763e8079120a485a566))
- Split hash library files up. ([3e676f2](https://github.com/ethers-io/ethers.js/commit/3e676f21b00931ed966f4561e4f28792a1f8f154))
- Added EIP-712 multi-dimensional array support. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [5a4dd5a](https://github.com/ethers-io/ethers.js/commit/5a4dd5a70377d3e86823d279d6ff466d03767644))
- Consolidated TypedDataEncoder methods. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [345a830](https://github.com/ethers-io/ethers.js/commit/345a830dc4bc869d5f3edfdc27465797e7663055))
- Initial EIP-712 utilities. ([#687](https://github.com/ethers-io/ethers.js/issues/687); [cfa6dec](https://github.com/ethers-io/ethers.js/commit/cfa6dec29314fe485df283974612d40550bc4179))
- Added initial PocketProvider. ([#1052](https://github.com/ethers-io/ethers.js/issues/1052); [a62d20d](https://github.com/ethers-io/ethers.js/commit/a62d20d86f2d545b9a7bcda5418993790b7db91c))
ethers/v5.0.17 (2020-10-07 20:08)
---------------------------------
- Better error message for parseUnits of non-strings. ([#981](https://github.com/ethers-io/ethers.js/issues/981); [5abc2f3](https://github.com/ethers-io/ethers.js/commit/5abc2f36e20eef79a935961f3dd8133b5528d9e5))
- Add gzip support to AlchemyProivder and InfuraProvider fetching. ([#1085](https://github.com/ethers-io/ethers.js/issues/1085); [38a068b](https://github.com/ethers-io/ethers.js/commit/38a068bcea3f251c8f3a349a90fcb077a39d23ad))
- Add gzip support to getUrl in node. ([#1085](https://github.com/ethers-io/ethers.js/issues/1085); [65772a8](https://github.com/ethers-io/ethers.js/commit/65772a8e1a55d663bdb67e3a2b160fecc9f986ef))
- Added CommunityResourcable to mark Providers as highly throttled. ([a022093](https://github.com/ethers-io/ethers.js/commit/a022093ce03f55db7ba2cac36e365d1af39ac45b))
- Added debug event info to WebSocketProvider. ([#1018](https://github.com/ethers-io/ethers.js/issues/1018); [8e682cc](https://github.com/ethers-io/ethers.js/commit/8e682cc8481c6051a6f8115b29d78f4996120ccd))
ethers/v5.0.16 (2020-10-05 15:44)
---------------------------------
- ABI encoding performance additions. ([#1012](https://github.com/ethers-io/ethers.js/issues/1012); [f3e5b0d](https://github.com/ethers-io/ethers.js/commit/f3e5b0ded1b227a377fd4799507653c95c76e353))
- Export hexConcat in utils. ([#1079](https://github.com/ethers-io/ethers.js/issues/1079); [3d051e4](https://github.com/ethers-io/ethers.js/commit/3d051e454db978f58c7b38ff4484096c3eb85b94))
- Cache chain ID for WebSocketProvider. ([#1054](https://github.com/ethers-io/ethers.js/issues/1054); [40264ff](https://github.com/ethers-io/ethers.js/commit/40264ff9006156ba8441e6101e5a7149a5cf03f6))
ethers/v5.0.15 (2020-09-26 03:22)
---------------------------------
- Add more accurate intrinsic gas cost to ABI calls with specified gas property. ([#1058](https://github.com/ethers-io/ethers.js/issues/1058); [f0a5869](https://github.com/ethers-io/ethers.js/commit/f0a5869c53475e55a5f47d8651f609fff45dc9a7))
- Better errors for unconfigured ENS names. ([#1066](https://github.com/ethers-io/ethers.js/issues/1066); [5cd1668](https://github.com/ethers-io/ethers.js/commit/5cd1668e0d29099c5b7ce1fdc1d0e8a41af1a249))
- Updated CLI solc to versin 0.7.1. ([4306b35](https://github.com/ethers-io/ethers.js/commit/4306b3563a171baa9d7bf4872475a13c3434f834))
ethers/v5.0.14 (2020-09-16 02:39)
---------------------------------
- More robust blockchain error detection ([#1047](https://github.com/ethers-io/ethers.js/issues/1047); [49f7157](https://github.com/ethers-io/ethers.js/commit/49f71574f4799d685a5ae8fd24fe1134f752d70a))
- Forward blockchain errors from Signer during gas estimation. ([#1047](https://github.com/ethers-io/ethers.js/issues/1047); [9ee685d](https://github.com/ethers-io/ethers.js/commit/9ee685df46753c46cbbde12d05d6ea04f2b5ea3f))
- Improve fetch errors with looser mime-type detection. ([#1047](https://github.com/ethers-io/ethers.js/issues/1047); [263bfe5](https://github.com/ethers-io/ethers.js/commit/263bfe5ce632790e0399d06a0ab660a501997998))
ethers/v5.0.13 (2020-09-11 02:10)
---------------------------------
- Force content-length in web fetching. ([be92339](https://github.com/ethers-io/ethers.js/commit/be923396962ea76bf0fb566dcf8801e58ccf0e7e))
- Better error forwarding from FallbackProvider. ([#1021](https://github.com/ethers-io/ethers.js/issues/1021); [bc3eeec](https://github.com/ethers-io/ethers.js/commit/bc3eeeca39adb734f24019d0e942eff2eac6ad4d))
- Add clamping functions to FixedNumber. ([#1037](https://github.com/ethers-io/ethers.js/issues/1037); [042b74e](https://github.com/ethers-io/ethers.js/commit/042b74e6ee648d4fa37bf674194273d8f4483bfb))
ethers/v5.0.12 (2020-09-07 19:54)
---------------------------------
- Allow events to use compact bytes ABI coded data for Solidity 0.4 external events. ([#891](https://github.com/ethers-io/ethers.js/issues/891), [#992](https://github.com/ethers-io/ethers.js/issues/992); [4e394fc](https://github.com/ethers-io/ethers.js/commit/4e394fc68019445ae4b4e201e41f95d6793dbe92))
ethers/v5.0.11 (2020-09-05 23:51)
---------------------------------
- Synced unorm in shims to most recent version. ([bdccf7b](https://github.com/ethers-io/ethers.js/commit/bdccf7b8d352ba400317266a0a37e6e290633e3c))
- Fixed LedgerSigner sendTransaction. ([#936](https://github.com/ethers-io/ethers.js/issues/936); [cadb28d](https://github.com/ethers-io/ethers.js/commit/cadb28d6b364e68e43a06f7a9b8a31797afbd920))
- Added BrainWallet to experimental exports. ([72385c2](https://github.com/ethers-io/ethers.js/commit/72385c228783a3158511b3cddc5cb4f9ce1dddae))
- More readable server errors. ([201e5ce](https://github.com/ethers-io/ethers.js/commit/201e5ced9c38da2de1dd7518ffbf24284d477e80))
ethers/v5.0.10 (2020-09-05 01:21)
---------------------------------
- Added retry logic to provider tests. ([0558bba](https://github.com/ethers-io/ethers.js/commit/0558bba8eb1b783ef50bb37bcf4c9bae1f86f1e1), [35b64b9](https://github.com/ethers-io/ethers.js/commit/35b64b9a65e2c09ecb63b0eca712b45a3092c204), [681f2a5](https://github.com/ethers-io/ethers.js/commit/681f2a50b26d7954795dba5aec55bede4740e494))
- Fixed link in docs. ([#1028](https://github.com/ethers-io/ethers.js/issues/1028); [2359a98](https://github.com/ethers-io/ethers.js/commit/2359a98641d99b26cf88ec892e3601a8a2c81c9c))
- Added memory-like support and new opcodes to asm. ([6fd3bb6](https://github.com/ethers-io/ethers.js/commit/6fd3bb62d10eab1563dc4ddbd88732b4f484ec7a))
- Added basic ENS resolver functions for contenthash, text and multi-coin addresses. ([#1003](https://github.com/ethers-io/ethers.js/issues/1003); [83db8a6](https://github.com/ethers-io/ethers.js/commit/83db8a6bd1364458dcfeea544de707df41890b4e))
- Added support for changing Reporter logging function. ([d01d0c8](https://github.com/ethers-io/ethers.js/commit/d01d0c8448df40de52253f9e92889ab7e75c6a97))
- Initial React Native test harness. ([#993](https://github.com/ethers-io/ethers.js/issues/993); [57eb5b7](https://github.com/ethers-io/ethers.js/commit/57eb5b777e2c67f1f8d74e41d3413e9f0564528d), [d3b473e](https://github.com/ethers-io/ethers.js/commit/d3b473e7c738fdfc65b6f1c8f80bcdacf9827d8a))
- Updating shims for constrained environments. ([#944](https://github.com/ethers-io/ethers.js/issues/944), [#993](https://github.com/ethers-io/ethers.js/issues/993); [8abdbbb](https://github.com/ethers-io/ethers.js/commit/8abdbbbf633f96fde2346c4ae70e538895fd7829), [240aac5](https://github.com/ethers-io/ethers.js/commit/240aac568303deff14cbb2366b94c8c89cacefc1))
ethers/v5.0.9 (2020-08-25 01:45)
--------------------------------
- Updated docs for all packages on npm pages. ([#1013](https://github.com/ethers-io/ethers.js/issues/1013); [cb8f4a3](https://github.com/ethers-io/ethers.js/commit/cb8f4a3a4e378a749c6bbbddf46d8d79d35722cc))
- Added JSON support to BigNumber. ([#1010](https://github.com/ethers-io/ethers.js/issues/1010); [8facc1a](https://github.com/ethers-io/ethers.js/commit/8facc1a5305b1f699aa3afc5a0a692abe7927652))
- Updated packages for security audit. ([5b5904e](https://github.com/ethers-io/ethers.js/commit/5b5904ea9977ecf8c079a57593b627553f0126a0))
- Fix emitted error for ABI code array count mismatch. ([#1004](https://github.com/ethers-io/ethers.js/issues/1004); [b0c082d](https://github.com/ethers-io/ethers.js/commit/b0c082d728dc66b0f2a5ec315da44d6295716284))
ethers/v5.0.8 (2020-08-04 20:55)
--------------------------------
- Abstract fetchJson for data. ([e2d6f28](https://github.com/ethers-io/ethers.js/commit/e2d6f281d5a2bd749bc72549a4e55f2c752a7bd8), [2c49a52](https://github.com/ethers-io/ethers.js/commit/2c49a52a41a30ae844376561de95f0c851d19f73), [e1bbb06](https://github.com/ethers-io/ethers.js/commit/e1bbb064a10d0b4bf5563e0a79396665d83935a1))
ethers/v5.0.7 (2020-07-20 02:22)
--------------------------------
- Fix Logger setLogLevel with enum case mismatch. ([#947](https://github.com/ethers-io/ethers.js/issues/947); [5443363](https://github.com/ethers-io/ethers.js/commit/5443363de43e92de712e72d55165c3f4d7f652e9), [af10705](https://github.com/ethers-io/ethers.js/commit/af10705632bc1f8203ea50ea7ed3120b01c67122))
- Removed UUID dependency from json-wallets. ([#966](https://github.com/ethers-io/ethers.js/issues/966); [e3f7426](https://github.com/ethers-io/ethers.js/commit/e3f7426af4d6d7e43db322700d768216b06433e0))
- Removed unnecessary dependency from BigNumber. ([#951](https://github.com/ethers-io/ethers.js/issues/951); [78b350b](https://github.com/ethers-io/ethers.js/commit/78b350bbc5ea73561bf47038743b9e51049496f7))
ethers/v5.0.6 (2020-07-16 05:54)
--------------------------------
@@ -64,4 +343,3 @@ ethers/v5.0.0 (2020-06-12 19:58)
- Preserve config canary string. ([7157816](https://github.com/ethers-io/ethers.js/commit/7157816fa53f660d750811b293e3b1d5a2f70bd4))
- Updated docs. ([9e4c7e6](https://github.com/ethers-io/ethers.js/commit/9e4c7e609d9eeb5f2a11d6a90bfa9d32ee696431))

View File

@@ -17,7 +17,7 @@ A complete Ethereum wallet implementation and utilities in JavaScript (and TypeS
- **Tiny** (~104kb compressed; 322kb uncompressed)
- **Modular** packages; include only what you need
- **Complete** functionality for all your Ethereum desires
- Extensive [documentation](https://docs.ethers.io/ethers.js/html/)
- Extensive [documentation](https://docs.ethers.io/v5/)
- Large collection of **test cases** which are maintained and added to
- Fully **TypeScript** ready, with definition files and full TypeScript source
- **MIT License** (including ALL dependencies); completely open source to do with as you please
@@ -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>
```
@@ -75,14 +75,14 @@ Ancillary Packages
These are a number of packages not included in the umbrella `ethers` npm package, and
additional packages are always being added. Often these packages are for specific
use-cases, so rather than adding them to the umbrella package, they are added as
ancillary packaged, which can be included by those who need them, while not bloating
ancillary packages, which can be included by those who need them, while not bloating
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,124 +0,0 @@
"use strict";
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));
}
(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) {
{
// The password above already succeeded
const username = await config.get("github-user");
const password = await config.get("github-release");
// Get the latest change from the changelog
const change = latestChange();
// Publish the release
const link = await createRelease(username, password, change.version, change.title, change.content, beta, gitCommit);
log(`<bold:Published Release:> ${ link }`);
}
/*
{
const accessKey = await config.get("aws-upload-scripts-accesskey");
const secretKey = await config.get("aws-upload-scripts-secretkey");
const s3 =
}
*/
}
})();

View File

@@ -1,5 +0,0 @@
"use strict";
const { setupBuild } = require("../build");
setupBuild(false);

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,37 +0,0 @@
const { setupBuild } = require("../build");
const { loadPackage, savePackage } = require("../local");
const arg = process.argv[2];
(async function() {
process.argv.slice(2).forEach((arg) => {
console.log("Setting Option:", arg);
switch(arg) {
case "esm":
setupBuild(true);
break;
case "cjs":
setupBuild(false);
break;
// This will remove the browser field entirely, so make sure
// to set esm of cjs first as they will restore the browser
// field
case "browser-lang-all": {
const info = loadPackage("wordlists");
delete info.browser;
savePackage("wordlists", info);
break;
}
default:
console.log("Unknown option:", arg);
return 1;
}
});
return 0;
})().then((result) => {
process.exit(result);
});

View File

@@ -1,16 +0,0 @@
"use stricT";
const depgraph = require("../depgraph");
const { log } = require("../log");
const { loadJson, resolve, saveJson } = require("../utils");
(async function() {
log(`<bold:Updating dependency-graph build order (tsconfig.project.json)...>`);
let ordered = depgraph.getOrdered(true);
let path = resolve("tsconfig.project.json")
let projectConfig = loadJson(path);
projectConfig.references = ordered.map((name) => ({ path: ("./packages/" + name) }));
saveJson(path, projectConfig);
})();

View File

@@ -1,30 +0,0 @@
"use strict";
const fs = require("fs");
const { resolve } = require("path");
const sourceEthers = fs.readFileSync(resolve(__dirname, "../../packages/ethers/src.ts/ethers.ts")).toString();
const targets = sourceEthers.match(/export\s*{\s*((.|\s)*)}/)[1].trim();
const output = `"use strict";
// To modify this file, you must update ./admin/cmds/update-exports.js
import * as ethers from "./ethers";
try {
const anyGlobal = (window as any);
if (anyGlobal._ethers == null) {
anyGlobal._ethers = ethers;
}
} catch (error) { }
export { ethers };
export {
${ targets }
} from "./ethers";
`;
fs.writeFileSync(resolve(__dirname, "../../packages/ethers/src.ts/index.ts"), output);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,11 +10,11 @@ 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
own API key), they are aggressively throttled which means reties occur more
own API key), they are aggressively throttled which means retries occur more
frequently and the responses are slower.
It is **highly recommended** that you sign up for a free API key from each service for 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,78 +1,119 @@
_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, bydecode [ , signer ]) @SRC<contracts:constructor.ContractFactory>
_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>
_property: contractFactory.attach(address) => [[Contract]] @<ContractFactory-attach>
Return an instance of a [[Contract]] attched to //address//. This is the
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
retruns 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``.
// <hide>
const signer = ethers.LocalSigner();
const ContractFactory = ethers.ContractFactory;
// </hide>
_code: Deploying a Contract @lang<javascript>
//_hide: const signer = localSigner;
//_hide: const ContractFactory = ethers.ContractFactory;
//_hide: const bytecode = "608060405234801561001057600080fd5b5060405161012e38038061012e8339818101604052604081101561003357600080fd5b81019080805190602001909291908051906020019092919050505081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060008190555050506088806100a66000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633fa4f24514602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000805490509056fea2646970667358221220926465385af0e8706644e1ff3db7161af699dc063beaadd55405f2ccd6478d7564736f6c63430007040033";
// 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
//_result:
contract.address
//!
//_log:
// The transaction that the signer sent to deploy
//_result:
contract.deployTransaction
//!
//_log:
// Wait until the transaction is mined
contract.deployTransaction.wait()
//!
// Wait until the transaction is mined (i.e. contract is deployed)
// - returns the receipt
// - throws on failure (the reciept is on the error)
//_result:
await contract.deployTransaction.wait()
//_log:
// Now the contract is safe to interact with
contract.value()
//!
//_result:
await contract.value()
//_log:

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>
@@ -178,7 +178,7 @@ _subsection: Meta-Class Filters @NOTE<(added at Runtime)>
Since the Contract is a Meta-Class, the methods available here depend
on the ABI which was passed into the **Contract**.
_property: erc20.filters.Transafer([ fromAddress [ , toAddress ] ]) => Filter
_property: erc20.filters.Transfer([ fromAddress [ , toAddress ] ]) => Filter
Returns a new Filter which can be used to [query](erc20-queryfilter) or
to [subscribe/unsubscribe to events](erc20-events).

View File

@@ -5,6 +5,10 @@ to be included in the base library. The API should not be considered
stable and does not follow [[link-semver]] versioning, so applications
requiring it should specify the //exact version// needed.
These features are not available in the core ethers package, so to use them
you must install the ``@ethersproject/experimental`` package and import them
from that.
_subsection: BrainWallet @<experimental-brainwallet> @INHERIT<[[Wallet]]>
Ethers removed support for BrainWallets in v4, since they are unsafe and
@@ -17,7 +21,15 @@ Generates a brain wallet, with a slightly improved experience, in which
the generated wallet has a mnemonic.
_property: BrainWallet.generateLegacy(username, password [ , progressCallback ]) => [[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.
_code: Importing @lang<script>
// Node
const { BrainWallet } = require("@ethersproject/experimental");
// ESM/TypeScript
import { BrainWallet } from "@ethersproject/experimental";
_subsection: EIP1193Bridge @<experimental-eip1193bridge> @INHERIT<[[link-npm-events]]>
@@ -26,6 +38,14 @@ The **EIP1193Bridge** allows a normal Ethers [[Signer]] and [[Provider]] to be
exposed in as a standard [EIP-1193 Provider](link-eip-1193), which may be useful
when interacting with other libraries.
_code: Importing @lang<script>
// Node
const { Eip1193Bridge } = require("@ethersproject/experimental");
// ESM/TypeScript
import { Eip1193Bridge } from "@ethersproject/experimental";
_subsection: NonceManager @<experimental-noncemanager> @INHERIT<[[Signer]]>
@@ -55,11 +75,19 @@ 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.
_code: Importing @lang<script>
// Node
const { NonceManager } = require("@ethersproject/experimental");
// ESM/TypeScript
import { NonceManager } from "@ethersproject/experimental";

View File

@@ -26,7 +26,7 @@ Create a formatted output of an array of [[asm-operation]].
_heading: Bytecode @<asm-bytecode> @INHERIT<Array\<[[asm-operation]]\>>
Each arary index represents an operation, collapsing multi-byte operations
Each array index represents an operation, collapsing multi-byte operations
(i.e. ``PUSH``) into a single operation.
_property: bytecode.getOperation(offset) => [[asm-operation]]
@@ -52,7 +52,7 @@ If the opcode is a ``PUSH``, this is the value of that push
_subsection: Opcode @<asm-opcode> @SRC<asm/opcodes:class.Opcode>
_property: asm.Opcode.from(valueOrMnemonic) => [[asm-opcode]]
Create a new instnace of an Opcode for a given numeric value
Create a new instance of an Opcode for a given numeric value
(e.g. 0x60 is PUSH1) or mnemonic string (e.g. "PUSH1").
_heading: Properties

View File

@@ -49,7 +49,7 @@ string of a decimal number.
_property: literalNode.verbatim => boolean
This is true in a [[asm-datanode]] context, since in that case the
value should be taken verbatim and no ``PUSH`` operation shoud be
value should be taken verbatim and no ``PUSH`` operation should be
added, otherwise false.
@@ -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
@@ -96,7 +96,7 @@ any output assembly, using the ``{{! code here }}`` syntax.
_property: literalNode.verbatim => boolean
This is true in a [[asm-datanode]] context, since in that case the
value should be taken verbatim and no ``PUSH`` operation shoud be
value should be taken verbatim and no ``PUSH`` operation should be
added, otherwise false.
_property: evaluationNode.script => string
@@ -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

@@ -1,9 +1,9 @@
_section: Ethers ASM Dialect @<asm-dialect>
This provides a quick, high-level overcview of the **Ethers ASM Dialect**
This provides a quick, high-level overview of the **Ethers ASM Dialect**
for EVM, which is defined by the [Ethers ASM Dialect Grammar](link-ethers-asm-grammar)
Once a program is compiled by a higher level langauge into ASM (assembly),
Once a program is compiled by a higher level language into ASM (assembly),
or hand-coded directly in ASM, it needs to be assembled into bytecode.
The assembly process performs a very small set of operations and is
@@ -34,7 +34,7 @@ A **Label** is a position in the program which can be jumped to. A
``JUMPDEST`` is automatically added to this point in the assembled
output.
@TODO: Exmaples
@TODO: Examples
_subsection: Literals @<asm-dialect-literal>
@@ -45,7 +45,7 @@ operation.
A **Literal** can be provided using a [[DataHexString]] or a decimal
byte value.
@TODO: exmples
@TODO: examples
_subsection: Comments @<asm-dialect-comment>
@@ -64,7 +64,7 @@ within a **deployment bytecode**, which can be used as **init code**.
When deploying a program to Ethereum, an **init transaction** is used. An
//init transaction// has a null ``to`` address and contains bytecode in
the ``data``. This ``data`` bytecode is a program, that when executed
returns some other bytecode as a result, this restul is the bytecode
returns some other bytecode as a result, this result is the bytecode
to be installed.
Therefore it is important that embedded code uses jumps relative to itself,
@@ -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>
@@ -84,7 +84,7 @@ _subsection: Data Segment @<asm-dialect-datasegment>
A **Data Segment** allows arbitrary data to be embedded into a program,
which can be useful for lookup tables or deploy-time constants.
An emtpty **Data Segment** can also be used when a labelled location is
An empty **Data Segment** can also be used when a labelled location is
required, but without the ``JUMPDEST`` which a [[asm-dialect-label]] adds.
@TODO: Example
@@ -111,5 +111,5 @@ _subsection: Stack Placeholders @<asm-dialect-placeholder>
@TODO: exampl
_subsection: Evaluation and Excution @<asm-dialect-scripting>
_subsection: Evaluation and Execution @<asm-dialect-scripting>

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).
@@ -47,10 +47,8 @@ _definition: **Supported Networks**
_code: Etherscan Examples @lang<javascript>
// <hide>
const EtherscanProvider = ethers.providers.EtherscanProvider;
const apiKey = "...";
// </hide>
//_hide: const EtherscanProvider = ethers.providers.EtherscanProvider;
//_hide: const apiKey = "...";
// Connect to mainnet (homestead)
provider = new EtherscanProvider();
@@ -59,12 +57,9 @@ provider = new EtherscanProvider();
provider = new EtherscanProvider("rinkeby");
provider = new EtherscanProvider(4);
const network = ethers.providers.getNetwork("rinkeby");
// <hide>
delete network._defaultProvider;
network
// </hide>
//!
network = ethers.providers.getNetwork("rinkeby");
//_hide: delete network._defaultProvider;
//_log: network
provider = new EtherscanProvider(network);
@@ -86,7 +81,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).
@@ -119,11 +114,9 @@ _definition: **Supported Networks**
_code: INFURA Examples @lang<javascript>
// <hide>
const InfuraProvider = ethers.providers.InfuraProvider;
const projectId = "...";
const projectSecret = "...";
// </hide>
//_hide: const InfuraProvider = ethers.providers.InfuraProvider;
//_hide: const projectId = "...";
//_hide: const projectSecret = "...";
// Connect to mainnet (homestead)
provider = new InfuraProvider();
@@ -144,9 +137,7 @@ provider = new InfuraProvider("homestead", {
// Connect to the INFURA WebSocket endpoints with a WebSocketProvider
provider = InfuraProvider.getWebSocketProvider()
// <hide>
provider.destroy();
// </hide>
//_hide: await provider.destroy();
_subsection: AlchemyProvider @<AlchemyProvider> @inherit<[[UrlJsonRpcProvider]]> @src<providers:class.AlchemyProvider>
@@ -157,7 +148,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).
@@ -178,10 +169,8 @@ _definition: **Supported Networks**
_code: Alchemy Examples @lang<javascript>
// <hide>
const AlchemyProvider = ethers.providers.AlchemyProvider;
const apiKey = "...";
// </hide>
//_hide: const AlchemyProvider = ethers.providers.AlchemyProvider;
//_hide: const apiKey = "...";
// Connect to mainnet (homestead)
provider = new AlchemyProvider();
@@ -196,9 +185,7 @@ provider = new AlchemyProvider("homestead", apiKey);
// Connect to the Alchemy WebSocket endpoints with a WebSocketProvider
provider = AlchemyProvider.getWebSocketProvider()
// <hide>
provider.destroy();
// </hide>
//_hide: provider.destroy();
_subsection: CloudflareProvider @<CloudflareProvider> @inherit<[[UrlJsonRpcProvider]]> @src<providers:class.CloudflareProvider>
@@ -214,9 +201,7 @@ _definition: **Supported Networks**
_code: Cloudflare Examples @lang<javascript>
// <hide>
const CloudflareProvider = ethers.providers.CloudflareProvider;
// </hide>
//_hide: const CloudflareProvider = ethers.providers.CloudflareProvider;
// Connect to mainnet (homestead)
provider = new CloudflareProvider();

View File

@@ -9,7 +9,7 @@ cover the vast majority of use-cases, but also includes the
necessary functions and classes for sub-classing if a more
custom configuration is necessary.
Most users should be able to simply use the [[providers-getDefaultProvider]].
Most users should use the [[providers-getDefaultProvider]].
_subsection: Default Provider @<providers-getDefaultProvider>
@@ -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,29 +31,34 @@ 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``
or ``wss:/\/example.com``.
The //options// is an object, with the following properties:
_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
@@ -67,6 +72,54 @@ used the most.
Some services also provide additional paid features, which are only
available when specifying an API Key.
_subsection: Networks
There are several official common Ethereum networks as well as custom
networks and other compatible projects.
Any API that accept a [[providers-Networkish]] can be passed a common
name (such as ``"mainnet"`` or ``"ropsten"``) or chain ID to use that
network definition or may specify custom parameters.
_property: ethers.providers.getNetwork(aNetworkish) => [[providers-Network]]
Returns the full [[providers-Network]] for the given standard
//aNetworkish// [[providers-Networkish]].
This is useful for functions and classes which wish to accept [[providers-Networkish]]
as an input parameter.
_code: @lang<javascript>
//_hide: const getNetwork = ethers.providers.getNetwork;
// By Chain Name
//_result:
getNetwork("homestead");
//_hide: delete _._defaultProvider;
//_log:
// By Chain ID
//_result:
getNetwork(1);
//_hide: delete _._defaultProvider;
//_log:
_heading: Custom ENS Contract
One common reason to specify custom properties for a [[providers-Network]] is to override
the address of the root ENS registry, either on a common network to intercept
the [ENS Methods](Provider--ens-methods) or to specify the ENS registry on a
dev network (on most dev networks you must deploy the ENS contracts manually).
_code: Example: Override the ENS registry @lang<script>
const network = {
name: "dev",
chianId: 1337,
ensAddress: customEnsAddress
};
_subsection: Provider Documentation

View File

@@ -1,15 +1,17 @@
_section: JsonRpcProvider @<JsonRpcProvider> @INHERIT<[[Provider]]> @SRC<providers:class.JsonRpcProvider>
The [JSON-RPC API](link-jsonrpc) is a very popular method for interacting
The [JSON-RPC API](link-jsonrpc) is a popular method for interacting
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
choosen (higher prioirty 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 choosen
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
@@ -96,7 +94,7 @@ The URL to use for the JsonRpcProvider instance.
_subsection: Web3Provider @<Web3Provider> @INHERIT<[[JsonRpcProvider]]> @SRC<providers:class.Web3Provider>
The Web3Provider is meant to ease moving from a [web3.js based](link-web3)
application to ethers by wraping an existing Web3-compatible (such as a
application to ethers by wrapping an existing Web3-compatible (such as a
[Web3HttpProvider](link-web3-http), [Web3IpcProvider](link-web3-ipc) or
[Web3WsProvider](link-web3-ws)) and exposing it as an ethers.js [[Provider]]
which can then be used with the rest of the library.
@@ -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.WebSockerProvider([ 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,42 +1,61 @@
_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>
_property: provider.getBalance(address [ , blockTag = latest ]) => Promise<[[BigNumber]]> @<Provider-getBalance> @SRC<providers/base-provider>
Returns the balance of //address// as of the //blockTag// block height.
_code: @lang<javascript>
//_result:
await provider.getBalance("ricmoo.eth");
//_log:
_property: provider.getCode(address [ , blockTag = latest ]) => Promise<string<[[DataHexString]]>> @<Provider-getCode> @SRC<providers/base-provider>
Returns the contract code of //address// as of the //blockTag// block height. If there is
no contract currently deployed, the result is ``0x``.
_code: @lang<javascript>
//_result:
await provider.getCode("registrar.firefly.eth");
//_log:
_property: provider.getStorageAt(addr, pos [ , blockTag = latest ]) => Promise<string<[[DataHexString]]>> @<Provider-getStorageAt> @SRC<providers/base-provider>
Returns the ``Bytes32`` value of the position //pos// at address //addr//, as of the //blockTag//.
_code: @lang<javascript>
//_result:
await provider.getStorageAt("registrar.firefly.eth", 0)
//_log:
_property: provider.getTransactionCount(address [ , blockTag = latest ]) => Promise<number> @<Provider-getTransactionCount> @SRC<providers/base-provider>
Returns the number of transactions //address// has ever **sent**, as of //blockTag//.
This value is required to be the nonce for the next transaction from //address//
sent to the network.
_code: Account Examples @lang<javascript>
_code: @lang<javascript>
// Get the balance for an account...
provider.getBalance("ricmoo.firefly.eth");
//!
// Get the code for a contract...
provider.getCode("registrar.firefly.eth");
//!
// Get the storage value at position 0...
provider.getStorageAt("registrar.firefly.eth", 0)
//!
// Get transaction count of an account...
provider.getTransactionCount("ricmoo.firefly.eth");
//!
//_result:
await provider.getTransactionCount("ricmoo.eth");
//_log:
_subsection: Blocks Methods @<Provider--block-methods>
@@ -45,17 +64,21 @@ _property: provider.getBlock(block) => Promise<[[providers-Block]]> @<Provider-
Get the //block// from the network, where the ``result.transactions`` is a list
of transaction hashes.
_code: @lang<javascript>
//_result:
await provider.getBlock(100004)
//_log:
_property: provider.getBlockWithTransactions(block) => Promise<[[providers-BlockWithTransactions]]> @<Provider-getBlockWithTransactions> @SRC<providers/base-provider>
Get the //block// from the network, where the ``result.transactions`` is
an Array of [[providers-TransactionResponse]] objects.
_code: Block Examples @lang<javascript>
_code: @lang<javascript>
provider.getBlock(100004)
//!
provider.getBlockWithTransactions(100004)
//!
//_result:
await provider.getBlockWithTransactions(100004)
//_log:
_subsection: Ethereum Naming Service (ENS) Methods @<Provider--ens-methods>
@@ -73,26 +96,102 @@ 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.
_code: @lang<javascript>
//_hide: provider = ethers.getDefaultProvider();
// See below (Resolver) for examples of using this object
const resolver = await provider.getResolver("ricmoo.eth");
//_hide: _page.resolver = resolver;
_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
forward lookup does not match, ``null`` is returned.
An ENS name requries additional configuration to setup a reverse
record, they are not automatically set up.
_code: @lang<javascript>
//_result:
await provider.lookupAddress("0x5555763613a12D8F3e73be831DFf8598089d3dCa");
//_log:
_property: provider.resolveName(name) => Promise<string<[Address](address)>> @<Provider-ResolveName> @SRC<providers/base-provider>
Looks up the address of //name//. If the name is not owned, or
does not have a //Resolver// configured, or the //Resolver// does
not have an address configured, ``null`` is returned.
_code: ENS Examples @lang<javascript>
_code: @lang<javascript>
// Reverse lookup of an ENS by address...
provider.lookupAddress("0x6fC21092DA55B392b045eD78F4732bff3C580e2c");
//!
//_result:
await provider.resolveName("ricmoo.eth");
//_log:
// Lookup an address of an ENS name...
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.
_code: @lang<javascript>
//_hide: const resolver = _page.resolver;
// By default, looks up the Ethereum address
// (this will match provider.resolveName)
//_result:
await resolver.getAddress();
//_log:
// Specify the coinType for other coin addresses (0 = Bitcoin)
//_result:
await resolver.getAddress(0);
//_log:
_property: resolver.getContentHash() => Promise<string>
Returns a Promise which resolves to any stored [[link-eip-1577]] content hash.
_code: @lang<javascript>
//_hide: const resolver = _page.resolver;
//_result:
await resolver.getContentHash();
//_log:
_property: resolver.getText(key) => Promise<string>
Returns a Promise which resolves to any stored [[link-eip-634]] text entry for //key//.
_code: @lang<javascript>
//_hide: const resolver = _page.resolver;
//_result:
await resolver.getText("email");
//_log:
//_result:
await resolver.getText("url");
//_log:
//_result:
await resolver.getText("com.twitter");
//_log:
_subsection: Logs Methods @<Provider--log-methods>
@@ -109,36 +208,44 @@ _subsection: Network Status Methods @<Provider--network-methods>
_property: provider.getNetwork() => Promise<[[providers-Network]]> @<Provider-getNetwork> @SRC<providers/base-provider:method.BaseProvider.getNetwork>
Returns the [[providers-Network]] this Provider is connected to.
_code: @lang<javascript>
//_result:
await provider.getNetwork()
//_hide: _ = utils.shallowCopy(_);
//_hide: delete _._defaultProvider;
//_log:
_property: provider.getBlockNumber() => Promise<number> @<Provider-getBlockNumber> @SRC<providers/base-provider>
Returns the block number (or height) of the most recently mined block.
_code: @lang<javascript>
//_result:
await provider.getBlockNumber()
//_log:
_property: provider.getGasPrice() => Promise<[[BigNumber]]> @<Provider-getGasPrice> @SRC<providers/base-provider>
Returns a //best guess// of the [[gas-price]] to use in a transaction.
_code: Network Status Examples @lang<javascript>
_code: @lang<javascript>
// The network information
provider.getNetwork()
// <hide>
//!
network = utils.shallowCopy(_)
delete network._defaultProvider
network
// </hide>
//!
// The current block number
provider.getBlockNumber()
//!
// Get the current suggested gas price (in wei)...
// The gas price (in wei)...
gasPrice = await provider.getGasPrice()
//! async gasPrice
//_log: gasPrice
// ...often this gas price is easier to understand or
// display to the user in gwei (giga-wei, or 1e9 wei)
// display to the user in gwei
//_result:
utils.formatUnits(gasPrice, "gwei")
//!
//_log:
_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.
_subsection: Transactions Methods @<Provider--transaction-methods>
@@ -146,7 +253,19 @@ _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.
_code: @lang<javascript>
//_result:
await provider.call({
// ENS public resovler address
to: "0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41",
// `function addr(namehash("ricmoo.eth")) view returns (address)`
data: "0x3b3b57debf074faa138b72c65adbdcfb329847e4f2c04bde7f7dd7fcad5a52d2f395a558"
});
//_log:
_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,44 +275,113 @@ 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.
_code: @lang<javascript>
//_hide: const parseEther = ethers.utils.parseEther;
//_result:
await provider.estimateGas({
// Wrapped ETH address
to: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
// `function deposit() payable`
data: "0xd0e30db0",
// 1 ether
value: parseEther("1.0")
});
//_log:
_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.
_code: @lang<javascript>
//_result:
await provider.getTransaction("0x5b73e239c55d790e3c9c3bbb84092652db01bb8dbf49ccc9e4a318470419d9a0");
//_log:
_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.
_code: @lang<javascript>
//_result:
await provider.getTransactionReceipt("0x5b73e239c55d790e3c9c3bbb84092652db01bb8dbf49ccc9e4a318470419d9a0");
//_log:
_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
for the transaction).
_code: @lang<javascript>
//_hide: const provider = localProvider;
//_hide: const wallet = new ethers.Wallet(ethers.utils.id("HelloWorld"), provider);
//_hide: const fundTx = await localSigner.sendTransaction({
//_hide: to: wallet.address,
//_hide: value: ethers.utils.parseEther("2.0")
//_hide: });
//_hide: await fundTx.wait();
//_result:
await provider.sendTransaction("0xf86e808502540be400825208948ba1f109551bd432803012645ac136ddd64dba72880de0b6b3a764000080820a96a0f0c5bcb11e5a16ab116c60a0e5837ae98ec36e7f217740076572e8183002edd2a01ed1b4411c2840b9793e8be5415a554507f1ea320069be6dcecabd7b9097dbd4");
//_log:
_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 +395,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 +404,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.
@@ -260,11 +450,9 @@ $Debug: each Provider may use this to emit useful debugging information
_code: Events Example @lang<javascript>
// <hide>
const txHash = utils.id("dummy-data");
const myAddress = ethers.constants.HashZero;
const myOtherAddress = ethers.constants.HashZero;
// </hide>
//_hide: const txHash = utils.id("dummy-data");
//_hide: const myAddress = ethers.constants.HashZero;
//_hide: const myOtherAddress = ethers.constants.HashZero;
provider.on("block", (blockNumber) => {
// Emitted on every block change
@@ -282,7 +470,7 @@ provider.once(txHash, (transaction) => {
filter = {
address: "dai.tokens.ethers.eth",
topics: [
utils.id("Transfer(address,address,uint256")
utils.id("Transfer(address,address,uint256)")
]
}
provider.on(filter, (log, event) => {
@@ -293,7 +481,7 @@ provider.on(filter, (log, event) => {
// Notice this is an array of topic-sets and is identical to
// using a filter with no address (i.e. match any address)
topicSets = [
utils.id("Transfer(address,address,uint256"),
utils.id("Transfer(address,address,uint256)"),
null,
[
myAddress,
@@ -314,10 +502,7 @@ provider.on("error", (tx) => {
// Emitted when any error occurs
});
// <hide>
// Make sure our documentation builds without waiting forever
provider.removeAllListeners()
// </hide>
//_hide: provider.removeAllListeners() /* Make sure the docs build without waiting forever */
_subsection: Inspection Methods @<Provider--inspection-methods>

View File

@@ -1,26 +1,27 @@
_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
- **//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)
_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...
_subsection: Networkish @<providers-Networkish>
A **Networkish** may be any of the following:
- a [[providers-Network]] object
- the name of a common network as a string (e.g. ``"homestead"``)
- the chain ID a network as a number; if the chain ID is that of a
common network, the ``name`` and ``ensAddress`` will be populated, otherwise,
the default name ``"unknown"`` and no ``ensAddress`` is used
_subsection: Network @<providers-Network>
A **Network** represents an Etherem network.
A **Network** represents an Ethereum network.
_property: network.name => string
The human-readable name of the network, such as ``homestead``. If the network
@@ -50,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.
@@ -74,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)
@@ -102,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]]>
@@ -196,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]]>
@@ -222,14 +239,48 @@ 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``
If the transaction is replaced by another transaction, a
[TRANSACTION_REPLACED](errors--transaction-replaced) error will be rejected
with the following properties:
- ``error.hash`` - the hash of the original transaction which was replaced
- ``error.reason`` - a string reason; one of ``"repriced"``, ``"cancelled"`` or ``"replaced"``
- ``error.cancelled`` - a boolean; a ``"repriced"`` transaction is not considered cancelled, but ``"cancelled"`` and ``"replaced"`` are
- ``error.replacement`` - the replacement transaction (a [[providers-TransactionResponse]])
- ``error.receipt`` - the receipt of the replacement transaction (a [[providers-TransactionReceipt]])
Transactions are replaced when the user uses an option in their client to
send a new transaction from the same account with the original ``nonce``.
This is usually to speed up a transaction or to cancel one, by bribing
miners with additional fees to prefer the new transaction over the original one.
_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]]>
@@ -264,7 +315,7 @@ The amount of gas actually used by this transaction.
_property: receipt.logsBloom => string<[[DataHexString]]>
A [bloom-filter](link-wiki-bloomfilter), which
incldues all the addresses and topics included in any log in this
includes all the addresses and topics included in any log in this
transaction.
_property: receipt.blockHash => string<[[DataHexString]]<32>>
@@ -286,7 +337,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.
@@ -299,3 +350,102 @@ _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> ] >
//_hide: ;
accessList = [
[
"0x0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
[
"0x0000000000000000000000000000000000000000000000000000000000000004",
"0x0bcad17ecf260d6506c6b97768bdc2acfb6694445d27ffd3f9c1cfbee4a9bd6d"
]
],
[
"0x5FfC014343cd971B7eb70732021E26C35B744cc4",
[
"0x0000000000000000000000000000000000000000000000000000000000000001"
]
]
];
// Option 3:
// Record<Address, Array<Bytes32>>
accessList = {
"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e": [
"0x0000000000000000000000000000000000000000000000000000000000000004",
"0x0bcad17ecf260d6506c6b97768bdc2acfb6694445d27ffd3f9c1cfbee4a9bd6d"
],
"0x5FfC014343cd971B7eb70732021E26C35B744cc4": [
"0x0000000000000000000000000000000000000000000000000000000000000001"
]
};
_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 > >
// }
accessList = [
{
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>
@@ -74,6 +74,12 @@ _property: signer.signMessage(message) => Promise<string<[RawSignature](signatur
This returns a Promise which resolves to the [[signature-raw]]
of //message//.
A signed message is prefixd with ``"\\x19Ethereum signed message:\\n"`` and
the length of the message, using the [hashMessage](utils-hashMessage)
method, so that it is [EIP-191](link-eip-191) compliant. If recovering
the address in Solidity, this prefix will be required to create a matching
hash.
Sub-classes **must** implement this, however they may throw if signing a
message is not supported, such as in a Contract-based Wallet or
Meta-Transaction-based Wallet.
@@ -112,6 +118,61 @@ 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");
// 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!'
};
//_result:
signature = await signer._signTypedData(domain, types, value);
//_log:
_heading: Sub-Classes @<Signer--subclassing>
It is very important that all important properties of a **Signer** are
@@ -124,20 +185,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 +254,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
@@ -224,35 +285,43 @@ walletMnemonic = Wallet.fromMnemonic(mnemonic)
// ...or from a private key
walletPrivateKey = new Wallet(walletMnemonic.privateKey)
//_result:
walletMnemonic.address === walletPrivateKey.address
//!
//_log:
// The address as a Promise per the Signer API
walletMnemonic.getAddress()
//!
//_result:
await walletMnemonic.getAddress()
//_log:
// A Wallet address is also available synchronously
//_result:
walletMnemonic.address
//!
//_log:
// The internal cryptographic components
//_result:
walletMnemonic.privateKey
//!
//_log:
//_result:
walletMnemonic.publicKey
//!
//_log:
// The wallet mnemonic
//_result:
walletMnemonic.mnemonic
//!
//_log:
// Note: A wallet created with a private key does not
// have a mnemonic (the derivation prevents it)
//_result:
walletPrivateKey.mnemonic
//!
//_log:
// Signing a message
walletMnemonic.signMessage("Hello World")
//!
//_result:
await walletMnemonic.signMessage("Hello World")
//_log:
tx = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
@@ -260,24 +329,29 @@ tx = {
}
// Signing a transaction
walletMnemonic.signTransaction(tx)
//!
//_result:
await walletMnemonic.signTransaction(tx)
//_log:
// The connect method returns a new instance of the
// Wallet connected to a provider
//_result:
wallet = walletMnemonic.connect(provider)
//_null:
// Querying the network
wallet.getBalance();
//!
wallet.getTransactionCount();
//!
//_result:
await wallet.getBalance();
//_log:
//_result:
await wallet.getTransactionCount();
//_log:
// Sending ether
wallet.sendTransaction(tx)
// <hide>
//! error
// </hide>
//_hide: wallet = localSigner; /* prevent insufficient funds error from blowing up the docs */
//_result:
await wallet.sendTransaction(tx)
//_log:
@@ -310,12 +384,10 @@ abi = [
]
contract = new ethers.Contract("dai.tokens.ethers.eth", abi, signer)
// <hide>
//!
// </hide>
// Get the number of tokens for this account
//_result:
tokens = await contract.balanceOf(signer.getAddress())
//! async tokens
//_log:
//
// Pre-flight (check for revert) on DAI from the signer
@@ -327,12 +399,14 @@ tokens = await contract.balanceOf(signer.getAddress())
//
// This will pass since the token balance is available
contract.callStatic.transfer("donations.ethers.eth", tokens)
//!
//_result:
await contract.callStatic.transfer("donations.ethers.eth", tokens)
//_log:
// This will fail since it is greater than the token balance
contract.callStatic.transfer("donations.ethers.eth", tokens.add(1))
//! error
//_throws:
await contract.callStatic.transfer("donations.ethers.eth", tokens.add(1))
//_log:
_subsection: ExternallyOwnedAccount @<ExternallyOwnedAccount>
@@ -352,5 +426,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

@@ -12,7 +12,7 @@ _subsection: Creating Instance @<AbiCoder--creating>
For the most part, there should never be a need to manually create
an instance of an [[AbiCoder]], since one is created with the
default coersion function when the library is loaded which can
default coercion function when the library is loaded which can
be used universally.
This is likely only needed by those with specific needs to override
@@ -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

@@ -1,11 +1,289 @@
_section: ABI Formats @<abi-formats>
@TODO: Expand this section
There are several formats available to specify an ABI for
a Smart Contract, which specifies to the under-lying library
what methods, events and errors exist so that encoding and
decoding the data from and to the network can be handled by
the library.
The supports ABI types are:
- [Human-Readable ABI](abi-formats--human-readable-abi)
- [Solidity JSON ABI](abi-formats--solidity)
- [Solidity Object ABI](abi-formats--object)
_subsection: Human-Readable ABI @<abi-formats--human-readable-abi>
See [Human-Readable Abi](link-ricmoo-humanreadableabi).
The **Human-Readable ABI** was [introduced early by ethers](link-ricmoo-humanreadableabi),
which allows for a Solidity signatures to be used to describe each
method, event and error.
It is important to note that a Solidity signature **fully describes**
all the properties the ABI requires:
- name
- type (constructor, event, function)
- inputs (types, nested structures and optionally names)
- outputs (types nested structures and optionally names)
- state mutability (for constructors and methods)
- payability (for constructors and methods)
- whether inputs are indexed (for events)
This allows for a simple format which is both machine-readalbe (since
the parser is a machine) and human-readable (at least **developer-readable**),
as well as simple for humans to type and inline into code, which improves
code readability. The Human-Readable ABI is also considerably smaller, which
helps reduce code size.
A Huamn-Readable ABI is simple an array of strings, where each string is
the Solidity signature.
Signatures may be minimally specified (i.e. names of inputs and outputs
may be omitted) or fully specified (i.e. with all property names) and
whitespace is ignored.
Several modifiers available in Solidity are dropped internally, as they
are not required for the ABI and used old by Solidity's semantic checking
system, such as input parameter data location like ``"calldata"``
and ``"memory"``. As such, they can be safely dropped in the ABI as well.
_code: Human-Readable ABI Example @lang<javascript>
const humanReadableAbi = [
// Simple types
"constructor(string symbol, string name)",
"function transferFrom(address from, address to, uint value)",
"function balanceOf(address owner) view returns (uint balance)",
"event Transfer(address indexed from, address indexed to, address value)",
"error InsufficientBalance(account owner, uint balance)",
// Some examples with the struct type, we use the tuple keyword:
// (note: the tuple keyword is optional, simply using additional
// parentheses accomplishes the same thing)
// struct Person {
// string name;
// uint16 age;
// }
"function addPerson(tuple(string name, uint16 age) person)",
"function addPeople(tuple(string name, uint16 age)[] person)",
"function getPerson(uint id) view returns (tuple(string name, uint16 age))",
"event PersonAdded(uint indexed id, tuple(string name, uint16 age) person)"
];
//_hide: _page.humanReadableAbi = humanReadableAbi;
_subsection: Solidity JSON ABI @<abi-formats--solidity>
See [Solidity compiler](link-solc-output).
The **Solidity JSON ABI** is a standard format that many tools export,
including the Solidity compiler. For the full specification, see
the [Solidity compiler documentation](link-solc-output).
Various versions include slightly different keys and values. For example,
early compilers included only a boolean ``"constant"`` to indicate mutability,
while newer versions include a string ``"mutabilityState"``, which encompasses
several older properties.
When creating an instance of a [Fragment](Fragment) using a JSON ABI, it will
automatically infer all legacy properties for new-age ABIs and for legacy
ABIs will infer the new-age properties. All properties will be populated, so
it will match the equivalent created using a Human-Readable ABI fragment.
_code: The same ABI as JSON ABI @lang<javascript>
const jsonAbi = `[
{
"type": "constructor",
"payable": false,
"inputs": [
{ "type": "string", "name": "symbol" },
{ "type": "string", "name": "name" }
]
},
{
"type": "function",
"name": "transferFrom",
"constant": false,
"payable": false,
"inputs": [
{ "type": "address", "name": "from" },
{ "type": "address", "name": "to" },
{ "type": "uint256", "name": "value" }
],
"outputs": [ ]
},
{
"type": "function",
"name": "balanceOf",
"constant":true,
"stateMutability": "view",
"payable":false, "inputs": [
{ "type": "address", "name": "owner"}
],
"outputs": [
{ "type": "uint256"}
]
},
{
"type": "event",
"anonymous": false,
"name": "Transfer",
"inputs": [
{ "type": "address", "name": "from", "indexed":true},
{ "type": "address", "name": "to", "indexed":true},
{ "type": "address", "name": "value"}
]
},
{
"type": "error",
"name": "InsufficientBalance",
"inputs": [
{ "type": "account", "name": "owner"},
{ "type": "uint256", "name": "balance"}
]
},
{
"type": "function",
"name": "addPerson",
"constant": false,
"payable": false,
"inputs": [
{
"type": "tuple",
"name": "person",
"components": [
{ "type": "string", "name": "name" },
{ "type": "uint16", "name": "age" }
]
}
],
"outputs": []
},
{
"type": "function",
"name": "addPeople",
"constant": false,
"payable": false,
"inputs": [
{
"type": "tuple[]",
"name": "person",
"components": [
{ "type": "string", "name": "name" },
{ "type": "uint16", "name": "age" }
]
}
],
"outputs": []
},
{
"type": "function",
"name": "getPerson",
"constant": true,
"stateMutability": "view",
"payable": false,
"inputs": [
{ "type": "uint256", "name": "id" }
],
"outputs": [
{
"type": "tuple",
"components": [
{ "type": "string", "name": "name" },
{ "type": "uint16", "name": "age" }
]
}
]
},
{
"type": "event",
"anonymous": false,
"name": "PersonAdded",
"inputs": [
{ "type": "uint256", "name": "id", "indexed": true },
{
"type": "tuple",
"name": "person",
"components": [
{ "type": "string", "name": "name", "indexed": false },
{ "type": "uint16", "name": "age", "indexed": false }
]
}
]
}
]`;
//_hide: _page.jsonAbi = jsonAbi;
_subsection: Solidity Object ABI @<abi-formats--object>
The output from parsing (using JSON.parse) a Solidity JSON ABI
is also fully compatible with the [[Interface]] class and each
method, event and error from that object are compatible with
the [[Fragment]] class.
Some developers may prefer this as it allows access to the ABI
properties as normal JavaScript objects, and closely matches the
JSON ABI that those familiar with the Solidity ABI will recognize.
_subsection: Converting Between Formats
The [[Fragment]] object makes it simple to reformat a single
method, event or error, however most developers will be interested
in converting an entire ABI.
For production code it is recommended to inline the Human-Readable
ABI as it makes it easy to see at a glance which methods, events
and errors are available. It is also highly recommend to strip out
unused parts of the ABI (such as admin methods) to further reduce
code size.
_code: Converting to Full Human-Readable ABI @lang<javascript>
//_hide: const Interface = ethers.utils.Interface;
//_hide: const FormatTypes = ethers.utils.FormatTypes;
//_hide: jsonAbi = _page.jsonAbi;
// Using the "full" format will ensure the Result objects
// have named properties, which improves code readability
const iface = new Interface(jsonAbi);
//_result:
iface.format(FormatTypes.full);
//_log:
_code: Converting to Minimal Human-Readable ABI @lang<javascript>
//_hide: const Interface = ethers.utils.Interface;
//_hide: const FormatTypes = ethers.utils.FormatTypes;
//_hide: jsonAbi = _page.jsonAbi;
// Using the "minimal" format will save a small amount of
// space, but is generally not worth it as named properties
// on Results will not be available
const iface = new Interface(jsonAbi);
//_result:
iface.format(FormatTypes.minimal);
//_log:
_code: Converting to JSON ABI @lang<javascript>
//_hide: const Interface = ethers.utils.Interface;
//_hide: const FormatTypes = ethers.utils.FormatTypes;
//_hide: humanReadableAbi = _page.humanReadableAbi;
// Sometimes you may need to export a Human-Readable ABI to
// JSON for tools that do not have Human-Readable support
// For compactness, the JSON is kept with minimal white-space
const iface = new Interface(humanReadableAbi);
//_result:
jsonAbi = iface.format(FormatTypes.json);
//_log:
// However it is easy to use JSON.parse and JSON.stringify
// with formatting parameters to assist with readability
//_result:
JSON.stringify(JSON.parse(jsonAbi), null, 2);
//_log:

View File

@@ -5,7 +5,6 @@ Explain an ABI.
_subsection: Formats
_heading: JSON String ABI (Solidity Output JSON)
The **JSON ABI Format** is the format that is
[output from the Solidity compiler](link-solc-output).
@@ -15,50 +14,74 @@ of Objects, where each Object has various properties describing the [[Fragment]]
The deserialized JSON string (which is a normal JavaScript Object) may
also be passed into any function which accepts a JSON String ABI.
_heading: Humanb-Readable ABI
_heading: Humanb-Readable ABI @<human-readable-abi>
The Human-Readable ABI was introduced by ethers in [this article](link-ricmoo-humanreadableabi)
and has since gained wider adoption.
The Human-Readable ABI was @TODO
The ABI is described by using an array of strings, where each string is the
Solidity signature of the **constructor**, **function**, **event** or **error**.
[article](link-ricmoo-humanreadableabi)
When parsing a fragment, all inferred properties will be injected (e.g. a //payable//
method will have its ``constant`` proeprty set to false).
Tuples can be specified by using the ``tuple(...)`` syntax or with bare (additional)
parenthesis, ``(...)``.
_code: Example Human-Readable ABI
const ABI = [
// Constructor
"constructor(address ens)",
// Constant functions (pure or view)
"function balanceOf(address owner) view returns (uint)",
// State-mutating functions (payable or non-payable)
"function mint(uint amount) payable",
"function transfer(address to, uint amount) returns (bool)",
// Events
"event Transfer(address indexed from, address indexed to, uint amount)",
// Errors
"error InsufficientFunds(address from, uint balance)",
]
_heading: Output Formats @<fragments--output-formats> @SRC<abi/fragments:FormatTypes>
Each [[Fragment]] and [[ParamType]] may be output using its ``format``
method.
_property: ethers.utils.FragmentTypes.full => string
_property: ethers.utils.FormatTypes.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.
_property: ethers.utils.FragmentTypes.minimal => string
to aid in human readability.
_property: ethers.utils.FormatTypes.minimal => string
This is similar to ``full``, except with no unnecessary whitespace or parameter
names. This is useful for storing a minimal string which can still fully
reconstruct the original Fragment using [Fragment&thinsp;.&thinsp;from](Fragment-from).
_property: ethers.utils.FragmentTypes.json => string
_property: ethers.utils.FormatTypes.json => string
This returns a JavaScript Object which is safe to call ``JSON.stringify``
on to create a JSON string.
_property: ethers.utils.FragmentTypes.sighash => string
_property: ethers.utils.FormatTypes.sighash => string
This is a minimal output format, which is used by Solidity when computing a
signature hash or an event topic hash.
_warning: Note
The ``sighash`` format is **insufficient** to re-create the original [[Fragment]],
since it discards modifiers such as indexed, anonymous, stateMutability, etc.
It is only useful for computing the selector for a Fragment, and cannot
be used to format an Interface.
_subsection: Fragment @<Fragment> @SRC<abi/fragments:class.Fragment>
An ABI is a collection of **Fragments**, where each fragment specifies:
- An [Error](ErrorFragment)
- An [Event](EventFragment)
- A [Function](FunctionFragment)
- A [Constructor](ConstructorFragment)
@@ -66,12 +89,10 @@ An ABI is a collection of **Fragments**, where each fragment specifies:
_heading: Properties
_property: fragment.name => string
This is the name of the Event or Function. This will be null for
a [[ConstructorFragment]].
_property: fragment.type => string
This is a string which indicates the type of the [[Fragment]]. This
will be one of:
@@ -80,19 +101,20 @@ will be one of:
- ``function``
_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
_property: ethers.utils.Fragment.from(objectOrString) => [[Fragment]] @<Fragment-from> @SRC<abi/fragments:Fragment.from>
_property: fragment.format([ format = sighash]) => string @<Fragment-format> @SRC<abi/fragments:Fragment.format>
Creates a string representation of the Fragment using the available
[output formats](fragments--output-formats).
Returns a
_property: ethers.utils.Fragment.from(objectOrString) => [[Fragment]] @<Fragment-from> @SRC<abi/fragments:Fragment.from>
Creates a new **Fragment** sub-class from any compatible //objectOrString//.
_property: ethers.utils.Fragment.isFragment(object) => boolean @<Fragment-isFragment> @SRC<abi/fragments:Fragment.isFragment>
Tra lal al
Returns true if //object// is a **Fragment**.
_subsection: ConstructorFragment @<ConstructorFragment> @INHERIT<[[Fragment]]> @SRC<abi/fragments:class.ConstructorFragment>
@@ -100,17 +122,14 @@ _subsection: ConstructorFragment @<ConstructorFragment> @INHERIT<[[Fragment]]> @
_heading: Properties
_property: fragment.gas => [[BigNumber]]
This is the gas limit that should be used during deployment. It may be
null.
_property: fragment.payable => boolean
This is whether the constructor may receive ether during deployment as
an endowment (i.e. msg.value != 0).
_property: fragment.stateMutability => string
This is the state mutability of the constructor. It can be any of:
- ``nonpayable``
@@ -119,12 +138,21 @@ This is the state mutability of the constructor. It can be any of:
_heading: Methods
_property: ethers.utils.ConstructorFragment.from(objectOrString) => [[ConstructorFragment]] @<ConstructorFragment-from> @SRC<abi/fragments:ConstructorFragment.from>
Tra la la...
Creates a new **ConstructorFragment** from any compatible //objectOrString//.
_property: ethers.utils.ConstructorFragment.isConstructorFragment(object) => boolean @<ConstructorFragment-isConstructorFragment> @SRC<abi/fragments:ConstructorFragment.isConstructorFragment>
Returns true if //object// is a **ConstructorFragment**.
Tra lal al
_subsection: ErrorFragment @<ErrorFragment> @INHERIT<[[Fragment]]> @SRC<abi/fragments:class.ErrorFragment>
_heading: Methods
_property: ethers.utils.ErrorFragment.from(objectOrString) => [[ErrorFragment]] @<ErrorFragment-from> @SRC<abi/fragments:ErrorFragment.from>
Creates a new **ErrorFragment** from any compatible //objectOrString//.
_property: ethers.utils.ErrorFragment.isErrorFragment(object) => boolean @<ErrorFragment-isErrorFragment> @SRC<abi/fragments:ErrorFragment.isErrorFragment>
Returns true if //object// is an **ErrorFragment**.
_subsection: EventFragment @<EventFragment> @INHERIT<[[Fragment]]> @SRC<abi/fragments:class.EventFragment>
@@ -132,19 +160,16 @@ _subsection: EventFragment @<EventFragment> @INHERIT<[[Fragment]]> @SRC<abi/frag
_heading: Properties
_property: fragment.anonymous => boolean
This is whether the event is anonymous. An anonymous Event does not inject its
topic hash as topic0 when creating a log.
_heading: Methods
_property: ethers.utils.EventFragment.from(objectOrString) => [[EventFragment]] @<EventFragment-from> @SRC<abi/fragments:EventFragment.from>
Tra la la...
Creates a new **EventFragment** from any compatible //objectOrString//.
_property: ethers.utils.EventFragment.isEventFragment(object) => boolean @<EventFragment-isEventFragment> @SRC<abi/fragments:EventFragment.isEventFragment>
Tra lal al
Returns true if //object// is an **EventFragment**.
_subsection: FunctionFragment @<FunctionFragment> @INHERIT<[[ConstructorFragment]]> @SRC<abi/fragments:class.FunctionFragment>
@@ -152,12 +177,10 @@ _subsection: FunctionFragment @<FunctionFragment> @INHERIT<[[ConstructorFragment
_heading: Properties
_property: fragment.constant => boolean
This is whether the function is constant (i.e. does not change state). This
is true if the state mutability is ``pure`` or ``view``.
_property: fragment.stateMutability => string
This is the state mutability of the constructor. It can be any of:
- ``nonpayable``
@@ -166,22 +189,18 @@ This is the state mutability of the constructor. It can be any of:
- ``view``
_property: fragment.outputs => Array<[[ParamType]]>
A list of the Function output parameters.
_heading: Method
_heading: Methods
_property: ethers.utils.FunctionFragment.from(objectOrString) => [[FunctionFragment]] @<FunctionFragment-from> @SRC<abi/fragments:ConstructorFragment.from>
Tra la la...
Creates a new **FunctionFragment** from any compatible //objectOrString//.
_property: ethers.utils.FunctionFragment.isFunctionFragment(object) => boolean @<FunctionFragment-isFunctionFragment> @SRC<abi/fragments:FunctionFragment.isFunctionFragment>
Tra lal al
Returns true if //object// is a **FunctionFragment**.
_subsection: ParamType @<ParamType> @SRC<abi/fragments:class.ParamType>
The following examples will represent the Solidity parameter:
``string foobar``
@@ -189,53 +208,42 @@ The following examples will represent the Solidity parameter:
_heading: Properties
_property: paramType.name => string @<ParamType-name>
The local parameter name. This may be null for unnamed parameters. For example,
the parameter definition ``string foobar`` would be ``foobar``.
_property: paramType.type => string @<ParamType-type>
The full type of the parameter, including tuple and array symbols. This may be null
for unnamed parameters. For the above example, this would be ``foobar``.
_property: paramType.baseType => string @<ParamType-baseType>
The base type of the parameter. For primitive types (e.g. ``address``, ``uint256``, etc)
this is equal to [type](ParamType-type). For arrays, it will be the string ``array`` and for
a tuple, it will be the string ``tuple``.
_property: paramType.indexed => boolean @<ParamType-indexed>
Whether the parameter has been marked as indexed. This **only** applies
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
wjhich is not an array.
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>
The components of a tuple. This is null for non-tuple parameters.
_heading: Methods
Tra la la...
_property: paramType.format([ outputType = sighash ])
Tra la la...
Creates a string representation of the Fragment using the available
[output formats](fragments--output-formats).
_property: ethers.utils.ParamType.from(objectOrString) => [[ParamType]] @<ParamType-from> @SRC<abi/fragments:ParamType.from>
Tra la la...
Creates a new **ParamType** from any compatible //objectOrString//.
_property: ethers.utils.ParamType.isParamType(object) => boolean @<ParamType-isParamType> @SRC<abi/fragments:ParamType.isParamType>
Tra la la...
Returns true if //object// is a **ParamType**.

View File

@@ -4,7 +4,7 @@ The **Interface** Class abstracts the encoding and decoding required
to interact with contracts on the Ethereum network.
Many of the standards organically evolved along side the [[link-solidity]]
language, which other languages have adopted to remain compatibile with
language, which other languages have adopted to remain compatible with
existing deployed contracts.
The EVM itself does not understand what the ABI is. It is simply an agreed
@@ -26,11 +26,47 @@ which is a format the Ethers created to simplify manually typing the ABI
into the source and so that a Contract ABI can also be referenced easily
within the same source file.
_code: Creating an Interface instance @lang<javascript>
//_hide: const Interface = ethers.utils.Interface;
// This interface is used for the below examples
const iface = new Interface([
// Constructor
"constructor(string symbol, string name)",
// State mutating method
"function transferFrom(address from, address to, uint amount)",
// State mutating method, which is payable
"function mint(uint amount) payable",
// Constant method (i.e. "view" or "pure")
"function balanceOf(address owner) view returns (uint)",
// An Event
"event Transfer(address indexed from, address indexed to, uint256 amount)",
// A Custom Solidity Error
"error AccountLocked(address owner, uint256 balance)",
// Examples with structured types
"function addUser(tuple(string name, address addr) user) returns (uint id)",
"function addUsers(tuple(string name, address addr)[] user) returns (uint[] id)",
"function getUser(uint id) view returns (tuple(string name, address addr) user)"
]);
//_hide: _page.iface = iface;
_subsection: Properties @<Interface--properties>
_property: interface.fragments => Array<[[Fragment]]>
All the [Fragments](Fragment) in the interface.
_property: interface.errors => Array<[[ErrorFragment]]>
All the [Error Fragments](ErrorFragment) in the interface.
_property: interface.events => Array<[[EventFragment]]>
All the [Event Fragments](EventFragment) in the interface.
@@ -48,24 +84,133 @@ Return the formatted **Interface**. If the format type is ``json`` a
single string is returned, otherwise an Array of the human-readable
strings is returned.
_code: @lang<javascript>
//_hide: const iface = _page.iface;
const FormatTypes = ethers.utils.FormatTypes;
//_result:
iface.format(FormatTypes.json)
//_log:
//_result:
iface.format(FormatTypes.full)
//_log:
//_result:
iface.format(FormatTypes.minimal)
//_log:
_subsection: Fragment Access @<Interface--fragments>
_property: interface.getFunction(fragment) => [[FunctionFragment]] @SRC<abi/interface>
Returns the [[FunctionFragment]] for //fragment// (see [[Interface--specifying-fragments]]).
_code: @lang<javascript>
//_hide: const iface = _page.iface;
// By method signature, which is normalized so whitespace
// and superfluous attributes are ignored
iface.getFunction("transferFrom(address, address, uint256)");
// By name; this ONLY works if the method is non-ambiguous
iface.getFunction("transferFrom");
// By method selector
iface.getFunction("0x23b872dd");
// Throws if the method does not exist
//_throws:
iface.getFunction("doesNotExist()");
//_log:
_property: interface.getError(fragment) => [[ErrorFragment]] @SRC<abi/interface>
Returns the [[ErrorFragment]] for //fragment// (see [[Interface--specifying-fragments]]).
_code: @lang<javascript>
//_hide: const iface = _page.iface;
// By error signature, which is normalized so whitespace
// and superfluous attributes are ignored
iface.getError("AccountLocked(address, uint256)");
// By name; this ONLY works if the error is non-ambiguous
iface.getError("AccountLocked");
// By error selector
iface.getError("0xf7c3865a");
// Throws if the error does not exist
//_throws:
iface.getError("DoesNotExist()");
//_log:
_property: interface.getEvent(fragment) => [[EventFragment]] @SRC<abi/interface>
Returns the [[EventFragment]] for //fragment// (see [[Interface--specifying-fragments]]).
_code: @lang<javascript>
//_hide: const iface = _page.iface;
// By event signature, which is normalized so whitespace
// and superfluous attributes are ignored
iface.getEvent("Transfer(address, address, uint256)");
// By name; this ONLY works if the event is non-ambiguous
iface.getEvent("Transfer");
// By event topic hash
iface.getEvent("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef");
// Throws if the event does not exist
//_throws:
iface.getEvent("DoesNotExist()");
//_log:
_subsection: Signature and Topic Hashes @<Interface--selectors>
_property: interface.getSighash(fragment) => string<[[DataHexString]]<4>> @SRC<abi/interface:method.Interface.getSighash>
Return the sighash (or Function Selector) for //fragment// (see [[Interface--specifying-fragments]]).
_code: @lang<javascript>
//_hide: const iface = _page.iface;
//_result:
iface.getSighash("balanceOf");
//_log:
//_result:
iface.getSighash("balanceOf(address)");
//_log:
const fragment = iface.getFunction("balanceOf")
//_result:
iface.getSighash(fragment);
//_log:
_property: interface.getEventTopic(fragment) => string<[[DataHexString]]<32>> @SRC<abi/interface:method.Interface.getEventTopic>
Return the topic hash for //fragment// (see [[Interface--specifying-fragments]]).
_code: @lang<javascript>
//_hide: const iface = _page.iface;
//_result:
iface.getEventTopic("Transfer");
//_log:
//_result:
iface.getEventTopic("Transfer(address, address, uint)");
//_log:
const fragment = iface.getEvent("Transfer")
//_result:
iface.getEventTopic(fragment);
//_log:
_subsection: Encoding Data @<Interface--encoding>
@@ -74,22 +219,103 @@ Return the encoded deployment data, which can be concatenated to the
deployment bytecode of a contract to pass //values// into the contract
constructor.
_property: interface.encodeFilterTopics(fragment [ , values ]) => Array<topic | Array<topic>> @SRC<abi/interface>
_code: @lang<javascript>
//_hide: const iface = _page.iface;
//_hide: const parseEther = ethers.utils.parseEther;
// The data that should be appended to the bytecode to pass
// parameters to the constructor during deployment
//_result:
iface.encodeDeploy([ "SYM", "Some Name" ])
//_log:
_property: interface.encodeFilterTopics(fragment, values) => Array<topic | Array<topic>> @SRC<abi/interface>
Returns the encoded topic filter, which can be passed to getLogs for //fragment//
(see [[Interface--specifying-fragments]]) for the given //values//.
Each //topic// is a 32 byte (64 nibble) [[DataHexString]].
_code: @lang<javascript>
//_hide: const iface = _page.iface;
//_hide: const parseEther = ethers.utils.parseEther;
// Filter that matches all Transfer events
//_result:
iface.encodeFilterTopics("Transfer", [])
//_log:
// Filter that matches the sender
//_result:
iface.encodeFilterTopics("Transfer", [
"0x8ba1f109551bD432803012645Ac136ddd64DBA72"
])
//_log:
// Filter that matches the receiver
//_result:
iface.encodeFilterTopics("Transfer", [
null,
"0x8ba1f109551bD432803012645Ac136ddd64DBA72"
])
//_log:
_property: interface.encodeFunctionData(fragment [ , values ]) => string<[[DataHexString]]> @SRC<abi/interface>
Returns the encoded data, which can be used as the data for a transaction for
//fragment// (see [[Interface--specifying-fragments]]) for the given //values//.
_code: @lang<javascript>
//_hide: const iface = _page.iface;
//_hide: const parseEther = ethers.utils.parseEther;
// Encoding data for the tx.data of a call or transaction
//_result:
iface.encodeFunctionData("transferFrom", [
"0x8ba1f109551bD432803012645Ac136ddd64DBA72",
"0xaB7C8803962c0f2F5BBBe3FA8bf41cd82AA1923C",
parseEther("1.0")
])
//_log:
// Encoding structured data (using positional Array)
user = [
"Richard Moore",
"0x8ba1f109551bD432803012645Ac136ddd64DBA72"
];
//_result:
iface.encodeFunctionData("addUser", [ user ]);
//_log:
// Encoding structured data, using objects. Only available
// if paramters are named.
user = {
name: "Richard Moore",
addr: "0x8ba1f109551bD432803012645Ac136ddd64DBA72"
};
//_result:
iface.encodeFunctionData("addUser", [ user ]);
//_log:
_property: interface.encodeFunctionResult(fragment [ , values ]) => string<[[DataHexString]]> @SRC<abi/interface>
Returns the encoded result, which would normally be the response from a call for
//fragment// (see [[Interface--specifying-fragments]]) for the given //values//.
Most developers will not need this method, but may be useful for authors of a mock blockchain.
_code: @lang<javascript>
//_hide: const iface = _page.iface;
//_hide: const parseEther = ethers.utils.parseEther;
// Encoding result data (like is returned by eth_call)
//_result:
iface.encodeFunctionResult("balanceOf", [
"0x8ba1f109551bD432803012645Ac136ddd64DBA72"
])
//_log:
_subsection: Decoding Data @<Interface--decoding>
@@ -100,6 +326,26 @@ with the optional //topics//.
If //topics// is not specified, placeholders will be inserted into the result.
Most develoeprs will find the [parsing methods](Interface--parsing) more
convenient for decoding event data, as they will automatically detect the
matching event.
_code: @lang<javascript>
//_hide: const iface = _page.iface;
// Decoding log data and topics (the entries in a receipt)
const data = "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000";
const topics = [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72",
"0x000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c"
];
//_result:
iface.decodeEventLog("Transfer", data, topics);
//_log:
_property: interface.decodeFunctionData(fragment, data) => [[Result]] @SRC<abi/interface>
Returns the decoded values from transaction data for
//fragment// (see [[Interface--specifying-fragments]]) for the given //data//.
@@ -107,11 +353,62 @@ Returns the decoded values from transaction data for
Most developers will not need this method, but may be useful for debugging
or inspecting transactions.
Most develoeprs will also find the [parsing methods](Interface--parsing) more
convenient for decoding transation data, as they will automatically detect the
matching function.
_code: @lang<javascript>
//_hide: const iface = _page.iface;
// Decoding function data (the value of tx.data)
const txData = "0x23b872dd0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c0000000000000000000000000000000000000000000000000de0b6b3a7640000";
//_result:
iface.decodeFunctionData("transferFrom", txData);
//_log:
_property: interface.decodeFunctionResult(fragment, data) => [[Result]] @SRC<abi/interface>
Returns the decoded values from the result of a call for
//fragment// (see [[Interface--specifying-fragments]]) for the given //data//.
_code: @lang<javascript>
//_hide: const iface = _page.iface;
// Decoding result data (e.g. from an eth_call)
resultData = "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000";
//_result:
iface.decodeFunctionResult("balanceOf", resultData)
//_log:
// Decoding result data which was caused by a revert
// Throws a CALL_EXCEPTION, with extra details
errorData = "0xf7c3865a0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000000de0b6b3a7640000";
//_throws:
iface.decodeFunctionResult("balanceOf", errorData)
//_log:
// Decoding structured data returns a Result object, which
// will include all values positionally and if the ABI
// included names, values will additionally be available
// by their name.
resultData = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000000000000000000000000000000000000000000d52696368617264204d6f6f726500000000000000000000000000000000000000";
//_result:
result = iface.decodeFunctionResult("getUser", resultData);
//_log:
// Access positionally:
// The 0th output parameter, the 0th proerty of the structure
//_result:
result[0][0];
//_log:
// Access by name: (only avilable because parameters were named)
//_result:
result.user.name
//_log:
_subsection: Parsing @<Interface--parsing>
The functions are generally the most useful for most developers. They will
@@ -122,10 +419,38 @@ _property: interface.parseLog(log) => [[LogDescription]] @SRC<abi/interface>
Search the event that matches the //log// topic hash and parse the values
the log represents.
_code: @lang<javascript>
//_hide: const iface = _page.iface;
const data = "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000";
const topics = [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72",
"0x000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c"
];
//_result:
iface.parseLog({ data, topics });
//_hide: _.eventFragment = createClass("EventFragment");
//_log:
_property: interface.parseTransaction(transaction) => [[TransactionDescription]] @SRC<abi/interface>
Search for the function that matches the //transaction// data sighash
and parse the transaction properties.
_code: @lang<javascript>
//_hide: const iface = _page.iface;
//_hide: const parseEther = ethers.utils.parseEther;
const data = "0x23b872dd0000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72000000000000000000000000ab7c8803962c0f2f5bbbe3fa8bf41cd82aa1923c0000000000000000000000000000000000000000000000000de0b6b3a7640000";
const value = parseEther("1.0");
//_result:
iface.parseTransaction({ data, value });
//_hide: _.functionFragment = createClass("FunctionFragment");
//_log:
_subsection: Types @<Interface--types>

View File

@@ -18,7 +18,6 @@ of errors introduced from typing an address or cut and paste issues.
All functions that return an Address will return a Checksum Address.
_heading: ICAP Address @<address-icap>
The **ICAP Address Format** was an early attempt to introduce a checksum
@@ -45,17 +44,76 @@ _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.
_code: @lang<javascript>
//_hide: const getAddress = ethers.utils.getAddress;
// Injects the checksum (via upper-casing specific letters)
//_result:
getAddress("0x8ba1f109551bd432803012645ac136ddd64dba72");
//_log:
// Converts and injects the checksum
//_result:
getAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK36");
//_log:
// Throws if a checksummed address is provided, but a
// letter is the wrong case
// ------------v (should be lower-case)
//_throws:
getAddress("0x8Ba1f109551bD432803012645Ac136ddd64DBA72")
//_log:
// Throws if the ICAP/IBAN checksum fails
//_throws:
getIcapAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK37");
//_log:
// Throws if the address is invalid, in general
//_throws:
getIcapAddress("I like turtles!");
//_log:
_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).
_code: @lang<javascript>
//_hide: const getIcapAddress = ethers.utils.getIcapAddress;
//_result:
getIcapAddress("0x8ba1f109551bd432803012645ac136ddd64dba72");
//_log:
//_result:
getIcapAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK36");
//_log:
_property: ethers.utils.isAddress(address) => boolean @<utils-isAddress> @SRC<address>
Returns true if //address// is valid (in any supported format).
_code: @lang<javascript>
//_hide: const isAddress = ethers.utils.isAddress;
//_result:
isAddress("0x8ba1f109551bd432803012645ac136ddd64dba72");
//_log:
//_result:
isAddress("XE65GB6LDNXYOFTX0NSV3FUWKOWIXAMJK36");
//_log:
//_result:
isAddress("I like turtles.");
//_log:
_subsection: Derivation @<utils--address-derivation>
@@ -64,10 +122,49 @@ Returns the address for //publicOrPrivateKey//. A public key may be
compressed or uncompressed, and a private key will be converted
automatically to a public key for the derivation.
_code: @lang<javascript>
//_hide: const computeAddress = ethers.utils.computeAddress;
// Private Key
//_result:
computeAddress("0xb976778317b23a1385ec2d483eda6904d9319135b89f1d8eee9f6d2593e2665d");
//_log:
// Public Key (compressed)
//_result:
computeAddress("0x0376698beebe8ee5c74d8cc50ab84ac301ee8f10af6f28d0ffd6adf4d6d3b9b762");
//_log:
// Public Key (uncompressed)
//_result:
computeAddress("0x0476698beebe8ee5c74d8cc50ab84ac301ee8f10af6f28d0ffd6adf4d6d3b9b762d46ca56d3dad2ce13213a6f42278dabbb53259f2d92681ea6a0b98197a719be3");
//_log:
_property: ethers.utils.recoverAddress(digest, signature) => string<[[address]]> @<utils-recoverAddress> @SRC<transactions>
Use [[link-wiki-ecrecover]] to determine the address that signed //digest// to
which generated //signature//.
_code: @lang<javascript>
//_hide: const recoverAddress = ethers.utils.recoverAddress;
const digest = "0x7c5ea36004851c764c44143b1dcb59679b11c9a68e5f41497f6cf3d480715331";
// Using an expanded Signature
//_result:
recoverAddress(digest, {
r: "0x528459e4aec8934dc2ee94c4f3265cf6ce00d47cf42bb106afda3642c72e25eb",
s: "0x42544137118256121502784e5a6425e6183ca964421ecd577db6c66ba9bccdcf",
v: 27
});
//_log:
// Using a flat Signature
const signature = "0x528459e4aec8934dc2ee94c4f3265cf6ce00d47cf42bb106afda3642c72e25eb42544137118256121502784e5a6425e6183ca964421ecd577db6c66ba9bccdcf1b";
//_result:
recoverAddress(digest, signature);
//_log:
_subsection: Contracts Addresses @<utils--contract-addresses>
@@ -75,9 +172,33 @@ _property: ethers.utils.getContractAddress(transaction) => string<[[address]]>
Returns the contract address that would result if //transaction// was
used to deploy a contract.
_code: @lang<javascript>
//_hide: const getContractAddress = ethers.utils.getContractAddress;
const from = "0x8ba1f109551bD432803012645Ac136ddd64DBA72";
const nonce = 5;
//_result:
getContractAddress({ from, nonce });
//_log:
_property: ethers.utils.getCreate2Address(from, salt, initCodeHash) => string<[[address]]> @<utils-getCreate2Address> @SRC<address>
Returns the contract address that would result from the given
[CREATE2](link-eip-1014) call.
_code: @lang<javascript>
//_hide: const getCreate2Address = ethers.utils.getCreate2Address;
//_hide: const keccak256 = ethers.utils.keccak256;
const from = "0x8ba1f109551bD432803012645Ac136ddd64DBA72";
const salt = "0x7c5ea36004851c764c44143b1dcb59679b11c9a68e5f41497f6cf3d480715331";
const initCode = "0x6394198df16000526103ff60206004601c335afa6040516060f3";
const initCodeHash = keccak256(initCode);
//_result:
getCreate2Address(from, salt, initCodeHash);
//_log:

View File

@@ -1,10 +1,10 @@
_section: BigNumber @<BigNumber>
Many operations in Ethereum operation on numbers which are
Many operations in Ethereum operate 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**
@@ -17,7 +17,7 @@ _heading: BigNumberish @<BigNumberish>
Many functions and methods in this library take in values which
can be non-ambiguously and safely converted to a BigNumber. These
values can be sepcified as:
values can be specified as:
_definition: **//string//**
A [[HexString]] or a decimal string, either of which may
@@ -49,43 +49,52 @@ _heading: Examples: @<>
_code: @lang<javascript>
// From a decimal string...
//_result:
BigNumber.from("42")
//!
//_log:
// From a HexString...
//_result:
BigNumber.from("0x2a")
//!
//_log:
// From a negative HexString...
//_result:
BigNumber.from("-0x2a")
//!
//_log:
// From an Array (or Uint8Array)...
//_result:
BigNumber.from([ 42 ])
//!
//_log:
// From an existing BigNumber...
let one1 = constants.One;
let one2 = BigNumber.from(one1)
//_result:
one2
//!
//_log:
// ...which returns the same instance
//_result:
one1 === one2
//!
//_log:
// From a (safe) number...
//_result:
BigNumber.from(42)
//!
//_log:
// From a ES2015 BigInt... (only on platforms with BigInt support)
//_result:
BigNumber.from(42n)
//!
//_log:
// Numbers outside the safe range fail:
//_throws:
BigNumber.from(Number.MAX_SAFE_INTEGER);
//! error
//_log:
_subsection: Methods @<BigNumber--methods>
@@ -122,18 +131,18 @@ Returns a BigNumber with the value of //BigNumber// with bits beyond
the //bitcount// least significant bits set to zero.
_heading: Two's Compliment
_heading: Two's Complement
[Two's Complicment](link-wiki-twoscomplement)
[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>
Returns a BigNumber with the value of //BigNumber// converted from twos-compliment with //bitwidth//.
Returns a BigNumber with the value of //BigNumber// converted from twos-complement with //bitwidth//.
_property: BigNumber.toTwos(bitwidth) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// converted to twos-compliment with //bitwidth//.
Returns a BigNumber with the value of //BigNumber// converted to twos-complement with //bitwidth//.
_heading: Comparison and Equivalence
@@ -175,7 +184,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.
@@ -186,8 +195,9 @@ _code: @lang<javascript>
let a = BigNumber.from(42);
let b = BigNumber.from("91");
//_result:
a.mul(b);
//!
//_log:
_subsection: Notes @<BigNumber--notes>
@@ -214,8 +224,9 @@ To demonstrate how this may be an issue in your code, consider:
_code: @lang<javascript>
//_result:
(Number.MAX_SAFE_INTEGER + 2 - 2) == (Number.MAX_SAFE_INTEGER)
//!
//_log:
_null:
@@ -232,7 +243,7 @@ mathematical operations handled safely.
_heading: Why not BigNumber.js, BN.js, BigDecimal, etc?
Everyone has their own favourite Big Number library, and once someone
has choosen one, it becomes part of their identity, like their editor,
has chosen one, it becomes part of their identity, like their editor,
vi vs emacs. There are over 100 Big Number libraries on [npm](link-npm-query-bignumber).
One of the biggest differences between the Ethers [[BigNumber]] object and
@@ -246,7 +257,7 @@ low-level library's objects which supports myriad in-place operations.
Second, the Ethers [[BigNumber]] provides all the functionality required
internally and should generally be sufficient for most developers while
not exposing some of the more advanced and rare functionality. So it will
be eaiser to swap out the underlying library without impacting consumers.
be easier to swap out the underlying library without impacting consumers.
For example, if [[link-npm-bnjs]] was exposed, someone may use the
greatest-common-denominator functions, which would then be functionality
@@ -270,7 +281,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
@@ -25,7 +32,7 @@ binary data as a string.
_heading: HexString @<HexString>
A **Hexstring** is a string which has a ``0x`` prefix followed by any
number of nibbles (i.e. case-insensitive hexidecumal characters, ``0-9`` and ``a-f``).
number of nibbles (i.e. case-insensitive hexadecimal characters, ``0-9`` and ``a-f``).
_heading: Signature @<Signature>
@@ -37,7 +44,7 @@ _heading: Signature @<Signature>
_heading: Raw Signature @<signature-raw> @inherit<string\<[[DataHexString]]\<65\>\>>
A **Raw Signature** is a common Signature format where the r, s and v are
concanenated into a 65 byte (130 nibble) [[DataHexString]].
concatenated into a 65 byte (130 nibble) [[DataHexString]].
_heading: SignatureLike @<SignatureLike>
@@ -79,28 +86,34 @@ zeros.
_code: Examples @lang<javascript>
// Convert a hexstring to a Uint8Array
//_result:
arrayify("0x1234")
//!
//_log:
// Convert an Array to a hexstring
//_result:
hexlify([1, 2, 3, 4])
//!
//_log:
// Convert an Object to a hexstring
//_result:
hexlify({ length: 2, "0": 1, "1": 2 })
//!
//_log:
// Convert an Array to a hexstring
//_result:
hexlify([ 1 ])
//!
//_log:
// Convert a number to a stripped hex value
//_result:
hexValue(1)
//!
//_log:
// Convert an Array to a stripped hex value
//_result:
hexValue([ 1, 2 ])
//!
//_log:
_subsection: Array Manipulation
@@ -112,7 +125,7 @@ _property: ethers.utils.stripZeros(aBytesLike) => Uint8Array @<utils-stripZeros
Returns a Uint8Array with all leading ``0`` bytes of //aBtyesLike// removed.
_property: ethers.utils.zeroPad(aBytesLike, length) => Uint8Array @<utils-zeroPad> @SRC<bytes>
Retutns a Uint8Array of the data in //aBytesLike// with ``0`` bytes prepended to
Returns a Uint8Array of the data in //aBytesLike// with ``0`` bytes prepended to
//length// bytes long.
If //aBytesLike// is already longer than //length// bytes long, an InvalidArgument
@@ -155,7 +168,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>
@@ -163,15 +176,18 @@ Return a copy of //array// shuffled using [[link-wiki-shuffle]].
_code: Examples @lang<javascript>
//_result:
utils.randomBytes(8)
//!
//_log:
const data = [ 1, 2, 3, 4, 5, 6, 7 ];
// Returns a new Array
//_result:
utils.shuffled(data);
//!
//_log:
// The Original is unscathed...
//_result:
data
//!
//_log:

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,13 +46,20 @@ _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 ``,``.
_code: @lang<javascript>
//_hide: const commify = ethers.utils.commify;
//_result:
commify("-1000.3000");
//_log:
_heading: Conversion @<unit-conversion>
@@ -60,13 +67,88 @@ _property: ethers.utils.formatUnits(value [ , unit = "ether" ] ) => string @<ut
Returns a string representation of //value// formatted with //unit//
digits (if it is a number) or to the unit specified (if a string).
_code: @lang<javascript>
//_hide: const formatUnits = ethers.utils.formatUnits;
//_hide: const BigNumber = ethers.BigNumber;
const oneGwei = BigNumber.from("1000000000");
const oneEther = BigNumber.from("1000000000000000000");
//_result:
formatUnits(oneGwei, 0);
//_log:
//_result:
formatUnits(oneGwei, "gwei");
//_log:
//_result:
formatUnits(oneGwei, 9);
//_log:
//_result:
formatUnits(oneEther);
//_log:
//_result:
formatUnits(oneEther, 18);
//_log:
_property: ethers.utils.formatEther(value) => string @<utils-formatEther> @SRC<units>
The equivalent to calling ``formatUnits(value, "ether")``.
_code: @lang<javascript>
//_hide: const formatEther = ethers.utils.formatEther;
//_hide: const BigNumber = ethers.BigNumber;
const value = BigNumber.from("1000000000000000000");
//_result:
formatEther(value);
//_log:
_property: ethers.utils.parseUnits(value [ , unit = "ether" ] ) => [BigNumber](BigNumber) @<utils-parseUnits> @SRC<units>
Returns a [BigNumber](BigNumber) representation of //value//, parsed with
//unit// digits (if it is a number) or from the unit specified (if
a string).
_code: @lang<javascript>
//_hide: const parseUnits = ethers.utils.parseUnits;
//_result:
parseUnits("1.0");
//_log:
//_result:
parseUnits("1.0", "ether");
//_log:
//_result:
parseUnits("1.0", 18);
//_log:
//_result:
parseUnits("121.0", "gwei");
//_log:
//_result:
parseUnits("121.0", 9);
//_log:
_property: ethers.utils.parseEther(value) => [BigNumber](BigNumber) @<utils-parseEther> @SRC<units>
The equivalent to calling ``parseUnits(value, "ether")``.
_code: @lang<javascript>
//_hide: const parseEther = ethers.utils.parseEther;
//_result:
parseEther("1.0");
//_log:
//_result:
parseEther("-0.5");
//_log:

View File

@@ -2,23 +2,63 @@ _section: Encoding Utilities @<encoding>
_subsection: Base58 @<Bse58> @SRC<basex:Base58>
_property: ethers.utils.base58.decode(textData) => Uin8Array
_property: ethers.utils.base58.decode(textData) => Uint8Array
Return a typed Uint8Array representation of //textData// decoded using
base-58 encoding.
_code: @lang<javascript>
//_hide: const base58 = ethers.utils.base58;
//_result:
base58.decode("TzMhH");
//_log:
_property: ethers.utils.base58.encode(aBytesLike) => string
Return //aBytesLike// encoded as a string using the base-58 encoding.
_code: @lang<javascript>
//_hide: const base58 = ethers.utils.base58;
//_result:
base58.encode("0x12345678");
//_log:
//_result:
base58.encode([ 0x12, 0x34, 0x56, 0x78 ]);
//_log:
_subsection: Base64 @<Base64>
_property: ethers.utils.base64.decode(textData) => Uin8Array @SRC<base64>
_property: ethers.utils.base64.decode(textData) => Uint8Array @SRC<base64>
Return a typed Uint8Array representation of //textData// decoded using
base-64 encoding.
_code: @lang<javascript>
//_hide: const base64 = ethers.utils.base64;
//_result:
base64.decode("EjQ=");
//_log:
_property: ethers.utils.base64.encode(aBytesLike) => string @SRC<base64>
Return //aBytesLike// encoded as a string using the base-64 encoding.
_code: @lang<javascript>
//_hide: const base64 = ethers.utils.base64;
//_result:
base64.encode("0x1234");
//_log:
//_result:
base64.encode([ 0x12, 0x34 ]);
//_log:
_subsection: Recursive-Length Prefix @<rlp--methods>
@@ -26,15 +66,53 @@ The [[link-rlp]] encoding is used throughout Ethereum to serialize nested
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.
Encode a structured [Data Object](rlp--dataobject) into its RLP-encoded representation.
Each Data component may be an valid [[BytesLike]].
_code: @lang<javascript>
//_hide: const RLP = ethers.utils.RLP;
//_result:
RLP.encode("0x12345678");
//_log:
//_result:
RLP.encode([ "0x12345678" ]);
//_log:
//_result:
RLP.encode([ new Uint8Array([ 0x12, 0x34, 0x56, 0x78 ]) ]);
//_log:
//_result:
RLP.encode([ [ "0x42", [ "0x43" ] ], "0x12345678", [ ] ]);
//_log:
//_result:
RLP.encode([ ]);
//_log:
_property: ethers.utils.RLP.decode(aBytesLike) => [DataObject](rlp--dataobject) @<utils.rlpDecode> @SRC<rlp>
Decode an RLP-encoded //aBytesLike// into its structured Data Object.
Decode an RLP-encoded //aBytesLike// into its structured [Data Object](rlp--dataobject).
All Data components will be returned as a [[DataHexString]].
_code: @lang<javascript>
//_hide: const RLP = ethers.utils.RLP;
//_result:
RLP.decode("0x8412345678");
//_log:
//_result:
RLP.decode("0xcac342c1438412345678c0");
//_log:
//_result:
RLP.decode("0xc0");
//_log:
_heading: Data Object @<rlp--dataobject>
A **Data Object** is a recursive structure which is used to serialize many

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>
@@ -93,7 +93,7 @@ A signed format string begins with ``fixed``, which an unsigned format
string begins with ``ufixed``, followed by the width (in bits) and the
number of decimals.
The width must be conguent to 0 mod 8 (i.e. ``(width % 8) == 0``) and no
The width must be congruent to 0 mod 8 (i.e. ``(width % 8) == 0``) and no
larger than 256 bits and the number of decimals must be no larger than 80.
For example:

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>
@@ -9,7 +11,7 @@ The [Cryptographic Hash Functions](link-wiki-cryptographichash)
are a specific family of hash functions.
_property: ethers.utils.id(text) => string<[[DataHexString]]<32>> @<utils-id> @SRC<hash>
The Ethereum Identity function computs the [KECCAK256](link-wiki-sha3) hash of the //text// bytes.
The Ethereum Identity function computes the [KECCAK256](link-wiki-sha3) hash of the //text// bytes.
_property: ethers.utils.keccak256(aBytesLike) => string<[[DataHexString]]<32>> @<utils-keccak256> @SRC<keccak256>
Returns the [KECCAK256](link-wiki-sha3) digest //aBytesLike//.
@@ -25,14 +27,17 @@ Returns the [SHA2-512](link-wiki-sha2) digest of //aBytesLike//.
_code: KECCAK256 @lang<javascript>
//_result:
utils.keccak256([ 0x12, 0x34 ])
//!
//_log:
//_result:
utils.keccak256("0x")
//!
//_log:
//_result:
utils.keccak256("0x1234")
//!
//_log:
// The value MUST be data, such as:
// - an Array of numbers
@@ -40,16 +45,19 @@ utils.keccak256("0x1234")
// - a Uint8Array
// Do NOT use UTF-8 strings that are not a DataHexstring
//_throws:
utils.keccak256("hello world")
//! error
//_log:
// If needed, convert strings to bytes first:
//_result:
utils.keccak256(utils.toUtf8Bytes("hello world"))
//!
//_log:
// Or equivalently use the identity function:
//_result:
utils.id("hello world")
//!
//_log:
// Keep in mind that the string "0x1234" represents TWO
// bytes (i.e. [ 0x12, 0x34 ]. If you wish to compute the
@@ -59,48 +67,56 @@ utils.id("hello world")
// Consider the following examples:
// Hash of TWO (2) bytes:
//_result:
utils.keccak256("0x1234")
//!
//_log:
// Hash of TWO (2) bytes: (same result)
//_result:
utils.keccak256([ 0x12, 0x34 ])
//!
//_log:
const bytes = utils.toUtf8Bytes("0x1234");
// <hide>
bytes
// </hide>
//!
//_result:
bytes = utils.toUtf8Bytes("0x1234")
//_log:
// Hash of SIX (6) characters (different than above)
//_result:
utils.keccak256(bytes)
//!
//_log:
// Hash of SIX (6) characters (same result)
//_result:
utils.id("0x1234")
//!
//_log:
_code: RIPEMD160 @lang<javascript>
//_result:
utils.ripemd160("0x")
//!
//_log:
//_result:
utils.ripemd160("0x1234")
//!
//_log:
_code: SHA-2 @lang<javascript>
//_result:
utils.sha256("0x")
//!
//_log:
//_result:
utils.sha256("0x1234")
//!
//_log:
//_result:
utils.sha512("0x")
//!
//_log:
//_result:
utils.sha512("0x1234")
//!
//_log:
_subsection: HMAC @<utils--hmac>
@@ -119,10 +135,11 @@ 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"
//_result:
utils.computeHmac("sha256", key, data)
//!
//_log:
_subsection: Hashing Helpers @<utils--hashing-helpers>
@@ -132,27 +149,179 @@ 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//.
_code: Hashing Messages @lang<javascript>
// Hashing a string message
//_result:
utils.hashMessage("Hello World")
//_log:
// Hashing binary data (also "Hello World", but as bytes)
//_result:
utils.hashMessage( [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 ])
//_log:
// 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' ]
//_result:
utils.hashMessage("0x42")
//_log:
// Hashing the binary data
// Note: this is the hash of the 1 byte [ 0x42 ]
//_result:
utils.hashMessage([ 0x42 ])
//_log:
// Hashing the binary data
// Note: similarly, this is the hash of the 1 byte [ 0x42 ]
//_result:
utils.hashMessage(utils.arrayify("0x42"))
//_log:
_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. :)
_code: Namehash @lang<javascript>
//_result:
utils.namehash("")
//!
//_log:
//_result:
utils.namehash("eth")
//!
//_log:
//_result:
utils.namehash("ricmoo.firefly.eth")
//!
//_log:
//_result:
utils.namehash("ricmoo.xyz")
//!
//_log:
_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
domain = {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
};
// The named list of all type definitions
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
value = {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
},
contents: 'Hello, Bob!'
};
//_result:
TypedDataEncoder.encode(domain, types, value)
//_log:
//_result:
TypedDataEncoder.getPayload(domain, types, value)
//_log:
//_result:
TypedDataEncoder.getPrimaryType(types)
//_log:
//_result:
TypedDataEncoder.hash(domain, types, value)
//_log:
//_result:
TypedDataEncoder.hashDomain(domain)
//_log:
_subsection: Solidity Hashing Algorithms @<utils--solidity-hashing>
@@ -163,7 +332,7 @@ the tightly packing algorithm.
_property: ethers.utils.solidityPack(types, values) => string<[[DataHexString]]> @<utils-solidityPack> @SRC<solidity:pack>
Returns the non-standard encoded //values// packed according to
their respecive type in //types//.
their respective type in //types//.
_property: ethers.utils.solidityKeccak256(types, values) => string<[[DataHexString]]<32>> @<utils-solidityKeccak256> @SRC<solidity:keccak256>
Returns the [KECCAK256](link-wiki-sha3) of the non-standard encoded //values// packed
@@ -175,15 +344,40 @@ according to their respective type in //types//.
_code: Solidity Hashing @lang<javascript>
//_result:
utils.solidityPack([ "int16", "uint48" ], [ -1, 12 ])
//!
//_log:
//_result:
utils.solidityPack([ "string", "uint8" ], [ "Hello", 3 ])
//!
//_log:
//_result:
utils.solidityKeccak256([ "int16", "uint48" ], [ -1, 12 ])
//!
//_log:
//_result:
utils.soliditySha256([ "int16", "uint48" ], [ -1, 12 ])
//!
//_log:
// 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.
//_result:
utils.solidityPack([ "string", "string" ], [ "hello", "world01" ])
//_log:
//_result:
utils.solidityPack([ "string", "string" ], [ "helloworld", "01" ])
//_log:
//_result:
utils.solidityPack([ "string", "string", "uint16" ], [ "hell", "oworld", 0x3031 ])
//_log:
//_result:
utils.solidityPack([ "uint96" ], [ "32309054545061485574011236401" ])
//_log:

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
@@ -101,7 +111,7 @@ _heading: Methods @<HDNode--methods>
_property: hdNode.neuter() => [[HDNode]] @<HDNode-neuter> @SRC<hdnode>
Return a new instance of //hdNode// with its private key removed
but all otehr properties preserved. This ensures that the key
but all other properties preserved. This ensures that the key
can not leak the private key of itself or any derived children,
but may still be used to compute the addresses of itself and
any non-hardened children.

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 operatons
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, expectedCound [ , 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,28 @@ 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.TRANSACTION_REPLACED @<errors--transaction-replaced>
When a transaction has been replaced by the user, by broadcasting a new transaction
with the same nonce as an existing in-flight (unmined) transaction in the mempool,
this error will occur while waiting if the transaction being waited for has become
invalidated by that other transaction.
This can happen for several reasons, but most commonly because the user has increased
the gas price (which changes the transaction hash) to "speed up" a transaction or if
a user has "cancelled" the transaction in their client. In either case this is
usually accomplished by bribing the miners with a higher gas priced transaction.
This error will have the additional properties, ``cancelled``, ``hash``, ``reason``,
``receipt`` and ``replacement``.
See the [[providers-TransactionResponse]] for the ``wait`` method for more details.
_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 +251,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

@@ -8,11 +8,11 @@ The private key for this Signing Key.
_property: signingKey.publicKey => string<[[DataHexString]]<65>>
The uncompressed public key for this Signing Key. It will always be
65 bytes (130 nibbles) and begine with ``0x04``.
65 bytes (130 nibbles) and begins with ``0x04``.
_property: signingKey.compressedPublicKey => string<[[DataHexString]]<33>>
The compressed public key for this Signing Key. It will always be
33 bytes (66 nibbles) and begine with either ``0x02`` or ``0x03``.
33 bytes (66 nibbles) and begins with either ``0x02`` or ``0x03``.
_property: signingKey.signDigest(digest) => [[Signature]]
Sign the //digest// and return the signature.
@@ -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>
@@ -40,7 +44,7 @@ Returns the Array of codepoints of //text//, optionally normalized using the
_note: Note
This function correctly splits each **user-perceived character** into
its codepoint, accounting for surrogate pairs. This should not be confused with
``string.split("")``, which destroys surrogate pairs, spliting between each UTF-16
``string.split("")``, which destroys surrogate pairs, splitting between each UTF-16
codeunit instead.
_property: ethers.utils.toUtf8String(aBytesLike [ , onError = error ] ) => string @<utils-toUtf8String> @SRC<strings>
@@ -88,7 +92,7 @@ See NFKC for more an example.
_note: Note
Only certain specified characters are folded in Canonical Equivalence, and thus
it should **not** be considered a method to acheive //any// level of security from
it should **not** be considered a method to achieve //any// level of security from
[homoglyph attacks](link-wiki-homoglyph).

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.
@@ -54,7 +54,7 @@ _property: transaction.gasLimit => [[BigNumber]]
The gas limit for //transaction//. An account must have enough ether to
cover the gas (at the specified **gasPrice**). Any unused gas is
refunded at the end of the transaction, and if there is insufficient gas
to complete execution, the effects of the trasaction are reverted, but
to complete execution, the effects of the transaction are reverted, but
the gas is **fully consumed** and an out-of-gas error occurs.
_property: transaction.gasPrice => [[BigNumber]]
@@ -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>
@@ -37,7 +37,7 @@ Additional headers to include in the connection.
_heading: PollOptions @<PollOptions>
_property: options.timeout => number
The amount of time allowed to ellapse before triggering a timeout
The amount of time allowed to elapse before triggering a timeout
error.
_property: options.floor => number

View File

@@ -30,8 +30,8 @@ the registered //name//.
_subsection: Languages @<wordlists--languages>
The [official wordlists](link-bip39-wordlists) availalbe in at
`ethers.wordlists`. In the browser, only the english langauge is
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

@@ -2,7 +2,7 @@ _section: Assembler @<cli-asm>
The assembler Command-Line utility allows you to assemble the
[Ethers ASM Dialect](asm-dialect) into deployable EVM bytecode
and disassemle EVM bytecode into human-readable mnemonics.
and disassemble EVM bytecode into human-readable mnemonics.
_subsection: Help
@@ -31,7 +31,7 @@ _code: SimpleStore.asm @lang<asm>
; SimpleStore (uint)
; Set the inital value of 42
; Set the initial value of 42
sstore(0, 42)
; Init code to deploy myContract
@@ -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>
@@ -144,7 +144,7 @@ Byt specifying the **Position Independent Code** flag, code
will be generated in a way such that all offsets are relative, allowing
the program to be moved without any impact to its logic.
This does incur an additional gsas cost of 8 gas per offset access though.
This does incur an additional gas cost of 8 gas per offset access though.
_definition: **-\-target LABEL**
All programs have a root scope named ``_`` which is by default

View File

@@ -62,7 +62,7 @@ TRANSACTION OPTIONS (default: query network)
--gasPrice GWEI Default gas price for transactions(in wei)
--gasLimit GAS Default gas limit for transactions
--nonce NONCE Initial nonce for the first transaction
--yes Always accept Siging and Sending
--yes Always accept Signing and Sending
OTHER OPTIONS
--wait Wait until transactions are mined

View File

@@ -1,7 +1,7 @@
_section: Sandbox Utility
The sandbox utility provides a simple way to use the most common
ethers utilities required during learning, debuging and managing
ethers utilities required during learning, debugging and managing
interactions with the Ethereum network.
If no command is given, it will enter a REPL interface with many
@@ -64,7 +64,7 @@ TRANSACTION OPTIONS (default: query network)
--gasPrice GWEI Default gas price for transactions(in wei)
--gasLimit GAS Default gas limit for transactions
--nonce NONCE Initial nonce for the first transaction
--yes Always accept Siging and Sending
--yes Always accept Signing and Sending
OTHER OPTIONS
--wait Wait until transactions are mined

View File

@@ -21,7 +21,7 @@ associated plugin class will be instantiated and run.
_property: setPlugin(pluginClass) => void @<cli-setplugin> @SRC<cli/cli>
Set a dedicated [[cli-plugin]] class which will handle all input. This
may not be used in conjuction with addPlugin and will not automatically
may not be used in conjunction with addPlugin and will not automatically
accept a command from the arguments.
_property: showUsage([ message = "" [ , status = 0 ] ]) => never @<cli-showusage> @SRC<cli/cli>
@@ -36,7 +36,7 @@ _subsection: Plugin @<cli-plugin> @SRC<cli:class.Plugin>
Each **Plugin** manages each command of a CLI and is executed in phases.
If the usage (i.e. help) of a CLI is requested, the static methods ``getHelp``
and ``getOptionHelp`` are used to geneate the help screen.
and ``getOptionHelp`` are used to generate the help screen.
Otherwise, a plugin is instantiated and the ``prepareOptions`` is called. Each
plugin **must** call ``super.prepareOptions``, otherwise the basic options are
@@ -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``
@@ -83,7 +83,7 @@ _property: plugin.prepareArgs(args) => Promise<void> @<plugin-prepareargs> @SR
_property: plugin.run() => Promise<void> @<plugin-run> @SRC<cli/cli:Plugin.run>
_property: plugin.getAddress(addressOrName [ , message = "", [ allowZero = false ] ]) => Promise<string> @<plugin-getaddress> @SRC<cli/cli:Plugin.getAddress>
A plugin should use this method to resolve an address. If the resovled address is
A plugin should use this method to resolve an address. If the resolved address is
the zero address and //allowZero// is not true, an error is raised.
_property: plugin.dump(header, info) => void @<plugin-dump> @SRC<cli/cli:Plugin.dump>
@@ -92,7 +92,7 @@ formatted style. In the future, plugins may support a JSON output format
which will automatically work with this method.
_property: plugin.throwUsageError([ message = "" ]) => never @<plugin-throwusageerror> @SRC<cli/cli>
Stops exectuion of the plugin and shows the help screen of the plugin with
Stops execution of the plugin and shows the help screen of the plugin with
the optional //message//.
_property: plugin.throwError(message) => never @<plugin-throwerror> @SRC<cli/cli>
@@ -133,7 +133,7 @@ Flags are simple binary options (such as the ``--yes``), which are true if prese
otherwise false.
Options require a single parameter follow them on the command line
(such as ``--account wallet.json``, which nhas the name ``account`` and the value
(such as ``--account wallet.json``, which has the name ``account`` and the value
``wallet.json``)
Arguments are all other values on the command line, and are not accessed through

View File

@@ -20,7 +20,7 @@ refresh the page. This should cause all your UI components to
reset to a known-safe state, including any banners and warnings
to your users if they are on an unsupported network.
This can be acomplished by using the following function:
This can be accomplished by using the following function:
_code: Automatically Refresh on Network Change @lang<script>

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>
@@ -51,13 +57,11 @@ $TopicABaCD: **[** (topic[0] = A) **OR** (topic[0] = B) **]** **AND**
_code: ERC-20 Transfer Filter Examples @lang<javascript>
// <hide>
const tokenAddress = ethers.constants.AddressZero;
const myAddress = ethers.constants.AddressZero;
const myOtherAddress = ethers.constants.AddressZero;
const id = ethers.utils.id;
const hexZeroPad = ethers.utils.hexZeroPad;
// </hide>
//_hide: const tokenAddress = ethers.constants.AddressZero;
//_hide: const myAddress = ethers.constants.AddressZero;
//_hide: const myOtherAddress = ethers.constants.AddressZero;
//_hide: const id = ethers.utils.id;
//_hide: const hexZeroPad = ethers.utils.hexZeroPad;
// Short example of manually creating filters for an ERC-20
// Transfer event.
@@ -90,7 +94,7 @@ filter = {
id("Transfer(address,address,uint256)"),
hexZeroPad(myAddress, 32)
]
}
};
// List all token transfers *to* myAddress:
filter = {
@@ -100,7 +104,7 @@ filter = {
null,
hexZeroPad(myAddress, 32)
]
}
};
// List all token transfers *to* myAddress or myOtherAddress:
filter = {
@@ -113,7 +117,7 @@ filter = {
hexZeroPad(myOtherAddress, 32),
]
]
}
};
_null:
@@ -122,35 +126,87 @@ To simplify life, ..., explain here, the contract API
_code: ERC-20 Contract Filter Examples @lang<javascript>
// <hide>
const tokenAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; // DAI
const myAddress = "0x8ba1f109551bD432803012645Ac136ddd64DBA72";
const otherAddress = "0xEA517D5a070e6705Cc5467858681Ed953d285Eb9";
const provider = ethers.getDefaultProvider();
const Contract = ethers.Contract;
// </hide>
//_hide: const tokenAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; /* DAI */
//_hide: const myAddress = "0x8ba1f109551bD432803012645Ac136ddd64DBA72";
//_hide: const otherAddress = "0xEA517D5a070e6705Cc5467858681Ed953d285Eb9";
//_hide: const provider = ethers.getDefaultProvider();
//_hide: const Contract = ethers.Contract;
const abi = [
abi = [
"event Transfer(address indexed src, address indexed dst, uint val)"
];
const contract = new Contract(tokenAddress, abi, provider);
contract = new Contract(tokenAddress, abi, provider);
// List all token transfers *from* myAddress
//_result:
contract.filters.Transfer(myAddress)
//!
//_log:
// List all token transfers *to* myAddress:
//_result:
contract.filters.Transfer(null, myAddress)
//!
//_log:
// List all token transfers *from* myAddress *to* otherAddress:
//_result:
contract.filters.Transfer(myAddress, otherAddress)
//!
//_log:
// List all token transfers *to* myAddress OR otherAddress:
//_result:
contract.filters.Transfer(null, [ myAddress, otherAddress ])
//!
//_log:
_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

View File

@@ -1,13 +1,14 @@
_section: Ethereum Basics
This is a very breif overview of some aspects of //Ethereum//
This is a brief overview of some aspects of //Ethereum//
and blockchains which developers can make use of or should
be aware of.
This section is fairly sparse at the moment, but will be expanded
This section is sparse at the moment, but will be expanded
as time goes on.
_toc:
events
gas
security
best-practices

View File

@@ -1,5 +1,82 @@
_section: Security @<security>
While security should be a concern for all developers, in the
blockchain space developers must be additionally conscious of
many areas which can be exploited.
Once a problem has an economic incentives to exploit it, there
is a much larger risk and with blockchain apps it can become
quite valuable to attack.
In addition to many of the other security issues app developers
may have to worry about, there are a few additional vectors
that JavaScript developers should be aware of.
_subsection: Side-Channel Attacks
A [Side-Channel Attack](link-wiki-side-channel-attack) occurs
when something orthogonal to the implementation of the algorithm
used can be exploited to learn more about secure or private
information.
_heading: Released Data (Strings, Uint8Arrays, Buffers)
In JavaScript, memory may not be securely allocated, or more
importantly securely released.
[Historically](https://github.com/nodejs/node/issues/4660),
``new Buffer(16)`` would re-use old memory that had been
released. This would mean that code runnint later, may have
access to data that was discarded.
As an example of the dangers, imagine if you had used a Buffer
to store a private key, signed data and then returned from the
function, allowing the Buffer to be de-allocated. A future
function may be able to request a new Buffer, which would still
have that left-over private key, which it could then use to
steal the funds from that account.
There are also many debugging tools and systems designed to
assist develoeprs inspect the memory contents of JavaScript
programs. In these cases, any //private key// or //mnemonic//
siiting in memory may be visible to other users on the system,
or malicious scripts.
_heading: Timing Attack
Timing attacks allow a malicious user or script to determine
private data through analysing how long an operation requires
to execute.
In JavaScript, //Garbage Collection// occurs periodically when the
system determines it is required. Each JavaScript implementation
is different, with a variety of strategies and and abilities.
Most Garbage Collection requires "stopping the world", or pausing
all code being executed while it runs. This adds a large delay
to any code that was currently running.
This can be exploited by attackers to "condition cause a delay".
They will set up a scenario where the system is on the edge of
needing to garbage collect, and call your code with two paths,
a simple path and complex path. The simple path won't stir things
up enough to cause a garbage collection, while the complex one
will. By timing how long the code took to execute, they now know
whether garbage collection occured and therefore whether the simple
or complex path was taken.
Advancced timing attacks are very difficult to mitigate in any
garbage-collection-based language. Most libraries where this
matters will hopefully mitigated this for you as much as possible,
but it is still good to be aware of.
_heading: General Concerns
- [Cross-Site Scripting](link-wiki-xss)
- [Cross-Site Request Forgery](link-wiki-csrf)
- [Phishing](link-wiki-phishing)
_subsection: Key Derivation Functions @<security--pbkdf>
This is not specific to Ethereum, but is a useful technique
@@ -21,7 +98,7 @@ _heading: Why does it take so long?
The goal is to use as much CPU and memory as possible during
this algorithm, so that a single computer can only compute a
very small number of results for some fixed amount of time. To
scale up an attack, the attacker requires additional compuers,
scale up an attack, the attacker requires additional computers,
increasing the cost to [brute-force attack](link-wiki-bruteforce)
to guess the password.

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,33 +129,75 @@ 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()) } }`;
}
context.createClass = function(name) {
let C = class{ }
Object.defineProperty(C, "name", { value: name })
return C;
}
context._inspect = function(value, depth) {
if (toString.call(value) === '[object Error]') {
// Not an error from ethers...
if (ethers.utils.Logger.errors[value.code] == null) {
return `Error: ${ value.message }`;
}
// Trim the ethers errors down on their verbosity for the docs...
if (value.message) {
value.message = value.message.split(" (")[0];
}
value.stack = undefined;
}
if (value && value.constructor && value.constructor.name === "Uint8Array") {
return `Uint8Array [ ${ Array.prototype.join.call(value, ", ") } ]`;
}
if (typeof(value) === "string" && value.indexOf("\n") >= 0) {
return "`" + value + "`";
}
//return JSON.stringify(value);
return inspect(value, {
compact: false,
depth: null,
breakLength: Infinity,
sorted: true,
});
}
context._startup = function() {
console.log("Startup");
}
context._shutdown = function() {
console.log("Shutdown");
}
}
module.exports = {
title: "ethers",
subtitle: "v5.0",
subtitle: "v5.3",
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,28 +214,36 @@ 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/" },
"link-ethereum": { name: "Ethereum", url: "https:/\/ethereumorg" },
"link-etherscan": { name: "Etherscan", url: "https:/\/etherscan.io" },
"link-expo": { name: "Expo", url: "https:/\/expo.io" },
"link-etherscan-api": "https:/\/etherscan.io/apis",
"link-flatworm": { name: "Flatworm", url: "https:/\/github.com/ricmoo/flatworm" },
"link-geth": { name: "Geth", url: "https:/\/geth.ethereum.org" },
"link-infura": { name: "INFURA", url: "https:/\/infura.io" },
"link-javascriptcore": { name: "JavaScriptCore", url: "https:/\/developer.apple.com/documentation/javascriptcore?language=objc" },
"link-ledger": "https:/\/www.ledger.com",
"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:/\/alchemyapi.io/signup",
"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",
@@ -226,23 +278,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-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",
@@ -251,18 +312,25 @@ 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" },
"link-wiki-bruteforce": "https:/\/en.wikipedia.org/wiki/Brute-force_attack",
"link-wiki-cryptographichash": "https:/\/en.wikipedia.org/wiki/Cryptographic_hash_function",
"link-wiki-csrf": "https:/\/en.wikipedia.org/wiki/Cross-site_request_forgery",
"link-wiki-ecrecover": { name: "ECDSA Public Key Recovery", url: "https:/\/en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Public_key_recovery" },
"link-wiki-homoglyph": "https:/\/en.wikipedia.org/wiki/IDN_homograph_attack",
"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-phishing": "https:/\/en.wikipedia.org/wiki/Phishing",
"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",
@@ -270,9 +338,11 @@ module.exports = {
"link-wiki-utf8-overlong": "https:/\/en.wikipedia.org/wiki/UTF-8#Overlong_encodings",
"link-wiki-utf8-replacement": "https:/\/en.wikipedia.org/wiki/Specials_%28Unicode_block%29#Replacement_character",
"link-wiki-scrypt": "https:/\/en.wikipedia.org/wiki/Scrypt",
"link-wiki-side-channel-attack": "https:/\/en.wikipedia.org/wiki/Side-channel_attack",
"link-wiki-sha3": "https:/\/en.wikipedia.org/wiki/SHA-3",
"link-wiki-shuffle": { name: "Fisher-Yates Shuffle", url: "https:/\/en.wikipedia.org/wiki/Fisher-Yates_shuffle" },
"link-wiki-overflow": { name: "overflow", url: "https:/\/en.wikipedia.org/wiki/Integer_overflow" },
"link-wiki-underflow": { name: "arithmetic underflow", url: "https:/\/en.wikipedia.org/wiki/Arithmetic_underflow" },
"link-wiki-xss": "https:/\/en.wikipedia.org/wiki/Cross-site_scripting",
},
};

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>
@@ -94,8 +172,8 @@ Style Guide (this section will have much more coming):
- Avoid inline links in the source; use the ``externalLinks`` field in the config.js
- 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 symblinks in the future
- In general, I aim for xonsistency; look to similar situations throughout the documentation
to that section; flatworm will support symlinks in the future
- In general, I aim for consistency; look to similar situations throughout the documentation
_heading: Building

View File

@@ -1,5 +1,9 @@
_section: Cookbook
Cooking...
A collection (that will grow over time) of common, simple
snippets of code that are in general useful.
_toc:
react-native

View File

@@ -0,0 +1,60 @@
_section: React Native (and ilk) @<cookbook-reactnative>
The [[link-react-native]] framework has become quite popular and
has many popular forks, such as [[link-expo]].
React Native is based on [[link-javascriptcore]] (part of WebKit) and
does not use Node.js or the common Web and DOM APIs. As such,
there are many operations missing that a normal web environment
or Node.js instance would provide.
For this reason, there is a [[link-npm-ethersproject-shims]] module
provided to fill in the holes.
_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)
below for instructions on installing packages which can affect the security
of your application.
After installing packages, you may need to restart your packager and company.
_code: Installing @lang<shell>
/home/ricmoo/my-react-project> npm install @ethersproject/shims --save
_code: Importing @lang<script>
// Pull in the shims (BEFORE importing ethers)
import "@ethersproject/shims"
// Import the ethers library
import { ethers } from "ethers";
_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 possibly guess, allowing funds to be stolen and assets
manipulated.
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

@@ -219,58 +219,64 @@ for displaying code samples.
_heading: JavaScript Evaluation @<flatworm--code-eval>
For JavaScript files, the file is executed with some simple substitution.
For JavaScript files, the file is transpiled and executed in a VM,
allowiung output (or exceptions) of blocks to be included in the
fragment output.
A bare ``\/\/!`` on a line is replaced with the result of the last
statement. Building will fail if an error is thrown.
The entire **code fragment** source is included in an async IIFE,
whick means ``await`` is allowed, and several special comment
directives are allowed.
A bare ``\/\/!error`` is replaced with the throw error. Building will
fail if an error is not thrown.
A ``/\/_hide:`` will include any following code directly into the
output, but will not include it in the generated output for the fragment.
Also any code included between the lines **``\/\/ <hide>``** and
**``\/\/ </hide>``** will be omitted from the output, which can be used
to setup variables.
A ``/\/_log:`` will include the value of any following expression in the
output, prefixed with a ``/\/ ``. Renderers will mark output in different
style if possible.
A ``/\/_result:`` will begin a block, assigning the contents to ``_``. The
block can be ended with a ``/\/_log:`` or ``/\/_null:``, if no value is given
to log, then ``_`` is assumed. If an error occurs, generation fails.
A ``/\/_throws:`` will begin a block, which is expected to throw assigning
the error to ``_``. The block can be ended with a ``/\/_log:`` or ``/\/_null:``,
if no value is given to log, then ``_`` is assumed. If an error do not occur,
generation fails.
_code: Code Evaluation Example @lang<text>
\_code: Result of Code Example @lang<javascript>
// <hide>
const url = require("url");
// </hide>
//_hide: const url = require("url");
//_result:
url.parse("https://www.ricmoo.com/").protocol
//!
//_log:
//_throws:
url.parse(45)
//! error
//_log:
// You want to assign (doesn't emit eval) AND display the value
const foo = 4 + 5;
// <hide>
foo
// </hide>
//!
//_log: foo
_code: Result of Code Example @lang<javascript>
// <hide>
const url = require("url");
// </hide>
//_hide: const url = require("url");
//_result:
url.parse("https://www.ricmoo.com/").protocol
//!
//_log:
//_throws:
url.parse(45)
//! error
//_log:
// You want to assign (doesn't emit eval) AND display the value
const foo = 4 + 5;
// <hide>
foo
// </hide>
//!
//_log: foo
_heading: Languages
@@ -280,7 +286,7 @@ The language can be specified using the [@lang extension](flatworm--ext-lang).
_table:
| **Language** | **Notes** |
| javascript | Syntax highlights and [evaluates](flatworm--code-eval) the JavaScipt |
| javascript | Syntax highlights and [evaluates](flatworm--code-eval) the JavaScript |
| script | Same as ``javascript``, but does not evaluate the results |
| shell | Shell scripts or command-line |
| text | Plain text with no syntax highlighting |
@@ -379,8 +385,8 @@ _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 varaible
name must being with a letter and must only contain letters and numbers.
separately within a table directive using **variables**. A variable
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

@@ -3,14 +3,14 @@ _section: Getting Started @<getting-started>
_subsection: Installing @<installing>
The various Classes and Functions are available to be imported
Ethers' various Classes and Functions are available to import
manually from sub-packages under the [@ethersproject](link-ethers-npm)
organization but for most projects, the umbrella package is the
easiest way to get started.
_code: @lang<shell>
/home/ricmoo> npm install --save ethers@next
/home/ricmoo> npm install --save ethers
_subsection: Importing @<importing>
@@ -32,22 +32,22 @@ It is generally better practice (for security reasons) to copy the
[ethers library](link-ethers-js) to your own webserver and serve it
yourself.
For quick demos or prototyping though, it can be loaded in your
For quick demos or prototyping though, you can load it in your
Web Applications from our CDN.
_code: ES6 in the Browser @lang<html>
<script type="module">
import { ethers } from "https://cdn.ethers.io/lib/ethers-5.0.esm.min.js";
import { ethers } from "https://cdn.ethers.io/lib/ethers-5.2.esm.min.js";
// Your code here...
</script>
_code: ES3 (UMD) in the Browser @lang<html>
<script src="https://cdn.ethers.io/lib/ethers-5.0.umd.min.js"
type="application/javascipt"></script>
<script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js"
type="application/javascript"></script>
_subsection: Common Terminology @<getting-started--glossary>
@@ -64,8 +64,8 @@ $Signer: A Signer is a class which (usually) in some way directly or
and transactions to authorize the network to charge your account
ether to perform operations.
$Contract: A Contract is an abstraction which represents a connection to a
specific contract on the Ethereum Network, so that it can be
used like a normal JavaScipt object.
specific contract on the Ethereum Network, so that applications
can use it like a normal JavaScript object.
| **Provider** | $Provider |
@@ -90,35 +90,59 @@ const provider = new ethers.providers.Web3Provider(window.ethereum)
// The Metamask plugin also allows signing transactions to
// send ether and pay to change state within the blockchain.
// For this, we need the account signer...
// For this, you need the account signer...
const signer = provider.getSigner()
_subsection: Connecting to Ethereum: RPC @<getting-started--connecting-rpc>
The [JSON-RPC API](link-jsonrpc) is another popular method for interacting
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]]). It typically provides:
- A connection to the Ethereum network (a [[Provider]])
- Holds your private key and can sign things (a [[Signer]])
_code: Connecting to an RPC client @lang<script>
// If you don't specify a //url//, Ethers connects to the default
// (i.e. ``http:/\/localhost:8545``)
const provider = new ethers.providers.JsonRpcProvider();
// The provider also allows signing transactions to
// send ether and pay to change state within the blockchain.
// For this, we need the account signer...
const signer = provider.getSigner()
_heading: Querying the Blockchain @<getting-started--querying>
Once you have a [[Provider]], you have a read-only connection to the
blockchain, which can be used to query the current state, fetch historic
blockchain, which you can use to query the current state, fetch historic
logs, look up deployed code and so on.
_code: Basic Queries @lang<javascript>
// Look up the current block number
provider.getBlockNumber()
//!
//_result:
await provider.getBlockNumber()
//_log:
// Get the balance of an account (by address or ENS name)
// Get the balance of an account (by address or ENS name, if supported by network)
//_result:
balance = await provider.getBalance("ethers.eth")
//! async balance
//_log:
// Often you will need to format the output for the user
// which prefer to see values in ether (instead of wei)
// Often you need to format the output to something more user-friendly,
// such as in ether (instead of wei)
//_result:
ethers.utils.formatEther(balance)
//!
//_log:
// Or if a user enters a string in an input field, you may need
// If a user enters a string in an input field, you may need
// to convert it from ether (as a string) to wei (as a BigNumber)
//_result:
ethers.utils.parseEther("1.0")
//!
//_log:
_heading: Writing to the Blockchain @<getting-started--sending>
@@ -138,37 +162,36 @@ A Contract is an abstraction of program code which lives on the
Ethereum blockchain.
The [[Contract]] object makes it easier to use an on-chain
Contract as a normal JavaScript object, with the method all
Contract as a normal JavaScript object, with the methods
mapped to encoding and decoding data for you.
If you are familiar with Databases, this is similar to ORM.
If you are familiar with Databases, this is similar to an //Object Relational Mapper// (ORM).
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
at runtime, when you pass in the ABI to the constructor it uses that
This class is a //meta-class//, which means its methods are constructed
at runtime, and when you pass in the ABI to the constructor it uses it
to determine which methods to add.
While a on-chain Contract may have many methods available, you can safely ignore
While an on-chain Contract may have many methods available, you can safely ignore
any methods you don't need or use, providing a smaller subset of the ABI to
the contract.
An ABI often comes from the Solidity or Vyper compiler, but may also be
placed in the code easily using the Human-Readable ABI, which the following
examples use.
An ABI often comes from the Solidity or Vyper compiler, but you can use the
Human-Readable ABI in code, which the following examples use.
_code: Connecting to the DAI Contract @lang<javascript>
// We can use an ENS name for the contract address
// You can also use an ENS name for the contract address
const daiAddress = "dai.tokens.ethers.eth";
// The ERC-20 Contract ABI, which is a common contract interface
// for tokens (this is the Human-Readable ABI format)
const daiAbi = [
// Some simple details about the token
// Some details about the token
"function name() view returns (string)",
"function symbol() view returns (string)",
@@ -185,38 +208,33 @@ const daiAbi = [
// The Contract object
const daiContract = new ethers.Contract(daiAddress, daiAbi, provider);
//_hide: _page.daiAbi = daiAbi;
//_hide: _page.daiContract = daiContract;
_heading: Read-Only Methods @<getting-started--reading>
_code: Querying the DAI Contract @lang<javascript>
// <hide>
const daiAbi = [
// Some simple details about the token
"function name() view returns (string)",
"function symbol() view returns (string)",
// Get the account balance
"function balanceOf(address) view returns (uint)",
];
const daiContract = new ethers.Contract("dai.tokens.ethers.eth", daiAbi, provider);
// </hide>
//_hide: const daiContract = _page.daiContract;
// Get the ERC-20 token name
daiContract.name()
//!
//_result:
await daiContract.name()
//_log:
// Get the ERC-20 token synbol (for tickers and UIs)
daiContract.symbol()
//!
// Get the ERC-20 token symbol (for tickers and UIs)
//_result:
await daiContract.symbol()
//_log:
// Get the balance of an address
balance = await daiContract.balanceOf("ricmoo.firefly.eth")
//! async balance
//_log: balance
// Format the DAI for displaying to the user
//_result:
ethers.utils.formatUnits(balance, 18)
//!
//_log:
_heading: State Changing Methods @<getting-started--writing>
@@ -224,8 +242,8 @@ _heading: State Changing Methods @<getting-started--writing>
_code: Sending DAI @lang<script>
// The DAI Contract is currently connected to the Provider,
// which is read-only. We need to connect to a Signer, so
// that we can pay to send state-changing transactions.
// which is read-only. You need to connect to a Signer, so
// that you can pay to send state-changing transactions.
const daiWithSigner = contract.connect(signer);
// Each DAI has 18 decimal places
@@ -239,13 +257,8 @@ _heading: Listening to Events @<getting-started--events>
_code: Listening to Events @lang<javascript>
// <hide>
const daiAbi = [
"event Transfer(address indexed, address indexed, uint256)"
];
const daiContract = new ethers.Contract("dai.tokens.ethers.eth", daiAbi, provider);
const formatEther = ethers.utils.formatEther;
// </hide>
//_hide: const daiContract = _page.daiContract;
//_hide: const formatEther = ethers.utils.formatEther;
// Receive an event when ANY transfer occurs
daiContract.on("Transfer", (from, to, amount, event) => {
@@ -258,10 +271,7 @@ daiContract.on("Transfer", (from, to, amount, event) => {
// A filter for when a specific address receives tokens
myAddress = "0x8ba1f109551bD432803012645Ac136ddd64DBA72";
filter = daiContract.filters.Transfer(null, myAddress)
// <hide>
filter
// </hide>
//!
//_log: filter
// Receive an event when that filter occurs
daiContract.on(filter, (from, to, amount, event) => {
@@ -269,73 +279,55 @@ daiContract.on(filter, (from, to, amount, event) => {
console.log(`I got ${ formatEther(amount) } from ${ from }.`);
});
// <hide>
// Don't want to block the docs from compiling...
daiContract.removeAllListeners();
// </hide>
//_hide: daiContract.removeAllListeners(); /* Don't want to block the docs from compiling... */
_heading: Query Historic Events @<getting-started--history>
_code: Filtering Historic Events @lang<javascript>
// <hide>
const signer = new ethers.VoidSigner("0x8ba1f109551bD432803012645Ac136ddd64DBA72");
const daiAbi = [
"event Transfer(address indexed, address indexed, uint256)"
];
const daiContract = new ethers.Contract("dai.tokens.ethers.eth", daiAbi, provider);
//!
// </hide>
//_hide: const signer = new ethers.VoidSigner("0x8ba1f109551bD432803012645Ac136ddd64DBA72");
//_hide: const daiContract = _page.daiContract;
// Get the address of the Signer
myAddress = await signer.getAddress()
//! async myAddress
// Filter for all token transfers to me
filterFrom = daiContract.filters.Transfer(myAddress, null);
// <hide>
filterFrom
// </hide>
//!
//_log: myAddress
// Filter for all token transfers from me
filterFrom = daiContract.filters.Transfer(myAddress, null);
//_log: filterFrom
// Filter for all token transfers to me
filterTo = daiContract.filters.Transfer(null, myAddress);
// <hide>
filterTo
// </hide>
//!
//_log: filterTo
// List all transfers sent from me a specific block range
daiContract.queryFilter(filterFrom, 9843470, 9843480)
//!
//_result:
await daiContract.queryFilter(filterFrom, 9843470, 9843480)
//_log:
//
// The following have had the results omitted due to the
// number of entries; but they provide some useful examples
//
// List all transfers I sent in the last 10,000 blocks
daiContract.queryFilter(filterFrom, -10000)
// List all transfers sent in the last 10,000 blocks
await daiContract.queryFilter(filterFrom, -10000)
// List all transfers ever sent to me
daiContract.queryFilter(filterTo)
await daiContract.queryFilter(filterTo)
_subsection: Signing Messages @<getting-started--signing>
_code: Signing Messages @lang<javascript>
// <hide>
const signer = ethers.Wallet.createRandom();
//!
// </hide>
//_hide: const signer = ethers.Wallet.createRandom();
// To sign a simple string, which can often be used for
// logging into a service, such as CryptoKitties simply
// To sign a simple string, which are used for
// logging into a service, such as CryptoKitties,
// pass the string in.
signature = await signer.signMessage("Hello World");
//! async signature
//_log: signature
//
// A common case is also signing a hash, which is 32
@@ -343,13 +335,13 @@ signature = await signer.signMessage("Hello World");
// data it MUST be an Array (or TypedArray)
//
// This string is 66 chacacters long
// This string is 66 characters long
message = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
// This array representation is 32 bytes long
messageBytes = ethers.utils.arrayify(message);
//!
//_log: messageBytes
// To sign a hash, you most often want to sign the bytes
signature = await signer.signMessage(messageBytes)
//! async signature
//_log: signature

View File

@@ -5,7 +5,7 @@ _subsection: What is Ethers? @<preamble>
The ethers.js library aims to be a complete and compact library for
interacting with the Ethereum Blockchain and its ecosystem. It was
originally designed for use with [ethers.io](link-ethersio) and
has since expanded into a much more general-purpose library.
has since expanded into a more general-purpose library.
_subsection: Features @<features>
@@ -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

@@ -3,7 +3,7 @@ _section: Migration: From Ethers v4 @<migration-v4>
This document only covers the features present in v4 which have changed
in some important way in v5.
It does not cover all the new additional featuers that have been added and
It does not cover all the new additional features that have been added and
mainly aims to help those updating their older scripts and applications to
retain functional parity.
@@ -52,7 +52,7 @@ _subsection: Contracts
_heading: ENS Name Resolution
The name of the resolved address has changed. If the address passed into the
constructor was an ENS name, the address will be resovled before any calls
constructor was an ENS name, the address will be resolved before any calls
are made to the contract.
The name of the property where the resolved address has changed from ``addressPromise``
@@ -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 fucntions 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

@@ -1,6 +1,6 @@
_section: Testing
Testing is a critcial part of any library which wishes to remain secure, safe
Testing is a critical part of any library which wishes to remain secure, safe
and reliable.
Ethers currently has **over 23k tests** among its test suites, which are all
@@ -15,7 +15,7 @@ fix and included to prevent future changes from causing a regression.
A large number of the test cases were created procedurally by using
known correct implementations from various sources (such as Geth) and
written in different languages and verifyied with multiple libraries.
written in different languages and verified with multiple libraries.
For example, the ABI test suites were generated by procedurally generating
a list of types, for each type choosing a random (valid) value, which then
@@ -52,16 +52,16 @@ and will require ES2015 for [Proxy](link-js-proxy).
Certain features in JavaScript are also avoided, such as look-behind tokens in regular
expressions, since these have caused conflicts (at import time) with certain JavaScript
environmants such as [Otto](link-otto).
environments such as [Otto](link-otto).
Basically, the moral of the story is "be inclusive and don't drop people needlessly".
_subsection: Test Suites @<testing-suites>
The test suites are avaialble a gzipped JSON files in the
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>
@@ -71,10 +71,10 @@ $ContractEvents: Compiled Solidity, ABI interfaces, input types/values with
output types/values for emitted events; all tests were
executed against real Ethereum nodes
$ContractAbi: Compiled Solidity, ABI interfaces, input types/values with the
output types/values, encoded and decoded binrary data and normalized
output types/values, encoded and decoded binary data and normalized
values for function calls executed against real Ethereum nodes.
$ContractAbi2: Identical to ``contract-interface``, except with emphasis on
the ABIv2 coder which supports nested dynami types and strutured
the ABIv2 coder which supports nested dynami types and structured
data
$ContractSignatures: Contract signatures and matching selectors
$Hashes: Data and respective hashes against a variety of hash functions
@@ -88,7 +88,7 @@ $Transactions: Signed and unsigned transactions with their serialized form
including both with and without EIP-155 replay protection
$Units: Values converted between various units
$Wallet: Keystore JSON format wallets, passwords and decrypted values
$Wordlist: Fully decompressed BIP-39 offcial wordlists
$Wordlist: Fully decompressed BIP-39 official wordlists
| **Filename** | **Test Cases** <|
| accounts.json.gz | $Account <|
@@ -116,7 +116,7 @@ _property: testcases.loadTests(tag) => Array<TestCase>
Load all the given testcases for the //tag//.
A tag is the string in the above list of test case names not including
any extenstion (e.g. ``"solidity-hashes"``)
any extension (e.g. ``"solidity-hashes"``)
_property: testcases.TestCase.TEST_NAME
Most testcases have its schema available as a TypeScript type to make testing
@@ -126,11 +126,11 @@ _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 eaxmple on each iteration change the value and
in recursive functions, concatentate to the seed.
sure to tweak the seed properly, for example on each iteration change the value and
in recursive functions, concatenate to the seed.
_property: testcases.randomBytes(seed, lower [, upper ]) => Uint8Array
Return at least //lower// random bytes, up to //upper// (exclusive) if specified,
@@ -159,9 +159,9 @@ accounts and transactions suites can be merged into one large collection.
_heading: Accounts
Basic account information using a private key and computing various addrss forms.
Basic account information using a private key and computing various address forms.
Tests were verfified against [EthereumJS](https:/\/github.com/ethereumjs) and custom
Tests were verified against [EthereumJS](https:/\/github.com/ethereumjs) and custom
scripts created to directly interact with Geth and cpp implementations.
//See: ``accounts.json.gz``//

View File

@@ -0,0 +1,8 @@
<html>
<head>
<title>API Keys - ethers</title>
</head>
<body>
Redirect to /v5/api-keys.
</body>
</html>

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

@@ -21,46 +21,33 @@ Developer Documentation
* [Importing](getting-started)
* [Common Terminology](getting-started)
* [Connecting to Ethereum: Metamask](getting-started)
* [Connecting to Ethereum: RPC](getting-started)
* [Contracts](getting-started)
* [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)
* [Contract Interaction](api/contract)
* [Contract](api/contract/contract)
* [Creating Instances](api/contract/contract)
* [Properties](api/contract/contract)
* [Methods](api/contract/contract)
* [Events](api/contract/contract)
* [Meta-Class](api/contract/contract)
* [ContractFactory](api/contract/contract-factory)
* [Creating Instances](api/contract/contract-factory)
* [Properties](api/contract/contract-factory)
* [Methods](api/contract/contract-factory)
* [Example: ERC-20 Contract](api/contract/example)
* [Connecting to a Contract](api/contract/example)
* [Properties](api/contract/example)
* [Methods](api/contract/example)
* [Events](api/contract/example)
* [Meta-Class Methods](api/contract/example)
* [Meta-Class Filters](api/contract/example)
* [Signers](api/signer)
* [Signer](api/signer)
* [Wallet](api/signer)
* [VoidSigner](api/signer)
* [ExternallyOwnedAccount](api/signer)
* [Providers](api/providers)
* [Provider](api/providers/provider)
* [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)
@@ -83,10 +70,34 @@ Developer Documentation
* [WebSocketProvider](api/providers/other)
* [Types](api/providers/types)
* [BlockTag](api/providers/types)
* [Networkish](api/providers/types)
* [Network](api/providers/types)
* [Block](api/providers/types)
* [Events and Logs](api/providers/types)
* [Transactions](api/providers/types)
* [Signers](api/signer)
* [Signer](api/signer)
* [Wallet](api/signer)
* [VoidSigner](api/signer)
* [ExternallyOwnedAccount](api/signer)
* [Contract Interaction](api/contract)
* [Contract](api/contract/contract)
* [Creating Instances](api/contract/contract)
* [Properties](api/contract/contract)
* [Methods](api/contract/contract)
* [Events](api/contract/contract)
* [Meta-Class](api/contract/contract)
* [ContractFactory](api/contract/contract-factory)
* [Creating Instances](api/contract/contract-factory)
* [Properties](api/contract/contract-factory)
* [Methods](api/contract/contract-factory)
* [Example: ERC-20 Contract](api/contract/example)
* [Connecting to a Contract](api/contract/example)
* [Properties](api/contract/example)
* [Methods](api/contract/example)
* [Events](api/contract/example)
* [Meta-Class Methods](api/contract/example)
* [Meta-Class Filters](api/contract/example)
* [Utilities](api/utils)
* [Application Binary Interface](api/utils/abi)
* [AbiCoder](api/utils/abi/coder)
@@ -186,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)
@@ -220,10 +231,14 @@ Developer Documentation
* [Plugin](cli/plugin)
* [ArgParser](cli/plugin)
* [Cookbook](cookbook)
* [React Native (and ilk)](cookbook/react-native)
* [Installing](cookbook/react-native)
* [Security](cookbook/react-native)
* [Migration Guide](migration)
* [Migration: From Web3.js](migration/web3)
* [Contracts](migration/web3)
* [Providers](migration/web3)
* [Signers](migration/web3)
* [Contracts](migration/web3)
* [Numbers](migration/web3)
* [Utilities](migration/web3)
* [Migration: From Ethers v4](migration/ethers-v4)
@@ -231,13 +246,18 @@ Developer Documentation
* [Contracts](migration/ethers-v4)
* [Errors](migration/ethers-v4)
* [Interface](migration/ethers-v4)
* [Utilities](migration/ethers-v4)
* [Wallet](migration/ethers-v4)
* [Testing](testing)
* [Supported Platforms](testing)
* [Test Suites](testing)
* [Test Suite API](testing)
* [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

@@ -0,0 +1,49 @@
-----
Documentation: [html](https://docs.ethers.io/)
-----
Provider API Keys
=================
Etherscan
---------
INFURA
------
Alchemy
-------
Pocket Gateway
--------------
Creating a Default Provider
---------------------------
```
// Use the mainnet
const network = "homestead";
// Specify your own API keys
// Each is optional, and if you omit it the default
// API key for that service will be used.
const provider = ethers.getDefaultProvider(network, {
etherscan: YOUR_ETHERSCAN_API_KEY,
infura: YOUR_INFURA_PROJECT_ID,
// 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:
// }
});
```

117
docs/v5/api-keys/index.html Normal file

File diff suppressed because one or more lines are too long

View File

@@ -7,34 +7,12 @@ Documentation: [html](https://docs.ethers.io/)
Application Programming Interface
=================================
* [Contract Interaction](contract)
* [Contract](contract/contract)
* [Creating Instances](contract/contract)
* [Properties](contract/contract)
* [Methods](contract/contract)
* [Events](contract/contract)
* [Meta-Class](contract/contract)
* [ContractFactory](contract/contract-factory)
* [Creating Instances](contract/contract-factory)
* [Properties](contract/contract-factory)
* [Methods](contract/contract-factory)
* [Example: ERC-20 Contract](contract/example)
* [Connecting to a Contract](contract/example)
* [Properties](contract/example)
* [Methods](contract/example)
* [Events](contract/example)
* [Meta-Class Methods](contract/example)
* [Meta-Class Filters](contract/example)
* [Signers](signer)
* [Signer](signer)
* [Wallet](signer)
* [VoidSigner](signer)
* [ExternallyOwnedAccount](signer)
* [Providers](providers)
* [Provider](providers/provider)
* [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)
@@ -57,10 +35,34 @@ Application Programming Interface
* [WebSocketProvider](providers/other)
* [Types](providers/types)
* [BlockTag](providers/types)
* [Networkish](providers/types)
* [Network](providers/types)
* [Block](providers/types)
* [Events and Logs](providers/types)
* [Transactions](providers/types)
* [Signers](signer)
* [Signer](signer)
* [Wallet](signer)
* [VoidSigner](signer)
* [ExternallyOwnedAccount](signer)
* [Contract Interaction](contract)
* [Contract](contract/contract)
* [Creating Instances](contract/contract)
* [Properties](contract/contract)
* [Methods](contract/contract)
* [Events](contract/contract)
* [Meta-Class](contract/contract)
* [ContractFactory](contract/contract-factory)
* [Creating Instances](contract/contract-factory)
* [Properties](contract/contract-factory)
* [Methods](contract/contract-factory)
* [Example: ERC-20 Contract](contract/example)
* [Connecting to a Contract](contract/example)
* [Properties](contract/example)
* [Methods](contract/example)
* [Events](contract/example)
* [Meta-Class Methods](contract/example)
* [Meta-Class Filters](contract/example)
* [Utilities](utils)
* [Application Binary Interface](utils/abi)
* [AbiCoder](utils/abi/coder)
@@ -160,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

@@ -10,16 +10,19 @@ ContractFactory
Creating Instances
------------------
#### **new ***ethers* . **ContractFactory**( interface , bydecode [ , signer ] )
#### **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

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