forked from tornado-packages/ethers.js
Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7250cdcd31 | ||
|
|
20f34f1ba9 | ||
|
|
4ac08432b8 | ||
|
|
3e3048df81 | ||
|
|
c6199bf52a | ||
|
|
20409c083c | ||
|
|
7a90f18145 | ||
|
|
df1ae611ba | ||
|
|
6009a26c89 | ||
|
|
30984b6f00 | ||
|
|
76a8e503dd | ||
|
|
d0e0e30532 | ||
|
|
b3f5266e78 | ||
|
|
0609ea9651 | ||
|
|
5af16a6090 | ||
|
|
4f88c5ba6e | ||
|
|
023e946072 | ||
|
|
004cb826d2 | ||
|
|
bfcf224b2b | ||
|
|
c969fe5a68 | ||
|
|
8737f12e1b | ||
|
|
1267eeef4a | ||
|
|
11c250ff7c | ||
|
|
c303199d26 | ||
|
|
ae458a1a49 | ||
|
|
760a5aec74 | ||
|
|
2967efc2b0 | ||
|
|
24f243e689 | ||
|
|
d719064628 | ||
|
|
a7d0b41d98 | ||
|
|
a980fc3db0 | ||
|
|
a34ca6b3a3 | ||
|
|
ef91dcd757 | ||
|
|
a5296a9258 | ||
|
|
f827ae68e2 | ||
|
|
fbf15c0ffe | ||
|
|
10fdbe7274 | ||
|
|
384fc328f2 | ||
|
|
055694ae61 | ||
|
|
edf59d2c26 | ||
|
|
92c978e5c2 | ||
|
|
34397fa2aa | ||
|
|
19587eea3f | ||
|
|
4a9373e773 | ||
|
|
2997bae935 | ||
|
|
b0bd9ee162 | ||
|
|
7075c8c235 | ||
|
|
a4a532fe8e | ||
|
|
77c771bf76 | ||
|
|
c93b48920e | ||
|
|
04c92bb8d5 | ||
|
|
16c9745326 | ||
|
|
05648177aa | ||
|
|
f318fd9cf1 | ||
|
|
c15a89832b | ||
|
|
94b0abc240 | ||
|
|
72edcd054f | ||
|
|
e4a2f8ac6c | ||
|
|
c6d7b31a84 | ||
|
|
0ed983a264 | ||
|
|
8fab48a380 | ||
|
|
86e815999d | ||
|
|
a2306f7870 | ||
|
|
60b75c10d7 | ||
|
|
41c2c8a729 | ||
|
|
9785eed8dd | ||
|
|
527de7ba5e | ||
|
|
14484e566e | ||
|
|
429af2c40d | ||
|
|
11fffd1690 | ||
|
|
af3aed4580 | ||
|
|
3a3764bdb4 | ||
|
|
18ee2c518c | ||
|
|
36172f7f7b | ||
|
|
908258f8d4 | ||
|
|
774b2d5fee | ||
|
|
b5f720ace6 | ||
|
|
9f201c386e | ||
|
|
700dd34137 | ||
|
|
f2dd977de4 | ||
|
|
5f013216c5 | ||
|
|
eac0805435 | ||
|
|
e5bee7e5a3 | ||
|
|
442553620a | ||
|
|
6d08968b87 | ||
|
|
c2ce59f95e | ||
|
|
f3ec27b95f | ||
|
|
c88cb5ea90 | ||
|
|
99a21660ab | ||
|
|
4bc62a1e8a | ||
|
|
26eb6cc01a | ||
|
|
bcba17a9e7 | ||
|
|
918b66bc2e | ||
|
|
152d672278 | ||
|
|
51fb472809 | ||
|
|
66440b8542 | ||
|
|
fefdd51084 | ||
|
|
6ca1d77298 | ||
|
|
4f6748ec4c | ||
|
|
f56fc572f1 | ||
|
|
16fdf6b621 | ||
|
|
a863037ca3 | ||
|
|
2d854bd94c | ||
|
|
9565c28a91 | ||
|
|
bc457bb3bd | ||
|
|
db383a3121 | ||
|
|
3f76f603d9 | ||
|
|
68304848ae | ||
|
|
bb6bc4cac3 | ||
|
|
ef8b9c36ef | ||
|
|
e6c943d01f | ||
|
|
31d3ee899f | ||
|
|
98143a845b | ||
|
|
bffc557be1 | ||
|
|
09208fa8fe | ||
|
|
048c571d3d | ||
|
|
24757f1064 | ||
|
|
88f2f51266 | ||
|
|
93152ef863 | ||
|
|
09b698b0a9 | ||
|
|
478aaf9619 | ||
|
|
fad902b438 | ||
|
|
7bfaf292db |
270
CHANGELOG.md
Normal file
270
CHANGELOG.md
Normal file
@@ -0,0 +1,270 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
ethers/v4.0.41 (2019-12-21 01:05)
|
||||
---------------------------------
|
||||
|
||||
- Added proper support for v0.6 Solidity JSON type ([#688](https://github.com/ethers-io/ethers.js/issues/688); [20f34f1](https://github.com/ethers-io/ethers.js/commit/20f34f1ba9c698d1731cb12c5de1822ad462fd7f)).
|
||||
|
||||
ethers/v4.0.40 (2019-11-24 19:58)
|
||||
---------------------------------
|
||||
|
||||
- Update elliptic package to protect from Minerva timing attack ([#666](https://github.com/ethers-io/ethers.js/issues/666); [20409c0](https://github.com/ethers-io/ethers.js/commit/20409c083cd428c46cba09488ee609cc14ff1d2b)).
|
||||
- Do not poll if disabled during the previous event loop. ([7a90f18](https://github.com/ethers-io/ethers.js/commit/7a90f18145931e7ff790cd9e1fd549929fbb9023)).
|
||||
- Moved node types to devDependencies ([#663](https://github.com/ethers-io/ethers.js/issues/663); [df1ae61](https://github.com/ethers-io/ethers.js/commit/df1ae611bab0955005b0da6604191b60b34f198f)).
|
||||
- Added provider property to Web3Provider ([#641](https://github.com/ethers-io/ethers.js/issues/641); [6009a26](https://github.com/ethers-io/ethers.js/commit/6009a26c89c359ae44ef4b6e8a664ed57db24f67)).
|
||||
|
||||
ethers/v4.0.39 (2019-10-30 19:15)
|
||||
---------------------------------
|
||||
|
||||
- Fix filters by forcing a poll instantly when polling starts to capture the current block. ([#613](https://github.com/ethers-io/ethers.js/issues/613); [d0e0e30](https://github.com/ethers-io/ethers.js/commit/d0e0e30532baf387df6b4a8efe0805986cc265f2))
|
||||
|
||||
ethers/v4.0.38 (2019-10-17 01:28)
|
||||
---------------------------------
|
||||
|
||||
- Fixed TypeScript 3.7-beta import issue. ([#622](https://github.com/ethers-io/ethers.js/issues/622); [0609ea9](https://github.com/ethers-io/ethers.js/commit/0609ea96519bf4afe6badc5f43c0d03ca91b8363))
|
||||
|
||||
ethers/v4.0.37 (2019-09-06 19:10)
|
||||
---------------------------------
|
||||
|
||||
- Added pkg.ethereum key for donations. ([#593](https://github.com/ethers-io/ethers.js/issues/593); [004cb82](https://github.com/ethers-io/ethers.js/commit/004cb826d2441cd5b0770161e66d351b2ba5abb5))
|
||||
- Fixed typo in error message. ([#592](https://github.com/ethers-io/ethers.js/issues/592); [bfcf224](https://github.com/ethers-io/ethers.js/commit/bfcf224b2bcfa10ff1a1250c3943d33daa98d6d8))
|
||||
- Fixed typo in error message. ([#580](https://github.com/ethers-io/ethers.js/issues/580); [c969fe5](https://github.com/ethers-io/ethers.js/commit/c969fe5a68a0703a892dc5ab6e09a6938ccc9e4c))
|
||||
- Fixed typo in error message. ([#574](https://github.com/ethers-io/ethers.js/issues/574); [8737f12](https://github.com/ethers-io/ethers.js/commit/8737f12e1bbeee477413e1d96c4124463256161e))
|
||||
|
||||
ethers/v4.0.36 (2019-08-26 16:09)
|
||||
---------------------------------
|
||||
|
||||
- Updated package-lock for security reasons; dev dependency only. ([11c250f](https://github.com/ethers-io/ethers.js/commit/11c250ff7c78fa6c28c1bc22f91ea214526c467d))
|
||||
- Fixed typo in error message. ([#592](https://github.com/ethers-io/ethers.js/issues/592); [c303199](https://github.com/ethers-io/ethers.js/commit/c303199d26d6c5959b1a85a24ca162a1e405c63b))
|
||||
- Fixed ENS lookupAddress when the resolver isn't configured. ([#581](https://github.com/ethers-io/ethers.js/issues/581); [760a5ae](https://github.com/ethers-io/ethers.js/commit/760a5aec74cfc2ce7467ae89214606500ed7a762))
|
||||
- Allow Secret Storage wallet address to be optional. ([#582](https://github.com/ethers-io/ethers.js/issues/582); [24f243e](https://github.com/ethers-io/ethers.js/commit/24f243e689112048df502e10dbc2935303280c4d))
|
||||
- Updated package-lock for lodash security advisory; the package is only a development dependency, so no urgent need to publish, just for developers. ([lodash/lodash#4336](https://github.com/lodash/lodash/pull/4336); [d719064](https://github.com/ethers-io/ethers.js/commit/d7190646280af9bb36352fc502ba7f6e84559026))
|
||||
|
||||
ethers/v4.0.33 (2019-07-09 20:17)
|
||||
---------------------------------
|
||||
|
||||
- Reduce number of HDNode tests which cause TravisCI to timeout. ([a7d0b41](https://github.com/ethers-io/ethers.js/commit/a7d0b41d9865ffb9bdda497f77c316938f44cd46))
|
||||
|
||||
ethers/v4.0.32 (2019-07-09 16:56)
|
||||
---------------------------------
|
||||
|
||||
- Added test cases for case-agnostic mnemonics. ([#557](https://github.com/ethers-io/ethers.js/issues/557); [a34ca6b](https://github.com/ethers-io/ethers.js/commit/a34ca6b3a38d0854d5b57c908d523a98262c0f53))
|
||||
- Make mnemonics case-agnostic. ([#557](https://github.com/ethers-io/ethers.js/issues/557); [ef91dcd](https://github.com/ethers-io/ethers.js/commit/ef91dcd757349dfb31ad2fbd0b840abe6a4043be))
|
||||
- Added tests for testnet extended private key. ([#553](https://github.com/ethers-io/ethers.js/issues/553); [a5296a9](https://github.com/ethers-io/ethers.js/commit/a5296a9258a475b6d3ebe4c6b848945a77ba4887))
|
||||
|
||||
ethers/v4.0.31 (2019-06-28 15:39)
|
||||
---------------------------------
|
||||
|
||||
- Fixed testnet exteneded private keys. ([#553](https://github.com/ethers-io/ethers.js/issues/553); [fbf15c0](https://github.com/ethers-io/ethers.js/commit/fbf15c0ffe046290749fe307e9d4e8624b81664a))
|
||||
|
||||
ethers/v4.0.30 (2019-06-21 19:18)
|
||||
---------------------------------
|
||||
|
||||
- No longer use hard-coded id of 42 in Web3Provider. ([384fc32](https://github.com/ethers-io/ethers.js/commit/384fc328f2989882bf6027b2af48efa02f2fab53))
|
||||
|
||||
ethers/v4.0.29 (2019-06-10 01:58)
|
||||
---------------------------------
|
||||
|
||||
- Fixed error in throwing an error for ABI decode. ([#539](https://github.com/ethers-io/ethers.js/issues/539); [92c978e](https://github.com/ethers-io/ethers.js/commit/92c978e5c20aca96a4297c7d494e154c3a796e71))
|
||||
|
||||
ethers/v4.0.28 (2019-05-24 14:57)
|
||||
---------------------------------
|
||||
|
||||
- Warn on deprecated INFURA API Token; use Project ID instead. ([#462](https://github.com/ethers-io/ethers.js/issues/462); [19587ee](https://github.com/ethers-io/ethers.js/commit/19587eea3f3fadc301ff4d949646b700ebb4a85b))
|
||||
- Fixed typo in error message. ([#470](https://github.com/ethers-io/ethers.js/issues/470); [4a9373e](https://github.com/ethers-io/ethers.js/commit/4a9373e773dd78c62f4f5127f8357001e5940a22))
|
||||
- Export poll function. ([#514](https://github.com/ethers-io/ethers.js/issues/514); [2997bae](https://github.com/ethers-io/ethers.js/commit/2997bae93599294935d1e467d8ede2960ee92e50))
|
||||
- Fixed error message for unconfigured ENS names. ([#504](https://github.com/ethers-io/ethers.js/issues/504); [7075c8c](https://github.com/ethers-io/ethers.js/commit/7075c8c2352ec306b5679da6fbe7c2ddf7bd65d1))
|
||||
- Fixed security recommendations (development deps only; not a problem, but quiets automatic audits). ([a4a532f](https://github.com/ethers-io/ethers.js/commit/a4a532fe8e6a9fd8ef2ff069ea1b6c9ae28c4e5a))
|
||||
|
||||
ethers/v4.0.27 (2019-04-18 07:50)
|
||||
---------------------------------
|
||||
|
||||
- Increment JSON-RPC ID for JsonRpcProviders for environments that unsafely manage callbacks. ([#489](https://github.com/ethers-io/ethers.js/issues/489); [c93b489](https://github.com/ethers-io/ethers.js/commit/c93b48920e4861b4fe35c60be19344abbb19a184))
|
||||
|
||||
ethers/v4.0.26 (2019-03-08 14:29)
|
||||
---------------------------------
|
||||
|
||||
- Added goerli to InfuraProvider. ([#421](https://github.com/ethers-io/ethers.js/issues/421); [16c9745](https://github.com/ethers-io/ethers.js/commit/16c974532603b6ed7e49cedd6ce11f2e92158bf0))
|
||||
|
||||
ethers/v4.0.25 (2019-02-15 13:43)
|
||||
---------------------------------
|
||||
|
||||
- Added fastRetry to polling for JsonRpcSigner to improve polling for sent transactions. ([#402](https://github.com/ethers-io/ethers.js/issues/402); [f318fd9](https://github.com/ethers-io/ethers.js/commit/f318fd9cf1303fe2770f400cbce14c778f77e454))
|
||||
- Fix waitForTransaction delay. ([#424](https://github.com/ethers-io/ethers.js/issues/424); [c15a898](https://github.com/ethers-io/ethers.js/commit/c15a89832b2fd8ab06b9ec655487cb50e8ded7c1))
|
||||
- Fixed waitForTransaction and removeListener. ([#410](https://github.com/ethers-io/ethers.js/issues/410); [72edcd0](https://github.com/ethers-io/ethers.js/commit/72edcd054fa78c52c82c33bcc7e389d93ff517ec))
|
||||
- Updated BIP39 list in readme. ([e4a2f8a](https://github.com/ethers-io/ethers.js/commit/e4a2f8ac6c5c9bb5fc30d5720e1457381c82e608))
|
||||
|
||||
ethers/v4.0.24 (2019-02-11 19:22)
|
||||
---------------------------------
|
||||
|
||||
- Fixed support for calling self-destructed contracts. ([#411](https://github.com/ethers-io/ethers.js/issues/411); [0ed983a](https://github.com/ethers-io/ethers.js/commit/0ed983a264077d74d23da194b580fc702e9139a9))
|
||||
- Updated balance address for Goerli test cases. ([8fab48a](https://github.com/ethers-io/ethers.js/commit/8fab48a3803f521a77ad8cfc7176f3b819996f88))
|
||||
- Fixed utils test case for phantomjs. ([a2306f7](https://github.com/ethers-io/ethers.js/commit/a2306f7870ab75802af95cc0eab7fa77ca17d8d8))
|
||||
- Initial support for EIP-234; filter by blockHash. ([#412](https://github.com/ethers-io/ethers.js/issues/412); [60b75c1](https://github.com/ethers-io/ethers.js/commit/60b75c10d702b5a04ec1e381191fe1cd5a93274c))
|
||||
- Fixed out-of-safe-range hexlify values to throw an exception. ([#420](https://github.com/ethers-io/ethers.js/issues/420); [41c2c8a](https://github.com/ethers-io/ethers.js/commit/41c2c8a729816226bc38a5bc0e73e0c573afe25d))
|
||||
- Added goerli testnet support. ([#421](https://github.com/ethers-io/ethers.js/issues/421); [9785eed](https://github.com/ethers-io/ethers.js/commit/9785eed8dd227234afbfcb0eef9892e6a7a2b187))
|
||||
- Fixed missing TypeArray slice on constrained environments. ([14484e5](https://github.com/ethers-io/ethers.js/commit/14484e566edf60a493acb1128708136d4205e606))
|
||||
- Fixed test-hdnode for phantomjs; does not support let keyword. ([429af2c](https://github.com/ethers-io/ethers.js/commit/429af2c40db40dc2ff1fd33409f198c2ab3c9b16))
|
||||
- Added xpub and xpriv deserialization. ([#405](https://github.com/ethers-io/ethers.js/issues/405); [af3aed4](https://github.com/ethers-io/ethers.js/commit/af3aed4580da47be1f89fce94c37b91012f92b91))
|
||||
- Added xpub and xpriv test cases for HD nodes. ([#405](https://github.com/ethers-io/ethers.js/issues/405); [3a3764b](https://github.com/ethers-io/ethers.js/commit/3a3764bdb4838c81dcd7afbb6eabd2792d3a5b00))
|
||||
- Support for xpub and xpriv derivation and generating extended keys; no fromExtendedKey yet. ([#405](https://github.com/ethers-io/ethers.js/issues/405); [18ee2c5](https://github.com/ethers-io/ethers.js/commit/18ee2c518c252a18fa172a8a7092c58cf6c0b7c5))
|
||||
|
||||
ethers/v4.0.23 (2019-01-25 19:09)
|
||||
---------------------------------
|
||||
|
||||
- Fixed duplicate events from triggering. ([#404](https://github.com/ethers-io/ethers.js/issues/404); [908258f](https://github.com/ethers-io/ethers.js/commit/908258f8d4c56b58f6826011a805c2e690d9a4a0))
|
||||
|
||||
ethers/v4.0.22 (2019-01-24 16:53)
|
||||
---------------------------------
|
||||
|
||||
- Ganache does not include from in receipts. ([#400](https://github.com/ethers-io/ethers.js/issues/400); [b5f720a](https://github.com/ethers-io/ethers.js/commit/b5f720ace6ac3e43beb2aaeda774f00f050192f4))
|
||||
- Added to and from for Transaction Receipts. ([#398](https://github.com/ethers-io/ethers.js/issues/398); [700dd34](https://github.com/ethers-io/ethers.js/commit/700dd3413718ecfa3800aab361c4c5b91d1a7137))
|
||||
- Added v3 INFURA end-points to InfuraProvider. ([#286](https://github.com/ethers-io/ethers.js/issues/286); [f2dd977](https://github.com/ethers-io/ethers.js/commit/f2dd977de4fb6216d6a990d13999644a9be5815d))
|
||||
- Fixed long-response bug in IpcProvider. ([#384](https://github.com/ethers-io/ethers.js/issues/384); [5f01321](https://github.com/ethers-io/ethers.js/commit/5f013216c5f51830ef3fd3f725d42272f7ae5c99))
|
||||
|
||||
ethers/v4.0.21 (2019-01-17 16:33)
|
||||
---------------------------------
|
||||
|
||||
- Fixed path for x-ethers metadata and wallet. ([#392](https://github.com/ethers-io/ethers.js/issues/392); [e5bee7e](https://github.com/ethers-io/ethers.js/commit/e5bee7e5a34ba9cfddae8e3c43de10a8060f911a))
|
||||
- Fixed contract removeAllListeners which did not clean up the event loop properly. ([#391](https://github.com/ethers-io/ethers.js/issues/391); [6d08968](https://github.com/ethers-io/ethers.js/commit/6d08968b8789976ee5a7ef23e3dd73e73342cf5b))
|
||||
|
||||
ethers/v4.0.20 (2018-12-27 15:49)
|
||||
---------------------------------
|
||||
|
||||
- Added customizable log levels to quiet warnings. ([#379](https://github.com/ethers-io/ethers.js/issues/379); [f3ec27b](https://github.com/ethers-io/ethers.js/commit/f3ec27b95fcb56d521952c708fdc0229f6d6f7f3))
|
||||
|
||||
ethers/v4.0.19 (2018-12-14 18:37)
|
||||
---------------------------------
|
||||
|
||||
- Allow unchecked transactions which will remain unwrapped for the JsonRpcSigner. ([#340](https://github.com/ethers-io/ethers.js/issues/340); [99a2166](https://github.com/ethers-io/ethers.js/commit/99a21660ab5b360cc4cbdba87dc54245c00565b9))
|
||||
- Make it easier for sub-classes of Wallet to manage nonces. ([4bc62a1](https://github.com/ethers-io/ethers.js/commit/4bc62a1e8a2c240ff567140b981c6bf9da57594f))
|
||||
|
||||
ethers/v4.0.18 (2018-12-12 16:57)
|
||||
---------------------------------
|
||||
|
||||
- Allow nonce to be a BigNumber. ([#228](https://github.com/ethers-io/ethers.js/issues/228); [bcba17a](https://github.com/ethers-io/ethers.js/commit/bcba17a9e76e9ff7867e3d8e32a508fc1582e003))
|
||||
- Fixed typo in error strings. ([#376](https://github.com/ethers-io/ethers.js/issues/376); [918b66b](https://github.com/ethers-io/ethers.js/commit/918b66bc2e176fc3c6f3088cc10b9d03e2df1f6e))
|
||||
- Add isHexString to exported utils. ([#367](https://github.com/ethers-io/ethers.js/issues/367); [152d672](https://github.com/ethers-io/ethers.js/commit/152d672278477321d6ff5dab03b2d1e812151f45))
|
||||
- Add abs method to BigNumber. ([#375](https://github.com/ethers-io/ethers.js/issues/375); [51fb472](https://github.com/ethers-io/ethers.js/commit/51fb4728091a30d147b7dcd61e08562c6171b372))
|
||||
- Better error messages for namehash. ([#364](https://github.com/ethers-io/ethers.js/issues/364); [66440b8](https://github.com/ethers-io/ethers.js/commit/66440b8542e80e056bd96d94a1be9fcbb1c9b2d7))
|
||||
|
||||
ethers/v4.0.17 (2018-12-08 18:47)
|
||||
---------------------------------
|
||||
|
||||
- Fixed function name in parsed transactions. ([#370](https://github.com/ethers-io/ethers.js/issues/370); [6ca1d77](https://github.com/ethers-io/ethers.js/commit/6ca1d772986482b8be467d97fd9cd3107c959ab5))
|
||||
- Include request body in web errors. ([4f6748e](https://github.com/ethers-io/ethers.js/commit/4f6748ec4cc432a1bc2097619a25b9e7ce2b2faa))
|
||||
- Squashed unhandled promise exception for Providers that are never used. ([#362](https://github.com/ethers-io/ethers.js/issues/362); [f56fc57](https://github.com/ethers-io/ethers.js/commit/f56fc572f159e6375db27caa1b3d464dd67803c7))
|
||||
- Added gas estimation back into JsonRpcSigner. ([#365](https://github.com/ethers-io/ethers.js/issues/365); [16fdf6b](https://github.com/ethers-io/ethers.js/commit/16fdf6b621fd45bb1d6ab4e636388d9e7a9028d2))
|
||||
|
||||
ethers/v4.0.16 (2018-12-04 17:17)
|
||||
---------------------------------
|
||||
|
||||
|
||||
ethers/v4.0.15 (2018-12-04 17:14)
|
||||
---------------------------------
|
||||
|
||||
- Do not fill in implicit values for JSON-RPC based signers. ([#335](https://github.com/ethers-io/ethers.js/issues/335); [2d854bd](https://github.com/ethers-io/ethers.js/commit/2d854bd94c799271ce5a2aa4f5ad17d22c8d8dc0))
|
||||
- More relaxed transaction parsing. ([#357](https://github.com/ethers-io/ethers.js/issues/357); [9565c28](https://github.com/ethers-io/ethers.js/commit/9565c28a91b558a96a3895ccfc03975efc639432))
|
||||
- Allow any whitespace characters in human-readable ABI. ([#360](https://github.com/ethers-io/ethers.js/issues/360); [bc457bb](https://github.com/ethers-io/ethers.js/commit/bc457bb3bde7f3c3f1ca2e8345cdf1a4e0701454))
|
||||
|
||||
ethers/v4.0.14 (2018-11-27 17:33)
|
||||
---------------------------------
|
||||
|
||||
- Fixed contract proxied tx.wait receipt properties. ([#355](https://github.com/ethers-io/ethers.js/issues/355); [3f76f60](https://github.com/ethers-io/ethers.js/commit/3f76f603d9de66cb38b8c5d2e2fc6f7c6794d234))
|
||||
|
||||
ethers/v4.0.13 (2018-11-27 15:60)
|
||||
---------------------------------
|
||||
|
||||
- Check for partially-working normalize support. ([bb6bc4c](https://github.com/ethers-io/ethers.js/commit/bb6bc4cac330120e691a4a0566ff547342f62c0c))
|
||||
- Support for platforms where UTF-8 is only half broken. ([ef8b9c3](https://github.com/ethers-io/ethers.js/commit/ef8b9c36ef42ce79d8b5db390eea3deec55d9a6b))
|
||||
- Throw exception instead of returning null for getDefaultProvider. ([#351](https://github.com/ethers-io/ethers.js/issues/351); [31d3ee8](https://github.com/ethers-io/ethers.js/commit/31d3ee899f4331cb75952eceb07b9a8ad7b30e9f))
|
||||
|
||||
ethers/v4.0.12 (2018-11-20 15:42)
|
||||
---------------------------------
|
||||
|
||||
- Added default provider support for Ethereum classic. ([#351](https://github.com/ethers-io/ethers.js/issues/351); [bffc557](https://github.com/ethers-io/ethers.js/commit/bffc557be1b84ae2b69edd5071f7a072c94421e9))
|
||||
|
||||
ethers/v4.0.11 (2018-11-13 07:49)
|
||||
---------------------------------
|
||||
|
||||
- Fixed 0 confirmation waiting. ([#346](https://github.com/ethers-io/ethers.js/issues/346); [048c571](https://github.com/ethers-io/ethers.js/commit/048c571d3d307f6b5a0094865b54106f6d7c5ffa))
|
||||
|
||||
ethers/v4.0.10 (2018-11-12 17:23)
|
||||
---------------------------------
|
||||
|
||||
- Fix spacing in checkArgument errors. ([#318](https://github.com/ethers-io/ethers.js/issues/318); [88f2f51](https://github.com/ethers-io/ethers.js/commit/88f2f51266a66cc8a5934ef5371e0458d08a46e8))
|
||||
- Do not replay block events when the provider event block is reset. ([#343](https://github.com/ethers-io/ethers.js/issues/343); [93152ef](https://github.com/ethers-io/ethers.js/commit/93152ef86394720e911aaf98011013e6dae87c77))
|
||||
|
||||
ethers/v4.0.9 (2018-11-09 14:37)
|
||||
--------------------------------
|
||||
|
||||
- Force unorm shim when String.prototype.normalize is broken. ([#338](https://github.com/ethers-io/ethers.js/issues/338); [478aaf9](https://github.com/ethers-io/ethers.js/commit/478aaf9619bd2e75e559ac73f1e007457480cb61))
|
||||
- Better error message when normalize is missing. ([fad902b](https://github.com/ethers-io/ethers.js/commit/fad902b438ee86d5ade3adc6bd4cd4e4a6c9348d))
|
||||
- Added shims for React-Native support. ([7bfaf29](https://github.com/ethers-io/ethers.js/commit/7bfaf292db90f3e25d5563cff63517ae61f88617))
|
||||
|
||||
ethers/v4.0.8 (2018-11-08 16:04)
|
||||
--------------------------------
|
||||
|
||||
- Updated dist files. ([be0488a](https://github.com/ethers-io/ethers.js/commit/be0488a1a02fffb6a31906a674b4a81da2cffd38))
|
||||
|
||||
ethers/v4.0.7 (2018-11-08 16:02)
|
||||
--------------------------------
|
||||
|
||||
- Fix for when blockTag is specified as a null equivalent value in contract overrides. ([#329](https://github.com/ethers-io/ethers.js/issues/329); [28a52cd](https://github.com/ethers-io/ethers.js/commit/28a52cd485f48599ced1cbf58535e41e179a69bf))
|
||||
- Added "debug" event for providers; do not depend on the format as it may change, but this should help debugging in most cases. ([#320](https://github.com/ethers-io/ethers.js/issues/320); [3a19f43](https://github.com/ethers-io/ethers.js/commit/3a19f43844b3161d536455ee0cbb0712263cd061))
|
||||
- Fix for Kovan filters without an address. ([#339](https://github.com/ethers-io/ethers.js/issues/339); [4852e83](https://github.com/ethers-io/ethers.js/commit/4852e837d2f47b70038136f3a702e9e127ad6c9c))
|
||||
|
||||
ethers/v4.0.6 (2018-10-14 19:02)
|
||||
--------------------------------
|
||||
|
||||
- Fixed lingering polling timer when no events left to process in a provider. ([d54609a](https://github.com/ethers-io/ethers.js/commit/d54609a4582b96bbf0bcb8395f0e01b8784a1369))
|
||||
- Fixed utils.poll from mutating passed variables. ([f682861](https://github.com/ethers-io/ethers.js/commit/f682861e0b420e1dc8123587734600cb00f91f06))
|
||||
- Fixed and refactored populating transaction values for signers. ([#306](https://github.com/ethers-io/ethers.js/issues/306); [023a20f](https://github.com/ethers-io/ethers.js/commit/023a20ff470f73a91a72d57bc85dfafd77255d4e))
|
||||
- Fixed test cases for phantomjs (must use ES3 syntax). ([e39cd84](https://github.com/ethers-io/ethers.js/commit/e39cd849236bf33f32168cfaaab0faf64e0ba69d))
|
||||
|
||||
ethers/v4.0.5 (2018-10-13 17:18)
|
||||
--------------------------------
|
||||
|
||||
- Fixed filtering with null non-indexed parameters. ([#305](https://github.com/ethers-io/ethers.js/issues/305); [6ac2d92](https://github.com/ethers-io/ethers.js/commit/6ac2d923b75526ab663a677f6a712f5400c2a621))
|
||||
|
||||
ethers/v4.0.4 (2018-10-11 16:04)
|
||||
--------------------------------
|
||||
|
||||
- Added optional blockTag to call; note that this may not behave as expected on all nodes. ([#226](https://github.com/ethers-io/ethers.js/issues/226); [493273d](https://github.com/ethers-io/ethers.js/commit/493273d698b9cc71ce1c0555f9df2bd791cd851e))
|
||||
- Check all transaction parameters are valid; protect against typos. ([#299](https://github.com/ethers-io/ethers.js/issues/299); [84344ac](https://github.com/ethers-io/ethers.js/commit/84344ac4c2a2502234373c24c0f02d8912417039))
|
||||
|
||||
ethers/v4.0.3 (2018-10-07 01:10)
|
||||
--------------------------------
|
||||
|
||||
- Added address to HDNode. ([#196](https://github.com/ethers-io/ethers.js/issues/196); [e39e2ed](https://github.com/ethers-io/ethers.js/commit/e39e2ed718364cfccb6921518500dd19f2a479fe))
|
||||
- Added French and Spanish to test-hdnode. ([71f781d](https://github.com/ethers-io/ethers.js/commit/71f781d5425f08fe3c88861e23b8a55860b3d074))
|
||||
- Mark progressCallback as optional. ([#293](https://github.com/ethers-io/ethers.js/issues/293); [b2db10e](https://github.com/ethers-io/ethers.js/commit/b2db10e216748e4c4d5d359bded904af7bd1128f))
|
||||
|
||||
ethers/v4.0.2 (2018-10-04 19:55)
|
||||
--------------------------------
|
||||
|
||||
- Added automatic event parsing for contract transaction receipts from tx.wait. ([2481581](https://github.com/ethers-io/ethers.js/commit/248158130e437b14f9d42666e0cdefa33a6be74d))
|
||||
- Added ability to wait for a specific number of confirmations. ([#229](https://github.com/ethers-io/ethers.js/issues/229); [f5c7ccb](https://github.com/ethers-io/ethers.js/commit/f5c7ccbb80e157ad27a51f310686d4ca3e1db7c8))
|
||||
- Fix for geth-etc. (official geth is fine; [24335d0](https://github.com/ethers-io/ethers.js/commit/24335d0dd71d11a2a9088c05728ed8507062434d))
|
||||
- Fixed confirmations tests and bootstrap fast blockNumber. ([908c2c1](https://github.com/ethers-io/ethers.js/commit/908c2c1096920c729669d8abc0fad10ad8f5b7e7))
|
||||
- Added confirmations to TransactionResponse. ([#156](https://github.com/ethers-io/ethers.js/issues/156); [#238](https://github.com/ethers-io/ethers.js/issues/238); [9797b36](https://github.com/ethers-io/ethers.js/commit/9797b36186add496aafc29c96b44d61fa62b23e3))
|
||||
- Fixed nested errors for providers that were masking true error. ([#292](https://github.com/ethers-io/ethers.js/issues/292); [731f189](https://github.com/ethers-io/ethers.js/commit/731f189010f03b22c085fa87f197d77988d7d0c2))
|
||||
- Added version to errors. ([99fed75](https://github.com/ethers-io/ethers.js/commit/99fed75202c19b976fa744d7e27c230da12f0f10))
|
||||
- Fixed French and Spanish for browsers without Uint8Array.forEach. ([cb5f9f5](https://github.com/ethers-io/ethers.js/commit/cb5f9f576aa6747f4ce85b727ea1c3b62c8fd047))
|
||||
- Added French and Spanish includes to phantomjs test page. ([aeac2cd](https://github.com/ethers-io/ethers.js/commit/aeac2cdb867380f3fc321c3b8cc1f5e733bb0d22))
|
||||
- Increased timeout for querying npm registry. ([0dafd83](https://github.com/ethers-io/ethers.js/commit/0dafd83033d16b73dc0d744cfd00d045e9623bd6))
|
||||
|
||||
ethers/v4.0.1 (2018-10-03 20:02)
|
||||
--------------------------------
|
||||
|
||||
- Added French and Spanish wordlist dist files. ([b9c07b5](https://github.com/ethers-io/ethers.js/commit/b9c07b549ca23b11bfac9abc147cad75a6db17b5))
|
||||
- Added French and Spanish BIP-39 wordlists. ([#191](https://github.com/ethers-io/ethers.js/issues/191); [c34a1f7](https://github.com/ethers-io/ethers.js/commit/c34a1f73c6e05a098bd15e760971f68c0a471770))
|
||||
- Added support for JSON serialized BigNumbers in the constructor. ([#288](https://github.com/ethers-io/ethers.js/issues/288); [281bd06](https://github.com/ethers-io/ethers.js/commit/281bd0613d9da2542b519122496387e9e25c51ac))
|
||||
- Fixed scrypt for long passwords. ([#223](https://github.com/ethers-io/ethers.js/issues/223); [d936b4c](https://github.com/ethers-io/ethers.js/commit/d936b4cd09126f395d5478b65c076049e560940c))
|
||||
|
||||
ethers/v4.0.0 (2018-10-01 17:34)
|
||||
--------------------------------
|
||||
|
||||
- Initial v4 release
|
||||
|
||||
@@ -9,7 +9,7 @@ Complete Ethereum wallet implementation and utilities in JavaScript (and TypeScr
|
||||
|
||||
- Keep your private keys in your client, **safe** and sound
|
||||
- Import and export **JSON wallets** (Geth, Parity and crowdsale)
|
||||
- Import and export BIP 39 **mnemonic phrases** (12 word backup phrases) and **HD Wallets** (English, Italian, Japanese, Korean, Simplified Chinese, Traditional Chinese; more coming soon)
|
||||
- Import and export BIP 39 **mnemonic phrases** (12 word backup phrases) and **HD Wallets** (English, French, Italian, Japanese, Korean, Simplified Chinese, Spanish, Traditional Chinese)
|
||||
- Meta-classes create JavaScript objects from any contract ABI, including **ABIv2** and **Human-Readable ABI**
|
||||
- Connect to Ethereum nodes over [JSON-RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC), [INFURA](https://infura.io), [Etherscan](https://etherscan.io), or [MetaMask](https://metamask.io)
|
||||
- **ENS names** are first-class citizens; they can be used anywhere an Ethereum addresses can be used
|
||||
|
||||
2
_version.d.ts
vendored
2
_version.d.ts
vendored
@@ -1 +1 @@
|
||||
export declare const version = "4.0.8";
|
||||
export declare const version = "4.0.41";
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.version = "4.0.8";
|
||||
exports.version = "4.0.41";
|
||||
|
||||
5
contract.d.ts
vendored
5
contract.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
import { BigNumber } from './utils/bignumber';
|
||||
import { Indexed, Interface } from './utils/interface';
|
||||
import { UnsignedTransaction } from './utils/transaction';
|
||||
import { Provider } from './providers/abstract-provider';
|
||||
import { BlockTag, Provider } from './providers/abstract-provider';
|
||||
import { Signer } from './abstract-signer';
|
||||
import { Arrayish } from './utils/bytes';
|
||||
import { ParamType } from './utils/abi-coder';
|
||||
@@ -50,9 +50,10 @@ export declare class Contract {
|
||||
readonly [name: string]: ContractFunction | any;
|
||||
readonly addressPromise: Promise<string>;
|
||||
readonly deployTransaction: TransactionResponse;
|
||||
private _deployed;
|
||||
private _deployedPromise;
|
||||
constructor(addressOrName: string, contractInterface: Array<string | ParamType> | string | Interface, signerOrProvider: Signer | Provider);
|
||||
deployed(): Promise<Contract>;
|
||||
_deployed(blockTag?: BlockTag): Promise<Contract>;
|
||||
fallback(overrides?: TransactionRequest): Promise<TransactionResponse>;
|
||||
connect(signerOrProvider: Signer | Provider | string): Contract;
|
||||
attach(addressOrName: string): Contract;
|
||||
|
||||
41
contract.js
41
contract.js
@@ -106,7 +106,6 @@ function resolveAddresses(provider, value, paramType) {
|
||||
function runMethod(contract, functionName, estimateOnly) {
|
||||
var method = contract.interface.functions[functionName];
|
||||
return function () {
|
||||
var _this = this;
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
@@ -136,8 +135,7 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
errors.throwError('cannot override ' + key, errors.UNSUPPORTED_OPERATION, { operation: key });
|
||||
}
|
||||
});
|
||||
// Send to the contract address (after checking the contract is deployed)
|
||||
tx.to = contract.deployed().then(function () {
|
||||
tx.to = contract._deployed(blockTag).then(function () {
|
||||
return contract.addressPromise;
|
||||
});
|
||||
return resolveAddresses(contract.provider, params, method.inputs).then(function (params) {
|
||||
@@ -206,7 +204,7 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
tx.gasLimit = bignumber_1.bigNumberify(method.gas).add(21000);
|
||||
}
|
||||
if (!contract.signer) {
|
||||
errors.throwError('sending a transaction require a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' });
|
||||
errors.throwError('sending a transaction requires a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' });
|
||||
}
|
||||
// Make sure they aren't overriding something they shouldn't
|
||||
if (tx.from != null) {
|
||||
@@ -218,19 +216,19 @@ function runMethod(contract, functionName, estimateOnly) {
|
||||
return wait(confirmations).then(function (receipt) {
|
||||
receipt.events = receipt.logs.map(function (log) {
|
||||
var event = properties_1.deepCopy(log);
|
||||
var parsed = _this.interface.parseLog(log);
|
||||
var parsed = contract.interface.parseLog(log);
|
||||
if (parsed) {
|
||||
event.args = parsed.values;
|
||||
event.decode = parsed.decode;
|
||||
event.event = parsed.name;
|
||||
event.eventSignature = parsed.signature;
|
||||
}
|
||||
event.removeListener = function () { return _this.provider; };
|
||||
event.removeListener = function () { return contract.provider; };
|
||||
event.getBlock = function () {
|
||||
return _this.provider.getBlock(receipt.blockHash);
|
||||
return contract.provider.getBlock(receipt.blockHash);
|
||||
};
|
||||
event.getTransaction = function () {
|
||||
return _this.provider.getTransaction(receipt.transactionHash);
|
||||
return contract.provider.getTransaction(receipt.transactionHash);
|
||||
};
|
||||
event.getTransactionReceipt = function () {
|
||||
return Promise.resolve(receipt);
|
||||
@@ -305,7 +303,6 @@ var Contract = /** @class */ (function () {
|
||||
}
|
||||
return address;
|
||||
}).catch(function (error) {
|
||||
console.log('ERROR: Cannot find Contract - ' + addressOrName);
|
||||
throw error;
|
||||
}));
|
||||
}
|
||||
@@ -324,7 +321,7 @@ var Contract = /** @class */ (function () {
|
||||
properties_1.defineReadOnly(_this, name, run);
|
||||
}
|
||||
else {
|
||||
console.log('WARNING: Multiple definitions for ' + name);
|
||||
errors.warn('WARNING: Multiple definitions for ' + name);
|
||||
}
|
||||
if (_this.functions[name] == null) {
|
||||
properties_1.defineReadOnly(_this.functions, name, run);
|
||||
@@ -334,11 +331,14 @@ var Contract = /** @class */ (function () {
|
||||
}
|
||||
// @TODO: Allow timeout?
|
||||
Contract.prototype.deployed = function () {
|
||||
return this._deployed();
|
||||
};
|
||||
Contract.prototype._deployed = function (blockTag) {
|
||||
var _this = this;
|
||||
if (!this._deployed) {
|
||||
if (!this._deployedPromise) {
|
||||
// If we were just deployed, we know the transaction we should occur in
|
||||
if (this.deployTransaction) {
|
||||
this._deployed = this.deployTransaction.wait().then(function () {
|
||||
this._deployedPromise = this.deployTransaction.wait().then(function () {
|
||||
return _this;
|
||||
});
|
||||
}
|
||||
@@ -346,7 +346,7 @@ var Contract = /** @class */ (function () {
|
||||
// @TODO: Once we allow a timeout to be passed in, we will wait
|
||||
// up to that many blocks for getCode
|
||||
// Otherwise, poll for our code to be deployed
|
||||
this._deployed = this.provider.getCode(this.address).then(function (code) {
|
||||
this._deployedPromise = this.provider.getCode(this.address, blockTag).then(function (code) {
|
||||
if (code === '0x') {
|
||||
errors.throwError('contract not deployed', errors.UNSUPPORTED_OPERATION, {
|
||||
contractAddress: _this.address,
|
||||
@@ -357,7 +357,7 @@ var Contract = /** @class */ (function () {
|
||||
});
|
||||
}
|
||||
}
|
||||
return this._deployed;
|
||||
return this._deployedPromise;
|
||||
};
|
||||
// @TODO:
|
||||
// estimateFallback(overrides?: TransactionRequest): Promise<BigNumber>
|
||||
@@ -366,7 +366,7 @@ var Contract = /** @class */ (function () {
|
||||
Contract.prototype.fallback = function (overrides) {
|
||||
var _this = this;
|
||||
if (!this.signer) {
|
||||
errors.throwError('sending a transaction require a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction(fallback)' });
|
||||
errors.throwError('sending a transaction requires a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction(fallback)' });
|
||||
}
|
||||
var tx = properties_1.shallowCopy(overrides || {});
|
||||
['from', 'to'].forEach(function (key) {
|
||||
@@ -556,12 +556,19 @@ var Contract = /** @class */ (function () {
|
||||
}).map(function (event) { return event.listener; });
|
||||
};
|
||||
Contract.prototype.removeAllListeners = function (eventName) {
|
||||
var _this = this;
|
||||
if (!this.provider) {
|
||||
return this;
|
||||
}
|
||||
var eventFilter = this._getEventFilter(eventName);
|
||||
this._events = this._events.filter(function (event) {
|
||||
return event.eventFilter.eventTag !== eventFilter.eventTag;
|
||||
// Keep all other events
|
||||
if (event.eventFilter.eventTag !== eventFilter.eventTag) {
|
||||
return true;
|
||||
}
|
||||
// Deregister this event from the provider and filter it out
|
||||
_this.provider.removeListener(event.eventFilter.filter, event.wrappedListener);
|
||||
return false;
|
||||
});
|
||||
return this;
|
||||
};
|
||||
@@ -655,7 +662,7 @@ var ContractFactory = /** @class */ (function () {
|
||||
errors.throwError('cannot override ' + key, errors.UNSUPPORTED_OPERATION, { operation: key });
|
||||
});
|
||||
// Make sure the call matches the constructor signature
|
||||
errors.checkArgumentCount(args.length, this.interface.deployFunction.inputs.length, 'in Contract constructor');
|
||||
errors.checkArgumentCount(args.length, this.interface.deployFunction.inputs.length, ' in Contract constructor');
|
||||
// Set the data to the bytecode + the encoded constructor arguments
|
||||
tx.data = this.interface.deployFunction.encode(this.bytecode, args);
|
||||
return tx;
|
||||
|
||||
1703
dist/ethers.js
vendored
1703
dist/ethers.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/ethers.min.js
vendored
2
dist/ethers.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/ethers.min.js.map
vendored
2
dist/ethers.min.js.map
vendored
File diff suppressed because one or more lines are too long
56
dist/ethers.types.txt
vendored
56
dist/ethers.types.txt
vendored
@@ -26,7 +26,7 @@ declare module 'ethers/contract' {
|
||||
import { BigNumber } from 'ethers/utils/bignumber';
|
||||
import { Indexed, Interface } from 'ethers/utils/interface';
|
||||
import { UnsignedTransaction } from 'ethers/utils/transaction';
|
||||
import { Provider } from 'ethers/providers/abstract-provider';
|
||||
import { BlockTag, Provider } from 'ethers/providers/abstract-provider';
|
||||
import { Signer } from 'ethers/abstract-signer';
|
||||
import { Arrayish } from 'ethers/utils/bytes';
|
||||
import { ParamType } from 'ethers/utils/abi-coder';
|
||||
@@ -77,6 +77,7 @@ declare module 'ethers/contract' {
|
||||
readonly deployTransaction: TransactionResponse;
|
||||
constructor(addressOrName: string, contractInterface: Array<string | ParamType> | string | Interface, signerOrProvider: Signer | Provider);
|
||||
deployed(): Promise<Contract>;
|
||||
_deployed(blockTag?: BlockTag): Promise<Contract>;
|
||||
fallback(overrides?: TransactionRequest): Promise<TransactionResponse>;
|
||||
connect(signerOrProvider: Signer | Provider | string): Contract;
|
||||
attach(addressOrName: string): Contract;
|
||||
@@ -188,6 +189,10 @@ declare module 'ethers/errors' {
|
||||
export function checkNew(self: any, kind: any): void;
|
||||
export function checkArgumentCount(count: number, expectedCount: number, suffix?: string): void;
|
||||
export function setCensorship(censorship: boolean, permanent?: boolean): void;
|
||||
export function checkNormalize(): void;
|
||||
export function setLogLevel(logLevel: string): void;
|
||||
export function warn(...args: Array<any>): void;
|
||||
export function info(...args: Array<any>): void;
|
||||
}
|
||||
|
||||
declare module 'ethers/providers' {
|
||||
@@ -209,7 +214,7 @@ declare module 'ethers/utils' {
|
||||
import { getAddress, getContractAddress, getIcapAddress } from 'ethers/utils/address';
|
||||
import * as base64 from 'ethers/utils/base64';
|
||||
import { BigNumber, bigNumberify } from 'ethers/utils/bignumber';
|
||||
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, joinSignature, padZeros, splitSignature, stripZeros } from 'ethers/utils/bytes';
|
||||
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, isHexString, joinSignature, padZeros, splitSignature, stripZeros } from 'ethers/utils/bytes';
|
||||
import { hashMessage, id, namehash } from 'ethers/utils/hash';
|
||||
import * as HDNode from 'ethers/utils/hdnode';
|
||||
import { Interface } from 'ethers/utils/interface';
|
||||
@@ -227,7 +232,7 @@ declare module 'ethers/utils' {
|
||||
import { parse as parseTransaction, serialize as serializeTransaction } from 'ethers/utils/transaction';
|
||||
import { formatBytes32String, parseBytes32String, toUtf8Bytes, toUtf8String } from 'ethers/utils/utf8';
|
||||
import { commify, formatEther, parseEther, formatUnits, parseUnits } from 'ethers/utils/units';
|
||||
import { fetchJson } from 'ethers/utils/web';
|
||||
import { fetchJson, poll } from 'ethers/utils/web';
|
||||
import { SupportedAlgorithms } from 'ethers/utils/hmac';
|
||||
import { UnicodeNormalizationForm } from 'ethers/utils/utf8';
|
||||
import { CoerceFunc, EventFragment, FunctionFragment, ParamType } from 'ethers/utils/abi-coder';
|
||||
@@ -239,7 +244,7 @@ declare module 'ethers/utils' {
|
||||
import { ConnectionInfo, OnceBlockable, PollOptions } from 'ethers/utils/web';
|
||||
import { EncryptOptions, ProgressCallback } from 'ethers/utils/secret-storage';
|
||||
import { Wordlist } from 'ethers/utils/wordlist';
|
||||
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
|
||||
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, isHexString, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, poll, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
|
||||
}
|
||||
|
||||
declare module 'ethers/wordlists' {
|
||||
@@ -261,7 +266,7 @@ declare module 'ethers/utils/shims' {
|
||||
}
|
||||
|
||||
declare module 'ethers/_version' {
|
||||
export const version = "4.0.8";
|
||||
export const version = "4.0.41";
|
||||
}
|
||||
|
||||
declare module 'ethers/utils/bignumber' {
|
||||
@@ -272,6 +277,7 @@ declare module 'ethers/utils/bignumber' {
|
||||
constructor(value: BigNumberish);
|
||||
fromTwos(value: number): BigNumber;
|
||||
toTwos(value: number): BigNumber;
|
||||
abs(): BigNumber;
|
||||
add(other: BigNumberish): BigNumber;
|
||||
sub(other: BigNumberish): BigNumber;
|
||||
div(other: BigNumberish): BigNumber;
|
||||
@@ -469,6 +475,11 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
address?: string;
|
||||
topics?: Array<string | Array<string>>;
|
||||
};
|
||||
export type FilterByBlock = {
|
||||
blockHash?: string;
|
||||
address?: string;
|
||||
topics?: Array<string | Array<string>>;
|
||||
};
|
||||
export interface Log {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
@@ -482,6 +493,8 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
logIndex?: number;
|
||||
}
|
||||
export interface TransactionReceipt {
|
||||
to?: string;
|
||||
from?: string;
|
||||
contractAddress?: string;
|
||||
transactionIndex?: number;
|
||||
root?: string;
|
||||
@@ -499,7 +512,7 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
export type TransactionRequest = {
|
||||
to?: string | Promise<string>;
|
||||
from?: string | Promise<string>;
|
||||
nonce?: number | string | Promise<number | string>;
|
||||
nonce?: BigNumberish | Promise<BigNumberish>;
|
||||
gasLimit?: BigNumberish | Promise<BigNumberish>;
|
||||
gasPrice?: BigNumberish | Promise<BigNumberish>;
|
||||
data?: Arrayish | Promise<Arrayish>;
|
||||
@@ -531,7 +544,7 @@ declare module 'ethers/providers/abstract-provider' {
|
||||
abstract getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
abstract getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
abstract getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
||||
abstract getLogs(filter: Filter): Promise<Array<Log>>;
|
||||
abstract getLogs(filter: Filter | FilterByBlock): Promise<Array<Log>>;
|
||||
abstract resolveName(name: string | Promise<string>): Promise<string>;
|
||||
abstract lookupAddress(address: string | Promise<string>): Promise<string>;
|
||||
abstract on(eventName: EventType, listener: Listener): Provider;
|
||||
@@ -551,7 +564,6 @@ declare module 'ethers/utils/bytes' {
|
||||
* Conversion Utilities
|
||||
*
|
||||
*/
|
||||
import { Arrayish } from 'ethers/utils/bytes';
|
||||
export type Arrayish = string | ArrayLike<number>;
|
||||
export interface Hexable {
|
||||
toHexString(): string;
|
||||
@@ -625,6 +637,8 @@ declare module 'ethers/utils/hdnode' {
|
||||
export class HDNode {
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly fingerprint: string;
|
||||
readonly parentFingerprint: string;
|
||||
readonly address: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
@@ -638,11 +652,14 @@ declare module 'ethers/utils/hdnode' {
|
||||
* - fromMnemonic
|
||||
* - fromSeed
|
||||
*/
|
||||
constructor(constructorGuard: any, privateKey: Arrayish, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string);
|
||||
constructor(constructorGuard: any, privateKey: string, publicKey: string, parentFingerprint: string, chainCode: string, index: number, depth: number, mnemonic: string, path: string);
|
||||
readonly extendedKey: string;
|
||||
neuter(): HDNode;
|
||||
derivePath(path: string): HDNode;
|
||||
static isHDNode(value: any): value is HDNode;
|
||||
}
|
||||
export function fromMnemonic(mnemonic: string, wordlist?: Wordlist): HDNode;
|
||||
export function fromExtendedKey(extendedKey: string): HDNode;
|
||||
export function fromMnemonic(mnemonic: string, wordlist?: Wordlist, password?: string): HDNode;
|
||||
export function fromSeed(seed: Arrayish): HDNode;
|
||||
export function mnemonicToSeed(mnemonic: string, password?: string): string;
|
||||
export function mnemonicToEntropy(mnemonic: string, wordlist?: Wordlist): string;
|
||||
@@ -710,12 +727,14 @@ declare module 'ethers/utils/secret-storage' {
|
||||
declare module 'ethers/providers/base-provider' {
|
||||
import { BigNumber } from 'ethers/utils/bignumber';
|
||||
import { Provider } from 'ethers/providers/abstract-provider';
|
||||
import { Block, BlockTag, EventType, Filter, Listener, Log, TransactionReceipt, TransactionRequest, TransactionResponse } from 'ethers/providers/abstract-provider';
|
||||
import { Block, BlockTag, EventType, Filter, FilterByBlock, Listener, Log, TransactionReceipt, TransactionRequest, TransactionResponse } from 'ethers/providers/abstract-provider';
|
||||
import { BigNumberish } from 'ethers/utils/bignumber';
|
||||
import { Transaction } from 'ethers/utils/transaction';
|
||||
import { Network, Networkish } from 'ethers/utils/networks';
|
||||
export class BaseProvider extends Provider {
|
||||
protected _emitted: any;
|
||||
protected _emitted: {
|
||||
[eventName: string]: number | 'pending';
|
||||
};
|
||||
/**
|
||||
* ready
|
||||
*
|
||||
@@ -749,8 +768,9 @@ declare module 'ethers/providers/base-provider' {
|
||||
getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
||||
getLogs(filter: Filter): Promise<Array<Log>>;
|
||||
getLogs(filter: Filter | FilterByBlock): Promise<Array<Log>>;
|
||||
getEtherPrice(): Promise<number>;
|
||||
_getAddress(addressOrName: string): Promise<string>;
|
||||
resolveName(name: string | Promise<string>): Promise<string>;
|
||||
lookupAddress(address: string | Promise<string>): Promise<string>;
|
||||
static checkTransactionResponse(transaction: any): TransactionResponse;
|
||||
@@ -764,7 +784,7 @@ declare module 'ethers/providers/base-provider' {
|
||||
emit(eventName: EventType, ...args: Array<any>): boolean;
|
||||
listenerCount(eventName?: EventType): number;
|
||||
listeners(eventName: EventType): Array<Listener>;
|
||||
removeAllListeners(eventName: EventType): Provider;
|
||||
removeAllListeners(eventName?: EventType): Provider;
|
||||
removeListener(eventName: EventType, listener: Listener): Provider;
|
||||
}
|
||||
}
|
||||
@@ -808,7 +828,8 @@ declare module 'ethers/providers/infura-provider' {
|
||||
import { Networkish } from 'ethers/utils/networks';
|
||||
export class InfuraProvider extends JsonRpcProvider {
|
||||
readonly apiAccessToken: string;
|
||||
constructor(network?: Networkish, apiAccessToken?: string);
|
||||
readonly projectId: string;
|
||||
constructor(network?: Networkish, projectId?: string);
|
||||
protected _startPending(): void;
|
||||
getSigner(address?: string): JsonRpcSigner;
|
||||
listAccounts(): Promise<Array<string>>;
|
||||
@@ -829,6 +850,7 @@ declare module 'ethers/providers/json-rpc-provider' {
|
||||
getAddress(): Promise<string>;
|
||||
getBalance(blockTag?: BlockTag): Promise<BigNumber>;
|
||||
getTransactionCount(blockTag?: BlockTag): Promise<number>;
|
||||
sendUncheckedTransaction(transaction: TransactionRequest): Promise<string>;
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse>;
|
||||
signMessage(message: Arrayish | string): Promise<string>;
|
||||
unlock(password: string): Promise<boolean>;
|
||||
@@ -904,6 +926,7 @@ declare module 'ethers/utils/keccak256' {
|
||||
|
||||
declare module 'ethers/utils/sha2' {
|
||||
import { Arrayish } from 'ethers/utils/bytes';
|
||||
export function ripemd160(data: Arrayish): string;
|
||||
export function sha256(data: Arrayish): string;
|
||||
export function sha512(data: Arrayish): string;
|
||||
}
|
||||
@@ -923,6 +946,7 @@ declare module 'ethers/utils/networks' {
|
||||
name: string;
|
||||
chainId: number;
|
||||
ensAddress?: string;
|
||||
_defaultProvider?: (providers: any) => any;
|
||||
};
|
||||
export type Networkish = Network | string | number;
|
||||
/**
|
||||
@@ -963,6 +987,7 @@ declare module 'ethers/utils/secp256k1' {
|
||||
constructor(privateKey: Arrayish | string);
|
||||
sign(digest: Arrayish | string): Signature;
|
||||
computeSharedSecret(otherKey: Arrayish | string): string;
|
||||
_addPoint(other: Arrayish | string): string;
|
||||
}
|
||||
export function computePublicKey(key: Arrayish | string, compressed?: boolean): string;
|
||||
export function computeAddress(key: Arrayish | string): string;
|
||||
@@ -1016,6 +1041,7 @@ declare module 'ethers/utils/web' {
|
||||
ceiling?: number;
|
||||
interval?: number;
|
||||
onceBlock?: OnceBlockable;
|
||||
fastRetry?: number;
|
||||
};
|
||||
export function fetchJson(connection: string | ConnectionInfo, json: string, processFunc: (value: any) => any): Promise<any>;
|
||||
export function poll(func: () => Promise<any>, options?: PollOptions): Promise<any>;
|
||||
|
||||
1
dist/shims.js
vendored
Normal file
1
dist/shims.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
errors.d.ts
vendored
4
errors.d.ts
vendored
@@ -14,3 +14,7 @@ export declare function throwError(message: string, code: string, params: any):
|
||||
export declare function checkNew(self: any, kind: any): void;
|
||||
export declare function checkArgumentCount(count: number, expectedCount: number, suffix?: string): void;
|
||||
export declare function setCensorship(censorship: boolean, permanent?: boolean): void;
|
||||
export declare function checkNormalize(): void;
|
||||
export declare function setLogLevel(logLevel: string): void;
|
||||
export declare function warn(...args: Array<any>): void;
|
||||
export declare function info(...args: Array<any>): void;
|
||||
|
||||
57
errors.js
57
errors.js
@@ -18,7 +18,7 @@ exports.MISSING_NEW = 'MISSING_NEW';
|
||||
// - reason: The reason (only for EIP848 "Error(string)")
|
||||
exports.CALL_EXCEPTION = 'CALL_EXCEPTION';
|
||||
// Invalid argument (e.g. value is incompatible with type) to a function:
|
||||
// - arg: The argument name that was invalid
|
||||
// - argument: The argument name that was invalid
|
||||
// - value: The value of the argument
|
||||
exports.INVALID_ARGUMENT = 'INVALID_ARGUMENT';
|
||||
// Missing argument to a function:
|
||||
@@ -102,9 +102,62 @@ function checkArgumentCount(count, expectedCount, suffix) {
|
||||
exports.checkArgumentCount = checkArgumentCount;
|
||||
function setCensorship(censorship, permanent) {
|
||||
if (_permanentCensorErrors) {
|
||||
throwError('error censorship permanent', exports.UNSUPPORTED_OPERATION, { operation: 'setCersorship' });
|
||||
throwError('error censorship permanent', exports.UNSUPPORTED_OPERATION, { operation: 'setCensorship' });
|
||||
}
|
||||
_censorErrors = !!censorship;
|
||||
_permanentCensorErrors = !!permanent;
|
||||
}
|
||||
exports.setCensorship = setCensorship;
|
||||
function checkNormalize() {
|
||||
try {
|
||||
// Make sure all forms of normalization are supported
|
||||
["NFD", "NFC", "NFKD", "NFKC"].forEach(function (form) {
|
||||
try {
|
||||
"test".normalize(form);
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error('missing ' + form);
|
||||
}
|
||||
});
|
||||
if (String.fromCharCode(0xe9).normalize('NFD') !== String.fromCharCode(0x65, 0x0301)) {
|
||||
throw new Error('broken implementation');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
throwError('platform missing String.prototype.normalize', exports.UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize', form: error.message });
|
||||
}
|
||||
}
|
||||
exports.checkNormalize = checkNormalize;
|
||||
var LogLevels = { debug: 1, "default": 2, info: 2, warn: 3, error: 4, off: 5 };
|
||||
var LogLevel = LogLevels["default"];
|
||||
function setLogLevel(logLevel) {
|
||||
var level = LogLevels[logLevel];
|
||||
if (level == null) {
|
||||
warn("invliad log level - " + logLevel);
|
||||
return;
|
||||
}
|
||||
LogLevel = level;
|
||||
}
|
||||
exports.setLogLevel = setLogLevel;
|
||||
function log(logLevel, args) {
|
||||
if (LogLevel > LogLevels[logLevel]) {
|
||||
return;
|
||||
}
|
||||
console.log.apply(console, args);
|
||||
}
|
||||
function warn() {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
log("warn", args);
|
||||
}
|
||||
exports.warn = warn;
|
||||
function info() {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
log("info", args);
|
||||
}
|
||||
exports.info = info;
|
||||
|
||||
15
ethers.js
15
ethers.js
@@ -36,9 +36,16 @@ exports.version = _version_1.version;
|
||||
////////////////////////
|
||||
// Helper Functions
|
||||
function getDefaultProvider(network) {
|
||||
return new providers.FallbackProvider([
|
||||
new providers.InfuraProvider(network),
|
||||
new providers.EtherscanProvider(network),
|
||||
]);
|
||||
if (network == null) {
|
||||
network = 'homestead';
|
||||
}
|
||||
var n = utils.getNetwork(network);
|
||||
if (!n || !n._defaultProvider) {
|
||||
errors.throwError('unsupported getDefaultProvider network', errors.UNSUPPORTED_OPERATION, {
|
||||
operation: 'getDefaultProvider',
|
||||
network: network
|
||||
});
|
||||
}
|
||||
return n._defaultProvider(providers);
|
||||
}
|
||||
exports.getDefaultProvider = getDefaultProvider;
|
||||
|
||||
34
gulpfile.js
34
gulpfile.js
@@ -111,7 +111,7 @@ function taskBundle(name, options) {
|
||||
"elliptic/package.json" : ellipticPackage,
|
||||
|
||||
// Remove RIPEMD160 and unneeded hashing algorithms
|
||||
"hash.js/lib/hash/ripemd.js": "module.exports = {ripemd160: null}",
|
||||
//"hash.js/lib/hash/ripemd.js": "module.exports = {ripemd160: null}",
|
||||
"hash.js/lib/hash/sha/1.js": empty,
|
||||
"hash.js/lib/hash/sha/224.js": empty,
|
||||
"hash.js/lib/hash/sha/384.js": empty,
|
||||
@@ -152,7 +152,9 @@ function taskBundle(name, options) {
|
||||
if (options.minify) {
|
||||
result = result.pipe(buffer())
|
||||
.pipe(sourcemaps.init({ loadMaps: true }))
|
||||
.pipe(uglify())
|
||||
.pipe(uglify({
|
||||
output: { ascii_only: true }
|
||||
}))
|
||||
.pipe(sourcemaps.write('./'))
|
||||
}
|
||||
|
||||
@@ -174,6 +176,30 @@ taskBundle("minified", { filename: "ethers.min.js", dest: 'dist', minify: true }
|
||||
// Creates dist/ethers.min.js
|
||||
taskBundle("minified-test", { filename: "ethers.min.js", dest: 'tests/dist', minify: true });
|
||||
|
||||
gulp.task('shims', function () {
|
||||
|
||||
var result = browserify({
|
||||
basedir: '.',
|
||||
debug: false,
|
||||
entries: [ './tests/shims/index.js' ],
|
||||
cache: { },
|
||||
packageCache: {},
|
||||
standalone: "_shims",
|
||||
insertGlobalVars: {
|
||||
process: function() { return; },
|
||||
}
|
||||
})
|
||||
.bundle()
|
||||
.pipe(source('shims.js'))
|
||||
.pipe(buffer())
|
||||
.pipe(uglify({
|
||||
output: { ascii_only: true }
|
||||
}))
|
||||
.pipe(gulp.dest('dist'));
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
/*
|
||||
// Dump the TypeScript definitions to dist/types/
|
||||
gulp.task("types", function() {
|
||||
@@ -265,7 +291,9 @@ function taskLang(locale) {
|
||||
.bundle()
|
||||
.pipe(source("wordlist-" + locale + ".js"))
|
||||
.pipe(buffer())
|
||||
.pipe(uglify())
|
||||
.pipe(uglify({
|
||||
output: { ascii_only: true }
|
||||
}))
|
||||
.pipe(gulp.dest("dist"));
|
||||
});
|
||||
}
|
||||
|
||||
2428
package-lock.json
generated
2428
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "ethers",
|
||||
"version": "4.0.8",
|
||||
"version": "4.0.41",
|
||||
"description": "Ethereum wallet library.",
|
||||
"main": "./index.js",
|
||||
"types": "./index.d.ts",
|
||||
"scripts": {
|
||||
"build": "npm run dist-version && tsc -p ./tsconfig.json",
|
||||
"auto-build": "npm run build -- -w",
|
||||
"dist": "npm run dist-version && npm run build && gulp default minified && npm run dist-types",
|
||||
"dist-test": "gulp default-test minified-test",
|
||||
"dist": "npm run dist-version && npm run build && gulp default minified shims && npm run dist-types",
|
||||
"dist-test": "gulp default-test minified-test shims",
|
||||
"dist-bip39": "gulp bip39-es bip39-fr bip39-it bip39-ja bip39-ko bip39-zh",
|
||||
"dist-types": "dts-bundle --name ethers --main ./index.d.ts --out ./dist/ethers.types.txt",
|
||||
"dist-version": "node -e \"let v = require('./package.json').version; require('fs').writeFileSync('./src.ts/_version.ts', 'export const version = \\\"' + v +'\\\";\\n')\"",
|
||||
@@ -19,10 +19,9 @@
|
||||
"version": "npm dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^10.3.2",
|
||||
"aes-js": "3.0.0",
|
||||
"bn.js": "^4.4.0",
|
||||
"elliptic": "6.3.3",
|
||||
"elliptic": "6.5.2",
|
||||
"hash.js": "1.1.3",
|
||||
"js-sha3": "0.5.7",
|
||||
"scrypt-js": "2.0.4",
|
||||
@@ -31,10 +30,11 @@
|
||||
"xmlhttprequest": "1.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^16.2.2",
|
||||
"@types/node": "^10.3.2",
|
||||
"browserify": "^16.2.3",
|
||||
"browserify-zlib": "^0.2.0",
|
||||
"dts-bundle": "^0.7.3",
|
||||
"eslint": "^5.0.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-promise": "^3.8.0",
|
||||
"ethereumjs-tx": "^1.3.5",
|
||||
"ethereumjs-util": "^5.2.0",
|
||||
@@ -64,5 +64,6 @@
|
||||
"type": "git",
|
||||
"url": "git://github.com/ethers-io/ethers.js.git"
|
||||
},
|
||||
"ethereum": "donations.ethers.eth",
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
11
providers/abstract-provider.d.ts
vendored
11
providers/abstract-provider.d.ts
vendored
@@ -24,6 +24,11 @@ export declare type Filter = {
|
||||
address?: string;
|
||||
topics?: Array<string | Array<string>>;
|
||||
};
|
||||
export declare type FilterByBlock = {
|
||||
blockHash?: string;
|
||||
address?: string;
|
||||
topics?: Array<string | Array<string>>;
|
||||
};
|
||||
export interface Log {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
@@ -37,6 +42,8 @@ export interface Log {
|
||||
logIndex?: number;
|
||||
}
|
||||
export interface TransactionReceipt {
|
||||
to?: string;
|
||||
from?: string;
|
||||
contractAddress?: string;
|
||||
transactionIndex?: number;
|
||||
root?: string;
|
||||
@@ -54,7 +61,7 @@ export interface TransactionReceipt {
|
||||
export declare type TransactionRequest = {
|
||||
to?: string | Promise<string>;
|
||||
from?: string | Promise<string>;
|
||||
nonce?: number | string | Promise<number | string>;
|
||||
nonce?: BigNumberish | Promise<BigNumberish>;
|
||||
gasLimit?: BigNumberish | Promise<BigNumberish>;
|
||||
gasPrice?: BigNumberish | Promise<BigNumberish>;
|
||||
data?: Arrayish | Promise<Arrayish>;
|
||||
@@ -86,7 +93,7 @@ export declare abstract class Provider implements OnceBlockable {
|
||||
abstract getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
abstract getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
abstract getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
||||
abstract getLogs(filter: Filter): Promise<Array<Log>>;
|
||||
abstract getLogs(filter: Filter | FilterByBlock): Promise<Array<Log>>;
|
||||
abstract resolveName(name: string | Promise<string>): Promise<string>;
|
||||
abstract lookupAddress(address: string | Promise<string>): Promise<string>;
|
||||
abstract on(eventName: EventType, listener: Listener): Provider;
|
||||
|
||||
11
providers/base-provider.d.ts
vendored
11
providers/base-provider.d.ts
vendored
@@ -1,13 +1,15 @@
|
||||
import { BigNumber } from '../utils/bignumber';
|
||||
import { Provider } from './abstract-provider';
|
||||
import { Block, BlockTag, EventType, Filter, Listener, Log, TransactionReceipt, TransactionRequest, TransactionResponse } from './abstract-provider';
|
||||
import { Block, BlockTag, EventType, Filter, FilterByBlock, Listener, Log, TransactionReceipt, TransactionRequest, TransactionResponse } from './abstract-provider';
|
||||
import { BigNumberish } from '../utils/bignumber';
|
||||
import { Transaction } from '../utils/transaction';
|
||||
import { Network, Networkish } from '../utils/networks';
|
||||
export declare class BaseProvider extends Provider {
|
||||
private _network;
|
||||
private _events;
|
||||
protected _emitted: any;
|
||||
protected _emitted: {
|
||||
[eventName: string]: number | 'pending';
|
||||
};
|
||||
private _pollingInterval;
|
||||
private _poller;
|
||||
private _lastBlockNumber;
|
||||
@@ -49,8 +51,9 @@ export declare class BaseProvider extends Provider {
|
||||
getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>, includeTransactions?: boolean): Promise<Block>;
|
||||
getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
||||
getLogs(filter: Filter): Promise<Array<Log>>;
|
||||
getLogs(filter: Filter | FilterByBlock): Promise<Array<Log>>;
|
||||
getEtherPrice(): Promise<number>;
|
||||
_getAddress(addressOrName: string): Promise<string>;
|
||||
private _resolveNames;
|
||||
private _getResolver;
|
||||
resolveName(name: string | Promise<string>): Promise<string>;
|
||||
@@ -67,6 +70,6 @@ export declare class BaseProvider extends Provider {
|
||||
emit(eventName: EventType, ...args: Array<any>): boolean;
|
||||
listenerCount(eventName?: EventType): number;
|
||||
listeners(eventName: EventType): Array<Listener>;
|
||||
removeAllListeners(eventName: EventType): Provider;
|
||||
removeAllListeners(eventName?: EventType): Provider;
|
||||
removeListener(eventName: EventType, listener: Listener): Provider;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var address_1 = require("../utils/address");
|
||||
var bignumber_1 = require("../utils/bignumber");
|
||||
var bytes_1 = require("../utils/bytes");
|
||||
var constants_1 = require("../constants");
|
||||
var hash_1 = require("../utils/hash");
|
||||
var networks_1 = require("../utils/networks");
|
||||
var properties_1 = require("../utils/properties");
|
||||
@@ -79,9 +80,15 @@ function arrayOf(check) {
|
||||
return result;
|
||||
});
|
||||
}
|
||||
function checkHash(hash) {
|
||||
if (typeof (hash) === 'string' && bytes_1.hexDataLength(hash) === 32) {
|
||||
return hash.toLowerCase();
|
||||
function checkHash(hash, requirePrefix) {
|
||||
if (typeof (hash) === 'string') {
|
||||
// geth-etc does add a "0x" prefix on receipt.root
|
||||
if (!requirePrefix && hash.substring(0, 2) !== '0x') {
|
||||
hash = '0x' + hash;
|
||||
}
|
||||
if (bytes_1.hexDataLength(hash) === 32) {
|
||||
return hash.toLowerCase();
|
||||
}
|
||||
}
|
||||
errors.throwError('invalid hash', errors.INVALID_ARGUMENT, { arg: 'hash', value: hash });
|
||||
return null;
|
||||
@@ -202,6 +209,10 @@ function checkTransactionResponse(transaction) {
|
||||
}
|
||||
var result = check(formatTransaction, transaction);
|
||||
var networkId = transaction.networkId;
|
||||
// geth-etc returns chainId
|
||||
if (transaction.chainId != null && networkId == null && result.v == null) {
|
||||
networkId = transaction.chainId;
|
||||
}
|
||||
if (bytes_1.isHexString(networkId)) {
|
||||
networkId = bignumber_1.bigNumberify(networkId).toNumber();
|
||||
}
|
||||
@@ -270,6 +281,8 @@ function checkTransactionReceiptLog(log) {
|
||||
return check(formatTransactionReceiptLog, log);
|
||||
}
|
||||
var formatTransactionReceipt = {
|
||||
to: allowNull(address_1.getAddress, null),
|
||||
from: allowNull(address_1.getAddress, null),
|
||||
contractAddress: allowNull(address_1.getAddress, null),
|
||||
transactionIndex: checkNumber,
|
||||
root: allowNull(checkHash),
|
||||
@@ -314,7 +327,15 @@ var formatFilter = {
|
||||
address: allowNull(address_1.getAddress, undefined),
|
||||
topics: allowNull(checkTopics, undefined),
|
||||
};
|
||||
var formatFilterByBlock = {
|
||||
blockHash: allowNull(checkHash, undefined),
|
||||
address: allowNull(address_1.getAddress, undefined),
|
||||
topics: allowNull(checkTopics, undefined),
|
||||
};
|
||||
function checkFilter(filter) {
|
||||
if (filter && filter.blockHash) {
|
||||
return check(formatFilterByBlock, filter);
|
||||
}
|
||||
return check(formatFilter, filter);
|
||||
}
|
||||
var formatLog = {
|
||||
@@ -405,6 +426,8 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
properties_1.defineReadOnly(_this, '_network', network);
|
||||
return network;
|
||||
}));
|
||||
// Squash any "unhandled promise" errors; the don't need to be handled
|
||||
_this.ready.catch(function (error) { });
|
||||
}
|
||||
else {
|
||||
var knownNetwork = networks_1.getNetwork((network == null) ? 'homestead' : network);
|
||||
@@ -422,50 +445,65 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
// Events being listened to
|
||||
_this._events = [];
|
||||
_this._pollingInterval = 4000;
|
||||
// We use this to track recent emitted events; for example, if we emit a "block" of 100
|
||||
// and we get a `getBlock(100)` request which would result in null, we should retry
|
||||
// until we get a response. This provides devs with a consistent view. Similarly for
|
||||
// transaction hashes.
|
||||
_this._emitted = { block: _this._lastBlockNumber };
|
||||
_this._emitted = { block: -2 };
|
||||
_this._fastQueryDate = 0;
|
||||
return _this;
|
||||
}
|
||||
BaseProvider.prototype._doPoll = function () {
|
||||
var _this = this;
|
||||
this.getBlockNumber().then(function (blockNumber) {
|
||||
if (!_this.polling) {
|
||||
return;
|
||||
}
|
||||
_this._setFastBlockNumber(blockNumber);
|
||||
// If the block hasn't changed, meh.
|
||||
if (blockNumber === _this._lastBlockNumber) {
|
||||
return;
|
||||
}
|
||||
if (_this._lastBlockNumber === -2) {
|
||||
_this._lastBlockNumber = blockNumber - 1;
|
||||
// First polling cycle, trigger a "block" events
|
||||
if (_this._emitted.block === -2) {
|
||||
_this._emitted.block = blockNumber - 1;
|
||||
}
|
||||
var _loop_1 = function (i) {
|
||||
if (_this._emitted.block < i) {
|
||||
_this._emitted.block = i;
|
||||
// Notify all listener for each block that has passed
|
||||
for (var i = _this._emitted.block + 1; i <= blockNumber; i++) {
|
||||
_this.emit('block', i);
|
||||
}
|
||||
// The emitted block was updated, check for obsolete events
|
||||
if (_this._emitted.block !== blockNumber) {
|
||||
_this._emitted.block = blockNumber;
|
||||
Object.keys(_this._emitted).forEach(function (key) {
|
||||
// The block event does not expire
|
||||
if (key === 'block') {
|
||||
return;
|
||||
}
|
||||
// The block we were at when we emitted this event
|
||||
var eventBlockNumber = _this._emitted[key];
|
||||
// We cannot garbage collect pending transactions or blocks here
|
||||
// They should be garbage collected by the Provider when setting
|
||||
// "pending" events
|
||||
if (eventBlockNumber === 'pending') {
|
||||
return;
|
||||
}
|
||||
// Evict any transaction hashes or block hashes over 12 blocks
|
||||
// old, since they should not return null anyways
|
||||
Object.keys(_this._emitted).forEach(function (key) {
|
||||
if (key === 'block') {
|
||||
return;
|
||||
}
|
||||
if (_this._emitted[key] > i + 12) {
|
||||
delete _this._emitted[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
_this.emit('block', i);
|
||||
};
|
||||
// Notify all listener for each block that has passed
|
||||
for (var i = _this._lastBlockNumber + 1; i <= blockNumber; i++) {
|
||||
_loop_1(i);
|
||||
if (blockNumber - eventBlockNumber > 12) {
|
||||
delete _this._emitted[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
// First polling cycle
|
||||
if (_this._lastBlockNumber === -2) {
|
||||
_this._lastBlockNumber = blockNumber - 1;
|
||||
}
|
||||
// Sweep balances and remove addresses we no longer have events for
|
||||
var newBalances = {};
|
||||
// Find all transaction hashes we are waiting on
|
||||
var uniqueEventTags = {};
|
||||
_this._events.forEach(function (event) {
|
||||
var comps = event.tag.split(':');
|
||||
uniqueEventTags[event.tag] = true;
|
||||
});
|
||||
Object.keys(uniqueEventTags).forEach(function (tag) {
|
||||
var comps = tag.split(':');
|
||||
switch (comps[0]) {
|
||||
case 'tx': {
|
||||
var hash_2 = comps[1];
|
||||
@@ -485,12 +523,12 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
newBalances[address_2] = _this._balances[address_2];
|
||||
}
|
||||
_this.getBalance(address_2, 'latest').then(function (balance) {
|
||||
var lastBalance = this._balances[address_2];
|
||||
var lastBalance = _this._balances[address_2];
|
||||
if (lastBalance && balance.eq(lastBalance)) {
|
||||
return;
|
||||
}
|
||||
this._balances[address_2] = balance;
|
||||
this.emit(address_2, balance);
|
||||
_this._balances[address_2] = balance;
|
||||
_this.emit(address_2, balance);
|
||||
return null;
|
||||
}).catch(function (error) { _this.emit('error', error); });
|
||||
break;
|
||||
@@ -528,8 +566,10 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
this.doPoll();
|
||||
};
|
||||
BaseProvider.prototype.resetEventsBlock = function (blockNumber) {
|
||||
this._lastBlockNumber = blockNumber;
|
||||
this._doPoll();
|
||||
this._lastBlockNumber = blockNumber - 1;
|
||||
if (this.polling) {
|
||||
this._doPoll();
|
||||
}
|
||||
};
|
||||
Object.defineProperty(BaseProvider.prototype, "network", {
|
||||
get: function () {
|
||||
@@ -543,10 +583,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
};
|
||||
Object.defineProperty(BaseProvider.prototype, "blockNumber", {
|
||||
get: function () {
|
||||
if (this._lastBlockNumber < 0) {
|
||||
return null;
|
||||
}
|
||||
return this._lastBlockNumber;
|
||||
return this._fastBlockNumber;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
@@ -560,6 +597,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
setTimeout(function () {
|
||||
if (value && !_this._poller) {
|
||||
_this._poller = setInterval(_this._doPoll.bind(_this), _this.pollingInterval);
|
||||
_this._doPoll();
|
||||
}
|
||||
else if (!value && _this._poller) {
|
||||
clearInterval(_this._poller);
|
||||
@@ -620,17 +658,24 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
// this will be used once we move to the WebSocket or other alternatives to polling
|
||||
BaseProvider.prototype.waitForTransaction = function (transactionHash, confirmations) {
|
||||
var _this = this;
|
||||
if (!confirmations) {
|
||||
if (confirmations == null) {
|
||||
confirmations = 1;
|
||||
}
|
||||
return web_1.poll(function () {
|
||||
return _this.getTransactionReceipt(transactionHash).then(function (receipt) {
|
||||
if (receipt == null || receipt.confirmations < confirmations) {
|
||||
return undefined;
|
||||
}
|
||||
return this.getTransactionReceipt(transactionHash).then(function (receipt) {
|
||||
if (confirmations === 0 || (receipt && receipt.confirmations >= confirmations)) {
|
||||
return receipt;
|
||||
});
|
||||
}, { onceBlock: this });
|
||||
}
|
||||
return (new Promise(function (resolve) {
|
||||
var handler = function (receipt) {
|
||||
if (receipt.confirmations < confirmations) {
|
||||
return;
|
||||
}
|
||||
_this.removeListener(transactionHash, handler);
|
||||
resolve(receipt);
|
||||
};
|
||||
_this.on(transactionHash, handler);
|
||||
}));
|
||||
});
|
||||
};
|
||||
BaseProvider.prototype.getBlockNumber = function () {
|
||||
var _this = this;
|
||||
@@ -658,7 +703,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(function (_a) {
|
||||
var addressOrName = _a.addressOrName, blockTag = _a.blockTag;
|
||||
return _this.resolveName(addressOrName).then(function (address) {
|
||||
return _this._getAddress(addressOrName).then(function (address) {
|
||||
var params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
return _this.perform('getBalance', params).then(function (result) {
|
||||
return bignumber_1.bigNumberify(result);
|
||||
@@ -672,7 +717,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(function (_a) {
|
||||
var addressOrName = _a.addressOrName, blockTag = _a.blockTag;
|
||||
return _this.resolveName(addressOrName).then(function (address) {
|
||||
return _this._getAddress(addressOrName).then(function (address) {
|
||||
var params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
return _this.perform('getTransactionCount', params).then(function (result) {
|
||||
return bignumber_1.bigNumberify(result).toNumber();
|
||||
@@ -686,7 +731,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(function (_a) {
|
||||
var addressOrName = _a.addressOrName, blockTag = _a.blockTag;
|
||||
return _this.resolveName(addressOrName).then(function (address) {
|
||||
return _this._getAddress(addressOrName).then(function (address) {
|
||||
var params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
return _this.perform('getCode', params).then(function (result) {
|
||||
return bytes_1.hexlify(result);
|
||||
@@ -700,7 +745,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ addressOrName: addressOrName, position: position, blockTag: blockTag }).then(function (_a) {
|
||||
var addressOrName = _a.addressOrName, position = _a.position, blockTag = _a.blockTag;
|
||||
return _this.resolveName(addressOrName).then(function (address) {
|
||||
return _this._getAddress(addressOrName).then(function (address) {
|
||||
var params = {
|
||||
address: address,
|
||||
blockTag: checkBlockTag(blockTag),
|
||||
@@ -742,10 +787,20 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
if (hash != null && tx.hash !== hash) {
|
||||
errors.throwError('Transaction hash mismatch from Provider.sendTransaction.', errors.UNKNOWN_ERROR, { expectedHash: tx.hash, returnedHash: hash });
|
||||
}
|
||||
this._emitted['t:' + tx.hash] = 'pending';
|
||||
// @TODO: (confirmations? number, timeout? number)
|
||||
result.wait = function (confirmations) {
|
||||
// We know this transaction *must* exist (whether it gets mined is
|
||||
// another story), so setting an emitted value forces us to
|
||||
// wait even if the node returns null for the receipt
|
||||
if (confirmations !== 0) {
|
||||
_this._emitted['t:' + tx.hash] = 'pending';
|
||||
}
|
||||
return _this.waitForTransaction(tx.hash, confirmations).then(function (receipt) {
|
||||
if (receipt == null && confirmations === 0) {
|
||||
return null;
|
||||
}
|
||||
// No longer pending, allow the polling loop to garbage collect this
|
||||
_this._emitted['t:' + tx.hash] = receipt.blockNumber;
|
||||
if (receipt.status === 0) {
|
||||
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
|
||||
transactionHash: tx.hash,
|
||||
@@ -823,7 +878,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getBlock', { blockTag: blockTag_1, includeTransactions: !!includeTransactions }).then(function (block) {
|
||||
if (block == null) {
|
||||
if (blockNumber_1 > _this._emitted.block) {
|
||||
if (blockNumber_1 <= _this._emitted.block) {
|
||||
return undefined;
|
||||
}
|
||||
return null;
|
||||
@@ -842,7 +897,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ transactionHash: transactionHash }).then(function (_a) {
|
||||
var transactionHash = _a.transactionHash;
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
var params = { transactionHash: checkHash(transactionHash, true) };
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getTransaction', params).then(function (result) {
|
||||
if (result == null) {
|
||||
@@ -877,7 +932,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.ready.then(function () {
|
||||
return properties_1.resolveProperties({ transactionHash: transactionHash }).then(function (_a) {
|
||||
var transactionHash = _a.transactionHash;
|
||||
var params = { transactionHash: checkHash(transactionHash) };
|
||||
var params = { transactionHash: checkHash(transactionHash, true) };
|
||||
return web_1.poll(function () {
|
||||
return _this.perform('getTransactionReceipt', params).then(function (result) {
|
||||
if (result == null) {
|
||||
@@ -933,6 +988,14 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
});
|
||||
});
|
||||
};
|
||||
BaseProvider.prototype._getAddress = function (addressOrName) {
|
||||
return this.resolveName(addressOrName).then(function (address) {
|
||||
if (address == null) {
|
||||
errors.throwError("ENS name not configured", errors.UNSUPPORTED_OPERATION, { operation: "resolveName(" + JSON.stringify(addressOrName) + ")" });
|
||||
}
|
||||
return address;
|
||||
});
|
||||
};
|
||||
// @TODO: Could probably use resolveProperties instead?
|
||||
BaseProvider.prototype._resolveNames = function (object, keys) {
|
||||
var promises = [];
|
||||
@@ -941,7 +1004,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
if (result[key] == null) {
|
||||
return;
|
||||
}
|
||||
promises.push(this.resolveName(result[key]).then(function (address) {
|
||||
promises.push(this._getAddress(result[key]).then(function (address) {
|
||||
result[key] = address;
|
||||
return;
|
||||
}));
|
||||
@@ -954,7 +1017,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return this.getNetwork().then(function (network) {
|
||||
// No ENS...
|
||||
if (!network.ensAddress) {
|
||||
errors.throwError('network does support ENS', errors.UNSUPPORTED_OPERATION, { operation: 'ENS', network: network.name });
|
||||
errors.throwError('network does not support ENS', errors.UNSUPPORTED_OPERATION, { operation: 'ENS', network: network.name });
|
||||
}
|
||||
// keccak256('resolver(bytes32)')
|
||||
var data = '0x0178b8bf' + hash_1.namehash(name).substring(2);
|
||||
@@ -964,7 +1027,11 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
if (bytes_1.hexDataLength(data) !== 32) {
|
||||
return null;
|
||||
}
|
||||
return address_1.getAddress(bytes_1.hexDataSlice(data, 12));
|
||||
var address = address_1.getAddress(bytes_1.hexDataSlice(data, 12));
|
||||
if (address === constants_1.AddressZero) {
|
||||
return null;
|
||||
}
|
||||
return address;
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -985,6 +1052,9 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
var nodeHash = hash_1.namehash(name);
|
||||
// Get the addr from the resovler
|
||||
return this._getResolver(name).then(function (resolverAddress) {
|
||||
if (resolverAddress == null) {
|
||||
return null;
|
||||
}
|
||||
// keccak256('addr(bytes32)')
|
||||
var data = '0x3b3b57de' + nodeHash.substring(2);
|
||||
var transaction = { to: resolverAddress, data: data };
|
||||
@@ -995,7 +1065,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return null;
|
||||
}
|
||||
var address = address_1.getAddress(bytes_1.hexDataSlice(data, 12));
|
||||
if (address === '0x0000000000000000000000000000000000000000') {
|
||||
if (address === constants_1.AddressZero) {
|
||||
return null;
|
||||
}
|
||||
return address;
|
||||
@@ -1021,6 +1091,9 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
var transaction = { to: resolverAddress, data: data };
|
||||
return self.call(transaction);
|
||||
}).then(function (data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
// Strip off the "0x"
|
||||
data = data.substring(2);
|
||||
// Strip off the dynamic string pointer (0x20)
|
||||
@@ -1056,7 +1129,7 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
return null;
|
||||
};
|
||||
BaseProvider.prototype._startPending = function () {
|
||||
console.log('WARNING: this provider does not support pending events');
|
||||
errors.warn('WARNING: this provider does not support pending events');
|
||||
};
|
||||
BaseProvider.prototype._stopPending = function () {
|
||||
};
|
||||
@@ -1123,13 +1196,19 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
});
|
||||
};
|
||||
BaseProvider.prototype.removeAllListeners = function (eventName) {
|
||||
var eventTag = getEventTag(eventName);
|
||||
this._events = this._events.filter(function (event) {
|
||||
return (event.tag !== eventTag);
|
||||
});
|
||||
if (eventName === 'pending') {
|
||||
if (eventName == null) {
|
||||
this._events = [];
|
||||
this._stopPending();
|
||||
}
|
||||
else {
|
||||
var eventTag_1 = getEventTag(eventName);
|
||||
this._events = this._events.filter(function (event) {
|
||||
return (event.tag !== eventTag_1);
|
||||
});
|
||||
if (eventName === 'pending') {
|
||||
this._stopPending();
|
||||
}
|
||||
}
|
||||
if (this._events.length === 0) {
|
||||
this.polling = false;
|
||||
}
|
||||
@@ -1139,13 +1218,13 @@ var BaseProvider = /** @class */ (function (_super) {
|
||||
var found = false;
|
||||
var eventTag = getEventTag(eventName);
|
||||
this._events = this._events.filter(function (event) {
|
||||
if (event.tag !== eventTag) {
|
||||
if (event.tag !== eventTag || event.listener != listener) {
|
||||
return true;
|
||||
}
|
||||
if (found) {
|
||||
return true;
|
||||
}
|
||||
found = false;
|
||||
found = true;
|
||||
return false;
|
||||
});
|
||||
if (eventName === 'pending' && this.listenerCount('pending') === 0) {
|
||||
|
||||
@@ -104,6 +104,9 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
case 'kovan':
|
||||
baseUrl = 'https://api-kovan.etherscan.io';
|
||||
break;
|
||||
case 'goerli':
|
||||
baseUrl = 'https://api-goerli.etherscan.io';
|
||||
break;
|
||||
default:
|
||||
throw new Error('unsupported network');
|
||||
}
|
||||
@@ -226,6 +229,16 @@ var EtherscanProvider = /** @class */ (function (_super) {
|
||||
if (params.filter.toBlock) {
|
||||
url += '&toBlock=' + checkLogTag(params.filter.toBlock);
|
||||
}
|
||||
if (params.filter.blockHash) {
|
||||
try {
|
||||
errors.throwError("Etherscan does not support blockHash filters", errors.UNSUPPORTED_OPERATION, {
|
||||
operation: "getLogs(blockHash)"
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
if (params.filter.address) {
|
||||
url += '&address=' + params.filter.address;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ function checkNetworks(networks) {
|
||||
// Matches!
|
||||
if (check.name === network.name &&
|
||||
check.chainId === network.chainId &&
|
||||
check.ensAddress === network.ensAddress) {
|
||||
((check.ensAddress === network.ensAddress) ||
|
||||
(check.ensAddress == null && network.ensAddress == null))) {
|
||||
return;
|
||||
}
|
||||
errors.throwError('provider mismatch', errors.INVALID_ARGUMENT, { arg: 'networks', value: networks });
|
||||
|
||||
3
providers/infura-provider.d.ts
vendored
3
providers/infura-provider.d.ts
vendored
@@ -2,7 +2,8 @@ import { JsonRpcProvider, JsonRpcSigner } from './json-rpc-provider';
|
||||
import { Networkish } from '../utils/networks';
|
||||
export declare class InfuraProvider extends JsonRpcProvider {
|
||||
readonly apiAccessToken: string;
|
||||
constructor(network?: Networkish, apiAccessToken?: string);
|
||||
readonly projectId: string;
|
||||
constructor(network?: Networkish, projectId?: string);
|
||||
protected _startPending(): void;
|
||||
getSigner(address?: string): JsonRpcSigner;
|
||||
listAccounts(): Promise<Array<string>>;
|
||||
|
||||
@@ -18,16 +18,21 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var json_rpc_provider_1 = require("./json-rpc-provider");
|
||||
var bytes_1 = require("../utils/bytes");
|
||||
var networks_1 = require("../utils/networks");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var errors = __importStar(require("../errors"));
|
||||
var defaultProjectId = "7d0d81d0919f4f05b9ab6634be01ee73";
|
||||
var InfuraProvider = /** @class */ (function (_super) {
|
||||
__extends(InfuraProvider, _super);
|
||||
function InfuraProvider(network, apiAccessToken) {
|
||||
function InfuraProvider(network, projectId) {
|
||||
var _this = this;
|
||||
network = networks_1.getNetwork((network == null) ? 'homestead' : network);
|
||||
var standard = networks_1.getNetwork((network == null) ? 'homestead' : network);
|
||||
if (projectId == null) {
|
||||
projectId = defaultProjectId;
|
||||
}
|
||||
var host = null;
|
||||
switch (network.name) {
|
||||
switch (standard.name) {
|
||||
case 'homestead':
|
||||
host = 'mainnet.infura.io';
|
||||
break;
|
||||
@@ -37,23 +42,39 @@ var InfuraProvider = /** @class */ (function (_super) {
|
||||
case 'rinkeby':
|
||||
host = 'rinkeby.infura.io';
|
||||
break;
|
||||
case 'goerli':
|
||||
host = 'goerli.infura.io';
|
||||
break;
|
||||
case 'kovan':
|
||||
host = 'kovan.infura.io';
|
||||
break;
|
||||
default:
|
||||
throw new Error('unsupported network');
|
||||
errors.throwError('unsupported network', errors.INVALID_ARGUMENT, {
|
||||
argument: "network",
|
||||
value: network
|
||||
});
|
||||
}
|
||||
// New-style Project ID
|
||||
if (bytes_1.isHexString("0x" + projectId, 16)) {
|
||||
_this = _super.call(this, 'https://' + host + '/v3/' + projectId, standard) || this;
|
||||
properties_1.defineReadOnly(_this, 'apiAccessToken', null);
|
||||
properties_1.defineReadOnly(_this, 'projectId', projectId);
|
||||
// Legacy API Access Token
|
||||
}
|
||||
else {
|
||||
errors.warn("The legacy INFURA apiAccesToken API is deprecated; please upgrade to a Project ID instead (see INFURA dshboard; https://infura.io)");
|
||||
_this = _super.call(this, 'https://' + host + '/' + projectId, standard) || this;
|
||||
properties_1.defineReadOnly(_this, 'apiAccessToken', projectId);
|
||||
properties_1.defineReadOnly(_this, 'projectId', null);
|
||||
}
|
||||
_this = _super.call(this, 'https://' + host + '/' + (apiAccessToken || ''), network) || this;
|
||||
errors.checkNew(_this, InfuraProvider);
|
||||
properties_1.defineReadOnly(_this, 'apiAccessToken', apiAccessToken || null);
|
||||
return _this;
|
||||
}
|
||||
InfuraProvider.prototype._startPending = function () {
|
||||
console.log('WARNING: INFURA does not support pending filters');
|
||||
errors.warn('WARNING: INFURA does not support pending filters');
|
||||
};
|
||||
InfuraProvider.prototype.getSigner = function (address) {
|
||||
errors.throwError('INFURA does not support signing', errors.UNSUPPORTED_OPERATION, { operation: 'getSigner' });
|
||||
return null;
|
||||
return errors.throwError('INFURA does not support signing', errors.UNSUPPORTED_OPERATION, { operation: 'getSigner' });
|
||||
};
|
||||
InfuraProvider.prototype.listAccounts = function () {
|
||||
return Promise.resolve([]);
|
||||
|
||||
@@ -29,7 +29,9 @@ var IpcProvider = /** @class */ (function (_super) {
|
||||
function IpcProvider(path, network) {
|
||||
var _this = this;
|
||||
if (path == null) {
|
||||
errors.throwError('missing path', errors.MISSING_ARGUMENT, { arg: 'path' });
|
||||
errors.throwError('missing path', errors.MISSING_ARGUMENT, {
|
||||
argument: 'path'
|
||||
});
|
||||
}
|
||||
_this = _super.call(this, 'ipc://' + path, network) || this;
|
||||
errors.checkNew(_this, IpcProvider);
|
||||
@@ -50,10 +52,14 @@ var IpcProvider = /** @class */ (function (_super) {
|
||||
jsonrpc: "2.0"
|
||||
});
|
||||
return new Promise(function (resolve, reject) {
|
||||
var response = Buffer.alloc(0);
|
||||
var stream = net_1.default.connect(_this.path);
|
||||
stream.on('data', function (data) {
|
||||
response = Buffer.concat([response, data]);
|
||||
});
|
||||
stream.on("end", function () {
|
||||
try {
|
||||
resolve(JSON.parse(data.toString('utf8')).result);
|
||||
resolve(JSON.parse(response.toString('utf8')).result);
|
||||
// @TODO: Better pull apart the error
|
||||
stream.destroy();
|
||||
}
|
||||
@@ -62,9 +68,6 @@ var IpcProvider = /** @class */ (function (_super) {
|
||||
stream.destroy();
|
||||
}
|
||||
});
|
||||
stream.on('end', function () {
|
||||
stream.destroy();
|
||||
});
|
||||
stream.on('error', function (error) {
|
||||
reject(error);
|
||||
stream.destroy();
|
||||
|
||||
1
providers/json-rpc-provider.d.ts
vendored
1
providers/json-rpc-provider.d.ts
vendored
@@ -13,6 +13,7 @@ export declare class JsonRpcSigner extends Signer {
|
||||
getAddress(): Promise<string>;
|
||||
getBalance(blockTag?: BlockTag): Promise<BigNumber>;
|
||||
getTransactionCount(blockTag?: BlockTag): Promise<number>;
|
||||
sendUncheckedTransaction(transaction: TransactionRequest): Promise<string>;
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse>;
|
||||
signMessage(message: Arrayish | string): Promise<string>;
|
||||
unlock(password: string): Promise<boolean>;
|
||||
|
||||
@@ -25,7 +25,6 @@ var address_1 = require("../utils/address");
|
||||
var bytes_1 = require("../utils/bytes");
|
||||
var networks_1 = require("../utils/networks");
|
||||
var properties_1 = require("../utils/properties");
|
||||
var transaction_1 = require("../utils/transaction");
|
||||
var utf8_1 = require("../utils/utf8");
|
||||
var web_1 = require("../utils/web");
|
||||
function timer(timeout) {
|
||||
@@ -52,6 +51,10 @@ function getLowerCase(value) {
|
||||
return value;
|
||||
}
|
||||
var _constructorGuard = {};
|
||||
// Some environments (Trust Wallet and company) use a global map
|
||||
// to track JSON-RPC ID, so we try to keep IDs unique across all
|
||||
// connections. See #489.
|
||||
var _nextId = 42;
|
||||
var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
__extends(JsonRpcSigner, _super);
|
||||
function JsonRpcSigner(constructorGuard, provider, addressOrIndex) {
|
||||
@@ -97,31 +100,32 @@ var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
JsonRpcSigner.prototype.getTransactionCount = function (blockTag) {
|
||||
return this.provider.getTransactionCount(this.getAddress(), blockTag);
|
||||
};
|
||||
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
|
||||
JsonRpcSigner.prototype.sendUncheckedTransaction = function (transaction) {
|
||||
var _this = this;
|
||||
// Once populateTransaction resolves, the from address will be populated from getAddress
|
||||
var from = null;
|
||||
var getAddress = this.getAddress().then(function (address) {
|
||||
transaction = properties_1.shallowCopy(transaction);
|
||||
var fromAddress = this.getAddress().then(function (address) {
|
||||
if (address) {
|
||||
from = address.toLowerCase();
|
||||
address = address.toLowerCase();
|
||||
}
|
||||
return from;
|
||||
return address;
|
||||
});
|
||||
return transaction_1.populateTransaction(transaction, this.provider, getAddress).then(function (tx) {
|
||||
// The JSON-RPC for eth_sendTransaction uses 90000 gas; if the user
|
||||
// wishes to use this, it is easy to specify explicitly, otherwise
|
||||
// we look it up for them.
|
||||
if (transaction.gasLimit == null) {
|
||||
var estimate = properties_1.shallowCopy(transaction);
|
||||
estimate.from = fromAddress;
|
||||
transaction.gasLimit = this.provider.estimateGas(estimate);
|
||||
}
|
||||
return Promise.all([
|
||||
properties_1.resolveProperties(transaction),
|
||||
fromAddress
|
||||
]).then(function (results) {
|
||||
var tx = results[0];
|
||||
var hexTx = JsonRpcProvider.hexlifyTransaction(tx);
|
||||
hexTx.from = from;
|
||||
hexTx.from = results[1];
|
||||
return _this.provider.send('eth_sendTransaction', [hexTx]).then(function (hash) {
|
||||
return web_1.poll(function () {
|
||||
return _this.provider.getTransaction(hash).then(function (tx) {
|
||||
if (tx === null) {
|
||||
return undefined;
|
||||
}
|
||||
return _this.provider._wrapTransaction(tx, hash);
|
||||
});
|
||||
}, { onceBlock: _this.provider }).catch(function (error) {
|
||||
error.transactionHash = hash;
|
||||
throw error;
|
||||
});
|
||||
return hash;
|
||||
}, function (error) {
|
||||
if (error.responseText) {
|
||||
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
|
||||
@@ -145,6 +149,22 @@ var JsonRpcSigner = /** @class */ (function (_super) {
|
||||
});
|
||||
});
|
||||
};
|
||||
JsonRpcSigner.prototype.sendTransaction = function (transaction) {
|
||||
var _this = this;
|
||||
return this.sendUncheckedTransaction(transaction).then(function (hash) {
|
||||
return web_1.poll(function () {
|
||||
return _this.provider.getTransaction(hash).then(function (tx) {
|
||||
if (tx === null) {
|
||||
return undefined;
|
||||
}
|
||||
return _this.provider._wrapTransaction(tx, hash);
|
||||
});
|
||||
}, { fastRetry: 250, onceBlock: _this.provider }).catch(function (error) {
|
||||
error.transactionHash = hash;
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
};
|
||||
JsonRpcSigner.prototype.signMessage = function (message) {
|
||||
var _this = this;
|
||||
var data = ((typeof (message) === 'string') ? utf8_1.toUtf8Bytes(message) : message);
|
||||
@@ -221,7 +241,7 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
var request = {
|
||||
method: method,
|
||||
params: params,
|
||||
id: 42,
|
||||
id: (_nextId++),
|
||||
jsonrpc: "2.0"
|
||||
};
|
||||
return web_1.fetchJson(this.connection, JSON.stringify(request), getResult).then(function (result) {
|
||||
@@ -308,6 +328,7 @@ var JsonRpcProvider = /** @class */ (function (_super) {
|
||||
}
|
||||
var seq = Promise.resolve();
|
||||
hashes.forEach(function (hash) {
|
||||
// @TODO: This should be garbage collected at some point... How? When?
|
||||
self._emitted['t:' + hash.toLowerCase()] = 'pending';
|
||||
seq = seq.then(function () {
|
||||
return self.getTransaction(hash).then(function (tx) {
|
||||
|
||||
@@ -27,6 +27,7 @@ utils.defineProperty(Web3Signer, 'onchange', {
|
||||
});
|
||||
|
||||
*/
|
||||
var _nextId = 42;
|
||||
var Web3Provider = /** @class */ (function (_super) {
|
||||
__extends(Web3Provider, _super);
|
||||
function Web3Provider(web3Provider, network) {
|
||||
@@ -46,6 +47,8 @@ var Web3Provider = /** @class */ (function (_super) {
|
||||
errors.throwError('invalid web3Provider', errors.INVALID_ARGUMENT, { arg: 'web3Provider', value: web3Provider });
|
||||
}
|
||||
properties_1.defineReadOnly(_this, '_web3Provider', web3Provider);
|
||||
// @TODO: In v5 remove the above definition; only this one is needed
|
||||
properties_1.defineReadOnly(_this, 'provider', web3Provider);
|
||||
return _this;
|
||||
}
|
||||
Web3Provider.prototype.send = function (method, params) {
|
||||
@@ -60,7 +63,7 @@ var Web3Provider = /** @class */ (function (_super) {
|
||||
var request = {
|
||||
method: method,
|
||||
params: params,
|
||||
id: 42,
|
||||
id: (_nextId++),
|
||||
jsonrpc: "2.0"
|
||||
};
|
||||
_this._sendAsync(request, function (error, result) {
|
||||
@@ -70,10 +73,10 @@ var Web3Provider = /** @class */ (function (_super) {
|
||||
}
|
||||
if (result.error) {
|
||||
// @TODO: not any
|
||||
var error = new Error(result.error.message);
|
||||
error.code = result.error.code;
|
||||
error.data = result.error.data;
|
||||
reject(error);
|
||||
var error_1 = new Error(result.error.message);
|
||||
error_1.code = result.error.code;
|
||||
error_1.data = result.error.data;
|
||||
reject(error_1);
|
||||
return;
|
||||
}
|
||||
resolve(result.result);
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const version = "4.0.8";
|
||||
export const version = "4.0.41";
|
||||
|
||||
@@ -181,8 +181,7 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
}
|
||||
});
|
||||
|
||||
// Send to the contract address (after checking the contract is deployed)
|
||||
tx.to = contract.deployed().then(() => {
|
||||
tx.to = contract._deployed(blockTag).then(() => {
|
||||
return contract.addressPromise;
|
||||
});
|
||||
|
||||
@@ -211,7 +210,6 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
}
|
||||
|
||||
return contract.provider.call(tx, blockTag).then((value) => {
|
||||
|
||||
if ((hexDataLength(value) % 32) === 4 && hexDataSlice(value, 0, 4) === '0x08c379a0') {
|
||||
let reason = defaultAbiCoder.decode([ 'string' ], hexDataSlice(value, 4));
|
||||
errors.throwError('call revert exception', errors.CALL_EXCEPTION, {
|
||||
@@ -264,7 +262,7 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
}
|
||||
|
||||
if (!contract.signer) {
|
||||
errors.throwError('sending a transaction require a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' })
|
||||
errors.throwError('sending a transaction requires a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction' })
|
||||
}
|
||||
|
||||
// Make sure they aren't overriding something they shouldn't
|
||||
@@ -280,7 +278,7 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
receipt.events = receipt.logs.map((log) => {
|
||||
let event: Event = (<Event>deepCopy(log));
|
||||
|
||||
let parsed = this.interface.parseLog(log);
|
||||
let parsed = contract.interface.parseLog(log);
|
||||
if (parsed) {
|
||||
event.args = parsed.values;
|
||||
event.decode = parsed.decode;
|
||||
@@ -288,12 +286,12 @@ function runMethod(contract: Contract, functionName: string, estimateOnly: boole
|
||||
event.eventSignature = parsed.signature;
|
||||
}
|
||||
|
||||
event.removeListener = () => { return this.provider; }
|
||||
event.removeListener = () => { return contract.provider; }
|
||||
event.getBlock = () => {
|
||||
return this.provider.getBlock(receipt.blockHash);
|
||||
return contract.provider.getBlock(receipt.blockHash);
|
||||
}
|
||||
event.getTransaction = () => {
|
||||
return this.provider.getTransaction(receipt.transactionHash);
|
||||
return contract.provider.getTransaction(receipt.transactionHash);
|
||||
}
|
||||
event.getTransactionReceipt = () => {
|
||||
return Promise.resolve(receipt);
|
||||
@@ -360,7 +358,7 @@ export class Contract {
|
||||
// This is only set if the contract was created with a call to deploy
|
||||
readonly deployTransaction: TransactionResponse;
|
||||
|
||||
private _deployed: Promise<Contract>;
|
||||
private _deployedPromise: Promise<Contract>;
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/5453
|
||||
// Once this issue is resolved (there are open PR) we can do this nicer
|
||||
@@ -411,7 +409,6 @@ export class Contract {
|
||||
if (address == null) { throw new Error('name not found'); }
|
||||
return address;
|
||||
}).catch((error: Error) => {
|
||||
console.log('ERROR: Cannot find Contract - ' + addressOrName);
|
||||
throw error;
|
||||
}));
|
||||
} else {
|
||||
@@ -429,7 +426,7 @@ export class Contract {
|
||||
if ((<any>this)[name] == null) {
|
||||
defineReadOnly(this, name, run);
|
||||
} else {
|
||||
console.log('WARNING: Multiple definitions for ' + name);
|
||||
errors.warn('WARNING: Multiple definitions for ' + name);
|
||||
}
|
||||
|
||||
if (this.functions[name] == null) {
|
||||
@@ -441,11 +438,15 @@ export class Contract {
|
||||
|
||||
// @TODO: Allow timeout?
|
||||
deployed(): Promise<Contract> {
|
||||
if (!this._deployed) {
|
||||
return this._deployed();
|
||||
}
|
||||
|
||||
_deployed(blockTag?: BlockTag): Promise<Contract> {
|
||||
if (!this._deployedPromise) {
|
||||
|
||||
// If we were just deployed, we know the transaction we should occur in
|
||||
if (this.deployTransaction) {
|
||||
this._deployed = this.deployTransaction.wait().then(() => {
|
||||
this._deployedPromise = this.deployTransaction.wait().then(() => {
|
||||
return this;
|
||||
});
|
||||
|
||||
@@ -454,7 +455,7 @@ export class Contract {
|
||||
// up to that many blocks for getCode
|
||||
|
||||
// Otherwise, poll for our code to be deployed
|
||||
this._deployed = this.provider.getCode(this.address).then((code) => {
|
||||
this._deployedPromise = this.provider.getCode(this.address, blockTag).then((code) => {
|
||||
if (code === '0x') {
|
||||
errors.throwError('contract not deployed', errors.UNSUPPORTED_OPERATION, {
|
||||
contractAddress: this.address,
|
||||
@@ -466,7 +467,7 @@ export class Contract {
|
||||
}
|
||||
}
|
||||
|
||||
return this._deployed;
|
||||
return this._deployedPromise;
|
||||
}
|
||||
|
||||
// @TODO:
|
||||
@@ -477,7 +478,7 @@ export class Contract {
|
||||
|
||||
fallback(overrides?: TransactionRequest): Promise<TransactionResponse> {
|
||||
if (!this.signer) {
|
||||
errors.throwError('sending a transaction require a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction(fallback)' })
|
||||
errors.throwError('sending a transaction requires a signer', errors.UNSUPPORTED_OPERATION, { operation: 'sendTransaction(fallback)' })
|
||||
}
|
||||
|
||||
var tx: TransactionRequest = shallowCopy(overrides || {});
|
||||
@@ -697,7 +698,15 @@ export class Contract {
|
||||
|
||||
let eventFilter = this._getEventFilter(eventName);
|
||||
this._events = this._events.filter((event) => {
|
||||
return event.eventFilter.eventTag !== eventFilter.eventTag
|
||||
|
||||
// Keep all other events
|
||||
if (event.eventFilter.eventTag !== eventFilter.eventTag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Deregister this event from the provider and filter it out
|
||||
this.provider.removeListener(event.eventFilter.filter, event.wrappedListener);
|
||||
return false;
|
||||
});
|
||||
|
||||
return this;
|
||||
@@ -799,7 +808,7 @@ export class ContractFactory {
|
||||
});
|
||||
|
||||
// Make sure the call matches the constructor signature
|
||||
errors.checkArgumentCount(args.length, this.interface.deployFunction.inputs.length, 'in Contract constructor');
|
||||
errors.checkArgumentCount(args.length, this.interface.deployFunction.inputs.length, ' in Contract constructor');
|
||||
|
||||
// Set the data to the bytecode + the encoded constructor arguments
|
||||
tx.data = this.interface.deployFunction.encode(this.bytecode, args);
|
||||
|
||||
@@ -23,7 +23,7 @@ export const MISSING_NEW = 'MISSING_NEW';
|
||||
export const CALL_EXCEPTION = 'CALL_EXCEPTION';
|
||||
|
||||
// Invalid argument (e.g. value is incompatible with type) to a function:
|
||||
// - arg: The argument name that was invalid
|
||||
// - argument: The argument name that was invalid
|
||||
// - value: The value of the argument
|
||||
export const INVALID_ARGUMENT = 'INVALID_ARGUMENT';
|
||||
|
||||
@@ -116,9 +116,53 @@ export function checkArgumentCount(count: number, expectedCount: number, suffix?
|
||||
|
||||
export function setCensorship(censorship: boolean, permanent?: boolean): void {
|
||||
if (_permanentCensorErrors) {
|
||||
throwError('error censorship permanent', UNSUPPORTED_OPERATION, { operation: 'setCersorship' });
|
||||
throwError('error censorship permanent', UNSUPPORTED_OPERATION, { operation: 'setCensorship' });
|
||||
}
|
||||
|
||||
_censorErrors = !!censorship;
|
||||
_permanentCensorErrors = !!permanent;
|
||||
}
|
||||
|
||||
export function checkNormalize(): void {
|
||||
try {
|
||||
// Make sure all forms of normalization are supported
|
||||
["NFD", "NFC", "NFKD", "NFKC"].forEach((form) => {
|
||||
try {
|
||||
"test".normalize(form);
|
||||
} catch(error) {
|
||||
throw new Error('missing ' + form);
|
||||
}
|
||||
});
|
||||
|
||||
if (String.fromCharCode(0xe9).normalize('NFD') !== String.fromCharCode(0x65, 0x0301)) {
|
||||
throw new Error('broken implementation')
|
||||
}
|
||||
} catch (error) {
|
||||
throwError('platform missing String.prototype.normalize', UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize', form: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
const LogLevels: { [ name: string ]: number } = { debug: 1, "default": 2, info: 2, warn: 3, error: 4, off: 5 };
|
||||
let LogLevel = LogLevels["default"];
|
||||
|
||||
export function setLogLevel(logLevel: string): void {
|
||||
let level = LogLevels[logLevel];
|
||||
if (level == null) {
|
||||
warn("invliad log level - " + logLevel);
|
||||
return;
|
||||
}
|
||||
LogLevel = level;
|
||||
}
|
||||
|
||||
function log(logLevel: string, args: Array<any>): void {
|
||||
if (LogLevel > LogLevels[logLevel]) { return; }
|
||||
console.log.apply(console, args);
|
||||
}
|
||||
|
||||
export function warn(...args: Array<any>): void {
|
||||
log("warn", args);
|
||||
}
|
||||
|
||||
export function info(...args: Array<any>): void {
|
||||
log("info", args);
|
||||
}
|
||||
|
||||
@@ -33,10 +33,15 @@ import { ContractFunction, ContractTransaction, Event, EventFilter } from './con
|
||||
// Helper Functions
|
||||
|
||||
function getDefaultProvider(network?: utils.Network | string): providers.BaseProvider {
|
||||
return new providers.FallbackProvider([
|
||||
new providers.InfuraProvider(network),
|
||||
new providers.EtherscanProvider(network),
|
||||
]);
|
||||
if (network == null) { network = 'homestead'; }
|
||||
let n = utils.getNetwork(network);
|
||||
if (!n || !n._defaultProvider) {
|
||||
errors.throwError('unsupported getDefaultProvider network', errors.UNSUPPORTED_OPERATION, {
|
||||
operation: 'getDefaultProvider',
|
||||
network: network
|
||||
});
|
||||
}
|
||||
return n._defaultProvider(providers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,16 @@ export type Filter = {
|
||||
topics?: Array<string | Array<string>>,
|
||||
}
|
||||
|
||||
// @TODO: This is not supported as an EventType yet, as it will
|
||||
// need some additional work to adhere to the serialized
|
||||
// format for events. But we want to allow it for getLogs
|
||||
// for now.
|
||||
export type FilterByBlock = {
|
||||
blockHash?: string,
|
||||
address?: string,
|
||||
topics?: Array<string | Array<string>>,
|
||||
}
|
||||
|
||||
export interface Log {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
@@ -60,6 +70,8 @@ export interface Log {
|
||||
}
|
||||
|
||||
export interface TransactionReceipt {
|
||||
to?: string;
|
||||
from?: string;
|
||||
contractAddress?: string,
|
||||
transactionIndex?: number,
|
||||
root?: string,
|
||||
@@ -78,7 +90,7 @@ export interface TransactionReceipt {
|
||||
export type TransactionRequest = {
|
||||
to?: string | Promise<string>,
|
||||
from?: string | Promise<string>,
|
||||
nonce?: number | string | Promise<number | string>,
|
||||
nonce?: BigNumberish | Promise<BigNumberish>,
|
||||
|
||||
gasLimit?: BigNumberish | Promise<BigNumberish>,
|
||||
gasPrice?: BigNumberish | Promise<BigNumberish>,
|
||||
@@ -132,7 +144,7 @@ export abstract class Provider implements OnceBlockable {
|
||||
abstract getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
abstract getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
||||
|
||||
abstract getLogs(filter: Filter): Promise<Array<Log>>;
|
||||
abstract getLogs(filter: Filter | FilterByBlock): Promise<Array<Log>>;
|
||||
|
||||
abstract resolveName(name: string | Promise<string>): Promise<string>;
|
||||
abstract lookupAddress(address: string | Promise<string>): Promise<string>;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { getAddress, getContractAddress } from '../utils/address';
|
||||
import { BigNumber, bigNumberify } from '../utils/bignumber';
|
||||
import { hexDataLength, hexDataSlice, hexlify, hexStripZeros, isHexString, stripZeros } from '../utils/bytes';
|
||||
import { AddressZero } from "../constants";
|
||||
import { namehash } from '../utils/hash';
|
||||
import { getNetwork } from '../utils/networks';
|
||||
import { defineReadOnly, inheritable, resolveProperties, shallowCopy } from '../utils/properties';
|
||||
@@ -23,7 +24,7 @@ import { Provider } from './abstract-provider';
|
||||
|
||||
import {
|
||||
Block, BlockTag,
|
||||
EventType, Filter,
|
||||
EventType, Filter, FilterByBlock,
|
||||
Listener,
|
||||
Log,
|
||||
TransactionReceipt, TransactionRequest, TransactionResponse
|
||||
@@ -82,9 +83,13 @@ function arrayOf(check: CheckFunc): CheckFunc {
|
||||
});
|
||||
}
|
||||
|
||||
function checkHash(hash: any): string {
|
||||
if (typeof(hash) === 'string' && hexDataLength(hash) === 32) {
|
||||
return hash.toLowerCase();
|
||||
function checkHash(hash: any, requirePrefix?: boolean): string {
|
||||
if (typeof(hash) === 'string') {
|
||||
// geth-etc does add a "0x" prefix on receipt.root
|
||||
if (!requirePrefix && hash.substring(0, 2) !== '0x') { hash = '0x' + hash; }
|
||||
if (hexDataLength(hash) === 32) {
|
||||
return hash.toLowerCase();
|
||||
}
|
||||
}
|
||||
errors.throwError('invalid hash', errors.INVALID_ARGUMENT, { arg: 'hash', value: hash });
|
||||
return null;
|
||||
@@ -220,11 +225,15 @@ function checkTransactionResponse(transaction: any): TransactionResponse {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let result = check(formatTransaction, transaction);
|
||||
|
||||
let networkId = transaction.networkId;
|
||||
|
||||
// geth-etc returns chainId
|
||||
if (transaction.chainId != null && networkId == null && result.v == null) {
|
||||
networkId = transaction.chainId;
|
||||
}
|
||||
|
||||
if (isHexString(networkId)) {
|
||||
networkId = bigNumberify(networkId).toNumber();
|
||||
}
|
||||
@@ -306,6 +315,8 @@ function checkTransactionReceiptLog(log: any): any {
|
||||
}
|
||||
|
||||
const formatTransactionReceipt = {
|
||||
to: allowNull(getAddress, null),
|
||||
from: allowNull(getAddress, null), // Gaanche does not populate this (#400)
|
||||
contractAddress: allowNull(getAddress, null),
|
||||
transactionIndex: checkNumber,
|
||||
root: allowNull(checkHash),
|
||||
@@ -356,7 +367,16 @@ const formatFilter = {
|
||||
topics: allowNull(checkTopics, undefined),
|
||||
};
|
||||
|
||||
const formatFilterByBlock = {
|
||||
blockHash: allowNull(checkHash, undefined),
|
||||
address: allowNull(getAddress, undefined),
|
||||
topics: allowNull(checkTopics, undefined),
|
||||
};
|
||||
|
||||
function checkFilter(filter: any): any {
|
||||
if (filter && filter.blockHash) {
|
||||
return check(formatFilterByBlock, filter);
|
||||
}
|
||||
return check(formatFilter, filter);
|
||||
}
|
||||
|
||||
@@ -475,10 +495,21 @@ export class BaseProvider extends Provider {
|
||||
private _network: Network;
|
||||
|
||||
private _events: Array<_Event>;
|
||||
protected _emitted: any;
|
||||
|
||||
// To help mitigate the eventually conssitent nature of the blockchain
|
||||
// we keep a mapping of events we emit. If we emit an event X, we expect
|
||||
// that a user should be able to query for that event in the callback,
|
||||
// if the node returns null, we stall the response until we get back a
|
||||
// meaningful value, since we may be hitting a re-org, or a node that
|
||||
// has not indexed the event yet.
|
||||
// Events:
|
||||
// - t:{hash} - Transaction hash
|
||||
// - b:{hash} - BlockHash
|
||||
// - block - The most recent emitted block
|
||||
protected _emitted: { [ eventName: string ]: number | 'pending' };
|
||||
|
||||
private _pollingInterval: number;
|
||||
private _poller: any; // @TODO: what does TypeScript thing setInterval returns?
|
||||
private _poller: any; // @TODO: what does TypeScript think setInterval returns?
|
||||
|
||||
private _lastBlockNumber: number;
|
||||
|
||||
@@ -511,6 +542,9 @@ export class BaseProvider extends Provider {
|
||||
return network;
|
||||
}));
|
||||
|
||||
// Squash any "unhandled promise" errors; the don't need to be handled
|
||||
this.ready.catch((error) => { });
|
||||
|
||||
} else {
|
||||
let knownNetwork = getNetwork((network == null) ? 'homestead': network);
|
||||
if (knownNetwork) {
|
||||
@@ -532,48 +566,70 @@ export class BaseProvider extends Provider {
|
||||
|
||||
this._pollingInterval = 4000;
|
||||
|
||||
// We use this to track recent emitted events; for example, if we emit a "block" of 100
|
||||
// and we get a `getBlock(100)` request which would result in null, we should retry
|
||||
// until we get a response. This provides devs with a consistent view. Similarly for
|
||||
// transaction hashes.
|
||||
this._emitted = { block: this._lastBlockNumber };
|
||||
this._emitted = { block: -2 };
|
||||
|
||||
this._fastQueryDate = 0;
|
||||
}
|
||||
|
||||
private _doPoll(): void {
|
||||
this.getBlockNumber().then((blockNumber) => {
|
||||
if (!this.polling) { return; }
|
||||
|
||||
this._setFastBlockNumber(blockNumber);
|
||||
|
||||
// If the block hasn't changed, meh.
|
||||
if (blockNumber === this._lastBlockNumber) { return; }
|
||||
|
||||
if (this._lastBlockNumber === -2) { this._lastBlockNumber = blockNumber - 1; }
|
||||
// First polling cycle, trigger a "block" events
|
||||
if (this._emitted.block === -2) {
|
||||
this._emitted.block = blockNumber - 1;
|
||||
}
|
||||
|
||||
// Notify all listener for each block that has passed
|
||||
for (let i = this._lastBlockNumber + 1; i <= blockNumber; i++) {
|
||||
if (this._emitted.block < i) {
|
||||
this._emitted.block = i;
|
||||
for (let i = (<number>this._emitted.block) + 1; i <= blockNumber; i++) {
|
||||
this.emit('block', i);
|
||||
}
|
||||
|
||||
// The emitted block was updated, check for obsolete events
|
||||
if ((<number>this._emitted.block) !== blockNumber) {
|
||||
this._emitted.block = blockNumber;
|
||||
|
||||
Object.keys(this._emitted).forEach((key) => {
|
||||
// The block event does not expire
|
||||
if (key === 'block') { return; }
|
||||
|
||||
// The block we were at when we emitted this event
|
||||
let eventBlockNumber = this._emitted[key];
|
||||
|
||||
// We cannot garbage collect pending transactions or blocks here
|
||||
// They should be garbage collected by the Provider when setting
|
||||
// "pending" events
|
||||
if (eventBlockNumber === 'pending') { return; }
|
||||
|
||||
// Evict any transaction hashes or block hashes over 12 blocks
|
||||
// old, since they should not return null anyways
|
||||
Object.keys(this._emitted).forEach((key) => {
|
||||
if (key === 'block') { return; }
|
||||
if (blockNumber - eventBlockNumber > 12) {
|
||||
delete this._emitted[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (this._emitted[key] > i + 12) {
|
||||
delete this._emitted[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
this.emit('block', i);
|
||||
// First polling cycle
|
||||
if (this._lastBlockNumber === -2) {
|
||||
this._lastBlockNumber = blockNumber - 1;
|
||||
}
|
||||
|
||||
// Sweep balances and remove addresses we no longer have events for
|
||||
let newBalances: any = {};
|
||||
|
||||
// Find all transaction hashes we are waiting on
|
||||
let uniqueEventTags: { [ tag: string ]: boolean } = { };
|
||||
this._events.forEach((event) => {
|
||||
let comps = event.tag.split(':');
|
||||
uniqueEventTags[event.tag] = true;
|
||||
});
|
||||
|
||||
Object.keys(uniqueEventTags).forEach((tag) => {
|
||||
let comps = tag.split(':');
|
||||
switch (comps[0]) {
|
||||
case 'tx': {
|
||||
let hash = comps[1];
|
||||
@@ -583,6 +639,7 @@ export class BaseProvider extends Provider {
|
||||
this.emit(hash, receipt);
|
||||
return null;
|
||||
}).catch((error: Error) => { this.emit('error', error); });
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -591,13 +648,15 @@ export class BaseProvider extends Provider {
|
||||
if (this._balances[address]) {
|
||||
newBalances[address] = this._balances[address];
|
||||
}
|
||||
this.getBalance(address, 'latest').then(function(balance) {
|
||||
|
||||
this.getBalance(address, 'latest').then((balance) => {
|
||||
let lastBalance = this._balances[address];
|
||||
if (lastBalance && balance.eq(lastBalance)) { return; }
|
||||
this._balances[address] = balance;
|
||||
this.emit(address, balance);
|
||||
return null;
|
||||
}).catch((error: Error) => { this.emit('error', error); });
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -609,6 +668,7 @@ export class BaseProvider extends Provider {
|
||||
toBlock: blockNumber,
|
||||
topics: topics
|
||||
}
|
||||
|
||||
if (!filter.address) { delete filter.address; }
|
||||
this.getLogs(filter).then((logs) => {
|
||||
if (logs.length === 0) { return; }
|
||||
@@ -630,12 +690,13 @@ export class BaseProvider extends Provider {
|
||||
|
||||
return null;
|
||||
}).catch((error: Error) => { });
|
||||
|
||||
this.doPoll();
|
||||
}
|
||||
|
||||
resetEventsBlock(blockNumber: number): void {
|
||||
this._lastBlockNumber = blockNumber;
|
||||
this._doPoll();
|
||||
this._lastBlockNumber = blockNumber - 1;
|
||||
if (this.polling) { this._doPoll(); }
|
||||
}
|
||||
|
||||
get network(): Network {
|
||||
@@ -647,8 +708,7 @@ export class BaseProvider extends Provider {
|
||||
}
|
||||
|
||||
get blockNumber(): number {
|
||||
if (this._lastBlockNumber < 0) { return null; }
|
||||
return this._lastBlockNumber;
|
||||
return this._fastBlockNumber;
|
||||
}
|
||||
|
||||
get polling(): boolean {
|
||||
@@ -659,6 +719,7 @@ export class BaseProvider extends Provider {
|
||||
setTimeout(() => {
|
||||
if (value && !this._poller) {
|
||||
this._poller = setInterval(this._doPoll.bind(this), this.pollingInterval);
|
||||
this._doPoll();
|
||||
|
||||
} else if (!value && this._poller) {
|
||||
clearInterval(this._poller);
|
||||
@@ -719,13 +780,22 @@ export class BaseProvider extends Provider {
|
||||
// this will be used once we move to the WebSocket or other alternatives to polling
|
||||
|
||||
waitForTransaction(transactionHash: string, confirmations?: number): Promise<TransactionReceipt> {
|
||||
if (!confirmations) { confirmations = 1; }
|
||||
return poll(() => {
|
||||
return this.getTransactionReceipt(transactionHash).then((receipt) => {
|
||||
if (receipt == null || receipt.confirmations < confirmations) { return undefined; }
|
||||
if (confirmations == null) { confirmations = 1; }
|
||||
|
||||
return this.getTransactionReceipt(transactionHash).then((receipt) => {
|
||||
if (confirmations === 0 || (receipt && receipt.confirmations >= confirmations)) {
|
||||
return receipt;
|
||||
});
|
||||
}, { onceBlock: this });
|
||||
}
|
||||
|
||||
return <Promise<TransactionReceipt>>(new Promise((resolve) => {
|
||||
let handler = (receipt: TransactionReceipt) => {
|
||||
if (receipt.confirmations < confirmations) { return; }
|
||||
this.removeListener(transactionHash, handler);
|
||||
resolve(receipt);
|
||||
}
|
||||
this.on(transactionHash, handler);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
getBlockNumber(): Promise<number> {
|
||||
@@ -751,7 +821,7 @@ export class BaseProvider extends Provider {
|
||||
getBalance(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<BigNumber> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(({ addressOrName, blockTag }) => {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
return this._getAddress(addressOrName).then((address) => {
|
||||
let params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
return this.perform('getBalance', params).then((result) => {
|
||||
return bigNumberify(result);
|
||||
@@ -764,7 +834,7 @@ export class BaseProvider extends Provider {
|
||||
getTransactionCount(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<number> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(({ addressOrName, blockTag }) => {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
return this._getAddress(addressOrName).then((address) => {
|
||||
let params = { address: address, blockTag: checkBlockTag(blockTag) };
|
||||
return this.perform('getTransactionCount', params).then((result) => {
|
||||
return bigNumberify(result).toNumber();
|
||||
@@ -777,7 +847,7 @@ export class BaseProvider extends Provider {
|
||||
getCode(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ addressOrName: addressOrName, blockTag: blockTag }).then(({ addressOrName, blockTag }) => {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
return this._getAddress(addressOrName).then((address) => {
|
||||
let params = {address: address, blockTag: checkBlockTag(blockTag)};
|
||||
return this.perform('getCode', params).then((result) => {
|
||||
return hexlify(result);
|
||||
@@ -790,7 +860,7 @@ export class BaseProvider extends Provider {
|
||||
getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ addressOrName: addressOrName, position: position, blockTag: blockTag }).then(({ addressOrName, position, blockTag }) => {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
return this._getAddress(addressOrName).then((address) => {
|
||||
let params = {
|
||||
address: address,
|
||||
blockTag: checkBlockTag(blockTag),
|
||||
@@ -832,11 +902,22 @@ export class BaseProvider extends Provider {
|
||||
errors.throwError('Transaction hash mismatch from Provider.sendTransaction.', errors.UNKNOWN_ERROR, { expectedHash: tx.hash, returnedHash: hash });
|
||||
}
|
||||
|
||||
this._emitted['t:' + tx.hash] = 'pending';
|
||||
|
||||
// @TODO: (confirmations? number, timeout? number)
|
||||
result.wait = (confirmations?: number) => {
|
||||
|
||||
// We know this transaction *must* exist (whether it gets mined is
|
||||
// another story), so setting an emitted value forces us to
|
||||
// wait even if the node returns null for the receipt
|
||||
if (confirmations !== 0) {
|
||||
this._emitted['t:' + tx.hash] = 'pending';
|
||||
}
|
||||
|
||||
return this.waitForTransaction(tx.hash, confirmations).then((receipt) => {
|
||||
if (receipt == null && confirmations === 0) { return null; }
|
||||
|
||||
// No longer pending, allow the polling loop to garbage collect this
|
||||
this._emitted['t:' + tx.hash] = receipt.blockNumber;
|
||||
|
||||
if (receipt.status === 0) {
|
||||
errors.throwError('transaction failed', errors.CALL_EXCEPTION, {
|
||||
transactionHash: tx.hash,
|
||||
@@ -918,7 +999,7 @@ export class BaseProvider extends Provider {
|
||||
return poll(() => {
|
||||
return this.perform('getBlock', { blockTag: blockTag, includeTransactions: !!includeTransactions }).then((block) => {
|
||||
if (block == null) {
|
||||
if (blockNumber > this._emitted.block) {
|
||||
if (blockNumber <= this._emitted.block) {
|
||||
return undefined;
|
||||
}
|
||||
return null;
|
||||
@@ -936,7 +1017,7 @@ export class BaseProvider extends Provider {
|
||||
getTransaction(transactionHash: string): Promise<TransactionResponse> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
|
||||
let params = { transactionHash: checkHash(transactionHash) };
|
||||
let params = { transactionHash: checkHash(transactionHash, true) };
|
||||
return poll(() => {
|
||||
return this.perform('getTransaction', params).then((result) => {
|
||||
if (result == null) {
|
||||
@@ -973,7 +1054,7 @@ export class BaseProvider extends Provider {
|
||||
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
|
||||
let params = { transactionHash: checkHash(transactionHash) };
|
||||
let params = { transactionHash: checkHash(transactionHash, true) };
|
||||
return poll(() => {
|
||||
return this.perform('getTransactionReceipt', params).then((result) => {
|
||||
if (result == null) {
|
||||
@@ -1010,7 +1091,7 @@ export class BaseProvider extends Provider {
|
||||
});
|
||||
}
|
||||
|
||||
getLogs(filter: Filter): Promise<Array<Log>> {
|
||||
getLogs(filter: Filter | FilterByBlock): Promise<Array<Log>> {
|
||||
return this.ready.then(() => {
|
||||
return resolveProperties(filter).then((filter) => {
|
||||
return this._resolveNames(filter, ['address']).then((filter) => {
|
||||
@@ -1032,6 +1113,15 @@ export class BaseProvider extends Provider {
|
||||
});
|
||||
}
|
||||
|
||||
_getAddress(addressOrName: string): Promise<string> {
|
||||
return this.resolveName(addressOrName).then((address) => {
|
||||
if (address == null) {
|
||||
errors.throwError("ENS name not configured", errors.UNSUPPORTED_OPERATION, { operation: "resolveName(" + JSON.stringify(addressOrName) + ")" });
|
||||
}
|
||||
return address;
|
||||
});
|
||||
}
|
||||
|
||||
// @TODO: Could probably use resolveProperties instead?
|
||||
private _resolveNames(object: any, keys: Array<string>): Promise<{ [key: string]: string }> {
|
||||
let promises: Array<Promise<void>> = [];
|
||||
@@ -1040,7 +1130,7 @@ export class BaseProvider extends Provider {
|
||||
|
||||
keys.forEach(function(key) {
|
||||
if (result[key] == null) { return; }
|
||||
promises.push(this.resolveName(result[key]).then((address: string) => {
|
||||
promises.push(this._getAddress(result[key]).then((address: string) => {
|
||||
result[key] = address;
|
||||
return;
|
||||
}));
|
||||
@@ -1056,7 +1146,7 @@ export class BaseProvider extends Provider {
|
||||
// No ENS...
|
||||
if (!network.ensAddress) {
|
||||
errors.throwError(
|
||||
'network does support ENS',
|
||||
'network does not support ENS',
|
||||
errors.UNSUPPORTED_OPERATION,
|
||||
{ operation: 'ENS', network: network.name }
|
||||
);
|
||||
@@ -1067,10 +1157,11 @@ export class BaseProvider extends Provider {
|
||||
let transaction = { to: network.ensAddress, data: data };
|
||||
|
||||
return this.call(transaction).then((data) => {
|
||||
|
||||
// extract the address from the data
|
||||
if (hexDataLength(data) !== 32) { return null; }
|
||||
return getAddress(hexDataSlice(data, 12));
|
||||
let address = getAddress(hexDataSlice(data, 12));
|
||||
if (address === AddressZero) { return null; }
|
||||
return address;
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1095,6 +1186,7 @@ export class BaseProvider extends Provider {
|
||||
|
||||
// Get the addr from the resovler
|
||||
return this._getResolver(name).then(function(resolverAddress) {
|
||||
if (resolverAddress == null) { return null; }
|
||||
|
||||
// keccak256('addr(bytes32)')
|
||||
let data = '0x3b3b57de' + nodeHash.substring(2);
|
||||
@@ -1105,7 +1197,7 @@ export class BaseProvider extends Provider {
|
||||
}).then(function(data) {
|
||||
if (hexDataLength(data) !== 32) { return null; }
|
||||
let address = getAddress(hexDataSlice(data, 12));
|
||||
if (address === '0x0000000000000000000000000000000000000000') { return null; }
|
||||
if (address === AddressZero) { return null; }
|
||||
return address;
|
||||
});
|
||||
}
|
||||
@@ -1133,6 +1225,8 @@ export class BaseProvider extends Provider {
|
||||
return self.call(transaction);
|
||||
|
||||
}).then(function(data) {
|
||||
if (data == null) { return null; }
|
||||
|
||||
// Strip off the "0x"
|
||||
data = data.substring(2);
|
||||
|
||||
@@ -1170,7 +1264,7 @@ export class BaseProvider extends Provider {
|
||||
}
|
||||
|
||||
protected _startPending(): void {
|
||||
console.log('WARNING: this provider does not support pending events');
|
||||
errors.warn('WARNING: this provider does not support pending events');
|
||||
}
|
||||
|
||||
protected _stopPending(): void {
|
||||
@@ -1236,13 +1330,18 @@ export class BaseProvider extends Provider {
|
||||
});
|
||||
}
|
||||
|
||||
removeAllListeners(eventName: EventType): Provider {
|
||||
let eventTag = getEventTag(eventName);
|
||||
this._events = this._events.filter((event) => {
|
||||
return (event.tag !== eventTag);
|
||||
});
|
||||
removeAllListeners(eventName?: EventType): Provider {
|
||||
if (eventName == null) {
|
||||
this._events = [ ];
|
||||
this._stopPending();
|
||||
} else {
|
||||
let eventTag = getEventTag(eventName);
|
||||
this._events = this._events.filter((event) => {
|
||||
return (event.tag !== eventTag);
|
||||
});
|
||||
if (eventName === 'pending') { this._stopPending(); }
|
||||
}
|
||||
|
||||
if (eventName === 'pending') { this._stopPending(); }
|
||||
if (this._events.length === 0) { this.polling = false; }
|
||||
|
||||
return this;
|
||||
@@ -1253,9 +1352,9 @@ export class BaseProvider extends Provider {
|
||||
|
||||
let eventTag = getEventTag(eventName);
|
||||
this._events = this._events.filter((event) => {
|
||||
if (event.tag !== eventTag) { return true; }
|
||||
if (event.tag !== eventTag || event.listener != listener) { return true; }
|
||||
if (found) { return true; }
|
||||
found = false;
|
||||
found = true;
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
@@ -98,6 +98,9 @@ export class EtherscanProvider extends BaseProvider{
|
||||
case 'kovan':
|
||||
baseUrl = 'https://api-kovan.etherscan.io';
|
||||
break;
|
||||
case 'goerli':
|
||||
baseUrl = 'https://api-goerli.etherscan.io';
|
||||
break;
|
||||
default:
|
||||
throw new Error('unsupported network');
|
||||
}
|
||||
@@ -234,6 +237,16 @@ export class EtherscanProvider extends BaseProvider{
|
||||
url += '&toBlock=' + checkLogTag(params.filter.toBlock);
|
||||
}
|
||||
|
||||
if (params.filter.blockHash) {
|
||||
try {
|
||||
errors.throwError("Etherscan does not support blockHash filters", errors.UNSUPPORTED_OPERATION, {
|
||||
operation: "getLogs(blockHash)"
|
||||
});
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.filter.address) {
|
||||
url += '&address=' + params.filter.address;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ function checkNetworks(networks: Array<Network>): boolean {
|
||||
// Matches!
|
||||
if (check.name === network.name &&
|
||||
check.chainId === network.chainId &&
|
||||
check.ensAddress === network.ensAddress) { return; }
|
||||
((check.ensAddress === network.ensAddress) ||
|
||||
(check.ensAddress == null && network.ensAddress == null))) { return; }
|
||||
|
||||
errors.throwError(
|
||||
'provider mismatch',
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { JsonRpcProvider, JsonRpcSigner } from './json-rpc-provider';
|
||||
|
||||
import { isHexString } from "../utils/bytes";
|
||||
import { getNetwork } from '../utils/networks';
|
||||
import { defineReadOnly } from '../utils/properties';
|
||||
|
||||
@@ -10,14 +11,18 @@ import { Networkish } from '../utils/networks';
|
||||
|
||||
import * as errors from '../errors';
|
||||
|
||||
const defaultProjectId = "7d0d81d0919f4f05b9ab6634be01ee73";
|
||||
|
||||
export class InfuraProvider extends JsonRpcProvider {
|
||||
readonly apiAccessToken: string;
|
||||
readonly projectId: string;
|
||||
|
||||
constructor(network?: Networkish, apiAccessToken?: string) {
|
||||
network = getNetwork((network == null) ? 'homestead': network);
|
||||
constructor(network?: Networkish, projectId?: string) {
|
||||
let standard = getNetwork((network == null) ? 'homestead': network);
|
||||
if (projectId == null) { projectId = defaultProjectId; }
|
||||
|
||||
var host = null;
|
||||
switch(network.name) {
|
||||
let host = null;
|
||||
switch(standard.name) {
|
||||
case 'homestead':
|
||||
host = 'mainnet.infura.io';
|
||||
break;
|
||||
@@ -27,30 +32,46 @@ export class InfuraProvider extends JsonRpcProvider {
|
||||
case 'rinkeby':
|
||||
host = 'rinkeby.infura.io';
|
||||
break;
|
||||
case 'goerli':
|
||||
host = 'goerli.infura.io';
|
||||
break;
|
||||
case 'kovan':
|
||||
host = 'kovan.infura.io';
|
||||
break;
|
||||
default:
|
||||
throw new Error('unsupported network');
|
||||
errors.throwError('unsupported network', errors.INVALID_ARGUMENT, {
|
||||
argument: "network",
|
||||
value: network
|
||||
});
|
||||
}
|
||||
|
||||
super('https://' + host + '/' + (apiAccessToken || ''), network);
|
||||
errors.checkNew(this, InfuraProvider);
|
||||
// New-style Project ID
|
||||
if (isHexString("0x" + projectId, 16)) {
|
||||
super('https://' + host + '/v3/' + projectId, standard);
|
||||
defineReadOnly(this, 'apiAccessToken', null);
|
||||
defineReadOnly(this, 'projectId', projectId);
|
||||
|
||||
defineReadOnly(this, 'apiAccessToken', apiAccessToken || null);
|
||||
// Legacy API Access Token
|
||||
} else {
|
||||
errors.warn("The legacy INFURA apiAccesToken API is deprecated; please upgrade to a Project ID instead (see INFURA dshboard; https://infura.io)");
|
||||
super('https://' + host + '/' + projectId, standard);
|
||||
defineReadOnly(this, 'apiAccessToken', projectId);
|
||||
defineReadOnly(this, 'projectId', null);
|
||||
}
|
||||
|
||||
errors.checkNew(this, InfuraProvider);
|
||||
}
|
||||
|
||||
protected _startPending(): void {
|
||||
console.log('WARNING: INFURA does not support pending filters');
|
||||
errors.warn('WARNING: INFURA does not support pending filters');
|
||||
}
|
||||
|
||||
getSigner(address?: string): JsonRpcSigner {
|
||||
errors.throwError(
|
||||
return errors.throwError(
|
||||
'INFURA does not support signing',
|
||||
errors.UNSUPPORTED_OPERATION,
|
||||
{ operation: 'getSigner' }
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
listAccounts(): Promise<Array<string>> {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
import net from 'net';
|
||||
|
||||
@@ -10,12 +11,15 @@ import { Networkish } from '../utils/networks';
|
||||
|
||||
import * as errors from '../errors';
|
||||
|
||||
|
||||
export class IpcProvider extends JsonRpcProvider {
|
||||
readonly path: string;
|
||||
|
||||
constructor(path: string, network?: Networkish) {
|
||||
if (path == null) {
|
||||
errors.throwError('missing path', errors.MISSING_ARGUMENT, { arg: 'path' });
|
||||
errors.throwError('missing path', errors.MISSING_ARGUMENT, {
|
||||
argument: 'path'
|
||||
});
|
||||
}
|
||||
|
||||
super('ipc://' + path, network);
|
||||
@@ -32,7 +36,7 @@ export class IpcProvider extends JsonRpcProvider {
|
||||
// advantage we are aiming for now is security. This simplifies
|
||||
// multiplexing requests (since we do not need to multiplex).
|
||||
|
||||
var payload = JSON.stringify({
|
||||
let payload = JSON.stringify({
|
||||
method: method,
|
||||
params: params,
|
||||
id: 42,
|
||||
@@ -40,10 +44,17 @@ export class IpcProvider extends JsonRpcProvider {
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
var stream = net.connect(this.path);
|
||||
stream.on('data', function(data) {
|
||||
let response = Buffer.alloc(0);
|
||||
|
||||
let stream = net.connect(this.path);
|
||||
|
||||
stream.on('data', (data) => {
|
||||
response = Buffer.concat([ response, data ]);
|
||||
});
|
||||
|
||||
stream.on("end", () => {
|
||||
try {
|
||||
resolve(JSON.parse(data.toString('utf8')).result);
|
||||
resolve(JSON.parse(response.toString('utf8')).result);
|
||||
// @TODO: Better pull apart the error
|
||||
stream.destroy();
|
||||
} catch (error) {
|
||||
@@ -52,14 +63,11 @@ export class IpcProvider extends JsonRpcProvider {
|
||||
}
|
||||
});
|
||||
|
||||
stream.on('end', function() {
|
||||
stream.destroy();
|
||||
});
|
||||
|
||||
stream.on('error', function(error) {
|
||||
stream.on('error', (error) => {
|
||||
reject(error);
|
||||
stream.destroy();
|
||||
});
|
||||
|
||||
stream.write(payload);
|
||||
stream.end();
|
||||
});
|
||||
|
||||
@@ -12,8 +12,7 @@ import { getAddress } from '../utils/address';
|
||||
import { BigNumber } from '../utils/bignumber';
|
||||
import { hexlify, hexStripZeros } from '../utils/bytes';
|
||||
import { getNetwork } from '../utils/networks';
|
||||
import { checkProperties, defineReadOnly, shallowCopy } from '../utils/properties';
|
||||
import { populateTransaction } from '../utils/transaction';
|
||||
import { checkProperties, defineReadOnly, resolveProperties, shallowCopy } from '../utils/properties';
|
||||
import { toUtf8Bytes } from '../utils/utf8';
|
||||
import { fetchJson, poll } from '../utils/web';
|
||||
|
||||
@@ -35,7 +34,7 @@ function timer(timeout: number): Promise<any> {
|
||||
function getResult(payload: { error?: { code?: number, data?: any, message?: string }, result?: any }): any {
|
||||
if (payload.error) {
|
||||
// @TODO: not any
|
||||
var error: any = new Error(payload.error.message);
|
||||
let error: any = new Error(payload.error.message);
|
||||
error.code = payload.error.code;
|
||||
error.data = payload.error.data;
|
||||
throw error;
|
||||
@@ -51,6 +50,11 @@ function getLowerCase(value: string): string {
|
||||
|
||||
const _constructorGuard = {};
|
||||
|
||||
// Some environments (Trust Wallet and company) use a global map
|
||||
// to track JSON-RPC ID, so we try to keep IDs unique across all
|
||||
// connections. See #489.
|
||||
let _nextId = 42;
|
||||
|
||||
export class JsonRpcSigner extends Signer {
|
||||
readonly provider: JsonRpcProvider;
|
||||
private _index: number;
|
||||
@@ -102,28 +106,32 @@ export class JsonRpcSigner extends Signer {
|
||||
return this.provider.getTransactionCount(this.getAddress(), blockTag);
|
||||
}
|
||||
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
|
||||
sendUncheckedTransaction(transaction: TransactionRequest): Promise<string> {
|
||||
transaction = shallowCopy(transaction);
|
||||
|
||||
// Once populateTransaction resolves, the from address will be populated from getAddress
|
||||
let from: string = null;
|
||||
let getAddress = this.getAddress().then((address) => {
|
||||
if (address) { from = address.toLowerCase(); }
|
||||
return from;
|
||||
let fromAddress = this.getAddress().then((address) => {
|
||||
if (address) { address = address.toLowerCase(); }
|
||||
return address;
|
||||
});
|
||||
|
||||
return populateTransaction(transaction, this.provider, getAddress).then((tx) => {
|
||||
// The JSON-RPC for eth_sendTransaction uses 90000 gas; if the user
|
||||
// wishes to use this, it is easy to specify explicitly, otherwise
|
||||
// we look it up for them.
|
||||
if (transaction.gasLimit == null) {
|
||||
let estimate = shallowCopy(transaction);
|
||||
estimate.from = fromAddress;
|
||||
transaction.gasLimit = this.provider.estimateGas(estimate);
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
resolveProperties(transaction),
|
||||
fromAddress
|
||||
]).then((results) => {
|
||||
let tx = results[0];
|
||||
let hexTx = JsonRpcProvider.hexlifyTransaction(tx);
|
||||
hexTx.from = from;
|
||||
hexTx.from = results[1];
|
||||
return this.provider.send('eth_sendTransaction', [ hexTx ]).then((hash) => {
|
||||
return poll(() => {
|
||||
return this.provider.getTransaction(hash).then((tx: TransactionResponse) => {
|
||||
if (tx === null) { return undefined; }
|
||||
return this.provider._wrapTransaction(tx, hash);
|
||||
});
|
||||
}, { onceBlock: this.provider }).catch((error: Error) => {
|
||||
(<any>error).transactionHash = hash;
|
||||
throw error;
|
||||
});
|
||||
return hash;
|
||||
}, (error) => {
|
||||
if (error.responseText) {
|
||||
// See: JsonRpcProvider.sendTransaction (@TODO: Expose a ._throwError??)
|
||||
@@ -148,8 +156,22 @@ export class JsonRpcSigner extends Signer {
|
||||
});
|
||||
}
|
||||
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
|
||||
return this.sendUncheckedTransaction(transaction).then((hash) => {
|
||||
return poll(() => {
|
||||
return this.provider.getTransaction(hash).then((tx: TransactionResponse) => {
|
||||
if (tx === null) { return undefined; }
|
||||
return this.provider._wrapTransaction(tx, hash);
|
||||
});
|
||||
}, { fastRetry: 250, onceBlock: this.provider }).catch((error: Error) => {
|
||||
(<any>error).transactionHash = hash;
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
signMessage(message: Arrayish | string): Promise<string> {
|
||||
var data = ((typeof(message) === 'string') ? toUtf8Bytes(message): message);
|
||||
let data = ((typeof(message) === 'string') ? toUtf8Bytes(message): message);
|
||||
return this.getAddress().then((address) => {
|
||||
|
||||
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
|
||||
@@ -158,7 +180,7 @@ export class JsonRpcSigner extends Signer {
|
||||
}
|
||||
|
||||
unlock(password: string): Promise<boolean> {
|
||||
var provider = this.provider;
|
||||
let provider = this.provider;
|
||||
|
||||
return this.getAddress().then(function(address) {
|
||||
return provider.send('personal_unlockAccount', [ address.toLowerCase(), password, null ]);
|
||||
@@ -233,7 +255,7 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
let request = {
|
||||
method: method,
|
||||
params: params,
|
||||
id: 42,
|
||||
id: (_nextId++),
|
||||
jsonrpc: "2.0"
|
||||
};
|
||||
|
||||
@@ -323,9 +345,9 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
|
||||
protected _startPending(): void {
|
||||
if (this._pendingFilter != null) { return; }
|
||||
var self = this;
|
||||
let self = this;
|
||||
|
||||
var pendingFilter: Promise<number> = this.send('eth_newPendingTransactionFilter', []);
|
||||
let pendingFilter: Promise<number> = this.send('eth_newPendingTransactionFilter', []);
|
||||
this._pendingFilter = pendingFilter;
|
||||
|
||||
pendingFilter.then(function(filterId) {
|
||||
@@ -333,8 +355,9 @@ export class JsonRpcProvider extends BaseProvider {
|
||||
self.send('eth_getFilterChanges', [ filterId ]).then(function(hashes: Array<string>) {
|
||||
if (self._pendingFilter != pendingFilter) { return null; }
|
||||
|
||||
var seq = Promise.resolve();
|
||||
let seq = Promise.resolve();
|
||||
hashes.forEach(function(hash) {
|
||||
// @TODO: This should be garbage collected at some point... How? When?
|
||||
self._emitted['t:' + hash.toLowerCase()] = 'pending';
|
||||
seq = seq.then(function() {
|
||||
return self.getTransaction(hash).then(function(tx) {
|
||||
|
||||
@@ -27,6 +27,8 @@ utils.defineProperty(Web3Signer, 'onchange', {
|
||||
|
||||
*/
|
||||
|
||||
let _nextId = 42;
|
||||
|
||||
export class Web3Provider extends JsonRpcProvider {
|
||||
readonly _web3Provider: AsyncSendable;
|
||||
private _sendAsync: (request: any, callback: (error: any, response: any) => void) => void;
|
||||
@@ -53,6 +55,9 @@ export class Web3Provider extends JsonRpcProvider {
|
||||
}
|
||||
|
||||
defineReadOnly(this, '_web3Provider', web3Provider);
|
||||
|
||||
// @TODO: In v5 remove the above definition; only this one is needed
|
||||
defineReadOnly(this, 'provider', web3Provider);
|
||||
}
|
||||
|
||||
send(method: string, params: any): Promise<any> {
|
||||
@@ -65,10 +70,10 @@ export class Web3Provider extends JsonRpcProvider {
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
var request = {
|
||||
let request = {
|
||||
method: method,
|
||||
params: params,
|
||||
id: 42,
|
||||
id: (_nextId++),
|
||||
jsonrpc: "2.0"
|
||||
};
|
||||
|
||||
@@ -80,7 +85,7 @@ export class Web3Provider extends JsonRpcProvider {
|
||||
|
||||
if (result.error) {
|
||||
// @TODO: not any
|
||||
var error: any = new Error(result.error.message);
|
||||
let error: any = new Error(result.error.message);
|
||||
error.code = result.error.code;
|
||||
error.data = result.error.data;
|
||||
reject(error);
|
||||
|
||||
@@ -107,9 +107,12 @@ type ParseNode = {
|
||||
|
||||
|
||||
function parseParam(param: string, allowIndexed?: boolean): ParamType {
|
||||
|
||||
let originalParam = param;
|
||||
function throwError(i: number) {
|
||||
throw new Error('unexpected character "' + param[i] + '" at position ' + i + ' in "' + param + '"');
|
||||
throw new Error('unexpected character "' + originalParam[i] + '" at position ' + i + ' in "' + originalParam + '"');
|
||||
}
|
||||
param = param.replace(/\s/g, ' ');
|
||||
|
||||
var parent: ParseNode = { type: '', name: '', state: { allowType: true } };
|
||||
var node = parent;
|
||||
@@ -263,7 +266,7 @@ function parseSignatureEvent(fragment: string): EventFragment {
|
||||
case '':
|
||||
break;
|
||||
default:
|
||||
console.log('unknown modifier: ' + modifier);
|
||||
errors.info('unknown modifier: ' + modifier);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -333,7 +336,7 @@ function parseSignatureFunction(fragment: string): FunctionFragment {
|
||||
case '':
|
||||
break;
|
||||
default:
|
||||
console.log('unknown modifier: ' + modifier);
|
||||
errors.info('unknown modifier: ' + modifier);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -380,6 +383,7 @@ export function formatSignature(fragment: EventFragment | FunctionFragment): str
|
||||
export function parseSignature(fragment: string): EventFragment | FunctionFragment {
|
||||
if(typeof(fragment) === 'string') {
|
||||
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
|
||||
fragment = fragment.replace(/\s/g, ' ');
|
||||
fragment = fragment.replace(/\(/g, ' (').replace(/\)/g, ') ').replace(/\s+/g, ' ');
|
||||
fragment = fragment.trim();
|
||||
|
||||
@@ -570,7 +574,7 @@ class CoderFixedBytes extends Coder {
|
||||
|
||||
decode(data: Uint8Array, offset: number): DecodedResult {
|
||||
if (data.length < offset + 32) {
|
||||
errors.throwError('insufficient data for ' + name + ' type', errors.INVALID_ARGUMENT, {
|
||||
errors.throwError('insufficient data for ' + this.name + ' type', errors.INVALID_ARGUMENT, {
|
||||
arg: this.localName,
|
||||
coderType: this.name,
|
||||
value: hexlify(data.slice(offset, offset + 32))
|
||||
@@ -844,7 +848,7 @@ class CoderArray extends Coder {
|
||||
result = uint256Coder.encode(count);
|
||||
}
|
||||
|
||||
errors.checkArgumentCount(count, value.length, 'in coder array' + (this.localName? (" "+ this.localName): ""));
|
||||
errors.checkArgumentCount(count, value.length, ' in coder array' + (this.localName? (" "+ this.localName): ""));
|
||||
|
||||
var coders = [];
|
||||
for (var i = 0; i < value.length; i++) { coders.push(this.coder); }
|
||||
|
||||
143
src.ts/utils/basex.ts
Normal file
143
src.ts/utils/basex.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* var basex = require('base-x');
|
||||
*
|
||||
* This implementation is heavily based on base-x. The main reason to
|
||||
* deviate was to prevent the dependency of Buffer.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* base-x encoding
|
||||
* Forked from https://github.com/cryptocoinjs/bs58
|
||||
* Originally written by Mike Hearn for BitcoinJ
|
||||
* Copyright (c) 2011 Google Inc
|
||||
* Ported to JavaScript by Stefan Thomas
|
||||
* Merged Buffer refactorings from base58-native by Stephen Pair
|
||||
* Copyright (c) 2013 BitPay Inc
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright base-x contributors (c) 2016
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
import { arrayify, Arrayish } from "./bytes";
|
||||
import { defineReadOnly } from "./properties";
|
||||
|
||||
export class BaseX {
|
||||
readonly alphabet: string;
|
||||
readonly base: number;
|
||||
|
||||
private _alphabetMap: { [ character: string ]: number };
|
||||
private _leader: string;
|
||||
|
||||
constructor(alphabet: string) {
|
||||
defineReadOnly(this, "alphabet", alphabet);
|
||||
defineReadOnly(this, "base", alphabet.length);
|
||||
|
||||
defineReadOnly(this, "_alphabetMap", { });
|
||||
defineReadOnly(this, "_leader", alphabet.charAt(0));
|
||||
|
||||
// pre-compute lookup table
|
||||
for (let i = 0; i < alphabet.length; i++) {
|
||||
this._alphabetMap[alphabet.charAt(i)] = i;
|
||||
}
|
||||
}
|
||||
|
||||
encode(value: Arrayish | string): string {
|
||||
let source = arrayify(value);
|
||||
|
||||
if (source.length === 0) { return ''; }
|
||||
|
||||
let digits = [ 0 ]
|
||||
for (let i = 0; i < source.length; ++i) {
|
||||
let carry = source[i];
|
||||
for (let j = 0; j < digits.length; ++j) {
|
||||
carry += digits[j] << 8;
|
||||
digits[j] = carry % this.base;
|
||||
carry = (carry / this.base) | 0;
|
||||
}
|
||||
|
||||
while (carry > 0) {
|
||||
digits.push(carry % this.base);
|
||||
carry = (carry / this.base) | 0;
|
||||
}
|
||||
}
|
||||
|
||||
let string = ''
|
||||
|
||||
// deal with leading zeros
|
||||
for (let k = 0; source[k] === 0 && k < source.length - 1; ++k) {
|
||||
string += this._leader;
|
||||
}
|
||||
|
||||
// convert digits to a string
|
||||
for (let q = digits.length - 1; q >= 0; --q) {
|
||||
string += this.alphabet[digits[q]];
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
decode(value: string): Uint8Array {
|
||||
if (typeof(value) !== 'string') {
|
||||
throw new TypeError('Expected String');
|
||||
}
|
||||
|
||||
let bytes: Array<number> = [];
|
||||
if (value.length === 0) { return new Uint8Array(bytes); }
|
||||
|
||||
bytes.push(0);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
let byte = this._alphabetMap[value[i]];
|
||||
|
||||
if (byte === undefined) {
|
||||
throw new Error('Non-base' + this.base + ' character');
|
||||
}
|
||||
|
||||
let carry = byte;
|
||||
for (let j = 0; j < bytes.length; ++j) {
|
||||
carry += bytes[j] * this.base;
|
||||
bytes[j] = carry & 0xff;
|
||||
carry >>= 8;
|
||||
}
|
||||
|
||||
while (carry > 0) {
|
||||
bytes.push(carry & 0xff);
|
||||
carry >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// deal with leading zeros
|
||||
for (let k = 0; value[k] === this._leader && k < value.length - 1; ++k) {
|
||||
bytes.push(0)
|
||||
}
|
||||
|
||||
return arrayify(new Uint8Array(bytes.reverse()))
|
||||
}
|
||||
}
|
||||
|
||||
const Base32 = new BaseX("abcdefghijklmnopqrstuvwxyz234567");
|
||||
const Base58 = new BaseX("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
||||
|
||||
export { Base32, Base58 };
|
||||
|
||||
//console.log(Base58.decode("Qmd2V777o5XvJbYMeMb8k2nU5f8d3ciUQ5YpYuWhzv8iDj"))
|
||||
//console.log(Base58.encode(Base58.decode("Qmd2V777o5XvJbYMeMb8k2nU5f8d3ciUQ5YpYuWhzv8iDj")))
|
||||
@@ -47,7 +47,6 @@ function _bnify(value: BigNumber): BN.BN {
|
||||
return new BN.BN(hex.substring(2), 16);
|
||||
}
|
||||
|
||||
|
||||
export type BigNumberish = BigNumber | string | number | Arrayish;
|
||||
|
||||
export class BigNumber implements Hexable {
|
||||
@@ -108,6 +107,13 @@ export class BigNumber implements Hexable {
|
||||
return toBigNumber(_bnify(this).toTwos(value));
|
||||
}
|
||||
|
||||
abs(): BigNumber {
|
||||
if (this._hex[0] === '-') {
|
||||
return toBigNumber(_bnify(this).mul(BN_1));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
add(other: BigNumberish): BigNumber {
|
||||
return toBigNumber(_bnify(this).add(toBN(other)));
|
||||
}
|
||||
|
||||
@@ -5,11 +5,6 @@
|
||||
|
||||
import * as errors from '../errors';
|
||||
|
||||
///////////////////////////////
|
||||
// Imported Types
|
||||
|
||||
import { Arrayish } from './bytes';
|
||||
|
||||
///////////////////////////////
|
||||
// Exported Types
|
||||
|
||||
@@ -40,7 +35,7 @@ function addSlice(array: Uint8Array): Uint8Array {
|
||||
|
||||
array.slice = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return new Uint8Array(Array.prototype.slice.apply(array, args));
|
||||
return addSlice(new Uint8Array(Array.prototype.slice.apply(array, args)));
|
||||
}
|
||||
|
||||
return array;
|
||||
@@ -168,6 +163,15 @@ export function hexlify(value: Arrayish | Hexable | number): string {
|
||||
errors.throwError('cannot hexlify negative value', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||
}
|
||||
|
||||
// @TODO: Roll this into the above error as a numeric fault (overflow); next version, not backward compatible
|
||||
// We can about (value == MAX_INT) to as well, since that may indicate we underflowed already
|
||||
if (value >= 9007199254740991) {
|
||||
errors.throwError("out-of-range", errors.NUMERIC_FAULT, {
|
||||
operartion: "hexlify",
|
||||
fault: "out-of-safe-range"
|
||||
});
|
||||
}
|
||||
|
||||
var hex = '';
|
||||
while (value) {
|
||||
hex = HexCharacters[value & 0x0f] + hex;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import * as errors from '../errors';
|
||||
|
||||
import { concat, hexlify } from './bytes';
|
||||
import { toUtf8Bytes } from './utf8';
|
||||
import { keccak256 } from './keccak256';
|
||||
@@ -11,11 +13,18 @@ import { Arrayish } from './bytes';
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
var Zeros = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
var Partition = new RegExp("^((.*)\\.)?([^.]+)$");
|
||||
var UseSTD3ASCIIRules = new RegExp("^[a-z0-9.-]*$");
|
||||
const Zeros = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
const Partition = new RegExp("^((.*)\\.)?([^.]+)$");
|
||||
const UseSTD3ASCIIRules = new RegExp("^[a-z0-9.-]*$");
|
||||
|
||||
export function namehash(name: string): string {
|
||||
if (typeof(name) !== 'string') {
|
||||
errors.throwError('invalid address - ' + String(name), errors.INVALID_ARGUMENT, {
|
||||
argument: 'name',
|
||||
value: name
|
||||
});
|
||||
}
|
||||
|
||||
name = name.toLowerCase();
|
||||
|
||||
// Supporting the full UTF-8 space requires additional (and large)
|
||||
@@ -23,13 +32,16 @@ export function namehash(name: string): string {
|
||||
// It should be fairly easy in the future to support systems with
|
||||
// String.normalize, but that is future work.
|
||||
if (!name.match(UseSTD3ASCIIRules)) {
|
||||
throw new Error('contains invalid UseSTD3ASCIIRules characters');
|
||||
errors.throwError('contains invalid UseSTD3ASCIIRules characters', errors.INVALID_ARGUMENT, {
|
||||
argument: 'name',
|
||||
value: name
|
||||
});
|
||||
}
|
||||
|
||||
var result: string | Uint8Array = Zeros;
|
||||
let result: string | Uint8Array = Zeros;
|
||||
while (name.length) {
|
||||
var partition = name.match(Partition);
|
||||
var label = toUtf8Bytes(partition[3]);
|
||||
let partition = name.match(Partition);
|
||||
let label = toUtf8Bytes(partition[3]);
|
||||
result = keccak256(concat([result, keccak256(label)]));
|
||||
|
||||
name = partition[2] || '';
|
||||
@@ -44,11 +56,10 @@ export function id(text: string): string {
|
||||
}
|
||||
|
||||
export function hashMessage(message: Arrayish | string): string {
|
||||
var payload = concat([
|
||||
return keccak256(concat([
|
||||
toUtf8Bytes('\x19Ethereum Signed Message:\n'),
|
||||
toUtf8Bytes(String(message.length)),
|
||||
((typeof(message) === 'string') ? toUtf8Bytes(message): message)
|
||||
]);
|
||||
return keccak256(payload);
|
||||
]));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
||||
@@ -13,14 +13,15 @@ import { langEn } from '../wordlists/lang-en';
|
||||
//import { register } from '../wordlists/wordlist';
|
||||
//register(langEn);
|
||||
|
||||
import { arrayify, hexlify } from './bytes';
|
||||
import { bigNumberify } from './bignumber';
|
||||
import { Base58 } from "./basex";
|
||||
import { arrayify, concat, hexDataSlice, hexZeroPad, hexlify } from './bytes';
|
||||
import { BigNumber, bigNumberify } from './bignumber';
|
||||
import { toUtf8Bytes, UnicodeNormalizationForm } from './utf8';
|
||||
import { pbkdf2 } from './pbkdf2';
|
||||
import { computeHmac, SupportedAlgorithms } from './hmac';
|
||||
import { defineReadOnly, isType, setType } from './properties';
|
||||
import { computeAddress, KeyPair } from './secp256k1';
|
||||
import { sha256 } from './sha2';
|
||||
import { ripemd160, sha256 } from './sha2';
|
||||
|
||||
const N = bigNumberify("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
||||
|
||||
@@ -30,9 +31,9 @@ import { Wordlist } from './wordlist';
|
||||
|
||||
|
||||
// "Bitcoin seed"
|
||||
var MasterSecret = toUtf8Bytes('Bitcoin seed');
|
||||
const MasterSecret = toUtf8Bytes('Bitcoin seed');
|
||||
|
||||
var HardenedBit = 0x80000000;
|
||||
const HardenedBit = 0x80000000;
|
||||
|
||||
// Returns a byte with the MSB bits set
|
||||
function getUpperMask(bits: number): number {
|
||||
@@ -44,16 +45,26 @@ function getLowerMask(bits: number): number {
|
||||
return (1 << bits) - 1;
|
||||
}
|
||||
|
||||
function bytes32(value: Arrayish | BigNumber | number): string {
|
||||
return hexZeroPad(hexlify(value), 32);
|
||||
}
|
||||
|
||||
function base58check(data: Uint8Array): string {
|
||||
let checksum = hexDataSlice(sha256(sha256(data)), 0, 4);
|
||||
return Base58.encode(concat([ data, checksum ]));
|
||||
}
|
||||
|
||||
const _constructorGuard: any = {};
|
||||
|
||||
export const defaultPath = "m/44'/60'/0'/0/0";
|
||||
|
||||
export class HDNode {
|
||||
private readonly keyPair: KeyPair;
|
||||
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
|
||||
readonly fingerprint: string;
|
||||
readonly parentFingerprint: string;
|
||||
|
||||
readonly address: string;
|
||||
|
||||
readonly mnemonic: string;
|
||||
@@ -71,21 +82,28 @@ export class HDNode {
|
||||
* - fromMnemonic
|
||||
* - fromSeed
|
||||
*/
|
||||
constructor(constructorGuard: any, privateKey: Arrayish, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string) {
|
||||
constructor(constructorGuard: any, privateKey: string, publicKey: string, parentFingerprint: string, chainCode: string, index: number, depth: number, mnemonic: string, path: string) {
|
||||
errors.checkNew(this, HDNode);
|
||||
|
||||
if (constructorGuard !== _constructorGuard) {
|
||||
throw new Error('HDNode constructor cannot be called directly');
|
||||
}
|
||||
|
||||
defineReadOnly(this, 'keyPair', new KeyPair(privateKey));
|
||||
if (privateKey) {
|
||||
let keyPair = new KeyPair(privateKey);
|
||||
defineReadOnly(this, 'privateKey', keyPair.privateKey);
|
||||
defineReadOnly(this, 'publicKey', keyPair.compressedPublicKey);
|
||||
} else {
|
||||
defineReadOnly(this, 'privateKey', null);
|
||||
defineReadOnly(this, 'publicKey', hexlify(publicKey));
|
||||
}
|
||||
|
||||
defineReadOnly(this, 'privateKey', this.keyPair.privateKey);
|
||||
defineReadOnly(this, 'publicKey', this.keyPair.compressedPublicKey);
|
||||
defineReadOnly(this, 'parentFingerprint', parentFingerprint);
|
||||
defineReadOnly(this, 'fingerprint', hexDataSlice(ripemd160(sha256(this.publicKey)), 0, 4));
|
||||
|
||||
defineReadOnly(this, 'address', computeAddress(this.publicKey));
|
||||
|
||||
defineReadOnly(this, 'chainCode', hexlify(chainCode));
|
||||
defineReadOnly(this, 'chainCode', chainCode);
|
||||
|
||||
defineReadOnly(this, 'index', index);
|
||||
defineReadOnly(this, 'depth', depth);
|
||||
@@ -96,22 +114,43 @@ export class HDNode {
|
||||
setType(this, 'HDNode');
|
||||
}
|
||||
|
||||
get extendedKey(): string {
|
||||
// We only support the mainnet values for now, but if anyone needs
|
||||
// testnet values, let me know. I believe current senitment is that
|
||||
// we should always use mainnet, and use BIP-44 to derive the network
|
||||
// - Mainnet: public=0x0488B21E, private=0x0488ADE4
|
||||
// - Testnet: public=0x043587CF, private=0x04358394
|
||||
|
||||
if (this.depth >= 256) { throw new Error("Depth too large!"); }
|
||||
|
||||
return base58check(concat([
|
||||
((this.privateKey != null) ? "0x0488ADE4": "0x0488B21E"),
|
||||
hexlify(this.depth),
|
||||
this.parentFingerprint,
|
||||
hexZeroPad(hexlify(this.index), 4),
|
||||
this.chainCode,
|
||||
((this.privateKey != null) ? concat([ "0x00", this.privateKey ]): this.publicKey),
|
||||
]));
|
||||
}
|
||||
|
||||
neuter(): HDNode {
|
||||
return new HDNode(_constructorGuard, null, this.publicKey, this.parentFingerprint, this.chainCode, this.index, this.depth, null, this.path);
|
||||
}
|
||||
|
||||
private _derive(index: number): HDNode {
|
||||
|
||||
// Public parent key -> public child key
|
||||
if (!this.privateKey) {
|
||||
if (index >= HardenedBit) { throw new Error('cannot derive child of neutered node'); }
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
var data = new Uint8Array(37);
|
||||
if (index > 0xffffffff) { throw new Error("invalid index - " + String(index)); }
|
||||
|
||||
// Base path
|
||||
var mnemonic = this.mnemonic;
|
||||
var path = this.path;
|
||||
if (path) { path += '/' + index; }
|
||||
let path = this.path;
|
||||
if (path) { path += '/' + (index & ~HardenedBit); }
|
||||
|
||||
let data = new Uint8Array(37);
|
||||
|
||||
if (index & HardenedBit) {
|
||||
if (!this.privateKey) {
|
||||
throw new Error('cannot derive child of neutered node');
|
||||
}
|
||||
|
||||
// Data = 0x00 || ser_256(k_par)
|
||||
data.set(arrayify(this.privateKey), 1);
|
||||
|
||||
@@ -120,43 +159,54 @@ export class HDNode {
|
||||
|
||||
} else {
|
||||
// Data = ser_p(point(k_par))
|
||||
data.set(this.keyPair.publicKeyBytes);
|
||||
data.set(arrayify(this.publicKey));
|
||||
}
|
||||
|
||||
// Data += ser_32(i)
|
||||
for (var i = 24; i >= 0; i -= 8) { data[33 + (i >> 3)] = ((index >> (24 - i)) & 0xff); }
|
||||
for (let i = 24; i >= 0; i -= 8) { data[33 + (i >> 3)] = ((index >> (24 - i)) & 0xff); }
|
||||
|
||||
var I = computeHmac(SupportedAlgorithms.sha512, this.chainCode, data);
|
||||
var IL = bigNumberify(I.slice(0, 32));
|
||||
var IR = I.slice(32);
|
||||
let I = computeHmac(SupportedAlgorithms.sha512, this.chainCode, data);
|
||||
let IL = I.slice(0, 32);
|
||||
let IR = I.slice(32);
|
||||
|
||||
var ki = IL.add(this.keyPair.privateKey).mod(N);
|
||||
// The private key
|
||||
|
||||
return new HDNode(_constructorGuard, arrayify(ki), IR, index, this.depth + 1, mnemonic, path);
|
||||
let ki: string = null
|
||||
// The public key
|
||||
let Ki: string = null;
|
||||
|
||||
if (this.privateKey) {
|
||||
ki = bytes32(bigNumberify(IL).add(this.privateKey).mod(N));
|
||||
} else {
|
||||
let ek = new KeyPair(hexlify(IL));
|
||||
Ki = ek._addPoint(this.publicKey);
|
||||
}
|
||||
|
||||
return new HDNode(_constructorGuard, ki, Ki, this.fingerprint, bytes32(IR), index, this.depth + 1, this.mnemonic, path);
|
||||
}
|
||||
|
||||
derivePath(path: string): HDNode {
|
||||
var components = path.split('/');
|
||||
let components = path.split('/');
|
||||
|
||||
if (components.length === 0 || (components[0] === 'm' && this.depth !== 0)) {
|
||||
throw new Error('invalid path');
|
||||
throw new Error('invalid path - ' + path);
|
||||
}
|
||||
|
||||
if (components[0] === 'm') { components.shift(); }
|
||||
|
||||
var result: HDNode = this;
|
||||
for (var i = 0; i < components.length; i++) {
|
||||
var component = components[i];
|
||||
let result: HDNode = this;
|
||||
for (let i = 0; i < components.length; i++) {
|
||||
let component = components[i];
|
||||
if (component.match(/^[0-9]+'$/)) {
|
||||
var index = parseInt(component.substring(0, component.length - 1));
|
||||
let index = parseInt(component.substring(0, component.length - 1));
|
||||
if (index >= HardenedBit) { throw new Error('invalid path index - ' + component); }
|
||||
result = result._derive(HardenedBit + index);
|
||||
} else if (component.match(/^[0-9]+$/)) {
|
||||
var index = parseInt(component);
|
||||
let index = parseInt(component);
|
||||
if (index >= HardenedBit) { throw new Error('invalid path index - ' + component); }
|
||||
result = result._derive(index);
|
||||
} else {
|
||||
throw new Error('invlaid path component - ' + component);
|
||||
throw new Error('invalid path component - ' + component);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,22 +218,53 @@ export class HDNode {
|
||||
}
|
||||
}
|
||||
|
||||
export function fromExtendedKey(extendedKey: string): HDNode {
|
||||
let bytes = Base58.decode(extendedKey);
|
||||
|
||||
if (bytes.length !== 82 || base58check(bytes.slice(0, 78)) !== extendedKey) {
|
||||
errors.throwError("invalid extended key", errors.INVALID_ARGUMENT, {
|
||||
argument: "extendedKey",
|
||||
value: "[REDACTED]"
|
||||
});
|
||||
}
|
||||
|
||||
let depth = bytes[4];
|
||||
let parentFingerprint = hexlify(bytes.slice(5, 9));
|
||||
let index = parseInt(hexlify(bytes.slice(9, 13)).substring(2), 16);
|
||||
let chainCode = hexlify(bytes.slice(13, 45));
|
||||
let key = bytes.slice(45, 78);
|
||||
|
||||
switch (hexlify(bytes.slice(0, 4))) {
|
||||
// Public Key
|
||||
case "0x0488b21e": case "0x043587cf":
|
||||
return new HDNode(_constructorGuard, null, hexlify(key), parentFingerprint, chainCode, index, depth, null, null);
|
||||
|
||||
// Private Key
|
||||
case "0x0488ade4": case "0x04358394":
|
||||
if (key[0] !== 0) { break; }
|
||||
return new HDNode(_constructorGuard, hexlify(key.slice(1)), null, parentFingerprint, chainCode, index, depth, null, null);
|
||||
}
|
||||
|
||||
return errors.throwError("invalid extended key", errors.INVALID_ARGUMENT, {
|
||||
argument: "extendedKey",
|
||||
value: "[REDACTED]"
|
||||
});
|
||||
}
|
||||
|
||||
function _fromSeed(seed: Arrayish, mnemonic: string): HDNode {
|
||||
let seedArray: Uint8Array = arrayify(seed);
|
||||
if (seedArray.length < 16 || seedArray.length > 64) { throw new Error('invalid seed'); }
|
||||
|
||||
var I: Uint8Array = arrayify(computeHmac(SupportedAlgorithms.sha512, MasterSecret, seedArray));
|
||||
let I: Uint8Array = arrayify(computeHmac(SupportedAlgorithms.sha512, MasterSecret, seedArray));
|
||||
|
||||
return new HDNode(_constructorGuard, I.slice(0, 32), I.slice(32), 0, 0, mnemonic, 'm');
|
||||
return new HDNode(_constructorGuard, bytes32(I.slice(0, 32)), null, "0x00000000", bytes32(I.slice(32)), 0, 0, mnemonic, 'm');
|
||||
}
|
||||
|
||||
export function fromMnemonic(mnemonic: string, wordlist?: Wordlist): HDNode {
|
||||
// Check that the checksum s valid (will throw an error)
|
||||
mnemonicToEntropy(mnemonic, wordlist);
|
||||
export function fromMnemonic(mnemonic: string, wordlist?: Wordlist, password?: string): HDNode {
|
||||
// Normalize the mnemonic (also throws if the checksum is invalid)
|
||||
mnemonic = entropyToMnemonic(mnemonicToEntropy(mnemonic, wordlist), wordlist);
|
||||
|
||||
return _fromSeed(mnemonicToSeed(mnemonic), mnemonic);
|
||||
return _fromSeed(mnemonicToSeed(mnemonic, password), mnemonic);
|
||||
}
|
||||
|
||||
export function fromSeed(seed: Arrayish): HDNode {
|
||||
@@ -193,7 +274,7 @@ export function fromSeed(seed: Arrayish): HDNode {
|
||||
export function mnemonicToSeed(mnemonic: string, password?: string): string {
|
||||
if (!password) { password = ''; }
|
||||
|
||||
var salt = toUtf8Bytes('mnemonic' + password, UnicodeNormalizationForm.NFKD);
|
||||
let salt = toUtf8Bytes('mnemonic' + password, UnicodeNormalizationForm.NFKD);
|
||||
|
||||
return hexlify(pbkdf2(toUtf8Bytes(mnemonic, UnicodeNormalizationForm.NFKD), salt, 2048, 64, 'sha512'));
|
||||
}
|
||||
@@ -201,17 +282,19 @@ export function mnemonicToSeed(mnemonic: string, password?: string): string {
|
||||
export function mnemonicToEntropy(mnemonic: string, wordlist?: Wordlist): string {
|
||||
if (!wordlist) { wordlist = langEn; }
|
||||
|
||||
var words = wordlist.split(mnemonic);
|
||||
errors.checkNormalize();
|
||||
|
||||
let words = wordlist.split(mnemonic);
|
||||
if ((words.length % 3) !== 0) { throw new Error('invalid mnemonic'); }
|
||||
|
||||
var entropy = arrayify(new Uint8Array(Math.ceil(11 * words.length / 8)));
|
||||
let entropy = arrayify(new Uint8Array(Math.ceil(11 * words.length / 8)));
|
||||
|
||||
var offset = 0;
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var index = wordlist.getWordIndex(words[i].normalize('NFKD'));
|
||||
let offset = 0;
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
let index = wordlist.getWordIndex(words[i].normalize('NFKD'));
|
||||
if (index === -1) { throw new Error('invalid mnemonic'); }
|
||||
|
||||
for (var bit = 0; bit < 11; bit++) {
|
||||
for (let bit = 0; bit < 11; bit++) {
|
||||
if (index & (1 << (10 - bit))) {
|
||||
entropy[offset >> 3] |= (1 << (7 - (offset % 8)));
|
||||
}
|
||||
@@ -219,12 +302,12 @@ export function mnemonicToEntropy(mnemonic: string, wordlist?: Wordlist): string
|
||||
}
|
||||
}
|
||||
|
||||
var entropyBits = 32 * words.length / 3;
|
||||
let entropyBits = 32 * words.length / 3;
|
||||
|
||||
var checksumBits = words.length / 3;
|
||||
var checksumMask = getUpperMask(checksumBits);
|
||||
let checksumBits = words.length / 3;
|
||||
let checksumMask = getUpperMask(checksumBits);
|
||||
|
||||
var checksum = arrayify(sha256(entropy.slice(0, entropyBits / 8)))[0];
|
||||
let checksum = arrayify(sha256(entropy.slice(0, entropyBits / 8)))[0];
|
||||
checksum &= checksumMask;
|
||||
|
||||
if (checksum !== (entropy[entropy.length - 1] & checksumMask)) {
|
||||
@@ -241,10 +324,10 @@ export function entropyToMnemonic(entropy: Arrayish, wordlist?: Wordlist): strin
|
||||
throw new Error('invalid entropy');
|
||||
}
|
||||
|
||||
var indices: Array<number> = [ 0 ];
|
||||
let indices: Array<number> = [ 0 ];
|
||||
|
||||
var remainingBits = 11;
|
||||
for (var i = 0; i < entropy.length; i++) {
|
||||
let remainingBits = 11;
|
||||
for (let i = 0; i < entropy.length; i++) {
|
||||
|
||||
// Consume the whole byte (with still more to go)
|
||||
if (remainingBits > 8) {
|
||||
@@ -266,8 +349,8 @@ export function entropyToMnemonic(entropy: Arrayish, wordlist?: Wordlist): strin
|
||||
}
|
||||
|
||||
// Compute the checksum bits
|
||||
var checksum = arrayify(sha256(entropy))[0];
|
||||
var checksumBits = entropy.length / 4;
|
||||
let checksum = arrayify(sha256(entropy))[0];
|
||||
let checksumBits = entropy.length / 4;
|
||||
checksum &= getUpperMask(checksumBits);
|
||||
|
||||
// Shift the checksum into the word indices
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSigna
|
||||
import { getAddress, getContractAddress, getIcapAddress } from './address';
|
||||
import * as base64 from './base64';
|
||||
import { BigNumber, bigNumberify } from './bignumber';
|
||||
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
|
||||
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, isHexString, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
|
||||
import { hashMessage, id, namehash } from './hash';
|
||||
import * as HDNode from './hdnode';
|
||||
import { Interface } from './interface';
|
||||
@@ -22,7 +22,7 @@ import { populateTransaction } from './transaction';
|
||||
import { parse as parseTransaction, serialize as serializeTransaction } from './transaction';
|
||||
import { formatBytes32String, parseBytes32String, toUtf8Bytes, toUtf8String } from './utf8';
|
||||
import { commify, formatEther, parseEther, formatUnits, parseUnits } from './units';
|
||||
import { fetchJson } from './web';
|
||||
import { fetchJson, poll } from './web';
|
||||
|
||||
|
||||
////////////////////////
|
||||
@@ -84,6 +84,7 @@ export {
|
||||
bigNumberify,
|
||||
|
||||
hexlify,
|
||||
isHexString,
|
||||
hexStripZeros,
|
||||
hexZeroPad,
|
||||
hexDataLength,
|
||||
@@ -135,6 +136,8 @@ export {
|
||||
recoverPublicKey,
|
||||
verifyMessage,
|
||||
|
||||
poll,
|
||||
|
||||
|
||||
////////////////////////
|
||||
// Enums
|
||||
|
||||
@@ -103,7 +103,7 @@ class _DeployDescription extends Description implements DeployDescription {
|
||||
});
|
||||
}
|
||||
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, 'in Interface constructor');
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, ' in Interface constructor');
|
||||
|
||||
try {
|
||||
return (bytecode + defaultAbiCoder.encode(this.inputs, params).substring(2));
|
||||
@@ -132,7 +132,7 @@ class _FunctionDescription extends Description implements FunctionDescription {
|
||||
readonly gas: BigNumber;
|
||||
|
||||
encode(params: Array<any>): string {
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, 'in interface function ' + this.name);
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, ' in interface function ' + this.name);
|
||||
|
||||
try {
|
||||
return this.sighash + defaultAbiCoder.encode(this.inputs, params).substring(2);
|
||||
@@ -311,6 +311,13 @@ function addMethod(method: any): void {
|
||||
let signature = formatSignature(method).replace(/tuple/g, '');
|
||||
let sighash = id(signature).substring(0, 10);
|
||||
|
||||
let isConst = false;
|
||||
if (method.constant != null) {
|
||||
isConst = method.constant;
|
||||
} else if (method.stateMutability != null) {
|
||||
isConst = (method.stateMutability == "view" || method.stateMutability == "pure");
|
||||
}
|
||||
|
||||
let description = new _FunctionDescription({
|
||||
inputs: method.inputs,
|
||||
outputs: method.outputs,
|
||||
@@ -318,15 +325,20 @@ function addMethod(method: any): void {
|
||||
gas: method.gas,
|
||||
|
||||
payable: (method.payable == null || !!method.payable),
|
||||
type: ((method.constant) ? 'call': 'transaction'),
|
||||
type: (isConst ? 'call': 'transaction'),
|
||||
|
||||
name: method.name,
|
||||
signature: signature,
|
||||
sighash: sighash,
|
||||
});
|
||||
|
||||
// Expose the first (and hopefully unique named function
|
||||
if (method.name && this.functions[method.name] == null) {
|
||||
defineReadOnly(this.functions, method.name, description);
|
||||
// Expose the first (and hopefully unique named function)
|
||||
if (method.name) {
|
||||
if (this.functions[method.name] == null) {
|
||||
defineReadOnly(this.functions, method.name, description);
|
||||
} else {
|
||||
errors.warn('WARNING: Multiple definitions for ' + method.name);
|
||||
}
|
||||
}
|
||||
|
||||
// Expose all methods by their signature, for overloaded functions
|
||||
@@ -367,7 +379,7 @@ function addMethod(method: any): void {
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('WARNING: unsupported ABI type - ' + method.type);
|
||||
errors.warn('WARNING: unsupported ABI type - ' + method.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -433,10 +445,10 @@ export class Interface {
|
||||
return new _TransactionDescription({
|
||||
args: result,
|
||||
decode: func.decode,
|
||||
name: name,
|
||||
name: func.name,
|
||||
signature: func.signature,
|
||||
sighash: func.sighash,
|
||||
value: bigNumberify(tx.value || null),
|
||||
value: bigNumberify(tx.value || '0'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,33 +7,69 @@ export type Network = {
|
||||
name: string,
|
||||
chainId: number,
|
||||
ensAddress?: string,
|
||||
_defaultProvider?: (providers: any) => any
|
||||
}
|
||||
|
||||
export type Networkish = Network | string | number;
|
||||
|
||||
function ethDefaultProvider(network: string): (providers: any) => any {
|
||||
return function(providers: any): any {
|
||||
let providerList: Array<any> = [];
|
||||
|
||||
if (providers.InfuraProvider) {
|
||||
providerList.push(new providers.InfuraProvider(network));
|
||||
}
|
||||
|
||||
if (providers.EtherscanProvider) {
|
||||
providerList.push(new providers.EtherscanProvider(network));
|
||||
}
|
||||
|
||||
if (providerList.length === 0) { return null; }
|
||||
|
||||
if (providers.FallbackProvider) {
|
||||
return new providers.FallbackProvider(providerList);;
|
||||
}
|
||||
|
||||
return providerList[0];
|
||||
}
|
||||
}
|
||||
|
||||
function etcDefaultProvider(url: string, network: string): (providers: any) => any {
|
||||
return function(providers: any): any {
|
||||
if (providers.JsonRpcProvider) {
|
||||
return new providers.JsonRpcProvider(url, network);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const homestead: Network = {
|
||||
chainId: 1,
|
||||
ensAddress: "0x314159265dd8dbb310642f98f50c066173c1259b",
|
||||
name: "homestead"
|
||||
name: "homestead",
|
||||
_defaultProvider: ethDefaultProvider('homestead')
|
||||
};
|
||||
|
||||
const ropsten: Network = {
|
||||
chainId: 3,
|
||||
ensAddress: "0x112234455c3a32fd11230c42e7bccd4a84e02010",
|
||||
name: "ropsten"
|
||||
name: "ropsten",
|
||||
_defaultProvider: ethDefaultProvider('ropsten')
|
||||
};
|
||||
|
||||
const networks: { [name: string]: { chainId: number, ensAddress?: string } } = {
|
||||
const networks: { [name: string]: Network } = {
|
||||
unspecified: {
|
||||
chainId: 0
|
||||
chainId: 0,
|
||||
name: 'unspecified'
|
||||
},
|
||||
|
||||
homestead: homestead,
|
||||
mainnet: homestead,
|
||||
|
||||
morden: {
|
||||
chainId: 2
|
||||
chainId: 2,
|
||||
name: 'morden'
|
||||
},
|
||||
|
||||
ropsten: ropsten,
|
||||
@@ -41,19 +77,34 @@ const networks: { [name: string]: { chainId: number, ensAddress?: string } } = {
|
||||
|
||||
rinkeby: {
|
||||
chainId: 4,
|
||||
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A"
|
||||
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A",
|
||||
name: 'rinkeby',
|
||||
_defaultProvider: ethDefaultProvider('rinkeby')
|
||||
},
|
||||
|
||||
goerli: {
|
||||
chainId: 5,
|
||||
ensAddress: "0x112234455c3a32fd11230c42e7bccd4a84e02010",
|
||||
name: "goerli",
|
||||
_defaultProvider: ethDefaultProvider('goerli')
|
||||
},
|
||||
|
||||
kovan: {
|
||||
chainId: 42
|
||||
chainId: 42,
|
||||
name: 'kovan',
|
||||
_defaultProvider: ethDefaultProvider('kovan')
|
||||
},
|
||||
|
||||
classic: {
|
||||
chainId: 61
|
||||
chainId: 61,
|
||||
name: 'classic',
|
||||
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io', 'classic')
|
||||
},
|
||||
|
||||
classicTestnet: {
|
||||
chainId: 62
|
||||
chainId: 62,
|
||||
name: 'classicTestnet',
|
||||
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io/morden', 'classicTestnet')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,17 +115,18 @@ const networks: { [name: string]: { chainId: number, ensAddress?: string } } = {
|
||||
* and verifies a network is a valid Network..
|
||||
*/
|
||||
export function getNetwork(network: Networkish): Network {
|
||||
// No network (null) or unspecified (chainId = 0)
|
||||
if (!network) { return null; }
|
||||
// No network (null)
|
||||
if (network == null) { return null; }
|
||||
|
||||
if (typeof(network) === 'number') {
|
||||
for (var name in networks) {
|
||||
for (let name in networks) {
|
||||
let n = networks[name];
|
||||
if (n.chainId === network) {
|
||||
return {
|
||||
name: name,
|
||||
name: n.name,
|
||||
chainId: n.chainId,
|
||||
ensAddress: n.ensAddress
|
||||
ensAddress: (n.ensAddress || null),
|
||||
_defaultProvider: (n._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -89,9 +141,10 @@ export function getNetwork(network: Networkish): Network {
|
||||
let n = networks[network];
|
||||
if (n == null) { return null; }
|
||||
return {
|
||||
name: network,
|
||||
name: n.name,
|
||||
chainId: n.chainId,
|
||||
ensAddress: n.ensAddress
|
||||
ensAddress: n.ensAddress,
|
||||
_defaultProvider: (n._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -110,10 +163,11 @@ export function getNetwork(network: Networkish): Network {
|
||||
errors.throwError('network chainId mismatch', errors.INVALID_ARGUMENT, { arg: 'network', value: network });
|
||||
}
|
||||
|
||||
// Standard Network
|
||||
// Standard Network (allow overriding the ENS address)
|
||||
return {
|
||||
name: network.name,
|
||||
chainId: n.chainId,
|
||||
ensAddress: n.ensAddress
|
||||
ensAddress: (network.ensAddress || n.ensAddress || null),
|
||||
_defaultProvider: (network._defaultProvider || n._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ function _decode(data: Uint8Array, offset: number): { consumed: number, result:
|
||||
} else if (data[offset] >= 0x80) {
|
||||
var length = data[offset] - 0x80;
|
||||
if (offset + 1 + length > data.length) {
|
||||
throw new Error('invlaid rlp data');
|
||||
throw new Error('invalid rlp data');
|
||||
}
|
||||
|
||||
var result = hexlify(data.slice(offset + 1, offset + 1 + length));
|
||||
|
||||
@@ -62,6 +62,12 @@ export class KeyPair {
|
||||
let otherKeyPair = getCurve().keyFromPublic(arrayify(computePublicKey(otherKey)));
|
||||
return hexZeroPad('0x' + keyPair.derive(otherKeyPair.getPublic()).toString(16), 32);
|
||||
}
|
||||
|
||||
_addPoint(other: Arrayish | string): string {
|
||||
let p0 = getCurve().keyFromPublic(arrayify(this.publicKey));
|
||||
let p1 = getCurve().keyFromPublic(arrayify(other));
|
||||
return "0x" + p0.pub.add(p1.pub).encodeCompressed("hex");
|
||||
}
|
||||
}
|
||||
|
||||
export function computePublicKey(key: Arrayish | string, compressed?: boolean): string {
|
||||
|
||||
@@ -171,7 +171,7 @@ export function decrypt(json: string, password: Arrayish, progressCallback?: Pro
|
||||
}
|
||||
|
||||
var signingKey = new SigningKey(privateKey);
|
||||
if (signingKey.address !== getAddress(data.address)) {
|
||||
if (data.address && signingKey.address !== getAddress(data.address)) {
|
||||
reject(new Error('address mismatch'));
|
||||
return null;
|
||||
}
|
||||
@@ -438,6 +438,7 @@ export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish |
|
||||
gethFilename: ('UTC--' + timestamp + '--' + data.address),
|
||||
mnemonicCounter: hexlify(mnemonicIv).substring(2),
|
||||
mnemonicCiphertext: hexlify(mnemonicCiphertext).substring(2),
|
||||
path: path,
|
||||
version: "0.1"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ import { arrayify } from './bytes';
|
||||
// Types
|
||||
import { Arrayish } from './bytes';
|
||||
|
||||
export function ripemd160(data: Arrayish): string {
|
||||
return '0x' + (hash.ripemd160().update(arrayify(data)).digest('hex'));
|
||||
}
|
||||
|
||||
export function sha256(data: Arrayish): string {
|
||||
return '0x' + (hash.sha256().update(arrayify(data)).digest('hex'));
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ export function parse(rawTransaction: Arrayish): Transaction {
|
||||
tx.v = bigNumberify(transaction[6]).toNumber();
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
errors.info(error);
|
||||
return tx;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ export function parse(rawTransaction: Arrayish): Transaction {
|
||||
try {
|
||||
tx.from = recoverAddress(digest, { r: hexlify(tx.r), s: hexlify(tx.s), recoveryParam: recoveryParam });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
errors.info(error);
|
||||
}
|
||||
|
||||
tx.hash = keccak256(rawTransaction);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import { HashZero } from '../constants';
|
||||
|
||||
import { checkNormalize } from '../errors';
|
||||
import { arrayify, concat, hexlify } from './bytes';
|
||||
|
||||
///////////////////////////////
|
||||
@@ -23,6 +23,7 @@ export enum UnicodeNormalizationForm {
|
||||
export function toUtf8Bytes(str: string, form: UnicodeNormalizationForm = UnicodeNormalizationForm.current): Uint8Array {
|
||||
|
||||
if (form != UnicodeNormalizationForm.current) {
|
||||
checkNormalize();
|
||||
str = str.normalize(form);
|
||||
}
|
||||
|
||||
@@ -189,7 +190,7 @@ export function parseBytes32String(bytes: Arrayish): string {
|
||||
|
||||
// Must be 32 bytes with a null-termination
|
||||
if (data.length !== 32) { throw new Error('invalid bytes32 - not 32 bytes long'); }
|
||||
if (data[31] !== 0) { throw new Error('invalid bytes32 sdtring - no null terminator'); }
|
||||
if (data[31] !== 0) { throw new Error('invalid bytes32 string - no null terminator'); }
|
||||
|
||||
// Find the null termination
|
||||
let length = 31;
|
||||
|
||||
@@ -28,7 +28,8 @@ export type PollOptions = {
|
||||
floor?: number,
|
||||
ceiling?: number,
|
||||
interval?: number,
|
||||
onceBlock?: OnceBlockable
|
||||
onceBlock?: OnceBlockable,
|
||||
fastRetry?: number
|
||||
};
|
||||
|
||||
|
||||
@@ -135,6 +136,9 @@ export function fetchJson(connection: string | ConnectionInfo, json: string, pro
|
||||
let jsonError: any = new Error('invalid json response');
|
||||
jsonError.orginialError = error;
|
||||
jsonError.responseText = request.responseText;
|
||||
if (json != null) {
|
||||
jsonError.requestBody = json;
|
||||
}
|
||||
jsonError.url = url;
|
||||
reject(jsonError);
|
||||
return;
|
||||
@@ -163,7 +167,7 @@ export function fetchJson(connection: string | ConnectionInfo, json: string, pro
|
||||
}
|
||||
|
||||
try {
|
||||
if (json) {
|
||||
if (json != null) {
|
||||
request.send(json);
|
||||
} else {
|
||||
request.send();
|
||||
@@ -205,6 +209,8 @@ export function poll(func: () => Promise<any>, options?: PollOptions): Promise<a
|
||||
}, options.timeout)
|
||||
}
|
||||
|
||||
let fastTimeout = options.fastRetry || null;
|
||||
|
||||
let attempt = 0;
|
||||
function check() {
|
||||
return func().then(function(result) {
|
||||
@@ -224,6 +230,13 @@ export function poll(func: () => Promise<any>, options?: PollOptions): Promise<a
|
||||
if (timeout < options.floor) { timeout = options.floor; }
|
||||
if (timeout > options.ceiling) { timeout = options.ceiling; }
|
||||
|
||||
// Fast Timeout, means we quickly try again the first time
|
||||
if (fastTimeout) {
|
||||
attempt--;
|
||||
timeout = fastTimeout;
|
||||
fastTimeout = null;
|
||||
}
|
||||
|
||||
setTimeout(check, timeout);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ export class Wallet extends AbstractSigner {
|
||||
get address(): string { return this.signingKey.address; }
|
||||
|
||||
get mnemonic(): string { return this.signingKey.mnemonic; }
|
||||
get path(): string { return this.signingKey.mnemonic; }
|
||||
get path(): string { return this.signingKey.path; }
|
||||
|
||||
get privateKey(): string { return this.signingKey.privateKey; }
|
||||
|
||||
@@ -62,7 +62,6 @@ export class Wallet extends AbstractSigner {
|
||||
return new Wallet(this.signingKey, provider);
|
||||
}
|
||||
|
||||
|
||||
getAddress(): Promise<string> {
|
||||
return Promise.resolve(this.address);
|
||||
}
|
||||
@@ -91,6 +90,13 @@ export class Wallet extends AbstractSigner {
|
||||
}
|
||||
|
||||
sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> {
|
||||
if (!this.provider) { throw new Error('missing provider'); }
|
||||
|
||||
if (transaction.nonce == null) {
|
||||
transaction = shallowCopy(transaction);
|
||||
transaction.nonce = this.getTransactionCount("pending");
|
||||
}
|
||||
|
||||
return populateTransaction(transaction, this.provider, this.address).then((tx) => {
|
||||
return this.sign(tx).then((signedTransaction) => {
|
||||
return this.provider.sendTransaction(signedTransaction);
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -132,9 +132,7 @@ class LangJa extends Wordlist {
|
||||
}
|
||||
|
||||
split(mnemonic: string): Array<string> {
|
||||
if (!mnemonic.normalize) {
|
||||
errors.throwError('Japanese is unsupported on this platform; missing String.prototype.normalize', errors.UNSUPPORTED_OPERATION, { operation: 'String.prototype.normalize' });
|
||||
}
|
||||
errors.checkNormalize();
|
||||
return mnemonic.split(/(?:\u3000| )+/g);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ Building Testcases
|
||||
------------------
|
||||
|
||||
Each suite of testcases is produced from a variety of sources. Many include a
|
||||
specific set of test vecotrs as well as procedurally generated tests using known
|
||||
specific set of test vectors as well as procedurally generated tests using known
|
||||
correct implementations.
|
||||
|
||||
The `contract-interface` test cases are created by selecting a (deterministically) random
|
||||
|
||||
@@ -32,6 +32,9 @@ function getHD(seed) {
|
||||
path: 'm',
|
||||
privateKey: '0x' + privateKey.toString('hex'),
|
||||
address: '0x' + ethereumUtil.privateToAddress(privateKey).toString('hex'),
|
||||
parentFingerprint: rootNode.parentFingerprint,
|
||||
xpriv: rootNode.toBase58(),
|
||||
xpub: rootNode.neutered().toBase58(),
|
||||
}];
|
||||
|
||||
for (var j = 0; j < 5; j++) {
|
||||
@@ -42,6 +45,9 @@ function getHD(seed) {
|
||||
path: path,
|
||||
privateKey: '0x' + privateKey.toString('hex'),
|
||||
address: '0x' + ethereumUtil.privateToAddress(privateKey).toString('hex'),
|
||||
parentFingerprint: node.parentFingerprint,
|
||||
xpriv: node.toBase58(),
|
||||
xpub: node.neutered().toBase58(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -96,6 +102,8 @@ Testcases['axic'] = {
|
||||
path: "m/44'/60'/0'/0/0",
|
||||
address: '0xac39b311dceb2a4b2f5d8461c1cdaf756f4f7ae9',
|
||||
privateKey: '0xb96e9ccb774cc33213cbcb2c69d3cdae17b0fe4888a1ccd343cbd1a17fd98b18',
|
||||
xpriv: "xprvA2xEQ2iTe9QB22rvf5cbfpUxEBmMdvc7stEFxLhiMXmdLrwLbqugPCHRZiRfEq2puC5vTgwyFneV38hppF8oTf9aoaUv7M8u2XvnACTe6r4",
|
||||
xpub: "xpub6FwaoYFMUWxUEWwPm79c2xRgnDbr3PKyF79rkj7KusJcDfGV9PDvvzbuQz32JYu3y2EpqY7xUag5Zw89YXokCKVtWLrfJ1RDUAYLLzTR8En"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ var path = require('path');
|
||||
var utils = require('../utils.js');
|
||||
|
||||
function prefixAddress(address) {
|
||||
if (!address) { return null; }
|
||||
if (address.substring(0, 2) !== '0x') {
|
||||
address = '0x' + address;
|
||||
}
|
||||
@@ -25,6 +26,10 @@ Output.push({
|
||||
});
|
||||
*/
|
||||
|
||||
var addresses = {
|
||||
"582": "0x008aeeda4d805471df9b2a5b0f38a0c3bcba786b"
|
||||
};
|
||||
|
||||
var privateKeys = {
|
||||
'0x0b88d4b324ec24c8c078551e6e5075547157e5b6': '0xd4375d2a931db84ea8825b69a3128913597744d9236cacec675cc18e1bda4446',
|
||||
'0x2e326fa404fc3661de4f4361776ed9bbabdc26e3': '0xcf367fc32bf789b3339c6664af4a12263e9db0e0eb70f247da1d1165e150c487',
|
||||
@@ -33,7 +38,8 @@ var privateKeys = {
|
||||
'0x88a5c2d9919e46f883eb62f7b8dd9d0cc45bc290': '0xf03e581353c794928373fb0893bc731aefc4c4e234e643f3a46998b03cd4d7c5',
|
||||
'0x17c5185167401ed00cf5f5b2fc97d9bbfdb7d025': '0x4242424242424242424242424242424242424242424242424242424242424242',
|
||||
'0x012363d61bdc53d0290a0f25e9c89f8257550fb8': '0x4c94faa2c558a998d10ee8b2b9b8eb1fbcb8a6ac5fd085c6f95535604fc1bffb',
|
||||
'0x15db397ed5f682acb22b0afc6c8de4cdfbda7cbc': '0xcdf3c34a2ea0ff181f462856168f5851e68c37b583eb158403e43aeab4964fee'
|
||||
'0x15db397ed5f682acb22b0afc6c8de4cdfbda7cbc': '0xcdf3c34a2ea0ff181f462856168f5851e68c37b583eb158403e43aeab4964fee',
|
||||
'0x008aeeda4d805471df9b2a5b0f38a0c3bcba786b': '0x7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d'
|
||||
}
|
||||
|
||||
var mnemonics = {
|
||||
@@ -62,14 +68,16 @@ fs.readdirSync(walletPath).forEach(function(filename) {
|
||||
});
|
||||
|
||||
} else {
|
||||
let address = (addresses[name] || prefixAddress(data.address));
|
||||
Output.push({
|
||||
type: 'secret-storage',
|
||||
address: prefixAddress(data.address),
|
||||
hasAddress: !addresses[name],
|
||||
address: address,
|
||||
json: JSON.stringify(data),
|
||||
mnemonic: mnemonics[prefixAddress(data.address)] || '',
|
||||
mnemonic: mnemonics[address] || '',
|
||||
name: name,
|
||||
password: password,
|
||||
privateKey: privateKeys[prefixAddress(data.address)],
|
||||
privateKey: privateKeys[address],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"6087dab2f9fdbbfaddc31a909735c1e6"},"ciphertext":"5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46","kdf":"pbkdf2","kdfparams":{"c":262144,"dklen":32,"prf":"hmac-sha256","salt":"ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"},"mac":"517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2"},"id":"3198bc9c-6672-5ab3-d995-4942343ae5b6","version":3}
|
||||
@@ -110,4 +110,8 @@ function Reporter(runner) {
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
window.ethersReporter = Reporter;
|
||||
} catch (error) { }
|
||||
|
||||
module.exports = Reporter;
|
||||
|
||||
99
tests/shims/base64.js
Normal file
99
tests/shims/base64.js
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* See: https://github.com/MaxArt2501/base64-js
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 MaxArt2501
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], function() {factory(root);});
|
||||
} else factory(root);
|
||||
// node.js has always supported base64 conversions, while browsers that support
|
||||
// web workers support base64 too, but you may never know.
|
||||
})(typeof exports !== "undefined" ? exports : this, function(root) {
|
||||
if (root.atob) {
|
||||
// Some browsers' implementation of atob doesn't support whitespaces
|
||||
// in the encoded string (notably, IE). This wraps the native atob
|
||||
// in a function that strips the whitespaces.
|
||||
// The original function can be retrieved in atob.original
|
||||
try {
|
||||
root.atob(" ");
|
||||
} catch(e) {
|
||||
root.atob = (function(atob) {
|
||||
var func = function(string) {
|
||||
return atob(String(string).replace(/[\t\n\f\r ]+/g, ""));
|
||||
};
|
||||
func.original = atob;
|
||||
return func;
|
||||
})(root.atob);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// base64 character set, plus padding character (=)
|
||||
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
||||
// Regular expression to check formal correctness of base64 encoded strings
|
||||
b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
||||
|
||||
root.btoa = function(string) {
|
||||
string = String(string);
|
||||
var bitmap, a, b, c,
|
||||
result = "", i = 0,
|
||||
rest = string.length % 3; // To determine the final padding
|
||||
|
||||
for (; i < string.length;) {
|
||||
if ((a = string.charCodeAt(i++)) > 255
|
||||
|| (b = string.charCodeAt(i++)) > 255
|
||||
|| (c = string.charCodeAt(i++)) > 255)
|
||||
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
|
||||
|
||||
bitmap = (a << 16) | (b << 8) | c;
|
||||
result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63)
|
||||
+ b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
|
||||
}
|
||||
|
||||
// If there's need of padding, replace the last 'A's with equal signs
|
||||
return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
|
||||
};
|
||||
|
||||
root.atob = function(string) {
|
||||
// atob can work with strings with whitespaces, even inside the encoded part,
|
||||
// but only \t, \n, \f, \r and ' ', which can be stripped.
|
||||
string = String(string).replace(/[\t\n\f\r ]+/g, "");
|
||||
if (!b64re.test(string))
|
||||
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
||||
|
||||
// Adding the padding if missing, for semplicity
|
||||
string += "==".slice(2 - (string.length & 3));
|
||||
var bitmap, result = "", r1, r2, i = 0;
|
||||
for (; i < string.length;) {
|
||||
bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12
|
||||
| (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));
|
||||
|
||||
result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255)
|
||||
: r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255)
|
||||
: String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
});
|
||||
80
tests/shims/index.js
Normal file
80
tests/shims/index.js
Normal file
@@ -0,0 +1,80 @@
|
||||
'use strict';
|
||||
|
||||
var shims = [];
|
||||
|
||||
// Shim String.prototype.normalize
|
||||
try {
|
||||
var missing = [];
|
||||
|
||||
// Some platforms are missing certain normalization forms
|
||||
var forms = ["NFD", "NFC", "NFKD", "NFKC"];
|
||||
for (var i = 0; i < forms.length; i++) {
|
||||
try {
|
||||
"test".normalize(forms[i]);
|
||||
} catch(error) {
|
||||
missing.push(forms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.length) {
|
||||
shims.push("String.prototype.normalize (missing: " + missing.join(", ") + ")");
|
||||
throw new Error('bad normalize');
|
||||
}
|
||||
|
||||
// Some platforms have a native normalize, but it is broken; so we force our shim
|
||||
if (String.fromCharCode(0xe9).normalize('NFD') !== String.fromCharCode(0x65, 0x0301)) {
|
||||
shims.push("String.prototype.normalize (broken)");
|
||||
throw new Error('bad normalize');
|
||||
}
|
||||
} catch (error) {
|
||||
var unorm = require('./unorm.js');
|
||||
String.prototype.normalize = function(form) {
|
||||
var func = unorm[(form || 'NFC').toLowerCase()];
|
||||
if (!func) { throw new RangeError('invalid form - ' + form); }
|
||||
return func(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Shim atob and btoa
|
||||
var base64 = require('./base64.js');
|
||||
if (!global.atob) {
|
||||
shims.push("atob");
|
||||
global.atob = base64.atob;
|
||||
}
|
||||
if (!global.btoa) {
|
||||
shims.push("btoa");
|
||||
global.btoa = base64.btoa;
|
||||
}
|
||||
|
||||
// Shim Promise
|
||||
// @TODO: Check first?
|
||||
var promise = require('./es6-promise.auto.js');
|
||||
|
||||
// Shim ArrayBuffer.isView
|
||||
if (!ArrayBuffer.isView) {
|
||||
shims.push("ArrayBuffer.isView");
|
||||
ArrayBuffer.isView = function(obj) {
|
||||
// @TODO: This should probably check various instanceof aswell
|
||||
return !!(obj.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.prototype.fill == null) {
|
||||
shims.push("Array.fill");
|
||||
Array.prototype.fill = function(value) {
|
||||
for (var i = 0; i < this.length; i++) { this[i] = value; }
|
||||
}
|
||||
}
|
||||
|
||||
// Shim nextTick
|
||||
if (!global.nextTick) {
|
||||
shims.push("nextTick");
|
||||
global.nextTick = function (callback) { setTimeout(callback, 0); }
|
||||
}
|
||||
|
||||
if (shims.length) {
|
||||
console.log("Shims Injected:");
|
||||
for (var i = 0; i < shims.length; i++) {
|
||||
console.log(' - ' + shims[i]);
|
||||
}
|
||||
}
|
||||
@@ -231,6 +231,36 @@ describe('Test Interface Signatures', function() {
|
||||
'derived the correct signature hash');
|
||||
})
|
||||
});
|
||||
|
||||
it('derives correct description for human-readable ABI', function() {
|
||||
var iface = new Interface([ "function transfer(address from, uint amount)" ]);
|
||||
[
|
||||
"transfer",
|
||||
"transfer(address,uint256)"
|
||||
].forEach(function(key) {
|
||||
var descr = iface.functions[key];
|
||||
assert.equal(descr.name, "transfer", "incorrect name key - " + key);
|
||||
assert.equal(descr.signature, "transfer(address,uint256)", "incorrect signature key - " + key);
|
||||
assert.equal(descr.sighash, "0xa9059cbb", "incorrect sighash key - " + key);
|
||||
});
|
||||
});
|
||||
|
||||
// See: https://github.com/ethers-io/ethers.js/issues/370
|
||||
it ('parses transaction function', function() {
|
||||
var iface = new Interface([ "function transfer(address from, uint amount)" ]);
|
||||
|
||||
// Transaction: 0x820cc57bc77be44d8f4f024a18e18f64a8b6e62a82a3d7897db5970dbe181ba1
|
||||
var rawTx = "0xf8aa028502540be4008316e36094334eec1482109bd802d9e72a447848de3bcc106380b844a9059cbb000000000000000000000000851b9167b7cbf772d38efaf89705b35022880a070000000000000000000000000000000000000000000000000de0b6b3a764000026a03200bf26e5f10f7eda59c0aad9adc2334dda79e785b9b004342524d97a66fca9a0450b07a4dc450bb472e08f8370350fa365fcef6db1a95309ae4c06c9d0748092";
|
||||
var tx = ethers.utils.parseTransaction(rawTx);
|
||||
|
||||
var descr = iface.parseTransaction(tx);
|
||||
assert.equal(descr.args[0], '0x851b9167B7cbf772D38eFaf89705b35022880A07', 'parsed tx - args[0]');
|
||||
assert.equal(descr.args[1].toString(), '1000000000000000000', 'parsed tx - args[1]');
|
||||
assert.equal(descr.name, 'transfer', 'parsed tx - name');
|
||||
assert.equal(descr.signature, 'transfer(address,uint256)', 'parsed tx - signature');
|
||||
assert.equal(descr.sighash, '0xa9059cbb', 'parsed tx - sighash');
|
||||
assert.equal(descr.value.toString(), '0', 'parsed tx - value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test Number Coder', function() {
|
||||
@@ -510,3 +540,46 @@ describe('Test Filters', function() {
|
||||
doTest(test);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test Solidity v0.6 ABI', function() {
|
||||
|
||||
var tests = [
|
||||
{
|
||||
inputs: [ ],
|
||||
outputs: [ ],
|
||||
stateMutability: "view",
|
||||
type: "function",
|
||||
name: "testView_call"
|
||||
},
|
||||
{
|
||||
inputs: [ ],
|
||||
outputs: [ ],
|
||||
stateMutability: "pure",
|
||||
type: "function",
|
||||
name: "testPure_call"
|
||||
},
|
||||
{
|
||||
inputs: [ ],
|
||||
outputs: [ ],
|
||||
stateMutability: "payable",
|
||||
type: "function",
|
||||
name: "testPayable_transaction"
|
||||
},
|
||||
{
|
||||
inputs: [ ],
|
||||
outputs: [ ],
|
||||
stateMutability: "nonpayable",
|
||||
type: "function",
|
||||
name: "testNonpayable_transaction"
|
||||
},
|
||||
];
|
||||
|
||||
tests.forEach(function(test, index) {
|
||||
var type = test.name.split("_")[1];
|
||||
it(('generates fragment from ABI - ' + test.name.split("_")[0]), function() {
|
||||
var iface = new ethers.utils.Interface(JSON.stringify([ test ]));
|
||||
var func = iface.functions[test.name];
|
||||
assert.equal(func.type, type, "matches type");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,25 +5,89 @@ var assert = require('assert');
|
||||
var utils = require('./utils');
|
||||
var ethers = utils.getEthers(__filename);
|
||||
|
||||
function skip(name) {
|
||||
var match = name.match(/^random-([0-9]+)$/);
|
||||
if (match && parseInt(match[1]) > 512) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
describe('Test HD Node Derivation', function(test) {
|
||||
|
||||
var tests = utils.loadTests('hdnode');
|
||||
tests.forEach(function(test) {
|
||||
if (skip(test.name)) { return; }
|
||||
it('Derives the HD nodes - ' + test.name, function() {
|
||||
this.timeout(10000);
|
||||
|
||||
var rootNode = new ethers.utils.HDNode.fromSeed(test.seed);
|
||||
test.hdnodes.forEach(function(nodeTest) {
|
||||
//var rootNode = new ethers.utils.HDNode.fromSeed(test.seed);
|
||||
var rootNode = new ethers.utils.HDNode.fromMnemonic(test.mnemonic, null, test.password || null);
|
||||
|
||||
test.hdnodes.forEach(function(nodeTest) {
|
||||
var node = rootNode.derivePath(nodeTest.path);
|
||||
assert.equal(node.privateKey, nodeTest.privateKey,
|
||||
'Generates privateKey - ' + nodeTest.privateKey);
|
||||
|
||||
assert.equal(node.extendedKey, nodeTest.xpriv,
|
||||
"Child Extended privateKey - " + nodeTest.privateKey);
|
||||
assert.equal(node.neuter().extendedKey, nodeTest.xpub,
|
||||
"Child Extended privateKey - " + nodeTest.privateKey);
|
||||
|
||||
var wallet = new ethers.Wallet(node.privateKey);
|
||||
assert.equal(wallet.address.toLowerCase(), nodeTest.address,
|
||||
'Generates address - ' + nodeTest.privateKey);
|
||||
|
||||
assert.equal(node.address, (new ethers.Wallet(node)).address, 'HDNode address matches - ' + nodeTest.privateKey);
|
||||
assert.equal(node.address, (new ethers.Wallet(node)).address,
|
||||
'HDNode address matches - ' + nodeTest.privateKey);
|
||||
|
||||
// Test public extended key derivation
|
||||
var lastHardened = nodeTest.path.match(/^(.*)'([^']*)$/);
|
||||
if (lastHardened && lastHardened[2].trim() !== "") {
|
||||
|
||||
// Derive as far as we can for hardened, then derive the remaining from neutered
|
||||
var hardNode = rootNode.derivePath(lastHardened[1] + "'");
|
||||
var neutered = hardNode.neuter();
|
||||
var nodeXpriv = ethers.utils.HDNode.fromExtendedKey(hardNode.extendedKey);
|
||||
nodeXpriv = nodeXpriv.derivePath(lastHardened[2].substring(1));
|
||||
var nodeXpub = ethers.utils.HDNode.fromExtendedKey(neutered.extendedKey);
|
||||
nodeXpub = nodeXpub.derivePath(lastHardened[2].substring(1));
|
||||
|
||||
assert.equal(neutered.privateKey, null,
|
||||
'Neutered HDNode privateKey null - ' + nodeTest.privateKey);
|
||||
assert.equal(neutered.xpriv, null,
|
||||
'Neutered HDNode xpriv null - ' + nodeTest.privateKey);
|
||||
|
||||
neutered = neutered.derivePath(lastHardened[2].substring(1));
|
||||
|
||||
assert.equal(neutered.address.toLowerCase(), nodeTest.address,
|
||||
'Derived Neutered HDNode address matches - ' + nodeTest.privateKey);
|
||||
|
||||
assert.equal(neutered.xpub, node.xpub,
|
||||
'Derived Neutered HDNode xpub matches - ' + nodeTest.privateKey);
|
||||
|
||||
assert.equal(neutered.privateKey, null,
|
||||
'Derived Neutered HDNode privateKey null - ' + nodeTest.privateKey);
|
||||
assert.equal(neutered.xpriv, null,
|
||||
'Neutered HDNode xpriv null - ' + nodeTest.privateKey);
|
||||
|
||||
// Test extended key derivation
|
||||
assert.equal(nodeXpub.xpriv, null,
|
||||
'Serialized Neutered HDNode xpriv null - ' + nodeTest.privateKey);
|
||||
assert.equal(nodeXpriv.extendedKey, node.extendedKey,
|
||||
'Serialized HDNode xpriv matches - ' + nodeTest.privateKey);
|
||||
assert.equal(nodeXpub.extendedKey, neutered.extendedKey,
|
||||
'Serialized Neutered HDNode xpub matches - ' + nodeTest.privateKey);
|
||||
}
|
||||
|
||||
// Test serialization
|
||||
var deserializedNode = ethers.utils.HDNode.fromExtendedKey(nodeTest.xpriv);
|
||||
|
||||
assert.equal(deserializedNode.extendedKey, nodeTest.xpriv,
|
||||
'Neutered HDNode xpriv null - ' + nodeTest.privateKey);
|
||||
assert.equal(deserializedNode.neuter().extendedKey, nodeTest.xpub,
|
||||
'Neutered HDNode xpriv null - ' + nodeTest.privateKey);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -32,6 +96,7 @@ describe('Test HD Node Derivation', function(test) {
|
||||
describe('Test HD Mnemonic Phrases', function testMnemonic() {
|
||||
var tests = utils.loadTests('hdnode');
|
||||
tests.forEach(function(test) {
|
||||
if (skip(test.name)) { return; }
|
||||
it(('converts mnemonic phrases - ' + test.name), function() {
|
||||
this.timeout(1000000);
|
||||
|
||||
@@ -73,3 +138,71 @@ testEasySeed(ethers.wordlists.zh_cn, 'zh_cn');
|
||||
testEasySeed(ethers.wordlists.zh_tw, 'zh_tw');
|
||||
testEasySeed(ethers.wordlists.it, 'it');
|
||||
testEasySeed(ethers.wordlists.ko, 'ko');
|
||||
|
||||
describe('Testnet Extended Key (#553)', function testMnemonic() {
|
||||
var tests = [
|
||||
{
|
||||
name: "testnet extended public key",
|
||||
extended: "tpubD6NzVbkrYhZ4Xbv9K5Ajt49a8XEPydLyfyFBNvqt3TRBa9S8L3PVoKBthRS8gimY2ZU2LQ3gXQKpXHRR6fu9W1rWp6jaBToyZ5ar7wbRNYs",
|
||||
node: {
|
||||
publicKey: "0x02ead6f326f28baf5af54ab4a1688d5784f92848bba73c004365da8871b1e8677e",
|
||||
parentFingerprint: "0x00000000",
|
||||
fingerprint: "0x68ff1104",
|
||||
address: "0xc17Ee49BA46A41FBdA2306d00DA5Ce410925a7cb",
|
||||
chainCode: "0x7eee1a867c6938de05f0677d290769a6db3d135d4c1b5ba84c753b56b027cfb7",
|
||||
index: 0,
|
||||
depth: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "testnet extended private key",
|
||||
extended: "tprv8ZgxMBicQKsPe8tMRRW9UeVTZViTpJA56feQ6QoadBcnjfBMheZucpa2XHqF6iuRJSngkasg1yXD7VpGgGafFJwhY5RoETMSbiyEDBzxdCd",
|
||||
node: {
|
||||
privateKey: "0x949219063180d462349e358ec93cec1067fc346b37530e44b592a8a6dbe96d4c",
|
||||
publicKey: "0x02ead6f326f28baf5af54ab4a1688d5784f92848bba73c004365da8871b1e8677e",
|
||||
parentFingerprint: "0x00000000",
|
||||
fingerprint: "0x68ff1104",
|
||||
address: "0xc17Ee49BA46A41FBdA2306d00DA5Ce410925a7cb",
|
||||
chainCode: "0x7eee1a867c6938de05f0677d290769a6db3d135d4c1b5ba84c753b56b027cfb7",
|
||||
index: 0,
|
||||
depth: 0
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
tests.forEach(function(test) {
|
||||
it(test.name, function() {
|
||||
var node = ethers.utils.HDNode.fromExtendedKey(test.extended);
|
||||
Object.keys(test.node).forEach(function(key) {
|
||||
assert.equal(node[key], test.node[key], "does not match " + key);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Test Mnemonic is Case Agnostic", function() {
|
||||
function randomCase(seed, text) {
|
||||
return text.split("").map(function(c, index) {
|
||||
if (utils.randomNumber(seed + "-" + index, 0, 1000) > 500) {
|
||||
return c.toUpperCase();
|
||||
}
|
||||
return c
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function addTest(mnemonic, altMnemonic) {
|
||||
it(altMnemonic, function() {
|
||||
var node = ethers.utils.HDNode.fromMnemonic(mnemonic);
|
||||
var altNode = ethers.utils.HDNode.fromMnemonic(altMnemonic);
|
||||
assert.equal(node.privateKey, altNode.privateKey, altMnemonic);
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0; i < 128; i++) {
|
||||
var seed = "test-" + i;
|
||||
var entropy = utils.randomBytes(seed, 16, 16);
|
||||
var mnemonic = ethers.utils.HDNode.entropyToMnemonic(entropy);
|
||||
var altMnemonic = randomCase(seed, mnemonic);
|
||||
addTest(mnemonic, altMnemonic);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -53,6 +53,7 @@ var blockchainData = {
|
||||
blockNumber: 0x3c92b5,
|
||||
contractAddress: null,
|
||||
cumulativeGasUsed: 0x1cca2e,
|
||||
from: "0x18C6045651826824FEBBD39d8560584078d1b247",
|
||||
gasUsed:0x14bb7,
|
||||
logs: [
|
||||
{
|
||||
@@ -78,11 +79,12 @@ var blockchainData = {
|
||||
transactionLogIndex: 0x1
|
||||
}
|
||||
],
|
||||
"logsBloom": "0x00000000000000040000000000100000010000000000000040000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000200000010000000004000000000000000000000000000000000002000000000000000000000000400000000020000000000000000000000000000000000000004000000000000000000000000000000000000000000000000801000000000000000000000020000000000040000000040000000000000000002000000004000000000000000000000000000000000000000000000010000000000000000000000000000000000200000000000000000",
|
||||
"root": "0x9b550a9a640ce50331b64504ef87aaa7e2aaf97344acb6ff111f879b319d2590",
|
||||
"status": null,
|
||||
"transactionHash": "0xc6fcb7d00d536e659a4559d2de29afa9e364094438fef3e72ba80728ce1cb616",
|
||||
"transactionIndex": 0x39
|
||||
logsBloom: "0x00000000000000040000000000100000010000000000000040000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000200000010000000004000000000000000000000000000000000002000000000000000000000000400000000020000000000000000000000000000000000000004000000000000000000000000000000000000000000000000801000000000000000000000020000000000040000000040000000000000000002000000004000000000000000000000000000000000000000000000010000000000000000000000000000000000200000000000000000",
|
||||
root: "0x9b550a9a640ce50331b64504ef87aaa7e2aaf97344acb6ff111f879b319d2590",
|
||||
status: null,
|
||||
to: "0x6090A6e47849629b7245Dfa1Ca21D94cd15878Ef",
|
||||
transactionHash: "0xc6fcb7d00d536e659a4559d2de29afa9e364094438fef3e72ba80728ce1cb616",
|
||||
transactionIndex: 0x39,
|
||||
},
|
||||
transactionReceiptByzantium: {
|
||||
byzantium: true,
|
||||
@@ -90,6 +92,7 @@ var blockchainData = {
|
||||
blockNumber: 0x444f76,
|
||||
contractAddress: null,
|
||||
cumulativeGasUsed: 0x15bfe7,
|
||||
from: "0x18C6045651826824FEBBD39d8560584078d1b247",
|
||||
gasUsed: 0x1b968,
|
||||
logs: [
|
||||
{
|
||||
@@ -106,6 +109,7 @@ var blockchainData = {
|
||||
],
|
||||
logsBloom: "0x00000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000200000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000800000000000000000800000000000000000000000000000000000000",
|
||||
status:1,
|
||||
to: "0xb90E64082D00437e65A76d4c8187596BC213480a",
|
||||
transactionHash: "0x7f1c6a58dc880438236d0b0a4ae166e9e9a038dbea8ec074149bd8b176332cac",
|
||||
transactionIndex: 0x1e
|
||||
}
|
||||
@@ -170,6 +174,7 @@ var blockchainData = {
|
||||
blockNumber: 0x1564d8,
|
||||
contractAddress: null,
|
||||
cumulativeGasUsed: bigNumberify("0x80b9"),
|
||||
from: "0xb346D5019EeafC028CfC01A5f789399C2314ae8D",
|
||||
gasUsed: bigNumberify("0x80b9"),
|
||||
logs: [
|
||||
{
|
||||
@@ -186,6 +191,7 @@ var blockchainData = {
|
||||
],
|
||||
logsBloom: "0x00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
root: "0xf1c3506ab619ac1b5e8f1ca355b16d6b9a1b7436b2960b0e9ec9a91f4238b5cc",
|
||||
to: "0x6fC21092DA55B392b045eD78F4732bff3C580e2c",
|
||||
transactionHash: "0x55c477790b105e69e98afadf0505cbda606414b0187356137132bf24945016ce",
|
||||
transactionIndex: 0x0
|
||||
},
|
||||
@@ -195,6 +201,7 @@ var blockchainData = {
|
||||
blockNumber: 0x1e1e3b,
|
||||
contractAddress: null,
|
||||
cumulativeGasUsed: bigNumberify("0x4142f"),
|
||||
from: "0xdc8F20170C0946ACCF9627b3EB1513CFD1c0499f",
|
||||
gasUsed: bigNumberify("0x1eb6d"),
|
||||
logs:[
|
||||
{
|
||||
@@ -211,10 +218,44 @@ var blockchainData = {
|
||||
],
|
||||
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000080000000202000000",
|
||||
status: 1,
|
||||
to: "0xB70560a43A9aBf6ea2016F40a3e84B8821E134c5",
|
||||
transactionHash: "0xf724f1d6813f13fb523c5f6af6261d06d41138dd094fff723e09fb0f893f03e6",
|
||||
transactionIndex: 0x2
|
||||
},
|
||||
},
|
||||
goerli: {
|
||||
balance: {
|
||||
address: "0x06B5955A67D827CDF91823E3bB8F069e6c89c1D6",
|
||||
balance: bigNumberify("314159000000000000")
|
||||
},
|
||||
block3: {
|
||||
hash: '0xd5daa825732729bb0d2fd187a1b888e6bfc890f1fc5333984740d9052afb2920',
|
||||
parentHash: '0xe675f1362d82cdd1ec260b16fb046c17f61d8a84808150f5d715ccce775f575e',
|
||||
number: 3,
|
||||
timestamp: 1548947483,
|
||||
difficulty: 2,
|
||||
gasLimit: bigNumberify('10455073'),
|
||||
gasUsed: bigNumberify('0'),
|
||||
miner: '0x0000000000000000000000000000000000000000',
|
||||
extraData: '0x506172697479205465636820417574686f7269747900000000000000000000002822e1b202411c38084d96c84302b8361ec4840a51cd2fad9cb4bd9921cad7e64bc2e5dc7b41f3f75b33358be3aec718cf4d4317ace940e01b3581a95c9259ac01',
|
||||
transactions: []
|
||||
},
|
||||
transactionReceipt: {
|
||||
blockHash: '0x2384e8e8bdcf6eb87ec7c138fa503ac34adb32cac817e4b35f14d4339eaa1993',
|
||||
blockNumber: 47464,
|
||||
byzantium: true,
|
||||
contractAddress: null,
|
||||
cumulativeGasUsed: bigNumberify(21000),
|
||||
from: '0x8c1e1e5b47980D214965f3bd8ea34C413E120ae4',
|
||||
gasUsed: bigNumberify(21000),
|
||||
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
to: '0x58Bb4221245461E1d4cf886f18a01E3Df40Bd359',
|
||||
transactionHash: '0xec8b1ac5d787f36c738cc7793fec606283b41f1efa69df4ae6b2a014dcd12797',
|
||||
transactionIndex: 0,
|
||||
logs: [],
|
||||
status: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockchainData['default'] = blockchainData.homestead;
|
||||
@@ -370,7 +411,7 @@ function testProvider(providerName, networkName) {
|
||||
});
|
||||
}
|
||||
|
||||
['default', 'homestead', 'ropsten', 'rinkeby', 'kovan'].forEach(function(networkName) {
|
||||
['default', 'homestead', 'ropsten', 'rinkeby', 'kovan', 'goerli'].forEach(function(networkName) {
|
||||
['getDefaultProvider', 'InfuraProvider', 'EtherscanProvider', 'Web3Provider'].forEach(function(providerName) {
|
||||
|
||||
// @TODO: Remove this! Temporary because Etherscan is down
|
||||
|
||||
@@ -327,3 +327,41 @@ describe('Test Bytes32String coder', function() {
|
||||
assert.equal(str2, str, "parsed correctly");
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test BigNumber', function() {
|
||||
it("computes absoltue values", function() {
|
||||
function testAbs(test) {
|
||||
var value = ethers.utils.bigNumberify(test.value);
|
||||
var expected = ethers.utils.bigNumberify(test.expected);
|
||||
assert.ok(value.abs().eq(expected), 'BigNumber.abs - ' + test.value);
|
||||
}
|
||||
|
||||
[
|
||||
{ value: "0x0", expected: "0x0" },
|
||||
{ value: "-0x0", expected: "0x0" },
|
||||
{ value: "0x5", expected: "0x5" },
|
||||
{ value: "-0x5", expected: "0x5" },
|
||||
{ value: "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", expected: "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
|
||||
{ value: "-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", expected: "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
|
||||
{ value: "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", expected: "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
|
||||
{ value: "-0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", expected: "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" },
|
||||
].forEach(testAbs);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Hexlify", function() {
|
||||
it("hexlify on string of unsafe number", function() {
|
||||
assert(ethers.utils.hexlify(ethers.utils.bigNumberify("9985956830000000000")), "0x8a953ed43a892c00", "hexlify on large BigNumber");
|
||||
});
|
||||
|
||||
[9007199254740991, 9985956830000000000].forEach(function(value) {
|
||||
it('hexlify fails on unsafe number - ' + value, function() {
|
||||
assert.throws(function() {
|
||||
var result = ethers.utils.hexlify(value);
|
||||
console.log('Result', result);
|
||||
}, function(error) {
|
||||
return (error.code === "NUMERIC_FAULT" && error.fault === "out-of-safe-range");
|
||||
}, "hexlify throws on out-of-range value - " + value);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,8 +12,10 @@ describe('Test JSON Wallets', function() {
|
||||
it(('decrypts wallet - ' + test.name), function() {
|
||||
this.timeout(1200000);
|
||||
|
||||
assert.ok((ethers.utils.getJsonWalletAddress(test.json) !== null),
|
||||
'detect encrypted JSON wallet');
|
||||
if (test.hasAddress) {
|
||||
assert.ok((ethers.utils.getJsonWalletAddress(test.json) !== null),
|
||||
'detect encrypted JSON wallet');
|
||||
}
|
||||
|
||||
return Wallet.fromEncryptedJson(test.json, test.password).then(function(wallet) {
|
||||
assert.equal(wallet.privateKey, test.privateKey,
|
||||
@@ -31,7 +33,7 @@ describe('Test JSON Wallets', function() {
|
||||
// A few extra test cases to test encrypting/decrypting
|
||||
['one', 'two', 'three'].forEach(function(i) {
|
||||
var password = 'foobar' + i;
|
||||
var wallet = new Wallet(utils.randomHexString('test-' + i, 32));
|
||||
var wallet = Wallet.createRandom({ path: "m/56'/82", extraEntropy: utils.randomHexString('test-' + i, 32) });
|
||||
it('encrypts and decrypts a random wallet - ' + i, function() {
|
||||
this.timeout(1200000);
|
||||
|
||||
@@ -39,6 +41,10 @@ describe('Test JSON Wallets', function() {
|
||||
return Wallet.fromEncryptedJson(json, password).then(function(decryptedWallet) {
|
||||
assert.equal(decryptedWallet.address, wallet.address,
|
||||
'decrypted wallet - ' + wallet.privateKey);
|
||||
assert.equal(decryptedWallet.mnemonic, wallet.mnemonic,
|
||||
"decrypted wallet menonic - " + wallet.privateKey);
|
||||
assert.equal(decryptedWallet.path, wallet.path,
|
||||
"decrypted wallet path - " + wallet.privateKey);
|
||||
return decryptedWallet.encrypt(password).then(function(encryptedWallet) {
|
||||
var parsedWallet = JSON.parse(encryptedWallet);
|
||||
assert.equal(decryptedWallet.address.toLowerCase().substring(2), parsedWallet.address,
|
||||
|
||||
@@ -11,37 +11,7 @@
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="../node_modules/mocha/mocha.js"></script>
|
||||
|
||||
<!--
|
||||
Shim for PhantomJS: Promise
|
||||
See: https://github.com/stefanpenner/es6-promise
|
||||
-->
|
||||
<script src="./dist/es6-promise.auto.js"></script>
|
||||
|
||||
<!--
|
||||
Shim for String.prototype.normalize
|
||||
See: https://github.com/walling/unorm
|
||||
-->
|
||||
<script src="./dist/unorm.js"></script>
|
||||
|
||||
<!--
|
||||
Shims for PhantomJS
|
||||
-->
|
||||
<script type="text/javascript">
|
||||
|
||||
// ArrayBuffer.isView
|
||||
if (!ArrayBuffer.isView) {
|
||||
ArrayBuffer.isView = function(obj) {
|
||||
// @TODO: This should probably check various instanceof aswell
|
||||
return !!(obj.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// nextTick
|
||||
if (!window.nextTick) {
|
||||
window.nextTick = function (callback) { setTimeout(callback, 0); }
|
||||
}
|
||||
</script>
|
||||
<script src="../dist/shims.js"></script>
|
||||
|
||||
<!-- Inject the mocha describe and it functions -->
|
||||
<script type="text/javascript">
|
||||
@@ -68,7 +38,7 @@
|
||||
|
||||
<!-- Run the test cases! -->
|
||||
<script type="text/javascript">
|
||||
mocha.reporter(tests.reporter);
|
||||
mocha.reporter(ethersReporter);
|
||||
|
||||
// Use this to focus on specific test cases
|
||||
//mocha.grep(new RegExp('easyseed')).run();
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
var assert = require('assert');
|
||||
|
||||
function getEthers(filename) {
|
||||
let ethers = require('../index');
|
||||
var ethers = require('../index');
|
||||
console.log('Loaded local ethers: ' + filename);
|
||||
assert.equal(ethers.platform, 'node', 'platform: ' + ethers.platform + ' != "node"');
|
||||
return ethers;
|
||||
|
||||
8
thirdparty.d.ts
vendored
8
thirdparty.d.ts
vendored
@@ -65,6 +65,11 @@ declare module "elliptic" {
|
||||
recoveryParam: number
|
||||
}
|
||||
|
||||
interface Point {
|
||||
add(point: Point): Point;
|
||||
encodeCompressed(enc: string): string
|
||||
}
|
||||
|
||||
interface KeyPair {
|
||||
sign(message: Uint8Array, options: { canonical?: boolean }): Signature;
|
||||
getPublic(compressed: boolean, encoding?: string): string;
|
||||
@@ -72,6 +77,7 @@ declare module "elliptic" {
|
||||
getPrivate(encoding?: string): string;
|
||||
encode(encoding: string, compressed: boolean): string;
|
||||
derive(publicKey: BN): BN;
|
||||
pub: Point;
|
||||
priv: BN;
|
||||
}
|
||||
|
||||
@@ -83,6 +89,8 @@ declare module "elliptic" {
|
||||
keyFromPublic(publicKey: string | Uint8Array): KeyPair;
|
||||
keyFromPrivate(privateKey: string | Uint8Array): KeyPair;
|
||||
recoverPubKey(data: Uint8Array, signature: BasicSignature, recoveryParam: number): KeyPair;
|
||||
|
||||
// curve: Curve;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,9 +51,11 @@ function verifyType(type) {
|
||||
return type;
|
||||
}
|
||||
function parseParam(param, allowIndexed) {
|
||||
var originalParam = param;
|
||||
function throwError(i) {
|
||||
throw new Error('unexpected character "' + param[i] + '" at position ' + i + ' in "' + param + '"');
|
||||
throw new Error('unexpected character "' + originalParam[i] + '" at position ' + i + ' in "' + originalParam + '"');
|
||||
}
|
||||
param = param.replace(/\s/g, ' ');
|
||||
var parent = { type: '', name: '', state: { allowType: true } };
|
||||
var node = parent;
|
||||
for (var i = 0; i < param.length; i++) {
|
||||
@@ -194,7 +196,7 @@ function parseSignatureEvent(fragment) {
|
||||
case '':
|
||||
break;
|
||||
default:
|
||||
console.log('unknown modifier: ' + modifier);
|
||||
errors.info('unknown modifier: ' + modifier);
|
||||
}
|
||||
});
|
||||
if (abi.name && !abi.name.match(regexIdentifier)) {
|
||||
@@ -258,7 +260,7 @@ function parseSignatureFunction(fragment) {
|
||||
case '':
|
||||
break;
|
||||
default:
|
||||
console.log('unknown modifier: ' + modifier);
|
||||
errors.info('unknown modifier: ' + modifier);
|
||||
}
|
||||
});
|
||||
// We have outputs
|
||||
@@ -298,6 +300,7 @@ exports.formatSignature = formatSignature;
|
||||
function parseSignature(fragment) {
|
||||
if (typeof (fragment) === 'string') {
|
||||
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
|
||||
fragment = fragment.replace(/\s/g, ' ');
|
||||
fragment = fragment.replace(/\(/g, ' (').replace(/\)/g, ') ').replace(/\s+/g, ' ');
|
||||
fragment = fragment.trim();
|
||||
if (fragment.substring(0, 6) === 'event ') {
|
||||
@@ -477,7 +480,7 @@ var CoderFixedBytes = /** @class */ (function (_super) {
|
||||
};
|
||||
CoderFixedBytes.prototype.decode = function (data, offset) {
|
||||
if (data.length < offset + 32) {
|
||||
errors.throwError('insufficient data for ' + name + ' type', errors.INVALID_ARGUMENT, {
|
||||
errors.throwError('insufficient data for ' + this.name + ' type', errors.INVALID_ARGUMENT, {
|
||||
arg: this.localName,
|
||||
coderType: this.name,
|
||||
value: bytes_1.hexlify(data.slice(offset, offset + 32))
|
||||
@@ -733,7 +736,7 @@ var CoderArray = /** @class */ (function (_super) {
|
||||
count = value.length;
|
||||
result = uint256Coder.encode(count);
|
||||
}
|
||||
errors.checkArgumentCount(count, value.length, 'in coder array' + (this.localName ? (" " + this.localName) : ""));
|
||||
errors.checkArgumentCount(count, value.length, ' in coder array' + (this.localName ? (" " + this.localName) : ""));
|
||||
var coders = [];
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
coders.push(this.coder);
|
||||
|
||||
52
utils/basex.d.ts
vendored
Normal file
52
utils/basex.d.ts
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* var basex = require('base-x');
|
||||
*
|
||||
* This implementation is heavily based on base-x. The main reason to
|
||||
* deviate was to prevent the dependency of Buffer.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* base-x encoding
|
||||
* Forked from https://github.com/cryptocoinjs/bs58
|
||||
* Originally written by Mike Hearn for BitcoinJ
|
||||
* Copyright (c) 2011 Google Inc
|
||||
* Ported to JavaScript by Stefan Thomas
|
||||
* Merged Buffer refactorings from base58-native by Stephen Pair
|
||||
* Copyright (c) 2013 BitPay Inc
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright base-x contributors (c) 2016
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
import { Arrayish } from "./bytes";
|
||||
export declare class BaseX {
|
||||
readonly alphabet: string;
|
||||
readonly base: number;
|
||||
private _alphabetMap;
|
||||
private _leader;
|
||||
constructor(alphabet: string);
|
||||
encode(value: Arrayish | string): string;
|
||||
decode(value: string): Uint8Array;
|
||||
}
|
||||
declare const Base32: BaseX;
|
||||
declare const Base58: BaseX;
|
||||
export { Base32, Base58 };
|
||||
123
utils/basex.js
Normal file
123
utils/basex.js
Normal file
@@ -0,0 +1,123 @@
|
||||
"use strict";
|
||||
/**
|
||||
* var basex = require('base-x');
|
||||
*
|
||||
* This implementation is heavily based on base-x. The main reason to
|
||||
* deviate was to prevent the dependency of Buffer.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* base-x encoding
|
||||
* Forked from https://github.com/cryptocoinjs/bs58
|
||||
* Originally written by Mike Hearn for BitcoinJ
|
||||
* Copyright (c) 2011 Google Inc
|
||||
* Ported to JavaScript by Stefan Thomas
|
||||
* Merged Buffer refactorings from base58-native by Stephen Pair
|
||||
* Copyright (c) 2013 BitPay Inc
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright base-x contributors (c) 2016
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var bytes_1 = require("./bytes");
|
||||
var properties_1 = require("./properties");
|
||||
var BaseX = /** @class */ (function () {
|
||||
function BaseX(alphabet) {
|
||||
properties_1.defineReadOnly(this, "alphabet", alphabet);
|
||||
properties_1.defineReadOnly(this, "base", alphabet.length);
|
||||
properties_1.defineReadOnly(this, "_alphabetMap", {});
|
||||
properties_1.defineReadOnly(this, "_leader", alphabet.charAt(0));
|
||||
// pre-compute lookup table
|
||||
for (var i = 0; i < alphabet.length; i++) {
|
||||
this._alphabetMap[alphabet.charAt(i)] = i;
|
||||
}
|
||||
}
|
||||
BaseX.prototype.encode = function (value) {
|
||||
var source = bytes_1.arrayify(value);
|
||||
if (source.length === 0) {
|
||||
return '';
|
||||
}
|
||||
var digits = [0];
|
||||
for (var i = 0; i < source.length; ++i) {
|
||||
var carry = source[i];
|
||||
for (var j = 0; j < digits.length; ++j) {
|
||||
carry += digits[j] << 8;
|
||||
digits[j] = carry % this.base;
|
||||
carry = (carry / this.base) | 0;
|
||||
}
|
||||
while (carry > 0) {
|
||||
digits.push(carry % this.base);
|
||||
carry = (carry / this.base) | 0;
|
||||
}
|
||||
}
|
||||
var string = '';
|
||||
// deal with leading zeros
|
||||
for (var k = 0; source[k] === 0 && k < source.length - 1; ++k) {
|
||||
string += this._leader;
|
||||
}
|
||||
// convert digits to a string
|
||||
for (var q = digits.length - 1; q >= 0; --q) {
|
||||
string += this.alphabet[digits[q]];
|
||||
}
|
||||
return string;
|
||||
};
|
||||
BaseX.prototype.decode = function (value) {
|
||||
if (typeof (value) !== 'string') {
|
||||
throw new TypeError('Expected String');
|
||||
}
|
||||
var bytes = [];
|
||||
if (value.length === 0) {
|
||||
return new Uint8Array(bytes);
|
||||
}
|
||||
bytes.push(0);
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
var byte = this._alphabetMap[value[i]];
|
||||
if (byte === undefined) {
|
||||
throw new Error('Non-base' + this.base + ' character');
|
||||
}
|
||||
var carry = byte;
|
||||
for (var j = 0; j < bytes.length; ++j) {
|
||||
carry += bytes[j] * this.base;
|
||||
bytes[j] = carry & 0xff;
|
||||
carry >>= 8;
|
||||
}
|
||||
while (carry > 0) {
|
||||
bytes.push(carry & 0xff);
|
||||
carry >>= 8;
|
||||
}
|
||||
}
|
||||
// deal with leading zeros
|
||||
for (var k = 0; value[k] === this._leader && k < value.length - 1; ++k) {
|
||||
bytes.push(0);
|
||||
}
|
||||
return bytes_1.arrayify(new Uint8Array(bytes.reverse()));
|
||||
};
|
||||
return BaseX;
|
||||
}());
|
||||
exports.BaseX = BaseX;
|
||||
var Base32 = new BaseX("abcdefghijklmnopqrstuvwxyz234567");
|
||||
exports.Base32 = Base32;
|
||||
var Base58 = new BaseX("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
||||
exports.Base58 = Base58;
|
||||
//console.log(Base58.decode("Qmd2V777o5XvJbYMeMb8k2nU5f8d3ciUQ5YpYuWhzv8iDj"))
|
||||
//console.log(Base58.encode(Base58.decode("Qmd2V777o5XvJbYMeMb8k2nU5f8d3ciUQ5YpYuWhzv8iDj")))
|
||||
1
utils/bignumber.d.ts
vendored
1
utils/bignumber.d.ts
vendored
@@ -6,6 +6,7 @@ export declare class BigNumber implements Hexable {
|
||||
constructor(value: BigNumberish);
|
||||
fromTwos(value: number): BigNumber;
|
||||
toTwos(value: number): BigNumber;
|
||||
abs(): BigNumber;
|
||||
add(other: BigNumberish): BigNumber;
|
||||
sub(other: BigNumberish): BigNumber;
|
||||
div(other: BigNumberish): BigNumber;
|
||||
|
||||
@@ -105,6 +105,12 @@ var BigNumber = /** @class */ (function () {
|
||||
BigNumber.prototype.toTwos = function (value) {
|
||||
return toBigNumber(_bnify(this).toTwos(value));
|
||||
};
|
||||
BigNumber.prototype.abs = function () {
|
||||
if (this._hex[0] === '-') {
|
||||
return toBigNumber(_bnify(this).mul(BN_1));
|
||||
}
|
||||
return this;
|
||||
};
|
||||
BigNumber.prototype.add = function (other) {
|
||||
return toBigNumber(_bnify(this).add(toBN(other)));
|
||||
};
|
||||
|
||||
1
utils/bytes.d.ts
vendored
1
utils/bytes.d.ts
vendored
@@ -2,7 +2,6 @@
|
||||
* Conversion Utilities
|
||||
*
|
||||
*/
|
||||
import { Arrayish } from './bytes';
|
||||
export declare type Arrayish = string | ArrayLike<number>;
|
||||
export interface Hexable {
|
||||
toHexString(): string;
|
||||
|
||||
@@ -23,7 +23,7 @@ function addSlice(array) {
|
||||
}
|
||||
array.slice = function () {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return new Uint8Array(Array.prototype.slice.apply(array, args));
|
||||
return addSlice(new Uint8Array(Array.prototype.slice.apply(array, args)));
|
||||
};
|
||||
return array;
|
||||
}
|
||||
@@ -135,6 +135,14 @@ function hexlify(value) {
|
||||
if (value < 0) {
|
||||
errors.throwError('cannot hexlify negative value', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||
}
|
||||
// @TODO: Roll this into the above error as a numeric fault (overflow); next version, not backward compatible
|
||||
// We can about (value == MAX_INT) to as well, since that may indicate we underflowed already
|
||||
if (value >= 9007199254740991) {
|
||||
errors.throwError("out-of-range", errors.NUMERIC_FAULT, {
|
||||
operartion: "hexlify",
|
||||
fault: "out-of-safe-range"
|
||||
});
|
||||
}
|
||||
var hex = '';
|
||||
while (value) {
|
||||
hex = HexCharacters[value & 0x0f] + hex;
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
'use strict';
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var errors = __importStar(require("../errors"));
|
||||
var bytes_1 = require("./bytes");
|
||||
var utf8_1 = require("./utf8");
|
||||
var keccak256_1 = require("./keccak256");
|
||||
@@ -8,13 +16,22 @@ var Zeros = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
var Partition = new RegExp("^((.*)\\.)?([^.]+)$");
|
||||
var UseSTD3ASCIIRules = new RegExp("^[a-z0-9.-]*$");
|
||||
function namehash(name) {
|
||||
if (typeof (name) !== 'string') {
|
||||
errors.throwError('invalid address - ' + String(name), errors.INVALID_ARGUMENT, {
|
||||
argument: 'name',
|
||||
value: name
|
||||
});
|
||||
}
|
||||
name = name.toLowerCase();
|
||||
// Supporting the full UTF-8 space requires additional (and large)
|
||||
// libraries, so for now we simply do not support them.
|
||||
// It should be fairly easy in the future to support systems with
|
||||
// String.normalize, but that is future work.
|
||||
if (!name.match(UseSTD3ASCIIRules)) {
|
||||
throw new Error('contains invalid UseSTD3ASCIIRules characters');
|
||||
errors.throwError('contains invalid UseSTD3ASCIIRules characters', errors.INVALID_ARGUMENT, {
|
||||
argument: 'name',
|
||||
value: name
|
||||
});
|
||||
}
|
||||
var result = Zeros;
|
||||
while (name.length) {
|
||||
@@ -31,11 +48,10 @@ function id(text) {
|
||||
}
|
||||
exports.id = id;
|
||||
function hashMessage(message) {
|
||||
var payload = bytes_1.concat([
|
||||
return keccak256_1.keccak256(bytes_1.concat([
|
||||
utf8_1.toUtf8Bytes('\x19Ethereum Signed Message:\n'),
|
||||
utf8_1.toUtf8Bytes(String(message.length)),
|
||||
((typeof (message) === 'string') ? utf8_1.toUtf8Bytes(message) : message)
|
||||
]);
|
||||
return keccak256_1.keccak256(payload);
|
||||
]));
|
||||
}
|
||||
exports.hashMessage = hashMessage;
|
||||
|
||||
10
utils/hdnode.d.ts
vendored
10
utils/hdnode.d.ts
vendored
@@ -2,9 +2,10 @@ import { Arrayish } from './bytes';
|
||||
import { Wordlist } from './wordlist';
|
||||
export declare const defaultPath = "m/44'/60'/0'/0/0";
|
||||
export declare class HDNode {
|
||||
private readonly keyPair;
|
||||
readonly privateKey: string;
|
||||
readonly publicKey: string;
|
||||
readonly fingerprint: string;
|
||||
readonly parentFingerprint: string;
|
||||
readonly address: string;
|
||||
readonly mnemonic: string;
|
||||
readonly path: string;
|
||||
@@ -18,12 +19,15 @@ export declare class HDNode {
|
||||
* - fromMnemonic
|
||||
* - fromSeed
|
||||
*/
|
||||
constructor(constructorGuard: any, privateKey: Arrayish, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string);
|
||||
constructor(constructorGuard: any, privateKey: string, publicKey: string, parentFingerprint: string, chainCode: string, index: number, depth: number, mnemonic: string, path: string);
|
||||
readonly extendedKey: string;
|
||||
neuter(): HDNode;
|
||||
private _derive;
|
||||
derivePath(path: string): HDNode;
|
||||
static isHDNode(value: any): value is HDNode;
|
||||
}
|
||||
export declare function fromMnemonic(mnemonic: string, wordlist?: Wordlist): HDNode;
|
||||
export declare function fromExtendedKey(extendedKey: string): HDNode;
|
||||
export declare function fromMnemonic(mnemonic: string, wordlist?: Wordlist, password?: string): HDNode;
|
||||
export declare function fromSeed(seed: Arrayish): HDNode;
|
||||
export declare function mnemonicToSeed(mnemonic: string, password?: string): string;
|
||||
export declare function mnemonicToEntropy(mnemonic: string, wordlist?: Wordlist): string;
|
||||
|
||||
134
utils/hdnode.js
134
utils/hdnode.js
@@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
@@ -16,6 +16,7 @@ var lang_en_1 = require("../wordlists/lang-en");
|
||||
// Automatically register English?
|
||||
//import { register } from '../wordlists/wordlist';
|
||||
//register(langEn);
|
||||
var basex_1 = require("./basex");
|
||||
var bytes_1 = require("./bytes");
|
||||
var bignumber_1 = require("./bignumber");
|
||||
var utf8_1 = require("./utf8");
|
||||
@@ -36,6 +37,13 @@ function getUpperMask(bits) {
|
||||
function getLowerMask(bits) {
|
||||
return (1 << bits) - 1;
|
||||
}
|
||||
function bytes32(value) {
|
||||
return bytes_1.hexZeroPad(bytes_1.hexlify(value), 32);
|
||||
}
|
||||
function base58check(data) {
|
||||
var checksum = bytes_1.hexDataSlice(sha2_1.sha256(sha2_1.sha256(data)), 0, 4);
|
||||
return basex_1.Base58.encode(bytes_1.concat([data, checksum]));
|
||||
}
|
||||
var _constructorGuard = {};
|
||||
exports.defaultPath = "m/44'/60'/0'/0/0";
|
||||
var HDNode = /** @class */ (function () {
|
||||
@@ -46,38 +54,69 @@ var HDNode = /** @class */ (function () {
|
||||
* - fromMnemonic
|
||||
* - fromSeed
|
||||
*/
|
||||
function HDNode(constructorGuard, privateKey, chainCode, index, depth, mnemonic, path) {
|
||||
function HDNode(constructorGuard, privateKey, publicKey, parentFingerprint, chainCode, index, depth, mnemonic, path) {
|
||||
errors.checkNew(this, HDNode);
|
||||
if (constructorGuard !== _constructorGuard) {
|
||||
throw new Error('HDNode constructor cannot be called directly');
|
||||
}
|
||||
properties_1.defineReadOnly(this, 'keyPair', new secp256k1_1.KeyPair(privateKey));
|
||||
properties_1.defineReadOnly(this, 'privateKey', this.keyPair.privateKey);
|
||||
properties_1.defineReadOnly(this, 'publicKey', this.keyPair.compressedPublicKey);
|
||||
if (privateKey) {
|
||||
var keyPair = new secp256k1_1.KeyPair(privateKey);
|
||||
properties_1.defineReadOnly(this, 'privateKey', keyPair.privateKey);
|
||||
properties_1.defineReadOnly(this, 'publicKey', keyPair.compressedPublicKey);
|
||||
}
|
||||
else {
|
||||
properties_1.defineReadOnly(this, 'privateKey', null);
|
||||
properties_1.defineReadOnly(this, 'publicKey', bytes_1.hexlify(publicKey));
|
||||
}
|
||||
properties_1.defineReadOnly(this, 'parentFingerprint', parentFingerprint);
|
||||
properties_1.defineReadOnly(this, 'fingerprint', bytes_1.hexDataSlice(sha2_1.ripemd160(sha2_1.sha256(this.publicKey)), 0, 4));
|
||||
properties_1.defineReadOnly(this, 'address', secp256k1_1.computeAddress(this.publicKey));
|
||||
properties_1.defineReadOnly(this, 'chainCode', bytes_1.hexlify(chainCode));
|
||||
properties_1.defineReadOnly(this, 'chainCode', chainCode);
|
||||
properties_1.defineReadOnly(this, 'index', index);
|
||||
properties_1.defineReadOnly(this, 'depth', depth);
|
||||
properties_1.defineReadOnly(this, 'mnemonic', mnemonic);
|
||||
properties_1.defineReadOnly(this, 'path', path);
|
||||
properties_1.setType(this, 'HDNode');
|
||||
}
|
||||
HDNode.prototype._derive = function (index) {
|
||||
// Public parent key -> public child key
|
||||
if (!this.privateKey) {
|
||||
if (index >= HardenedBit) {
|
||||
throw new Error('cannot derive child of neutered node');
|
||||
Object.defineProperty(HDNode.prototype, "extendedKey", {
|
||||
get: function () {
|
||||
// We only support the mainnet values for now, but if anyone needs
|
||||
// testnet values, let me know. I believe current senitment is that
|
||||
// we should always use mainnet, and use BIP-44 to derive the network
|
||||
// - Mainnet: public=0x0488B21E, private=0x0488ADE4
|
||||
// - Testnet: public=0x043587CF, private=0x04358394
|
||||
if (this.depth >= 256) {
|
||||
throw new Error("Depth too large!");
|
||||
}
|
||||
throw new Error('not implemented');
|
||||
return base58check(bytes_1.concat([
|
||||
((this.privateKey != null) ? "0x0488ADE4" : "0x0488B21E"),
|
||||
bytes_1.hexlify(this.depth),
|
||||
this.parentFingerprint,
|
||||
bytes_1.hexZeroPad(bytes_1.hexlify(this.index), 4),
|
||||
this.chainCode,
|
||||
((this.privateKey != null) ? bytes_1.concat(["0x00", this.privateKey]) : this.publicKey),
|
||||
]));
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
HDNode.prototype.neuter = function () {
|
||||
return new HDNode(_constructorGuard, null, this.publicKey, this.parentFingerprint, this.chainCode, this.index, this.depth, null, this.path);
|
||||
};
|
||||
HDNode.prototype._derive = function (index) {
|
||||
if (index > 0xffffffff) {
|
||||
throw new Error("invalid index - " + String(index));
|
||||
}
|
||||
var data = new Uint8Array(37);
|
||||
// Base path
|
||||
var mnemonic = this.mnemonic;
|
||||
var path = this.path;
|
||||
if (path) {
|
||||
path += '/' + index;
|
||||
path += '/' + (index & ~HardenedBit);
|
||||
}
|
||||
var data = new Uint8Array(37);
|
||||
if (index & HardenedBit) {
|
||||
if (!this.privateKey) {
|
||||
throw new Error('cannot derive child of neutered node');
|
||||
}
|
||||
// Data = 0x00 || ser_256(k_par)
|
||||
data.set(bytes_1.arrayify(this.privateKey), 1);
|
||||
// Hardened path
|
||||
@@ -87,22 +126,32 @@ var HDNode = /** @class */ (function () {
|
||||
}
|
||||
else {
|
||||
// Data = ser_p(point(k_par))
|
||||
data.set(this.keyPair.publicKeyBytes);
|
||||
data.set(bytes_1.arrayify(this.publicKey));
|
||||
}
|
||||
// Data += ser_32(i)
|
||||
for (var i = 24; i >= 0; i -= 8) {
|
||||
data[33 + (i >> 3)] = ((index >> (24 - i)) & 0xff);
|
||||
}
|
||||
var I = hmac_1.computeHmac(hmac_1.SupportedAlgorithms.sha512, this.chainCode, data);
|
||||
var IL = bignumber_1.bigNumberify(I.slice(0, 32));
|
||||
var IL = I.slice(0, 32);
|
||||
var IR = I.slice(32);
|
||||
var ki = IL.add(this.keyPair.privateKey).mod(N);
|
||||
return new HDNode(_constructorGuard, bytes_1.arrayify(ki), IR, index, this.depth + 1, mnemonic, path);
|
||||
// The private key
|
||||
var ki = null;
|
||||
// The public key
|
||||
var Ki = null;
|
||||
if (this.privateKey) {
|
||||
ki = bytes32(bignumber_1.bigNumberify(IL).add(this.privateKey).mod(N));
|
||||
}
|
||||
else {
|
||||
var ek = new secp256k1_1.KeyPair(bytes_1.hexlify(IL));
|
||||
Ki = ek._addPoint(this.publicKey);
|
||||
}
|
||||
return new HDNode(_constructorGuard, ki, Ki, this.fingerprint, bytes32(IR), index, this.depth + 1, this.mnemonic, path);
|
||||
};
|
||||
HDNode.prototype.derivePath = function (path) {
|
||||
var components = path.split('/');
|
||||
if (components.length === 0 || (components[0] === 'm' && this.depth !== 0)) {
|
||||
throw new Error('invalid path');
|
||||
throw new Error('invalid path - ' + path);
|
||||
}
|
||||
if (components[0] === 'm') {
|
||||
components.shift();
|
||||
@@ -125,7 +174,7 @@ var HDNode = /** @class */ (function () {
|
||||
result = result._derive(index);
|
||||
}
|
||||
else {
|
||||
throw new Error('invlaid path component - ' + component);
|
||||
throw new Error('invalid path component - ' + component);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -136,18 +185,50 @@ var HDNode = /** @class */ (function () {
|
||||
return HDNode;
|
||||
}());
|
||||
exports.HDNode = HDNode;
|
||||
function fromExtendedKey(extendedKey) {
|
||||
var bytes = basex_1.Base58.decode(extendedKey);
|
||||
if (bytes.length !== 82 || base58check(bytes.slice(0, 78)) !== extendedKey) {
|
||||
errors.throwError("invalid extended key", errors.INVALID_ARGUMENT, {
|
||||
argument: "extendedKey",
|
||||
value: "[REDACTED]"
|
||||
});
|
||||
}
|
||||
var depth = bytes[4];
|
||||
var parentFingerprint = bytes_1.hexlify(bytes.slice(5, 9));
|
||||
var index = parseInt(bytes_1.hexlify(bytes.slice(9, 13)).substring(2), 16);
|
||||
var chainCode = bytes_1.hexlify(bytes.slice(13, 45));
|
||||
var key = bytes.slice(45, 78);
|
||||
switch (bytes_1.hexlify(bytes.slice(0, 4))) {
|
||||
// Public Key
|
||||
case "0x0488b21e":
|
||||
case "0x043587cf":
|
||||
return new HDNode(_constructorGuard, null, bytes_1.hexlify(key), parentFingerprint, chainCode, index, depth, null, null);
|
||||
// Private Key
|
||||
case "0x0488ade4":
|
||||
case "0x04358394":
|
||||
if (key[0] !== 0) {
|
||||
break;
|
||||
}
|
||||
return new HDNode(_constructorGuard, bytes_1.hexlify(key.slice(1)), null, parentFingerprint, chainCode, index, depth, null, null);
|
||||
}
|
||||
return errors.throwError("invalid extended key", errors.INVALID_ARGUMENT, {
|
||||
argument: "extendedKey",
|
||||
value: "[REDACTED]"
|
||||
});
|
||||
}
|
||||
exports.fromExtendedKey = fromExtendedKey;
|
||||
function _fromSeed(seed, mnemonic) {
|
||||
var seedArray = bytes_1.arrayify(seed);
|
||||
if (seedArray.length < 16 || seedArray.length > 64) {
|
||||
throw new Error('invalid seed');
|
||||
}
|
||||
var I = bytes_1.arrayify(hmac_1.computeHmac(hmac_1.SupportedAlgorithms.sha512, MasterSecret, seedArray));
|
||||
return new HDNode(_constructorGuard, I.slice(0, 32), I.slice(32), 0, 0, mnemonic, 'm');
|
||||
return new HDNode(_constructorGuard, bytes32(I.slice(0, 32)), null, "0x00000000", bytes32(I.slice(32)), 0, 0, mnemonic, 'm');
|
||||
}
|
||||
function fromMnemonic(mnemonic, wordlist) {
|
||||
// Check that the checksum s valid (will throw an error)
|
||||
mnemonicToEntropy(mnemonic, wordlist);
|
||||
return _fromSeed(mnemonicToSeed(mnemonic), mnemonic);
|
||||
function fromMnemonic(mnemonic, wordlist, password) {
|
||||
// Normalize the mnemonic (also throws if the checksum is invalid)
|
||||
mnemonic = entropyToMnemonic(mnemonicToEntropy(mnemonic, wordlist), wordlist);
|
||||
return _fromSeed(mnemonicToSeed(mnemonic, password), mnemonic);
|
||||
}
|
||||
exports.fromMnemonic = fromMnemonic;
|
||||
function fromSeed(seed) {
|
||||
@@ -166,6 +247,7 @@ function mnemonicToEntropy(mnemonic, wordlist) {
|
||||
if (!wordlist) {
|
||||
wordlist = lang_en_1.langEn;
|
||||
}
|
||||
errors.checkNormalize();
|
||||
var words = wordlist.split(mnemonic);
|
||||
if ((words.length % 3) !== 0) {
|
||||
throw new Error('invalid mnemonic');
|
||||
|
||||
6
utils/index.d.ts
vendored
6
utils/index.d.ts
vendored
@@ -2,7 +2,7 @@ import { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSigna
|
||||
import { getAddress, getContractAddress, getIcapAddress } from './address';
|
||||
import * as base64 from './base64';
|
||||
import { BigNumber, bigNumberify } from './bignumber';
|
||||
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
|
||||
import { arrayify, concat, hexDataSlice, hexDataLength, hexlify, hexStripZeros, hexZeroPad, isHexString, joinSignature, padZeros, splitSignature, stripZeros } from './bytes';
|
||||
import { hashMessage, id, namehash } from './hash';
|
||||
import * as HDNode from './hdnode';
|
||||
import { Interface } from './interface';
|
||||
@@ -20,7 +20,7 @@ import { populateTransaction } from './transaction';
|
||||
import { parse as parseTransaction, serialize as serializeTransaction } from './transaction';
|
||||
import { formatBytes32String, parseBytes32String, toUtf8Bytes, toUtf8String } from './utf8';
|
||||
import { commify, formatEther, parseEther, formatUnits, parseUnits } from './units';
|
||||
import { fetchJson } from './web';
|
||||
import { fetchJson, poll } from './web';
|
||||
import { SupportedAlgorithms } from './hmac';
|
||||
import { UnicodeNormalizationForm } from './utf8';
|
||||
import { CoerceFunc, EventFragment, FunctionFragment, ParamType } from './abi-coder';
|
||||
@@ -32,4 +32,4 @@ import { Transaction, UnsignedTransaction } from './transaction';
|
||||
import { ConnectionInfo, OnceBlockable, PollOptions } from './web';
|
||||
import { EncryptOptions, ProgressCallback } from './secret-storage';
|
||||
import { Wordlist } from './wordlist';
|
||||
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
|
||||
export { AbiCoder, defaultAbiCoder, formatSignature, formatParamType, parseSignature, parseParamType, RLP, fetchJson, getNetwork, checkProperties, deepCopy, defineReadOnly, resolveProperties, shallowCopy, arrayify, concat, padZeros, stripZeros, HDNode, SigningKey, Interface, base64, BigNumber, bigNumberify, hexlify, isHexString, hexStripZeros, hexZeroPad, hexDataLength, hexDataSlice, toUtf8Bytes, toUtf8String, formatBytes32String, parseBytes32String, hashMessage, namehash, id, getAddress, getIcapAddress, getContractAddress, formatEther, parseEther, formatUnits, parseUnits, commify, keccak256, sha256, randomBytes, solidityPack, solidityKeccak256, soliditySha256, splitSignature, joinSignature, parseTransaction, populateTransaction, serializeTransaction, getJsonWalletAddress, computeAddress, computePublicKey, recoverAddress, recoverPublicKey, verifyMessage, poll, SupportedAlgorithms, UnicodeNormalizationForm, CoerceFunc, EventFragment, FunctionFragment, ParamType, BigNumberish, Arrayish, Hexable, Signature, Indexed, DeployDescription, EventDescription, FunctionDescription, LogDescription, TransactionDescription, Network, Networkish, Transaction, UnsignedTransaction, ConnectionInfo, OnceBlockable, PollOptions, EncryptOptions, ProgressCallback, Wordlist, };
|
||||
|
||||
@@ -31,6 +31,7 @@ exports.hexDataLength = bytes_1.hexDataLength;
|
||||
exports.hexlify = bytes_1.hexlify;
|
||||
exports.hexStripZeros = bytes_1.hexStripZeros;
|
||||
exports.hexZeroPad = bytes_1.hexZeroPad;
|
||||
exports.isHexString = bytes_1.isHexString;
|
||||
exports.joinSignature = bytes_1.joinSignature;
|
||||
exports.padZeros = bytes_1.padZeros;
|
||||
exports.splitSignature = bytes_1.splitSignature;
|
||||
@@ -91,6 +92,7 @@ exports.formatUnits = units_1.formatUnits;
|
||||
exports.parseUnits = units_1.parseUnits;
|
||||
var web_1 = require("./web");
|
||||
exports.fetchJson = web_1.fetchJson;
|
||||
exports.poll = web_1.poll;
|
||||
////////////////////////
|
||||
// Enums
|
||||
var hmac_1 = require("./hmac");
|
||||
|
||||
@@ -56,7 +56,7 @@ var _DeployDescription = /** @class */ (function (_super) {
|
||||
value: bytecode
|
||||
});
|
||||
}
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, 'in Interface constructor');
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, ' in Interface constructor');
|
||||
try {
|
||||
return (bytecode + abi_coder_1.defaultAbiCoder.encode(this.inputs, params).substring(2));
|
||||
}
|
||||
@@ -77,7 +77,7 @@ var _FunctionDescription = /** @class */ (function (_super) {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
_FunctionDescription.prototype.encode = function (params) {
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, 'in interface function ' + this.name);
|
||||
errors.checkArgumentCount(params.length, this.inputs.length, ' in interface function ' + this.name);
|
||||
try {
|
||||
return this.sighash + abi_coder_1.defaultAbiCoder.encode(this.inputs, params).substring(2);
|
||||
}
|
||||
@@ -243,18 +243,31 @@ function addMethod(method) {
|
||||
case 'function': {
|
||||
var signature = abi_coder_1.formatSignature(method).replace(/tuple/g, '');
|
||||
var sighash = hash_1.id(signature).substring(0, 10);
|
||||
var isConst = false;
|
||||
if (method.constant != null) {
|
||||
isConst = method.constant;
|
||||
}
|
||||
else if (method.stateMutability != null) {
|
||||
isConst = (method.stateMutability == "view" || method.stateMutability == "pure");
|
||||
}
|
||||
var description = new _FunctionDescription({
|
||||
inputs: method.inputs,
|
||||
outputs: method.outputs,
|
||||
gas: method.gas,
|
||||
payable: (method.payable == null || !!method.payable),
|
||||
type: ((method.constant) ? 'call' : 'transaction'),
|
||||
type: (isConst ? 'call' : 'transaction'),
|
||||
name: method.name,
|
||||
signature: signature,
|
||||
sighash: sighash,
|
||||
});
|
||||
// Expose the first (and hopefully unique named function
|
||||
if (method.name && this.functions[method.name] == null) {
|
||||
properties_1.defineReadOnly(this.functions, method.name, description);
|
||||
// Expose the first (and hopefully unique named function)
|
||||
if (method.name) {
|
||||
if (this.functions[method.name] == null) {
|
||||
properties_1.defineReadOnly(this.functions, method.name, description);
|
||||
}
|
||||
else {
|
||||
errors.warn('WARNING: Multiple definitions for ' + method.name);
|
||||
}
|
||||
}
|
||||
// Expose all methods by their signature, for overloaded functions
|
||||
if (this.functions[description.signature] == null) {
|
||||
@@ -285,7 +298,7 @@ function addMethod(method) {
|
||||
// Nothing to do for fallback
|
||||
break;
|
||||
default:
|
||||
console.log('WARNING: unsupported ABI type - ' + method.type);
|
||||
errors.warn('WARNING: unsupported ABI type - ' + method.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -339,10 +352,10 @@ var Interface = /** @class */ (function () {
|
||||
return new _TransactionDescription({
|
||||
args: result,
|
||||
decode: func.decode,
|
||||
name: name,
|
||||
name: func.name,
|
||||
signature: func.signature,
|
||||
sighash: func.sighash,
|
||||
value: bignumber_1.bigNumberify(tx.value || null),
|
||||
value: bignumber_1.bigNumberify(tx.value || '0'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
1
utils/networks.d.ts
vendored
1
utils/networks.d.ts
vendored
@@ -2,6 +2,7 @@ export declare type Network = {
|
||||
name: string;
|
||||
chainId: number;
|
||||
ensAddress?: string;
|
||||
_defaultProvider?: (providers: any) => any;
|
||||
};
|
||||
export declare type Networkish = Network | string | number;
|
||||
/**
|
||||
|
||||
@@ -8,39 +8,84 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var errors = __importStar(require("../errors"));
|
||||
function ethDefaultProvider(network) {
|
||||
return function (providers) {
|
||||
var providerList = [];
|
||||
if (providers.InfuraProvider) {
|
||||
providerList.push(new providers.InfuraProvider(network));
|
||||
}
|
||||
if (providers.EtherscanProvider) {
|
||||
providerList.push(new providers.EtherscanProvider(network));
|
||||
}
|
||||
if (providerList.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (providers.FallbackProvider) {
|
||||
return new providers.FallbackProvider(providerList);
|
||||
;
|
||||
}
|
||||
return providerList[0];
|
||||
};
|
||||
}
|
||||
function etcDefaultProvider(url, network) {
|
||||
return function (providers) {
|
||||
if (providers.JsonRpcProvider) {
|
||||
return new providers.JsonRpcProvider(url, network);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
var homestead = {
|
||||
chainId: 1,
|
||||
ensAddress: "0x314159265dd8dbb310642f98f50c066173c1259b",
|
||||
name: "homestead"
|
||||
name: "homestead",
|
||||
_defaultProvider: ethDefaultProvider('homestead')
|
||||
};
|
||||
var ropsten = {
|
||||
chainId: 3,
|
||||
ensAddress: "0x112234455c3a32fd11230c42e7bccd4a84e02010",
|
||||
name: "ropsten"
|
||||
name: "ropsten",
|
||||
_defaultProvider: ethDefaultProvider('ropsten')
|
||||
};
|
||||
var networks = {
|
||||
unspecified: {
|
||||
chainId: 0
|
||||
chainId: 0,
|
||||
name: 'unspecified'
|
||||
},
|
||||
homestead: homestead,
|
||||
mainnet: homestead,
|
||||
morden: {
|
||||
chainId: 2
|
||||
chainId: 2,
|
||||
name: 'morden'
|
||||
},
|
||||
ropsten: ropsten,
|
||||
testnet: ropsten,
|
||||
rinkeby: {
|
||||
chainId: 4,
|
||||
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A"
|
||||
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A",
|
||||
name: 'rinkeby',
|
||||
_defaultProvider: ethDefaultProvider('rinkeby')
|
||||
},
|
||||
goerli: {
|
||||
chainId: 5,
|
||||
ensAddress: "0x112234455c3a32fd11230c42e7bccd4a84e02010",
|
||||
name: "goerli",
|
||||
_defaultProvider: ethDefaultProvider('goerli')
|
||||
},
|
||||
kovan: {
|
||||
chainId: 42
|
||||
chainId: 42,
|
||||
name: 'kovan',
|
||||
_defaultProvider: ethDefaultProvider('kovan')
|
||||
},
|
||||
classic: {
|
||||
chainId: 61
|
||||
chainId: 61,
|
||||
name: 'classic',
|
||||
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io', 'classic')
|
||||
},
|
||||
classicTestnet: {
|
||||
chainId: 62
|
||||
chainId: 62,
|
||||
name: 'classicTestnet',
|
||||
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io/morden', 'classicTestnet')
|
||||
}
|
||||
};
|
||||
/**
|
||||
@@ -50,18 +95,19 @@ var networks = {
|
||||
* and verifies a network is a valid Network..
|
||||
*/
|
||||
function getNetwork(network) {
|
||||
// No network (null) or unspecified (chainId = 0)
|
||||
if (!network) {
|
||||
// No network (null)
|
||||
if (network == null) {
|
||||
return null;
|
||||
}
|
||||
if (typeof (network) === 'number') {
|
||||
for (var name in networks) {
|
||||
var n_1 = networks[name];
|
||||
for (var name_1 in networks) {
|
||||
var n_1 = networks[name_1];
|
||||
if (n_1.chainId === network) {
|
||||
return {
|
||||
name: name,
|
||||
name: n_1.name,
|
||||
chainId: n_1.chainId,
|
||||
ensAddress: n_1.ensAddress
|
||||
ensAddress: (n_1.ensAddress || null),
|
||||
_defaultProvider: (n_1._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -76,9 +122,10 @@ function getNetwork(network) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
name: network,
|
||||
name: n_2.name,
|
||||
chainId: n_2.chainId,
|
||||
ensAddress: n_2.ensAddress
|
||||
ensAddress: n_2.ensAddress,
|
||||
_defaultProvider: (n_2._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
var n = networks[network.name];
|
||||
@@ -93,11 +140,12 @@ function getNetwork(network) {
|
||||
if (network.chainId !== 0 && network.chainId !== n.chainId) {
|
||||
errors.throwError('network chainId mismatch', errors.INVALID_ARGUMENT, { arg: 'network', value: network });
|
||||
}
|
||||
// Standard Network
|
||||
// Standard Network (allow overriding the ENS address)
|
||||
return {
|
||||
name: network.name,
|
||||
chainId: n.chainId,
|
||||
ensAddress: n.ensAddress
|
||||
ensAddress: (network.ensAddress || n.ensAddress || null),
|
||||
_defaultProvider: (network._defaultProvider || n._defaultProvider || null)
|
||||
};
|
||||
}
|
||||
exports.getNetwork = getNetwork;
|
||||
|
||||
@@ -98,7 +98,7 @@ function _decode(data, offset) {
|
||||
else if (data[offset] >= 0x80) {
|
||||
var length = data[offset] - 0x80;
|
||||
if (offset + 1 + length > data.length) {
|
||||
throw new Error('invlaid rlp data');
|
||||
throw new Error('invalid rlp data');
|
||||
}
|
||||
var result = bytes_1.hexlify(data.slice(offset + 1, offset + 1 + length));
|
||||
return { consumed: (1 + length), result: result };
|
||||
|
||||
1
utils/secp256k1.d.ts
vendored
1
utils/secp256k1.d.ts
vendored
@@ -7,6 +7,7 @@ export declare class KeyPair {
|
||||
constructor(privateKey: Arrayish | string);
|
||||
sign(digest: Arrayish | string): Signature;
|
||||
computeSharedSecret(otherKey: Arrayish | string): string;
|
||||
_addPoint(other: Arrayish | string): string;
|
||||
}
|
||||
export declare function computePublicKey(key: Arrayish | string, compressed?: boolean): string;
|
||||
export declare function computeAddress(key: Arrayish | string): string;
|
||||
|
||||
@@ -45,6 +45,11 @@ var KeyPair = /** @class */ (function () {
|
||||
var otherKeyPair = getCurve().keyFromPublic(bytes_1.arrayify(computePublicKey(otherKey)));
|
||||
return bytes_1.hexZeroPad('0x' + keyPair.derive(otherKeyPair.getPublic()).toString(16), 32);
|
||||
};
|
||||
KeyPair.prototype._addPoint = function (other) {
|
||||
var p0 = getCurve().keyFromPublic(bytes_1.arrayify(this.publicKey));
|
||||
var p1 = getCurve().keyFromPublic(bytes_1.arrayify(other));
|
||||
return "0x" + p0.pub.add(p1.pub).encodeCompressed("hex");
|
||||
};
|
||||
return KeyPair;
|
||||
}());
|
||||
exports.KeyPair = KeyPair;
|
||||
|
||||
@@ -125,7 +125,7 @@ function decrypt(json, password, progressCallback) {
|
||||
return null;
|
||||
}
|
||||
var signingKey = new signing_key_1.SigningKey(privateKey);
|
||||
if (signingKey.address !== address_1.getAddress(data.address)) {
|
||||
if (data.address && signingKey.address !== address_1.getAddress(data.address)) {
|
||||
reject(new Error('address mismatch'));
|
||||
return null;
|
||||
}
|
||||
@@ -384,6 +384,7 @@ function encrypt(privateKey, password, options, progressCallback) {
|
||||
gethFilename: ('UTC--' + timestamp + '--' + data.address),
|
||||
mnemonicCounter: bytes_1.hexlify(mnemonicIv).substring(2),
|
||||
mnemonicCiphertext: bytes_1.hexlify(mnemonicCiphertext).substring(2),
|
||||
path: path,
|
||||
version: "0.1"
|
||||
};
|
||||
}
|
||||
|
||||
1
utils/sha2.d.ts
vendored
1
utils/sha2.d.ts
vendored
@@ -1,3 +1,4 @@
|
||||
import { Arrayish } from './bytes';
|
||||
export declare function ripemd160(data: Arrayish): string;
|
||||
export declare function sha256(data: Arrayish): string;
|
||||
export declare function sha512(data: Arrayish): string;
|
||||
|
||||
@@ -5,6 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var hash_js_1 = __importDefault(require("hash.js"));
|
||||
var bytes_1 = require("./bytes");
|
||||
function ripemd160(data) {
|
||||
return '0x' + (hash_js_1.default.ripemd160().update(bytes_1.arrayify(data)).digest('hex'));
|
||||
}
|
||||
exports.ripemd160 = ripemd160;
|
||||
function sha256(data) {
|
||||
return '0x' + (hash_js_1.default.sha256().update(bytes_1.arrayify(data)).digest('hex'));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user