Compare commits
203 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c27b45ac9 | ||
|
|
20f6e16394 | ||
|
|
2df9dd1120 | ||
|
|
74470defda | ||
|
|
8175c83026 | ||
|
|
e0ccafb140 | ||
|
|
20335e96c2 | ||
|
|
a56a0a3336 | ||
|
|
4ad47b1b43 | ||
|
|
0e6cc9a9a8 | ||
|
|
21c6c7ddb6 | ||
|
|
8efbfc6afa | ||
|
|
8e3cfd8517 | ||
|
|
0a6c15e691 | ||
|
|
d3b1ac046a | ||
|
|
86b413750d | ||
|
|
70c2b1b300 | ||
|
|
5cb418cf7d | ||
|
|
8e4ee887b9 | ||
|
|
ef09361539 | ||
|
|
6e36447aa0 | ||
|
|
1c4259881a | ||
|
|
ba00df1ab7 | ||
|
|
45a2902874 | ||
|
|
211defa27f | ||
|
|
bdc6df4b8b | ||
|
|
799896ac13 | ||
|
|
8b54f7ff23 | ||
|
|
2cf462c571 | ||
|
|
1f6646e131 | ||
|
|
e6a52b309b | ||
|
|
fb808d1362 | ||
|
|
fd2882d088 | ||
|
|
a8e3380ed5 | ||
|
|
7f775f7ad6 | ||
|
|
d122d18cfa | ||
|
|
34488cd7d8 | ||
|
|
95e2871966 | ||
|
|
4a8d579dca | ||
|
|
fbbe4ad638 | ||
|
|
20defec9f1 | ||
|
|
c8bb77d8af | ||
|
|
29f6c34343 | ||
|
|
a185e89181 | ||
|
|
c9e548071e | ||
|
|
62c7195ed6 | ||
|
|
cc63e61f73 | ||
|
|
2816850716 | ||
|
|
4b7028a661 | ||
|
|
0382faebb1 | ||
|
|
97efeba8dc | ||
|
|
cddc258c96 | ||
|
|
3abfdffffa | ||
|
|
02546b9401 | ||
|
|
fff72ef369 | ||
|
|
f10977ab35 | ||
|
|
1729f804fb | ||
|
|
8933467c01 | ||
|
|
22bd0c76dd | ||
|
|
4809325bee | ||
|
|
e0b1d0e1e0 | ||
|
|
fe17a29581 | ||
|
|
d8cdd0e94c | ||
|
|
5a9bc30336 | ||
|
|
28f60d5ef8 | ||
|
|
a21202c66b | ||
|
|
116cc89686 | ||
|
|
550ecf2f25 | ||
|
|
7b19fdfeed | ||
|
|
15a90af5be | ||
|
|
86146650d8 | ||
|
|
7fcae25a78 | ||
|
|
15893537c3 | ||
|
|
be4e2164e6 | ||
|
|
3e676f21b0 | ||
|
|
5a4dd5a703 | ||
|
|
345a830dc4 | ||
|
|
cfa6dec293 | ||
|
|
5a6d9a3a38 | ||
|
|
a62d20d86f | ||
|
|
5e0e3de52e | ||
|
|
d78b7a3998 | ||
|
|
5abc2f36e2 | ||
|
|
38a068bcea | ||
|
|
65772a8e1a | ||
|
|
a022093ce0 | ||
|
|
50f84b3c57 | ||
|
|
df21d5326a | ||
|
|
e65fa8fc00 | ||
|
|
8e682cc848 | ||
|
|
ef8e4330d3 | ||
|
|
a0278615a4 | ||
|
|
d8821d7317 | ||
|
|
78a82d9ff2 | ||
|
|
1ac7decd89 | ||
|
|
4fa7276cc1 | ||
|
|
6ae222d55c | ||
|
|
efeeda5e5c | ||
|
|
c75c937b13 | ||
|
|
d1ee596292 | ||
|
|
b61e2cc96a | ||
|
|
ca94445f0f | ||
|
|
4d95fe925d | ||
|
|
f3e5b0ded1 | ||
|
|
8ce9761bad | ||
|
|
3d051e454d | ||
|
|
c48ad4421f | ||
|
|
40264ff900 | ||
|
|
e86f83b9c0 | ||
|
|
e986b09e58 | ||
|
|
22dee96f51 | ||
|
|
0c614b7097 | ||
|
|
f0a5869c53 | ||
|
|
5cd1668e0d | ||
|
|
0b061d68cc | ||
|
|
ffa4a2d054 | ||
|
|
f8072a8004 | ||
|
|
4306b3563a | ||
|
|
c4de88af6f | ||
|
|
9486185ceb | ||
|
|
261eb04e97 | ||
|
|
832bd6c908 | ||
|
|
05844caf85 | ||
|
|
f7e82fcb46 | ||
|
|
27b3af0a7b | ||
|
|
f733fac875 | ||
|
|
1097a1b020 | ||
|
|
ea422d63b3 | ||
|
|
a3821f6c4b | ||
|
|
de8a717b4c | ||
|
|
86e0269a86 | ||
|
|
d15c097dba | ||
|
|
49f71574f4 | ||
|
|
9ee685df46 | ||
|
|
263bfe5ce6 | ||
|
|
e8a9eea493 | ||
|
|
1c499c9f42 | ||
|
|
c1a297db99 | ||
|
|
be92339696 | ||
|
|
bc3eeeca39 | ||
|
|
042b74e6ee | ||
|
|
6e10675adf | ||
|
|
2b83feb6bd | ||
|
|
19fd55e935 | ||
|
|
710998b19a | ||
|
|
828a35fdca | ||
|
|
95bcda0d8a | ||
|
|
ccfe205db8 | ||
|
|
f9684aeec2 | ||
|
|
9d5de46c84 | ||
|
|
28ee745211 | ||
|
|
4e394fc680 | ||
|
|
97acaa1129 | ||
|
|
fe280c8458 | ||
|
|
bdccf7b8d3 | ||
|
|
0234cfbbef | ||
|
|
cadb28d6b3 | ||
|
|
72385c2287 | ||
|
|
201e5ced9c | ||
|
|
bf481f4bbf | ||
|
|
681f2a50b2 | ||
|
|
18fdb96fe1 | ||
|
|
35b64b9a65 | ||
|
|
4ca98825d4 | ||
|
|
0558bba8eb | ||
|
|
a440317594 | ||
|
|
2359a98641 | ||
|
|
a32fbd835d | ||
|
|
6fd3bb62d1 | ||
|
|
83db8a6bd1 | ||
|
|
f24240eddf | ||
|
|
d01d0c8448 | ||
|
|
d3b473e7c7 | ||
|
|
57eb5b777e | ||
|
|
240aac5683 | ||
|
|
8abdbbbf63 | ||
|
|
5fcd03f27e | ||
|
|
cb8f4a3a4e | ||
|
|
8facc1a530 | ||
|
|
17fdca8994 | ||
|
|
df0caab5d6 | ||
|
|
9733927f82 | ||
|
|
28dbcfc38c | ||
|
|
bb8e77dc70 | ||
|
|
ae619bcfc7 | ||
|
|
5b5904ea99 | ||
|
|
8f4b3027ef | ||
|
|
e9009631d5 | ||
|
|
be273f26e9 | ||
|
|
b0c082d728 | ||
|
|
9640e864a6 | ||
|
|
e1bbb064a1 | ||
|
|
d38ebaeb23 | ||
|
|
39a16260a7 | ||
|
|
2c49a52a41 | ||
|
|
32de4f1930 | ||
|
|
232c7a895b | ||
|
|
c443a8bd9d | ||
|
|
0940944048 | ||
|
|
3ac0aeaac6 | ||
|
|
8557285da6 | ||
|
|
fb46e0fd79 | ||
|
|
84d6fdfc37 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
custom: [ 'https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2', 'https://www.buymeacoffee.com/ricmoo' ]
|
||||
114
.github/workflows/nodejs.yml
vendored
114
.github/workflows/nodejs.yml
vendored
@@ -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
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,4 +1,7 @@
|
||||
node_modules/
|
||||
packages/*/node_modules
|
||||
packages/*/lib._esm
|
||||
.package_node_modules/
|
||||
obsolete/
|
||||
.DS_Store
|
||||
.tmp/
|
||||
@@ -20,3 +23,7 @@ packages/*/tsconfig.tsbuildinfo
|
||||
packages/testcases/input/nameprep/**
|
||||
|
||||
.nyc_output/**
|
||||
|
||||
output/**
|
||||
|
||||
misc/testing/**
|
||||
|
||||
145
CHANGELOG.md
145
CHANGELOG.md
@@ -1,7 +1,149 @@
|
||||
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.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)
|
||||
--------------------------------
|
||||
@@ -71,4 +213,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))
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -75,7 +75,7 @@ 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.
|
||||
|
||||
@@ -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
|
||||
|
||||
111
admin/build.js
111
admin/build.js
@@ -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
|
||||
};
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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(">", ">") }>`);
|
||||
deps[name] = value;
|
||||
});
|
||||
});
|
||||
savePackage(dirname, info);
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -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 =
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -1,5 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
const { setupBuild } = require("../build");
|
||||
|
||||
setupBuild(false);
|
||||
@@ -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);
|
||||
})();
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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);
|
||||
})();
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
})();
|
||||
120
admin/config.js
120
admin/config.js
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
186
admin/git.js
186
admin/git.js
@@ -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,
|
||||
}
|
||||
162
admin/github.js
162
admin/github.js
@@ -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,
|
||||
}
|
||||
|
||||
401
admin/index.js
401
admin/index.js
@@ -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();
|
||||
}
|
||||
})();
|
||||
101
admin/local.js
101
admin/local.js
@@ -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,
|
||||
}
|
||||
53
admin/log.js
53
admin/log.js
@@ -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
|
||||
}
|
||||
104
admin/npm.js
104
admin/npm.js
@@ -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,
|
||||
};
|
||||
@@ -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" }
|
||||
}
|
||||
}
|
||||
@@ -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":"{}"}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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:
|
||||
// }
|
||||
});
|
||||
|
||||
@@ -1,64 +1,105 @@
|
||||
_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``.
|
||||
|
||||
_code: Deploying a Contract @lang<javascript>
|
||||
|
||||
// <hide>
|
||||
const signer = ethers.LocalSigner();
|
||||
const signer = localSigner;
|
||||
const ContractFactory = ethers.ContractFactory;
|
||||
const bytecode = "608060405234801561001057600080fd5b5060405161012e38038061012e8339818101604052604081101561003357600080fd5b81019080805190602001909291908051906020019092919050505081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060008190555050506088806100a66000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633fa4f24514602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000805490509056fea2646970667358221220926465385af0e8706644e1ff3db7161af699dc063beaadd55405f2ccd6478d7564736f6c63430007040033";
|
||||
// </hide>
|
||||
|
||||
|
||||
// If your contract constructor requires parameters, the ABI
|
||||
// must include the constructor
|
||||
const abi = [
|
||||
"constructor(address owner, uint256 initialValue)"
|
||||
"constructor(address owner, uint256 initialValue)",
|
||||
"function value() view returns (uint)"
|
||||
];
|
||||
|
||||
const factory = new ContractFactory(abi, bytecode, signer)
|
||||
// The factory we use for deploying contracts
|
||||
factory = new ContractFactory(abi, bytecode, signer)
|
||||
|
||||
const contract = await factory.deploy("ricmoo.eth", 42);
|
||||
// Deploy an instance of the contract
|
||||
contract = await factory.deploy("ricmoo.eth", 42);
|
||||
//<hide>
|
||||
//! async contract
|
||||
//</hide>
|
||||
|
||||
// The address is available immediately, but the contract
|
||||
// is NOT deployed yet
|
||||
@@ -69,7 +110,9 @@ contract.address
|
||||
contract.deployTransaction
|
||||
//!
|
||||
|
||||
// Wait until the transaction is mined
|
||||
// Wait until the transaction is mined (i.e. contract is deployed)
|
||||
// - returns the receipt
|
||||
// - throws on failure (the reciept is on the error)
|
||||
contract.deployTransaction.wait()
|
||||
//!
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ 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.
|
||||
|
||||
|
||||
_subsection: EIP1193Bridge @<experimental-eip1193bridge> @INHERIT<[[link-npm-events]]>
|
||||
@@ -55,11 +55,11 @@ The provider associated with the signer.
|
||||
_property: nonceManager.setTransactionCount(count) => void
|
||||
Set the current transaction count (nonce) for the signer.
|
||||
|
||||
This may be useful it interacting with the signer outside of using
|
||||
This may be useful in interacting with the signer outside of using
|
||||
this class.
|
||||
|
||||
_property: nonceManager.increaseTransactionCount( [ count = 1 ]) => void
|
||||
Bump the current transaction count (nonce) by //count//.
|
||||
|
||||
This may be useful it interacting with the signer outside of using
|
||||
This may be useful in interacting with the signer outside of using
|
||||
this class.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ to them, which simplifies development, since you do not need
|
||||
to run your own instance or cluster of Ethereum nodes.
|
||||
|
||||
However, this reliance on third-party services can reduce
|
||||
resiliance, security and increase the amount of required trust.
|
||||
resilience, security and increase the amount of required trust.
|
||||
To mitigate these issues, it is recommended you use a
|
||||
[Default Provider](providers-getDefaultProvider).
|
||||
|
||||
@@ -20,7 +20,7 @@ _property: new ethers.providers.EtherscanProvider([ network = "homestead", [ api
|
||||
Create a new **EtherscanProvider** connected to //network// with the
|
||||
optional //apiKey//.
|
||||
|
||||
The //network// may be specified as **string** for a common
|
||||
The //network// may be specified as a **string** for a common
|
||||
network name, a **number** for a common chain ID or a
|
||||
[Network Object]provider-(network).
|
||||
|
||||
@@ -86,7 +86,7 @@ _property: new ethers.providers.InfuraProvider([ network = "homestead", [ apiKey
|
||||
Create a new **InfuraProvider** connected to //network// with
|
||||
the optional //apiKey//.
|
||||
|
||||
The //network// may be specified as **string** for a common
|
||||
The //network// may be specified as a **string** for a common
|
||||
network name, a **number** for a common chain ID or a
|
||||
[Network Object]provider-(network).
|
||||
|
||||
@@ -157,7 +157,7 @@ _property: new ethers.providers.AlchemyProvider([ network = "homestead", [ apiKe
|
||||
Create a new **AlchemyProvider** connected to //network// with
|
||||
the optional //apiKey//.
|
||||
|
||||
The //network// may be specified as **string** for a common
|
||||
The //network// may be specified as a **string** for a common
|
||||
network name, a **number** for a common chain ID or a
|
||||
[Network Object](providers-Network).
|
||||
|
||||
|
||||
@@ -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,29 @@ 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"``) to use that network definition or may specify
|
||||
custom parameters.
|
||||
|
||||
_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
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
_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]])
|
||||
|
||||
@@ -11,7 +11,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 (higher 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.
|
||||
|
||||
@@ -41,7 +41,7 @@ The provider for this configuration.
|
||||
|
||||
_property: fallbackProviderConfig.priority => number
|
||||
The priority used for the provider. Higher priorities are favoured over lower
|
||||
priorities. If multiple providers share the same prioirty, they are choosen
|
||||
priorities. If multiple providers share the same priority, they are chosen
|
||||
at random.
|
||||
|
||||
_property: fallbackProviderConfig.stallTimeout => number
|
||||
@@ -96,7 +96,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 +152,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.provider.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.
|
||||
|
||||
@@ -146,7 +146,7 @@ _subsection: Transactions Methods @<Provider--transaction-methods>
|
||||
_property: provider.call(transaction [ , blockTag = latest ]) => Promise<string<[[DataHexString]]>> @<Provider-call> @SRC<providers/base-provider>
|
||||
Returns the result of executing the //transaction//, using //call//. A call
|
||||
does not require any ether, but cannot change any state. This is useful
|
||||
for calling gettings on Contracts.
|
||||
for calling getters on Contracts.
|
||||
|
||||
_property: provider.estimateGas(transaction) => Promise<[[BigNumber]]> @<Provider-estimateGas> @SRC<providers/base-provider>
|
||||
Returns an estimate of the amount of gas that would be required to submit //transaction//
|
||||
@@ -174,7 +174,7 @@ Add a //listener// to be triggered for each //eventName//.
|
||||
|
||||
_property: provider.once(eventName, listener) => this @<Provider-once> @SRC<providers/base-provider>
|
||||
Add a //listener// to be triggered for only the next //eventName//,
|
||||
at which time it be removed.
|
||||
at which time it will be removed.
|
||||
|
||||
_property: provider.emit(eventName, ...args) => boolean @<Provider-emit> @SRC<providers/base-provider>
|
||||
Notify all listeners of //eventName//, passing //args// to each listener. This
|
||||
|
||||
@@ -19,8 +19,17 @@ And **EventType** can be any of the following.
|
||||
- **//[[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 +59,19 @@ The timestamp of this block.
|
||||
_property: block.nonce => string<[[DataHexString]]>
|
||||
The nonce used as part of the proof-of-work to mine this block.
|
||||
|
||||
This property is generally of little interest developers.
|
||||
This property is generally of little interest to developers.
|
||||
|
||||
_property: block.difficulty => number
|
||||
The difficulty target required to be met by the miner of the block.
|
||||
|
||||
This property is generally of little interest developers.
|
||||
This property is generally of little interest to developers.
|
||||
|
||||
_property: block.gasLimit => [[BigNumber]]
|
||||
The maximum amount of gas that this block was permitted to use. This
|
||||
is a value that can be voted up or voted down by miners and is used
|
||||
to automatically adjust the bandwidth requirements of the network.
|
||||
|
||||
This property is generally of little interest developers.
|
||||
This property is generally of little interest to developers.
|
||||
|
||||
_property: block.gasUsed => [[BigNumber]]
|
||||
The total amount of gas used by all transactions in this block.
|
||||
@@ -74,7 +83,7 @@ miner that mined this block would like the subsidy reward to go to.
|
||||
_property: block.extraData => string
|
||||
This is extra data a miner may choose to include when mining a block.
|
||||
|
||||
This property is generally of little interest developers.
|
||||
This property is generally of little interest to developers.
|
||||
|
||||
_heading: Block (with transaction hashes)
|
||||
|
||||
@@ -229,7 +238,7 @@ Wait for //confirmations//. If 0, and the transaction has not been mined,
|
||||
_heading: TransactionReceipt @<providers-TransactionReceipt>
|
||||
|
||||
_property: receipt.to => string<[[address]]>
|
||||
The address this transaction is to. This is ``null`` if the the
|
||||
The address this transaction is to. This is ``null`` if the
|
||||
transaction was an **init transaction**, used to deploy a contract.
|
||||
|
||||
_property: receipt.from => string<[[address]]>
|
||||
@@ -264,7 +273,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 +295,7 @@ including the actual block it was mined in.
|
||||
|
||||
_property: receipt.cumulativeGasUsed => [[BigNumber]]
|
||||
For the block this transaction was included in, this is the sum of the
|
||||
gas used used by each transaction in the ordered list of transactions
|
||||
gas used by each transaction in the ordered list of transactions
|
||||
up to (and including) this transaction.
|
||||
|
||||
This is generally of little interest to developers.
|
||||
|
||||
@@ -6,7 +6,7 @@ which can be used to sign messages and transactions and send
|
||||
signed transactions to the Ethereum Network to execute state
|
||||
changing operations.
|
||||
|
||||
The available operations depends largely on the sub-class used.
|
||||
The available operations depend largely on the sub-class used.
|
||||
|
||||
For example, a Signer from MetaMask can send transactions and sign
|
||||
messages but cannot sign a transaction (without broadcasting it).
|
||||
@@ -20,9 +20,9 @@ The most common Signers you will encounter are:
|
||||
|
||||
_subsection: Signer @<Signer> @SRC<abstract-signer:class.Signer>
|
||||
|
||||
The **Signer** class is abstract and cannot be directly instaniated.
|
||||
The **Signer** class is abstract and cannot be directly instantiated.
|
||||
|
||||
Instead use one of the concreate sub-classes, such as the [[Wallet]],
|
||||
Instead use one of the concrete sub-classes, such as the [[Wallet]],
|
||||
[[VoidSigner]] or [[JsonRpcSigner]].
|
||||
|
||||
_property: signer.connect(provider) => [[Signer]] @<Signer-connect>
|
||||
@@ -112,6 +112,63 @@ Sub-classes **must** implement this, however they may throw if sending a
|
||||
transaction is not supported, such as the [[VoidSigner]] or if the
|
||||
Wallet is offline and not connected to a [[Provider]].
|
||||
|
||||
_property: signer._signTypedData(domain, types, value) => Promise<string<[RawSignature](signature-raw)>> @<Signer-signTypedData>
|
||||
|
||||
Signs the typed data //value// with //types// data structure for //domain// using
|
||||
the [[link-eip-712]] specification.
|
||||
|
||||
_warning: Experimental feature (this method name will change)
|
||||
|
||||
This is still an experimental feature. If using it, please specify the **exact**
|
||||
version of ethers you are using (e.g. spcify ``"5.0.18"``, **not** ``"^5.0.18"``) as
|
||||
the method name will be renamed from ``_signTypedData`` to ``signTypedData`` once
|
||||
it has been used in the field a bit.
|
||||
|
||||
_code: Typed Data Example @lang<javascript>
|
||||
|
||||
// <hide>
|
||||
signer = new Wallet("0x1234567890123456789012345678901234567890123456789012345678901234");
|
||||
// </hide>
|
||||
|
||||
// All properties on a domain are optional
|
||||
const domain = {
|
||||
name: 'Ether Mail',
|
||||
version: '1',
|
||||
chainId: 1,
|
||||
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
|
||||
};
|
||||
|
||||
// The named list of all type definitions
|
||||
const types = {
|
||||
Person: [
|
||||
{ name: 'name', type: 'string' },
|
||||
{ name: 'wallet', type: 'address' }
|
||||
],
|
||||
Mail: [
|
||||
{ name: 'from', type: 'Person' },
|
||||
{ name: 'to', type: 'Person' },
|
||||
{ name: 'contents', type: 'string' }
|
||||
]
|
||||
};
|
||||
|
||||
// The data to sign
|
||||
const value = {
|
||||
from: {
|
||||
name: 'Cow',
|
||||
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
|
||||
},
|
||||
to: {
|
||||
name: 'Bob',
|
||||
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
|
||||
},
|
||||
contents: 'Hello, Bob!'
|
||||
};
|
||||
|
||||
|
||||
const signature = await signer._signTypedData(domain, types, value);
|
||||
//! async signature
|
||||
|
||||
|
||||
_heading: Sub-Classes @<Signer--subclassing>
|
||||
|
||||
It is very important that all important properties of a **Signer** are
|
||||
@@ -124,20 +181,20 @@ and libraries make this assumption.
|
||||
A sub-class **must** extend Signer and **must** call ``super()``.
|
||||
|
||||
_property: signer.checkTransaction(transactionRequest) => [[providers-TransactionRequest]] @<Signer-checkTransaction> @SRC<abstract-signer>
|
||||
This is generally not required to be overridden, but may needed to provide
|
||||
This is generally not required to be overridden, but may be needed to provide
|
||||
custom behaviour in sub-classes.
|
||||
|
||||
This should return a **copy** of the //transactionRequest//, with any properties
|
||||
needed by ``call``, ``estimateGas`` and ``populateTransaction`` (which is used
|
||||
by sendTransaction). It should also throw an error if any unknown key is specified.
|
||||
|
||||
The default implementation checks only valid [[providers-TransactionRequest]] properties
|
||||
The default implementation checks only if valid [[providers-TransactionRequest]] properties
|
||||
exist and adds ``from`` to the transaction if it does not exist.
|
||||
|
||||
If there is a ``from`` field it **must** be verified to be equal to the Signer's address.
|
||||
|
||||
_property: signer.populateTransaction(transactionRequest) => Promise<[[providers-TransactionRequest]]> @<Signer-populateTransaction> @SRC<abstract-signer>
|
||||
This is generally not required to be overridden, but may needed to provide
|
||||
This is generally not required to be overridden, but may be needed to provide
|
||||
custom behaviour in sub-classes.
|
||||
|
||||
This should return a **copy** of //transactionRequest//, follow the same procedure
|
||||
@@ -193,7 +250,7 @@ _property: wallet.address => string<[[address]]>
|
||||
The address for the account this Wallet represents.
|
||||
|
||||
_property: wallet.provider => [[Provider]]
|
||||
The provider this wallet is connected to, which will ge used for any [[Signer--blockchain-methods]]
|
||||
The provider this wallet is connected to, which will be used for any [[Signer--blockchain-methods]]
|
||||
methods. This can be null.
|
||||
|
||||
_note: Note
|
||||
@@ -352,5 +409,5 @@ The privateKey of this EOA
|
||||
_property: eoa.mnemonic => [[Mnemonic]]
|
||||
|
||||
//Optional//. The account HD mnemonic, if it has one and can be
|
||||
determined. Some sources do not encode the mnemonic, such as an
|
||||
determined. Some sources do not encode the mnemonic, such as
|
||||
HD extended keys.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -31,7 +31,7 @@ _property: ethers.utils.FragmentTypes.full => string
|
||||
|
||||
This is a full human-readable string, including all parameter names, any
|
||||
optional modifiers (e.g. ``indexed``, ``public``, etc) and white-space
|
||||
to aid in human readabiliy.
|
||||
to aid in human readability.
|
||||
|
||||
_property: ethers.utils.FragmentTypes.minimal => string
|
||||
|
||||
@@ -81,7 +81,7 @@ will be one of:
|
||||
|
||||
_property: fragment.inputs => Array<[[ParamType]]>
|
||||
|
||||
This is an array of of each [[ParamType]] for the input parameters to
|
||||
This is an array of each [[ParamType]] for the input parameters to
|
||||
the Constructor, Event of Function.
|
||||
|
||||
_heading: Methods
|
||||
@@ -211,13 +211,13 @@ to parameters which are part of an [[EventFragment]].
|
||||
|
||||
_property: paramType.arrayChildren => [[ParamType]] @<ParamType-arrayChildren>
|
||||
|
||||
The type of children of the array. This is null for for any parameter
|
||||
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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,7 +4,7 @@ Many operations in Ethereum operation on numbers which are
|
||||
[outside the range of safe values](BigNumber--notes-safenumbers) to use
|
||||
in JavaScript.
|
||||
|
||||
A **BigNumber** is an object which safely allows mathematic operations
|
||||
A **BigNumber** is an object which safely allows mathematical operations
|
||||
on numbers of any magnitude.
|
||||
|
||||
Most operations which need to return a value will return a **BigNumber**
|
||||
@@ -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
|
||||
@@ -122,18 +122,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 +175,7 @@ Returns the value of //BigNumber// as a base-16, ``0x``-prefixed [[DataHexString
|
||||
|
||||
_heading: Inspection
|
||||
|
||||
_property: ethers.BigNumnber.isBigNumber(object) => boolean @SRC<bignumber>
|
||||
_property: ethers.BigNumber.isBigNumber(object) => boolean @SRC<bignumber>
|
||||
Returns true if and only if the //object// is a BigNumber object.
|
||||
|
||||
|
||||
@@ -232,7 +232,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 +246,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 +270,7 @@ various purposes.
|
||||
|
||||
_heading: Allow us to set a global Big Number library?
|
||||
|
||||
Another comment that comes up frequently is tha desire to specify a
|
||||
Another comment that comes up frequently is the desire to specify a
|
||||
global user-defined Big Number library, which all functions would
|
||||
return.
|
||||
|
||||
|
||||
@@ -25,7 +25,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 +37,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>
|
||||
@@ -112,7 +112,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 +155,7 @@ Any missing properties will be computed.
|
||||
|
||||
_subsection: Random Bytes
|
||||
|
||||
_property: ethers.utils.randomBytes(length) => Uint8Array @<utils-randomBytes> @SRC<random/index>
|
||||
_property: ethers.utils.randomBytes(length) => Uint8Array @<utils-randomBytes> @SRC<random/random>
|
||||
Return a new Uint8Array of //length// random bytes.
|
||||
|
||||
_property: ethers.utils.shuffled(array) => Array<any> @<utils-shuffled> @SRC<random>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
_section: Display Logic and Input
|
||||
_section: Display Logic and Input @<display-logic>
|
||||
|
||||
When creating an Application, it is useful to convert between
|
||||
user-friendly strings (usually displaying **ether**) and the
|
||||
@@ -17,11 +17,11 @@ The [formatUnits](unit-conversion) will format a [BigNumberish](BigNumberish)
|
||||
into a string, which is useful when displaying a balance.
|
||||
|
||||
|
||||
_subsection: Units
|
||||
_subsection: Units @<display-logic--units>
|
||||
|
||||
_heading: Decimal Count
|
||||
|
||||
A **Unit** can be specified as an number, which indicates the
|
||||
A **Unit** can be specified as a number, which indicates the
|
||||
number of decimal places that should be used.
|
||||
|
||||
**Examples:**
|
||||
@@ -29,7 +29,7 @@ number of decimal places that should be used.
|
||||
- 1 ether in wei, has **18** decimal places (i.e. 1 ether represents 10^^18^^ wei)
|
||||
- 1 bitcoin in Satoshi, has **8** decimal places (i.e. 1 bitcoin represents 10^^8^^ satoshi)
|
||||
|
||||
_heading: Named Units
|
||||
_heading: Named Units @<display-logic--named-units>
|
||||
|
||||
There are also several common **Named Units**, in which case their name (as
|
||||
a string) may be used.
|
||||
@@ -46,9 +46,9 @@ _table: @STYLE<compact>
|
||||
| //ether// | 18 |
|
||||
|
||||
|
||||
_subsection: Functions
|
||||
_subsection: Functions @<display-logic--functions>
|
||||
|
||||
_heading: Formatting
|
||||
_heading: Formatting @<display-logic--formatting>
|
||||
|
||||
_property: ethers.utils.commify(value) => string @<utils-commify> @SRC<units>
|
||||
Returns a string with value grouped by 3 digits, separated by ``,``.
|
||||
|
||||
@@ -28,7 +28,7 @@ structures of Arrays and data.
|
||||
_property: ethers.utils.RLP.encode(dataObject) => string<[[DataHexString]]> @<utils-rlpEncode> @SRC<rlp>
|
||||
Encode a structured Data Object into its RLP-encoded representation.
|
||||
|
||||
Each Data component may be an valid [[BytesLike]].
|
||||
Each Data component may be a valid [[BytesLike]].
|
||||
|
||||
_property: ethers.utils.RLP.decode(aBytesLike) => [DataObject](rlp--dataobject) @<utils.rlpDecode> @SRC<rlp>
|
||||
Decode an RLP-encoded //aBytesLike// into its structured Data Object.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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//.
|
||||
@@ -66,7 +68,7 @@ utils.keccak256("0x1234")
|
||||
utils.keccak256([ 0x12, 0x34 ])
|
||||
//!
|
||||
|
||||
const bytes = utils.toUtf8Bytes("0x1234");
|
||||
const bytes = utils.toUtf8Bytes("0x1234")
|
||||
// <hide>
|
||||
bytes
|
||||
// </hide>
|
||||
@@ -119,8 +121,8 @@ Use the [SHA2-512](link-wiki-sha2) hash algorithm.
|
||||
|
||||
_code: HMAC @lang<javascript>
|
||||
|
||||
const key = "0x0102";
|
||||
const data = "0x1234";
|
||||
const key = "0x0102"
|
||||
const data = "0x1234"
|
||||
utils.computeHmac("sha256", key, data)
|
||||
//!
|
||||
|
||||
@@ -132,13 +134,39 @@ Computes the [[link-eip-191]] personal message digest of //message//. Personal m
|
||||
converted to UTF-8 bytes and prefixed with ``\\x19Ethereum Signed Message:``
|
||||
and the length of //message//.
|
||||
|
||||
_property: ethers.utils.namehash(name) => string<[[DataHexString]]<32>> @<utils-namehash> @SRC<hash>
|
||||
Returns the [ENS Namehash](link-namehash) of //name//.
|
||||
|
||||
_code: Hashing Messages @lang<javascript>
|
||||
|
||||
// @TODO: include examples of hashMessage; it can be complex. :)
|
||||
// Hashing a string message
|
||||
utils.hashMessage("Hello World")
|
||||
//!
|
||||
|
||||
// Hashing binary data (also "Hello World", but as bytes)
|
||||
utils.hashMessage( [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 ])
|
||||
//!
|
||||
|
||||
// NOTE: It is important to understand how strings and binary
|
||||
// data is handled differently. A string is ALWAYS processed
|
||||
// as the bytes of the string, so a hexstring MUST be
|
||||
// converted to an ArrayLike object first.
|
||||
|
||||
// Hashing a hex string is the same as hashing a STRING
|
||||
// Note: this is the hash of the 4 characters [ '0', 'x', '4', '2' ]
|
||||
utils.hashMessage("0x42")
|
||||
//!
|
||||
|
||||
// Hashing the binary data
|
||||
// Note: this is the hash of the 1 byte [ 0x42 ]
|
||||
utils.hashMessage([ 0x42 ])
|
||||
//!
|
||||
|
||||
// Hashing the binary data
|
||||
// Note: similarly, this is the hash of the 1 byte [ 0x42 ]
|
||||
utils.hashMessage(utils.arrayify("0x42"))
|
||||
//!
|
||||
|
||||
|
||||
_property: ethers.utils.namehash(name) => string<[[DataHexString]]<32>> @<utils-namehash> @SRC<hash>
|
||||
Returns the [ENS Namehash](link-namehash) of //name//.
|
||||
|
||||
_code: Namehash @lang<javascript>
|
||||
|
||||
@@ -154,6 +182,121 @@ utils.namehash("ricmoo.firefly.eth")
|
||||
utils.namehash("ricmoo.xyz")
|
||||
//!
|
||||
|
||||
_heading: Typed Data Encoder @<TypedDataEncoder> @SRC<hash:class.TypedDataEncoder>
|
||||
|
||||
The **TypedDataEncoder** is used to compute the various encoded data required
|
||||
for [[link-eip-712]] signed data.
|
||||
|
||||
Signed data requires a domain, list of structures and their members and the data
|
||||
itself.
|
||||
|
||||
The **domain** is an object with values for any of the standard domain
|
||||
properties.
|
||||
|
||||
The **types** is an object with each property being the name of a structure, mapping
|
||||
to an array of field descriptions. It should **not** include the ``EIP712Domain``
|
||||
property unless it is required as a child structure of another.
|
||||
|
||||
_note: Experimental Feature (this exported class name will change)
|
||||
This is still an experimental feature. If using it, please specify the **exact**
|
||||
version of ethers you are using (e.g. spcify ``"5.0.18"``, **not** ``"^5.0.18"``) as
|
||||
the exported class name will be renamed from ``_TypedDataEncoder`` to ``TypedDataEncoder`` once
|
||||
it has been used in the field a bit.
|
||||
|
||||
_property: ethers.utils._TypedDataEncoder.from(types) => [TypedDataEncoder] @<TypedDataEncoder-from> @SRC<hash:TypedDataEncoder.from>
|
||||
|
||||
Creates a new **TypedDataEncoder** for //types//. This object is a fairly
|
||||
low-level object that most developers should not require using instances
|
||||
directly.
|
||||
|
||||
Most developers will find the static class methods below the most useful.
|
||||
|
||||
_property: TypedDataEncoder.encode(domain, types, values) => string @<TypedDataEncoder-encode> @SRC<hash:staticmethod.TypedDataEncoder.encode>
|
||||
|
||||
Encodes the Returns the hashed [[link-eip-712]] domain.
|
||||
|
||||
_property: TypedDataEncoder.getPayload(domain, types, value) => any @<TypedDataEncoder-getPayload> @SRC<hash:TypedDataEncoder.getPayload>
|
||||
|
||||
Returns the standard payload used by various JSON-RPC ``eth_signTypedData*``
|
||||
calls.
|
||||
|
||||
All domain values and entries in value are normalized and the types are
|
||||
verified.
|
||||
|
||||
_property: TypedDataEncoder.getPrimaryType(types) => string @<TypedDataEncoder-getPrimaryType> @SRC<hash:TypedDataEncoder.getPrimaryType>
|
||||
|
||||
Constructs a directed acyclic graph of the types and returns the
|
||||
root type, which can be used as the **primaryType** for [[link-eip-712]]
|
||||
payloads.
|
||||
|
||||
_property: TypedDataEncoder.hash(domain, types, values) => string<[[DataHexString]]<32>> @<TypedDataEncoder-hash> @SRC<hash:staticmethod.TypedDataEncoder.hash>
|
||||
|
||||
Returns the computed [[link-eip-712]] hash.
|
||||
|
||||
_property: TypedDataEncoder.hashDomain(domain) => string<[[DataHexString]]<32>> @<TypedDataEncoder-hashDomain> @SRC<hash:TypedDataEncoder.hashDomain>
|
||||
|
||||
Returns the hashed [[link-eip-712]] domain.
|
||||
|
||||
_property: TypedDataEncoder.resolveNames(domain, types, value, resolveName) => Promise<any> @<TypedDataEncoder-resolveNames> @SRC<hash:TypedDataEncoder.resolveNames>
|
||||
|
||||
Returns a copy of value, where any leaf value with a type of ``address`` will have
|
||||
been recursively replacedwith the value of calling //resolveName// with that value.
|
||||
|
||||
_code: Typed Data Example @lang<javascript>
|
||||
|
||||
// <hide>
|
||||
TypedDataEncoder = ethers.utils._TypedDataEncoder
|
||||
// </hide>
|
||||
|
||||
const domain = {
|
||||
name: 'Ether Mail',
|
||||
version: '1',
|
||||
chainId: 1,
|
||||
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
|
||||
}
|
||||
|
||||
// The named list of all type definitions
|
||||
const types = {
|
||||
Person: [
|
||||
{ name: 'name', type: 'string' },
|
||||
{ name: 'wallet', type: 'address' }
|
||||
],
|
||||
Mail: [
|
||||
{ name: 'from', type: 'Person' },
|
||||
{ name: 'to', type: 'Person' },
|
||||
{ name: 'contents', type: 'string' }
|
||||
]
|
||||
}
|
||||
|
||||
// The data to sign
|
||||
const value = {
|
||||
from: {
|
||||
name: 'Cow',
|
||||
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
|
||||
},
|
||||
to: {
|
||||
name: 'Bob',
|
||||
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
|
||||
},
|
||||
contents: 'Hello, Bob!'
|
||||
}
|
||||
|
||||
|
||||
TypedDataEncoder.encode(domain, types, value)
|
||||
//!
|
||||
|
||||
TypedDataEncoder.getPayload(domain, types, value)
|
||||
//!
|
||||
|
||||
TypedDataEncoder.getPrimaryType(types)
|
||||
//!
|
||||
|
||||
TypedDataEncoder.hash(domain, types, value)
|
||||
//!
|
||||
|
||||
TypedDataEncoder.hashDomain(domain)
|
||||
//!
|
||||
|
||||
|
||||
_subsection: Solidity Hashing Algorithms @<utils--solidity-hashing>
|
||||
|
||||
@@ -163,7 +306,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
|
||||
@@ -187,3 +330,20 @@ utils.solidityKeccak256([ "int16", "uint48" ], [ -1, 12 ])
|
||||
utils.soliditySha256([ "int16", "uint48" ], [ -1, 12 ])
|
||||
//!
|
||||
|
||||
// As a short example of the non-distinguished nature of
|
||||
// Solidity tight-packing (which is why it is inappropriate
|
||||
// for many things from a security point of view), consider
|
||||
// the following examples are all equal, despite representing
|
||||
// very different values and layouts.
|
||||
|
||||
utils.solidityPack([ "string", "string" ], [ "hello", "world01" ])
|
||||
//!
|
||||
|
||||
utils.solidityPack([ "string", "string" ], [ "helloworld", "01" ])
|
||||
//!
|
||||
|
||||
utils.solidityPack([ "string", "string", "uint16" ], [ "hell", "oworld", 0x3031 ])
|
||||
//!
|
||||
|
||||
utils.solidityPack([ "uint96" ], [ "32309054545061485574011236401" ])
|
||||
//!
|
||||
|
||||
@@ -101,7 +101,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.
|
||||
|
||||
@@ -56,11 +56,11 @@ _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
|
||||
Checks that //target// is not //kind// and performs the same operations
|
||||
as ``checkNew``. This is useful for ensuring abstract classes are not
|
||||
being instantiated.
|
||||
|
||||
_property: logger.checkArgumentCount(count, expectedCound [ , message) => void @SRC<logger>
|
||||
_property: logger.checkArgumentCount(count, expectedCount [ , message) => void @SRC<logger>
|
||||
If //count// is not equal to //expectedCount//, throws a [MISSING_ARGUMENT](errors-MissingArgument)
|
||||
or [UNEXPECTED_ARGUMENT](errors-UnexpectedArgument) error.
|
||||
|
||||
@@ -196,7 +196,7 @@ _property: Logger.levels.DEBUG
|
||||
Log all output, including debugging information.
|
||||
|
||||
_property: Logger.levels.INFO
|
||||
Only log output for infomational, warnings and errors.
|
||||
Only log output for informational, warnings and errors.
|
||||
|
||||
_property: Logger.levels.WARNING
|
||||
Only log output for warnings and errors.
|
||||
|
||||
@@ -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//
|
||||
|
||||
@@ -40,7 +40,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 +88,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).
|
||||
|
||||
|
||||
|
||||
@@ -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]]
|
||||
@@ -98,7 +98,7 @@ used to encode the chain ID into the serialized transaction.
|
||||
_subsection: Functions @<transactions--functions>
|
||||
|
||||
_property: ethers.utils.parseTransaction(aBytesLike) => [[Transaction]] @<utils-parseTransaction> @SRC<transactions:parse>
|
||||
Parses the transaction properties from a serialized transactions.
|
||||
Parses the transaction properties from a serialized transaction.
|
||||
|
||||
_property: ethers.utils.serializeTransaction(tx [ , signature ]) => string<[[DataHexString]]> @<utils-serializeTransaction> @SRC<transactions:serialize>
|
||||
Computes the serialized //transaction//, optionally serialized with
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -21,7 +21,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.
|
||||
|
||||
|
||||
@@ -127,7 +127,14 @@ function codeContextify(context) {
|
||||
context.hexlify = ethers.utils.hexlify;
|
||||
context.hexValue = ethers.utils.hexValue;
|
||||
context.Wallet = ethers.Wallet;
|
||||
context.provider = new ethers.providers.InfuraProvider();
|
||||
context.provider = new ethers.providers.InfuraProvider("mainnet", "49a0efa3aaee4fd99797bfa94d8ce2f1");
|
||||
|
||||
// We use a local dev node for some signing examples, but want to
|
||||
// resolve ENS names against mainnet; super hacky but makes the
|
||||
// docs nicer
|
||||
context.localProvider = new ethers.providers.JsonRpcProvider();
|
||||
context.localSigner = context.localProvider.getSigner();
|
||||
context.localProvider.resolveName = context.provider.resolveName.bind(context.provider);
|
||||
|
||||
context.BigNumber.prototype[inspect.custom] = function(depth, options) {
|
||||
return `{ BigNumber: ${JSON.stringify(this.toString()) } }`;
|
||||
@@ -142,6 +149,7 @@ function codeContextify(context) {
|
||||
//return JSON.stringify(value);
|
||||
return inspect(value, {
|
||||
compact: false,
|
||||
depth: null,
|
||||
breakLength: Infinity,
|
||||
sorted: true,
|
||||
});
|
||||
@@ -175,23 +183,28 @@ module.exports = {
|
||||
"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-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",
|
||||
@@ -233,6 +246,7 @@ module.exports = {
|
||||
"link-eip-155": { name: "EIP-155", url: "https:/\/eips.ethereum.org/EIPS/eip-155" },
|
||||
"link-eip-191": { name: "EIP-191", url: "https:/\/eips.ethereum.org/EIPS/eip-191" },
|
||||
"link-eip-609": { name: "EIP-609", url: "https:/\/eips.ethereum.org/EIPS/eip-609" },
|
||||
"link-eip-712": { name: "EIP-712", url: "https:/\/eips.ethereum.org/EIPS/eip-712" },
|
||||
"link-eip-1014": { name: "EIP-1014", url: "https:/\/eips.ethereum.org/EIPS/eip-1014" },
|
||||
"link-eip-1193": { name: "EIP-1193", url: "https:/\/eips.ethereum.org/EIPS/eip-1193" },
|
||||
"link-eip-2098": { name: "EIP-2098", url: "https:/\/eips.ethereum.org/EIPS/eip-2098" },
|
||||
@@ -240,9 +254,11 @@ module.exports = {
|
||||
"link-bip-32": { name: "BIP-32", url: "https:/\/github.com/bitcoin/bips/blob/master/bip-0032.mediawiki" },
|
||||
|
||||
"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",
|
||||
|
||||
@@ -21,7 +21,7 @@ So, pull requests are always welcome, but please keep a few points in mind:
|
||||
may not be accepted
|
||||
|
||||
In general, **please start an issue //before// beginning a pull request**, so we can
|
||||
have a public discussion and figure out the best way to address to problem/feature.
|
||||
have a public discussion and figure out the best way to address the problem/feature.
|
||||
**:)**
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ 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
|
||||
to that section; flatworm will support symlinks in the future
|
||||
- In general, I aim for xonsistency; look to similar situations throughout the documentation
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
60
docs.wrm/cookbook/react-native.wrm
Normal file
60
docs.wrm/cookbook/react-native.wrm
Normal 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";
|
||||
@@ -280,7 +280,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 +379,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.
|
||||
|
||||
|
||||
@@ -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,7 +32,7 @@ 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.
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ _code: ES6 in the Browser @lang<html>
|
||||
_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>
|
||||
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,14 +90,34 @@ 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 thing (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>
|
||||
@@ -106,16 +126,16 @@ _code: Basic Queries @lang<javascript>
|
||||
provider.getBlockNumber()
|
||||
//!
|
||||
|
||||
// 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)
|
||||
balance = await provider.getBalance("ethers.eth")
|
||||
//! async balance
|
||||
|
||||
// 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)
|
||||
ethers.utils.formatEther(balance)
|
||||
//!
|
||||
|
||||
// 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)
|
||||
ethers.utils.parseEther("1.0")
|
||||
//!
|
||||
@@ -138,37 +158,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)
|
||||
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)",
|
||||
|
||||
@@ -206,7 +225,7 @@ const daiContract = new ethers.Contract("dai.tokens.ethers.eth", daiAbi, provide
|
||||
daiContract.name()
|
||||
//!
|
||||
|
||||
// Get the ERC-20 token synbol (for tickers and UIs)
|
||||
// Get the ERC-20 token symbol (for tickers and UIs)
|
||||
daiContract.symbol()
|
||||
//!
|
||||
|
||||
@@ -224,8 +243,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
|
||||
@@ -315,7 +334,7 @@ daiContract.queryFilter(filterFrom, 9843470, 9843480)
|
||||
// number of entries; but they provide some useful examples
|
||||
//
|
||||
|
||||
// List all transfers I sent in the last 10,000 blocks
|
||||
// List all transfers sent in the last 10,000 blocks
|
||||
daiContract.queryFilter(filterFrom, -10000)
|
||||
|
||||
// List all transfers ever sent to me
|
||||
@@ -331,8 +350,8 @@ const signer = ethers.Wallet.createRandom();
|
||||
//!
|
||||
// </hide>
|
||||
|
||||
// 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
|
||||
@@ -343,7 +362,7 @@ 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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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``//
|
||||
|
||||
8
docs/api-keys/_index.html
Normal file
8
docs/api-keys/_index.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>API Keys - ethers</title>
|
||||
</head>
|
||||
<body>
|
||||
Redirect to /v5/api-keys.
|
||||
</body>
|
||||
</html>
|
||||
@@ -21,6 +21,7 @@ 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)
|
||||
@@ -32,30 +33,15 @@ Developer Documentation
|
||||
* [Gas Limit](concepts/gas)
|
||||
* [Security](concepts/security)
|
||||
* [Key Derivation Functions](concepts/security)
|
||||
* [Best Practices](concepts/best-practices)
|
||||
* [Network Changes](concepts/best-practices)
|
||||
* [Provider API Keys](api-keys)
|
||||
* [Etherscan](api-keys)
|
||||
* [INFURA](api-keys)
|
||||
* [Alchemy](api-keys)
|
||||
* [Pocket Gateway](api-keys)
|
||||
* [Creating a Default Provider](api-keys)
|
||||
* [Application Programming Interface](api)
|
||||
* [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)
|
||||
@@ -83,10 +69,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 +196,7 @@ Developer Documentation
|
||||
* [Data Segment](api/other/assembly/dialect)
|
||||
* [Links](api/other/assembly/dialect)
|
||||
* [Stack Placeholders](api/other/assembly/dialect)
|
||||
* [Evaluation and Excution](api/other/assembly/dialect)
|
||||
* [Evaluation and Execution](api/other/assembly/dialect)
|
||||
* [Utilities](api/other/assembly/api)
|
||||
* [Assembler](api/other/assembly/api)
|
||||
* [Disassembler](api/other/assembly/api)
|
||||
@@ -220,10 +230,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,9 +245,12 @@ 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)
|
||||
|
||||
49
docs/v5/api-keys/README.md
Normal file
49
docs/v5/api-keys/README.md
Normal 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:
|
||||
// }
|
||||
});
|
||||
```
|
||||
|
||||
112
docs/v5/api-keys/index.html
Normal file
112
docs/v5/api-keys/index.html
Normal file
File diff suppressed because one or more lines are too long
@@ -7,29 +7,6 @@ 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)
|
||||
@@ -57,10 +34,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 +161,7 @@ Application Programming Interface
|
||||
* [Data Segment](other/assembly/dialect)
|
||||
* [Links](other/assembly/dialect)
|
||||
* [Stack Placeholders](other/assembly/dialect)
|
||||
* [Evaluation and Excution](other/assembly/dialect)
|
||||
* [Evaluation and Execution](other/assembly/dialect)
|
||||
* [Utilities](other/assembly/api)
|
||||
* [Assembler](other/assembly/api)
|
||||
* [Disassembler](other/assembly/api)
|
||||
|
||||
@@ -10,7 +10,7 @@ ContractFactory
|
||||
Creating Instances
|
||||
------------------
|
||||
|
||||
#### **new ***ethers* . **ContractFactory**( interface , bydecode [ , signer ] )
|
||||
#### **new ***ethers* . **ContractFactory**( interface , bytecode [ , signer ] )
|
||||
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ Methods
|
||||
|
||||
#### *contractFactory* . **attach**( address ) => *[Contract](/v5/api/contract/contract/)*
|
||||
|
||||
Return an instance of a [Contract](/v5/api/contract/contract/) attched to *address*. This is the same as using the [Contract constructor](/v5/api/contract/contract/#Contract--creating) with *address* and this the the *interface* and *signerOrProvider* passed in when creating the ContractFactory.
|
||||
Return an instance of a [Contract](/v5/api/contract/contract/) attached to *address*. This is the same as using the [Contract constructor](/v5/api/contract/contract/#Contract--creating) with *address* and this the *interface* and *signerOrProvider* passed in when creating the ContractFactory.
|
||||
|
||||
|
||||
#### *contractFactory* . **getDeployTransaction**( ...args ) => *[UnsignedTransaction](/v5/api/utils/transactions/#UnsignedTransaction)*
|
||||
@@ -52,7 +52,7 @@ Returns the unsigned transaction which would deploy this Contract with *args* pa
|
||||
|
||||
#### *contractFactory* . **deploy**( ...args ) => *Promise< [Contract](/v5/api/contract/contract/) >*
|
||||
|
||||
Uses the signer to deploy the Contract with *args* passed into the constructor and retruns a Contract which is attached to the address where this contract **will** be deployed once the transaction is mined.
|
||||
Uses the signer to deploy the Contract with *args* passed into the constructor and returns a Contract which is attached to the address where this contract **will** be deployed once the transaction is mined.
|
||||
|
||||
The transaction can be found at `contract.deployTransaction`, and no interactions should be made until the transaction is mined.
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -199,7 +199,7 @@ When you perform a static call, the current state is taken into account as best
|
||||
Meta-Class Filters
|
||||
------------------
|
||||
|
||||
#### *erc20* . *filters* . **Transafer**( [ fromAddress [ , toAddress ] ] ) => *Filter*
|
||||
#### *erc20* . *filters* . **Transfer**( [ fromAddress [ , toAddress ] ] ) => *Filter*
|
||||
|
||||
Returns a new Filter which can be used to [query](/v5/api/contract/example/#erc20-queryfilter) or to [subscribe/unsubscribe to events](/v5/api/contract/example/#erc20-events).
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -17,7 +17,7 @@ Generates a brain wallet, with a slightly improved experience, in which the gene
|
||||
|
||||
#### *BrainWallet* . **generateLegacy**( username , password [ , progressCallback ] ) => *[BrainWallet](/v5/api/experimental/#experimental-brainwallet)*
|
||||
|
||||
Generate a brain wallet which is compatibile with the ethers v3 and earlier.
|
||||
Generate a brain wallet which is compatible with the ethers v3 and earlier.
|
||||
|
||||
|
||||
EIP1193Bridge
|
||||
@@ -45,13 +45,13 @@ The provider associated with the signer.
|
||||
|
||||
Set the current transaction count (nonce) for the signer.
|
||||
|
||||
This may be useful it interacting with the signer outside of using this class.
|
||||
This may be useful in interacting with the signer outside of using this class.
|
||||
|
||||
|
||||
#### *nonceManager* . **increaseTransactionCount**( [ count = 1 ] ) => *void*
|
||||
|
||||
Bump the current transaction count (nonce) by *count*.
|
||||
|
||||
This may be useful it interacting with the signer outside of using this class.
|
||||
This may be useful in interacting with the signer outside of using this class.
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -17,7 +17,7 @@ Other Libraries
|
||||
* [Data Segment](assembly/dialect)
|
||||
* [Links](assembly/dialect)
|
||||
* [Stack Placeholders](assembly/dialect)
|
||||
* [Evaluation and Excution](assembly/dialect)
|
||||
* [Evaluation and Execution](assembly/dialect)
|
||||
* [Utilities](assembly/api)
|
||||
* [Assembler](assembly/api)
|
||||
* [Disassembler](assembly/api)
|
||||
|
||||
@@ -16,7 +16,7 @@ Assembly
|
||||
* [Data Segment](dialect)
|
||||
* [Links](dialect)
|
||||
* [Stack Placeholders](dialect)
|
||||
* [Evaluation and Excution](dialect)
|
||||
* [Evaluation and Execution](dialect)
|
||||
* [Utilities](api)
|
||||
* [Assembler](api)
|
||||
* [Disassembler](api)
|
||||
|
||||
@@ -62,7 +62,7 @@ Opcode
|
||||
|
||||
#### *asm* . *Opcode* . **from**( valueOrMnemonic ) => *[Opcode](/v5/api/other/assembly/api/#asm-opcode)*
|
||||
|
||||
Create a new instnace of an Opcode for a given numeric value (e.g. 0x60 is PUSH1) or mnemonic string (e.g. "PUSH1").
|
||||
Create a new instance of an Opcode for a given numeric value (e.g. 0x60 is PUSH1) or mnemonic string (e.g. "PUSH1").
|
||||
|
||||
|
||||
### Properties
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@ The literal value of this node, which may be a [DataHexString](/v5/api/utils/byt
|
||||
|
||||
#### *literalNode* . **verbatim** => *boolean*
|
||||
|
||||
This is true in a [DataNode](/v5/api/other/assembly/ast/#asm-datanode) context, since in that case the value should be taken verbatim and no `PUSH` operation shoud be added, otherwise false.
|
||||
This is true in a [DataNode](/v5/api/other/assembly/ast/#asm-datanode) context, since in that case the value should be taken verbatim and no `PUSH` operation should be added, otherwise false.
|
||||
|
||||
|
||||
### PopNode
|
||||
@@ -67,7 +67,7 @@ The index this **PopNode** is representing. For an implicit place-holder this is
|
||||
|
||||
#### *linkNode* . **label** => *string*
|
||||
|
||||
Te name of the target node.
|
||||
The name of the target node.
|
||||
|
||||
|
||||
#### *linkNode* . **type** => *"offset" | "length"*
|
||||
@@ -91,7 +91,7 @@ A list of all operands passed into this Node.
|
||||
|
||||
#### *literalNode* . **verbatim** => *boolean*
|
||||
|
||||
This is true in a [DataNode](/v5/api/other/assembly/ast/#asm-datanode) context, since in that case the value should be taken verbatim and no `PUSH` operation shoud be added, otherwise false.
|
||||
This is true in a [DataNode](/v5/api/other/assembly/ast/#asm-datanode) context, since in that case the value should be taken verbatim and no `PUSH` operation should be added, otherwise false.
|
||||
|
||||
|
||||
#### *evaluationNode* . **script** => *string*
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -31,6 +31,6 @@ Links
|
||||
Stack Placeholders
|
||||
------------------
|
||||
|
||||
Evaluation and Excution
|
||||
-----------------------
|
||||
Evaluation and Execution
|
||||
------------------------
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -12,7 +12,9 @@ Default Provider
|
||||
|
||||
#### *ethers* . **getDefaultProvider**( [ network , [ options ] ] ) => *[Provider](/v5/api/providers/provider/)*
|
||||
|
||||
Returns a new Provider, backed by multiple services, connected to *network*. Is no *network* is provided, **homestead** (i.e. mainnet) is used.
|
||||
Returns a new Provider, backed by multiple services, connected to *network*. If no *network* is provided, **homestead** (i.e. mainnet) is used.
|
||||
|
||||
The *network* may also be a URL to connect to, such as `http://localhost:8545` or `wss://example.com`.
|
||||
|
||||
The *options* is an object, with the following properties:
|
||||
|
||||
@@ -23,7 +25,7 @@ Option Properties
|
||||
|
||||
#### Note: API Keys
|
||||
|
||||
It is highly recommended for production services that to acquire and specify an API Key for each sercice.
|
||||
It is highly recommended for production services to acquire and specify an API Key for each service.
|
||||
|
||||
The default API Keys used by ethers are shared across all users, so services may throttle all services that are using the default API Keys during periods of load without realizing it.
|
||||
|
||||
@@ -32,6 +34,19 @@ Many services also have monitoring and usage metrics, which are only available i
|
||||
Some services also provide additional paid features, which are only available when specifying an API Key.
|
||||
|
||||
|
||||
Networks
|
||||
--------
|
||||
|
||||
### Custom ENS Contract
|
||||
|
||||
```
|
||||
const network = {
|
||||
name: "dev",
|
||||
chianId: 1337,
|
||||
ensAddress: customEnsAddress
|
||||
};
|
||||
```
|
||||
|
||||
Provider Documentation
|
||||
----------------------
|
||||
|
||||
@@ -61,6 +76,7 @@ Provider Documentation
|
||||
* [WebSocketProvider](other)
|
||||
* [Types](types)
|
||||
* [BlockTag](types)
|
||||
* [Networkish](types)
|
||||
* [Network](types)
|
||||
* [Block](types)
|
||||
* [Events and Logs](types)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user