Updated dist files.

This commit is contained in:
Richard Moore 2020-09-16 19:44:55 -04:00
parent de8a717b4c
commit a3821f6c4b
No known key found for this signature in database
GPG Key ID: 665176BE8E9DC651
6 changed files with 720 additions and 581 deletions

@ -12,7 +12,7 @@ const Words = fs.readFileSync("/usr/share/dict/words").toString().split("\n").re
// Words missing from the dictionary // Words missing from the dictionary
accessing addresses aligned autofill called cancelled changed censored accessing addresses aligned autofill called cancelled changed censored
clamping compiled computed configured consumed creating decoded decoding clamping compiled computed configured consumed creating decoded decoding
decrypt decrypted decrypting deployed deploying deprecated detected decreased decrypt decrypted decrypting deployed deploying deprecated detected
discontinued earliest email enabled encoded encoding encrypt discontinued earliest email enabled encoded encoding encrypt
encrypted encrypting entries euro exceeded existing expected encrypted encrypting entries euro exceeded existing expected
expired failed fetches formatted formatting funding generated expired failed fetches formatted formatting funding generated
@ -47,9 +47,9 @@ bytecode callback calldata checksum ciphertext cli codepoint commify config
contenthash ctr ctrl debug dd dklen eexist encseed eof ethaddr contenthash ctr ctrl debug dd dklen eexist encseed eof ethaddr
ethseed ethers eval exec filename func gz hid http https hw iv ethseed ethers eval exec filename func gz hid http https hw iv
info init ipc json kdf kdfparams labelhash lang lib mm multihash nfc info init ipc json kdf kdfparams labelhash lang lib mm multihash nfc
nfkc nfd nfkd nodehash notok nullish oob opcode pbkdf pc plugin pragma pre prf nfkc nfd nfkd nodehash notok nowait nullish oob opcode pbkdf pc plugin
repl rpc sighash topichash solc stdin stdout subclasses subnode pragma pre prf repl rpc sighash topichash solc stdin stdout subclasses
timeout todo txt ufixed utc utf util url uuid vm vs websocket subnode timeout todo txt ufixed utc utf util url uuid vm vs websocket
wikipedia wx xe xpriv xpub xx yyyy zlib wikipedia wx xe xpriv xpub xx yyyy zlib
// AbiV2 // AbiV2

@ -65,7 +65,7 @@ const blockchainData = {
s: "0x269c3e5b3558267ad91b0a887d51f9f10098771c67b82ea6cb74f29638754f54", s: "0x269c3e5b3558267ad91b0a887d51f9f10098771c67b82ea6cb74f29638754f54",
v: 38, v: 38,
creates: null, creates: null,
raw: "0xf8d2808504a817c8008303d090946fc21092da55b392b045ed78f4732bff3c580e2c880186cc6acd4b0000b864f2c298be000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000067269636d6f6f000000000000000000000000000000000000000000000000000026a01e5605197a03e3f0a168f14749168dfeefc44c9228312dacbffdcbbb13263265a0269c3e5b3558267ad91b0a887d51f9f10098771c67b82ea6cb74f29638754f54", //raw: "0xf8d2808504a817c8008303d090946fc21092da55b392b045ed78f4732bff3c580e2c880186cc6acd4b0000b864f2c298be000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000067269636d6f6f000000000000000000000000000000000000000000000000000026a01e5605197a03e3f0a168f14749168dfeefc44c9228312dacbffdcbbb13263265a0269c3e5b3558267ad91b0a887d51f9f10098771c67b82ea6cb74f29638754f54",
chainId: 1 chainId: 1
} }
], ],
@ -364,6 +364,8 @@ function equals(name, actual, expected) {
if (actual == null) { if (actual == null) {
assert.ok(false, name + " - actual big number null"); assert.ok(false, name + " - actual big number null");
} }
expected = ethers.BigNumber.from(expected);
actual = ethers.BigNumber.from(actual);
assert.ok(expected.eq(actual), name + " matches"); assert.ok(expected.eq(actual), name + " matches");
} }
else if (Array.isArray(expected)) { else if (Array.isArray(expected)) {
@ -398,265 +400,315 @@ function equals(name, actual, expected) {
} }
function waiter(duration) { function waiter(duration) {
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(resolve, duration); const timer = setTimeout(resolve, duration);
if (timer.unref) {
timer.unref();
}
}); });
} }
function testProvider(providerName, networkName) { const allNetworks = ["default", "homestead", "ropsten", "rinkeby", "kovan", "goerli"];
// Delay (ms) after each test case to prevent the backends from throttling const providerFunctions = [
const delay = 1000; {
describe(("Read-Only " + providerName + " (" + networkName + ")"), function () { name: "getDefaultProvider",
this.retries(3); networks: allNetworks,
// Get the Provider based on the name of the provider we are testing and the network create: (network) => {
let provider = null; if (network == "default") {
if (networkName === "default") { return ethers.getDefaultProvider();
if (providerName === "getDefaultProvider") {
provider = ethers.getDefaultProvider();
}
else {
provider = new (ethers.providers)[providerName]();
} }
return ethers.getDefaultProvider(network);
} }
else { },
if (providerName === "getDefaultProvider") { {
provider = ethers.getDefaultProvider(networkName); name: "AlchemyProvider",
} networks: allNetworks,
else { create: (network) => {
provider = new (ethers.providers)[providerName](networkName); if (network == "default") {
return new ethers.providers.AlchemyProvider();
} }
return new ethers.providers.AlchemyProvider(network);
} }
const tests = blockchainData[networkName]; },
// And address test case can have any of the following: {
// - balance name: "CloudflareProvider",
// - code networks: ["homestead"],
// - storage create: (network) => {
// - ENS name return new ethers.providers.AlchemyProvider(network);
tests.addresses.forEach((test) => { }
if (test.balance) { },
it(`fetches address balance: ${test.address}`, function () { {
// Note: These tests could be fiddled with if someone sends ether name: "InfuraProvider",
// to our address; we just have to live with jerks sending us networks: allNetworks,
// money. *smile emoji* create: (network) => {
this.timeout(60000); if (network == "default") {
return provider.getBalance(test.address).then((balance) => { return new ethers.providers.InfuraProvider();
equals("Balance", test.balance, balance);
return waiter(delay);
});
});
} }
if (test.code) { return new ethers.providers.InfuraProvider(network);
it(`fetches address code: ${test.address}`, function () { }
this.timeout(60000); },
return provider.getCode(test.address).then((code) => { {
equals("Code", test.code, code); name: "EtherscanProvider",
return waiter(delay); networks: allNetworks,
}); create: (network) => {
}); if (network == "default") {
} return new ethers.providers.EtherscanProvider();
if (test.storage) {
Object.keys(test.storage).forEach((position) => {
it(`fetches storage: ${test.address}:${position}`, function () {
this.timeout(60000);
return provider.getStorageAt(test.address, bnify(position)).then((value) => {
equals("Storage", test.storage[position], value);
return waiter(delay);
});
});
});
}
if (test.name) {
it(`fetches the ENS name: ${test.name}`, function () {
this.timeout(60000);
return provider.resolveName(test.name).then((address) => {
equals("ENS Name", test.address, address);
return waiter(delay);
});
});
} }
return new ethers.providers.EtherscanProvider(network);
}
},
{
name: "NodesmithProvider",
networks: [],
create: (network) => {
throw new Error("not tested");
}
},
{
name: "Web3Provider",
networks: [],
create: (network) => {
throw new Error("not tested");
}
}
];
// This wallet can be funded and used for various test cases
const fundWallet = ethers.Wallet.createRandom();
const testFunctions = [];
Object.keys(blockchainData).forEach((network) => {
function addSimpleTest(name, func, expected) {
testFunctions.push({
name: name,
networks: [network],
execute: (provider) => __awaiter(this, void 0, void 0, function* () {
const value = yield func(provider);
equals(name, expected, value);
})
}); });
tests.blocks.forEach((test) => { }
function checkBlock(promise) { function addObjectTest(name, func, expected, checkSkip) {
return promise.then((block) => { testFunctions.push({
for (let key in test) { name,
equals("Block " + key, block[key], test[key]); networks: [network],
} checkSkip,
return waiter(delay); execute: (provider) => __awaiter(this, void 0, void 0, function* () {
const value = yield func(provider);
Object.keys(expected).forEach((key) => {
equals(`${name}.${key}`, value[key], expected[key]);
}); });
} })
it(`fetches block (by number) #${test.number}`, function () {
this.timeout(60000);
return checkBlock(provider.getBlock(test.number));
});
// Etherscan does not support getBlockByBlockhash... *sad emoji*
if (providerName === "EtherscanProvider") {
return;
}
it(`fetches block (by hash) ${test.hash}`, function () {
this.timeout(60000);
return checkBlock(provider.getBlock(test.hash));
});
}); });
tests.transactions.forEach((test) => { }
function testTransaction(expected) { const tests = blockchainData[network];
const title = ("Transaction " + expected.hash.substring(0, 10) + " - "); // And address test case can have any of the following:
return provider.getTransaction(expected.hash).then((tx) => { // - balance
// This changes with every block // - code
assert.equal(typeof (tx.confirmations), "number", "confirmations is a number"); // - storage
delete tx.confirmations; // - ENS name
assert.equal(typeof (tx.wait), "function", "wait is a function"); tests.addresses.forEach((test) => {
delete tx.wait; if (test.balance) {
for (const key in tx) { addSimpleTest(`fetches account balance: ${test.address}`, (provider) => {
equals((title + key), tx[key], expected[key]); return provider.getBalance(test.address);
} }, test.balance);
return waiter(delay); }
}); if (test.code) {
} addSimpleTest(`fetches account code: ${test.address}`, (provider) => {
it(`fetches transaction: ${test.hash}`, function () { return provider.getCode(test.address);
this.timeout(60000); }, test.code);
return testTransaction(test); }
}); if (test.storage) {
}); Object.keys(test.storage).forEach((position) => {
tests.transactionReceipts.forEach((test) => { addSimpleTest(`fetches storage: ${test.address}:${position}`, (provider) => {
function testTransactionReceipt(expected) { return provider.getStorageAt(test.address, bnify(position));
const title = ("Receipt " + expected.transactionHash.substring(0, 10) + " - "); }, test.storage[position]);
return provider.getTransactionReceipt(expected.transactionHash).then(function (receipt) {
// This changes with every block; so just make sure it is a number
assert.equal(typeof (receipt.confirmations), "number", "confirmations is a number");
delete receipt.confirmations;
for (const key in receipt) {
equals((title + key), receipt[key], expected[key]);
}
//equals(("Receipt " + expected.transactionHash.substring(0, 10)), receipt, expected);
return waiter(delay);
});
}
it(`fetches transaction receipt: ${test.transactionHash}`, function () {
this.timeout(60000);
return testTransactionReceipt(test);
});
});
if (networkName === "ropsten") {
it("throws correct NONCE_EXPIRED errors", function () {
return __awaiter(this, void 0, void 0, function* () {
this.timeout(60000);
try {
const tx = yield provider.sendTransaction("0xf86480850218711a0082520894000000000000000000000000000000000000000002801ba038aaddcaaae7d3fa066dfd6f196c8348e1bb210f2c121d36cb2c24ef20cea1fba008ae378075d3cd75aae99ab75a70da82161dffb2c8263dabc5d8adecfa9447fa");
console.log(tx);
assert.ok(false);
}
catch (error) {
assert.equal(error.code, ethers.utils.Logger.errors.NONCE_EXPIRED);
}
yield waiter(delay);
});
});
it("throws correct INSUFFICIENT_FUNDS errors", function () {
return __awaiter(this, void 0, void 0, function* () {
this.timeout(60000);
const txProps = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
gasPrice: 9000000000,
gasLimit: 21000,
value: 1
};
const wallet = ethers.Wallet.createRandom();
const tx = yield wallet.signTransaction(txProps);
try {
yield provider.sendTransaction(tx);
assert.ok(false);
}
catch (error) {
assert.equal(error.code, ethers.utils.Logger.errors.INSUFFICIENT_FUNDS);
}
yield waiter(delay);
});
});
it("throws correct INSUFFICIENT_FUNDS errors (signer)", function () {
return __awaiter(this, void 0, void 0, function* () {
this.timeout(60000);
const txProps = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
gasPrice: 9000000000,
gasLimit: 21000,
value: 1
};
const wallet = ethers.Wallet.createRandom().connect(provider);
try {
yield wallet.sendTransaction(txProps);
assert.ok(false);
}
catch (error) {
assert.equal(error.code, ethers.utils.Logger.errors.INSUFFICIENT_FUNDS);
}
yield waiter(delay);
});
});
it("throws correct UNPREDICTABLE_GAS_LIMIT errors", function () {
return __awaiter(this, void 0, void 0, function* () {
this.timeout(60000);
try {
yield provider.estimateGas({
to: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" // ENS; no payable fallback
});
assert.ok(false);
}
catch (error) {
assert.equal(error.code, ethers.utils.Logger.errors.UNPREDICTABLE_GAS_LIMIT);
}
yield waiter(delay);
});
});
it("sends a transaction", function () {
return __awaiter(this, void 0, void 0, function* () {
this.timeout(360000);
const wallet = ethers.Wallet.createRandom().connect(provider);
const funder = yield ethers.utils.fetchJson(`https:/\/api.ethers.io/api/v1/?action=fundAccount&address=${wallet.address.toLowerCase()}`);
yield provider.waitForTransaction(funder.hash);
const addr = "0x8210357f377E901f18E45294e86a2A32215Cc3C9";
const gasPrice = 9000000000;
let balance = yield provider.getBalance(wallet.address);
assert.ok(balance.eq(ethers.utils.parseEther("3.141592653589793238")), "balance is pi after funding");
const tx = yield wallet.sendTransaction({
to: addr,
gasPrice: gasPrice,
value: balance.sub(21000 * gasPrice)
});
yield tx.wait();
balance = yield provider.getBalance(wallet.address);
assert.ok(balance.eq(ethers.constants.Zero), "balance is zero after after sweeping");
yield waiter(delay);
});
}); });
} }
// Obviously many more cases to add here if (test.name) {
// - getTransactionCount addSimpleTest(`fetches ENS name: ${test.address}`, (provider) => {
// - getBlockNumber return provider.resolveName(test.name);
// - getGasPrice }, test.address);
// - estimateGas }
// - sendTransaction
// - call
// - getLogs
//
// Many of these are tLegacyParametersested in run-providers, which uses nodeunit, but
// also creates a local private key which must then be funded to
// execute the tests. I am working on a better test contract to deploy
// to all the networks to help test these.
}); });
} tests.blocks.forEach((test) => {
["default", "homestead", "ropsten", "rinkeby", "kovan", "goerli"].forEach(function (networkName) { addObjectTest(`fetches block (by number) #${test.number}`, (provider) => {
["getDefaultProvider", "AlchemyProvider", "CloudflareProvider", "InfuraProvider", "EtherscanProvider", "NodesmithProvider", "Web3Provider"].forEach(function (providerName) { return provider.getBlock(test.number);
if (providerName === "NodesmithProvider") { }, test);
return; });
} tests.blocks.forEach((test) => {
if (providerName === "CloudflareProvider") { addObjectTest(`fetches block (by hash) ${test.hash}`, (provider) => {
return; return provider.getBlock(test.hash);
} }, test, (provider, network, test) => {
if (providerName === "Web3Provider") { return (provider === "EtherscanProvider");
return; });
} });
if ((networkName !== "homestead" && networkName !== "default") && providerName === "CloudflareProvider") { tests.transactions.forEach((test) => {
return; addObjectTest(`fetches transaction ${test.hash}`, (provider) => __awaiter(void 0, void 0, void 0, function* () {
} const tx = yield provider.getTransaction(test.hash);
testProvider(providerName, networkName); // This changes with every block
assert.equal(typeof (tx.confirmations), "number", "confirmations is a number");
delete tx.confirmations;
assert.equal(typeof (tx.wait), "function", "wait is a function");
delete tx.wait;
return tx;
}), test, (provider, network, test) => {
return (provider === "EtherscanProvider");
});
});
tests.transactionReceipts.forEach((test) => {
addObjectTest(`fetches transaction receipt ${test.transactionHash}`, (provider) => __awaiter(void 0, void 0, void 0, function* () {
const receipt = yield provider.getTransactionReceipt(test.transactionHash);
if (test.status === null) {
assert.ok(receipt.status === undefined, "no status");
receipt.status = null;
}
// This changes with every block; so just make sure it is a number
assert.equal(typeof (receipt.confirmations), "number", "confirmations is a number");
delete receipt.confirmations;
return receipt;
}), test);
});
});
(function () {
function addErrorTest(code, func) {
testFunctions.push({
name: `throws correct ${code} error`,
networks: ["ropsten"],
execute: (provider) => __awaiter(this, void 0, void 0, function* () {
try {
const value = yield func(provider);
console.log(value);
assert.ok(false, "did not throw");
}
catch (error) {
assert.equal(error.code, code, "incorrect error thrown");
}
})
});
}
addErrorTest(ethers.utils.Logger.errors.NONCE_EXPIRED, (provider) => __awaiter(this, void 0, void 0, function* () {
return provider.sendTransaction("0xf86480850218711a0082520894000000000000000000000000000000000000000002801ba038aaddcaaae7d3fa066dfd6f196c8348e1bb210f2c121d36cb2c24ef20cea1fba008ae378075d3cd75aae99ab75a70da82161dffb2c8263dabc5d8adecfa9447fa");
}));
addErrorTest(ethers.utils.Logger.errors.INSUFFICIENT_FUNDS, (provider) => __awaiter(this, void 0, void 0, function* () {
const txProps = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
gasPrice: 9000000000,
gasLimit: 21000,
value: 1
};
const wallet = ethers.Wallet.createRandom();
const tx = yield wallet.signTransaction(txProps);
return provider.sendTransaction(tx);
}));
addErrorTest(ethers.utils.Logger.errors.INSUFFICIENT_FUNDS, (provider) => __awaiter(this, void 0, void 0, function* () {
const txProps = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
gasPrice: 9000000000,
gasLimit: 21000,
value: 1
};
const wallet = ethers.Wallet.createRandom().connect(provider);
return wallet.sendTransaction(txProps);
}));
addErrorTest(ethers.utils.Logger.errors.UNPREDICTABLE_GAS_LIMIT, (provider) => __awaiter(this, void 0, void 0, function* () {
return provider.estimateGas({
to: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" // ENS contract
});
}));
})();
testFunctions.push({
name: "sends a transaction",
extras: ["funding"],
timeout: 300,
networks: ["ropsten"],
execute: (provider) => __awaiter(void 0, void 0, void 0, function* () {
const wallet = fundWallet.connect(provider);
const addr = "0x8210357f377E901f18E45294e86a2A32215Cc3C9";
const b0 = yield provider.getBalance(wallet.address);
assert.ok(b0.gt(ethers.constants.Zero), "balance is non-zero");
const tx = yield wallet.sendTransaction({
to: addr,
value: 123
});
yield tx.wait();
const b1 = yield provider.getBalance(wallet.address);
assert.ok(b0.gt(b1), "balance is decreased");
})
});
describe("Test Provider Methods", function () {
let fundReceipt = null;
const faucet = "0x8210357f377E901f18E45294e86a2A32215Cc3C9";
before(function () {
return __awaiter(this, void 0, void 0, function* () {
// Get some ether from the faucet
const provider = ethers.getDefaultProvider("ropsten");
const funder = yield ethers.utils.fetchJson(`https:/\/api.ethers.io/api/v1/?action=fundAccount&address=${fundWallet.address.toLowerCase()}`);
fundReceipt = provider.waitForTransaction(funder.hash);
fundReceipt.then((receipt) => {
console.log(`*** Funded: ${fundWallet.address}`);
});
});
});
after(function () {
return __awaiter(this, void 0, void 0, function* () {
// Wait until the funding is complete
yield fundReceipt;
// Refund all unused ether to the faucet
const provider = ethers.getDefaultProvider("ropsten");
const gasPrice = yield provider.getGasPrice();
const balance = yield provider.getBalance(fundWallet.address);
fundWallet.connect(provider).sendTransaction({
to: faucet,
gasLimit: 21000,
gasPrice: gasPrice,
value: balance.sub(gasPrice.mul(21000))
});
});
});
providerFunctions.forEach(({ name, networks, create }) => {
networks.forEach((network) => {
const provider = create(network);
testFunctions.forEach((test) => {
// Skip tests not supported on this network
if (test.networks.indexOf(network) === -1) {
return;
}
if (test.checkSkip && test.checkSkip(name, network, test)) {
return;
}
// How many attempts to try?
const attempts = (test.attempts != null) ? test.attempts : 3;
const timeout = (test.timeout != null) ? test.timeout : 60;
const extras = (test.extras || []).reduce((accum, key) => {
accum[key] = true;
return accum;
}, {});
it(`${name}.${network ? network : "default"} ${test.name}`, function () {
return __awaiter(this, void 0, void 0, function* () {
this.timeout(timeout * 1000 * attempts);
// Wait for the funding transaction to be mined
if (extras.funding) {
yield fundReceipt;
}
// We wait at least 1 seconds between tests
if (!extras.nowait) {
yield waiter(1000);
}
let error = null;
for (let attempt = 0; attempt < attempts; attempt++) {
try {
return yield Promise.race([
test.execute(provider),
waiter(timeout * 1000).then((resolve) => { throw new Error("timeout"); })
]);
}
catch (attemptError) {
console.log(`*** Failed attempt ${attempt + 1}: ${attemptError.message}`);
error = attemptError;
}
}
throw error;
});
});
});
});
}); });
}); });
/* /*
@ -679,7 +731,7 @@ describe("Test extra Etherscan operations", function() {
}); });
*/ */
describe("Test Basic Authentication", function () { describe("Test Basic Authentication", function () {
this.retries(3); //this.retries(3);
function test(name, url) { function test(name, url) {
it("tests " + name, function () { it("tests " + name, function () {
this.timeout(60000); this.timeout(60000);

File diff suppressed because one or more lines are too long

@ -96,7 +96,7 @@ var blockchainData = {
s: "0x269c3e5b3558267ad91b0a887d51f9f10098771c67b82ea6cb74f29638754f54", s: "0x269c3e5b3558267ad91b0a887d51f9f10098771c67b82ea6cb74f29638754f54",
v: 38, v: 38,
creates: null, creates: null,
raw: "0xf8d2808504a817c8008303d090946fc21092da55b392b045ed78f4732bff3c580e2c880186cc6acd4b0000b864f2c298be000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000067269636d6f6f000000000000000000000000000000000000000000000000000026a01e5605197a03e3f0a168f14749168dfeefc44c9228312dacbffdcbbb13263265a0269c3e5b3558267ad91b0a887d51f9f10098771c67b82ea6cb74f29638754f54", //raw: "0xf8d2808504a817c8008303d090946fc21092da55b392b045ed78f4732bff3c580e2c880186cc6acd4b0000b864f2c298be000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000067269636d6f6f000000000000000000000000000000000000000000000000000026a01e5605197a03e3f0a168f14749168dfeefc44c9228312dacbffdcbbb13263265a0269c3e5b3558267ad91b0a887d51f9f10098771c67b82ea6cb74f29638754f54",
chainId: 1 chainId: 1
} }
], ],
@ -395,6 +395,8 @@ function equals(name, actual, expected) {
if (actual == null) { if (actual == null) {
assert_1.default.ok(false, name + " - actual big number null"); assert_1.default.ok(false, name + " - actual big number null");
} }
expected = ethers_1.ethers.BigNumber.from(expected);
actual = ethers_1.ethers.BigNumber.from(actual);
assert_1.default.ok(expected.eq(actual), name + " matches"); assert_1.default.ok(expected.eq(actual), name + " matches");
} }
else if (Array.isArray(expected)) { else if (Array.isArray(expected)) {
@ -429,344 +431,429 @@ function equals(name, actual, expected) {
} }
function waiter(duration) { function waiter(duration) {
return new Promise(function (resolve) { return new Promise(function (resolve) {
setTimeout(resolve, duration); var timer = setTimeout(resolve, duration);
if (timer.unref) {
timer.unref();
}
}); });
} }
function testProvider(providerName, networkName) { var allNetworks = ["default", "homestead", "ropsten", "rinkeby", "kovan", "goerli"];
// Delay (ms) after each test case to prevent the backends from throttling var providerFunctions = [
var delay = 1000; {
describe(("Read-Only " + providerName + " (" + networkName + ")"), function () { name: "getDefaultProvider",
this.retries(3); networks: allNetworks,
// Get the Provider based on the name of the provider we are testing and the network create: function (network) {
var provider = null; if (network == "default") {
if (networkName === "default") { return ethers_1.ethers.getDefaultProvider();
if (providerName === "getDefaultProvider") {
provider = ethers_1.ethers.getDefaultProvider();
}
else {
provider = new (ethers_1.ethers.providers)[providerName]();
} }
return ethers_1.ethers.getDefaultProvider(network);
} }
else { },
if (providerName === "getDefaultProvider") { {
provider = ethers_1.ethers.getDefaultProvider(networkName); name: "AlchemyProvider",
} networks: allNetworks,
else { create: function (network) {
provider = new (ethers_1.ethers.providers)[providerName](networkName); if (network == "default") {
return new ethers_1.ethers.providers.AlchemyProvider();
} }
return new ethers_1.ethers.providers.AlchemyProvider(network);
} }
var tests = blockchainData[networkName]; },
// And address test case can have any of the following: {
// - balance name: "CloudflareProvider",
// - code networks: ["homestead"],
// - storage create: function (network) {
// - ENS name return new ethers_1.ethers.providers.AlchemyProvider(network);
tests.addresses.forEach(function (test) { }
if (test.balance) { },
it("fetches address balance: " + test.address, function () { {
// Note: These tests could be fiddled with if someone sends ether name: "InfuraProvider",
// to our address; we just have to live with jerks sending us networks: allNetworks,
// money. *smile emoji* create: function (network) {
this.timeout(60000); if (network == "default") {
return provider.getBalance(test.address).then(function (balance) { return new ethers_1.ethers.providers.InfuraProvider();
equals("Balance", test.balance, balance);
return waiter(delay);
});
});
} }
if (test.code) { return new ethers_1.ethers.providers.InfuraProvider(network);
it("fetches address code: " + test.address, function () { }
this.timeout(60000); },
return provider.getCode(test.address).then(function (code) { {
equals("Code", test.code, code); name: "EtherscanProvider",
return waiter(delay); networks: allNetworks,
}); create: function (network) {
}); if (network == "default") {
return new ethers_1.ethers.providers.EtherscanProvider();
} }
if (test.storage) { return new ethers_1.ethers.providers.EtherscanProvider(network);
Object.keys(test.storage).forEach(function (position) { }
it("fetches storage: " + test.address + ":" + position, function () { },
this.timeout(60000); {
return provider.getStorageAt(test.address, bnify(position)).then(function (value) { name: "NodesmithProvider",
equals("Storage", test.storage[position], value); networks: [],
return waiter(delay); create: function (network) {
throw new Error("not tested");
}
},
{
name: "Web3Provider",
networks: [],
create: function (network) {
throw new Error("not tested");
}
}
];
// This wallet can be funded and used for various test cases
var fundWallet = ethers_1.ethers.Wallet.createRandom();
var testFunctions = [];
Object.keys(blockchainData).forEach(function (network) {
function addSimpleTest(name, func, expected) {
var _this = this;
testFunctions.push({
name: name,
networks: [network],
execute: function (provider) { return __awaiter(_this, void 0, void 0, function () {
var value;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, func(provider)];
case 1:
value = _a.sent();
equals(name, expected, value);
return [2 /*return*/];
}
});
}); }
});
}
function addObjectTest(name, func, expected, checkSkip) {
var _this = this;
testFunctions.push({
name: name,
networks: [network],
checkSkip: checkSkip,
execute: function (provider) { return __awaiter(_this, void 0, void 0, function () {
var value;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, func(provider)];
case 1:
value = _a.sent();
Object.keys(expected).forEach(function (key) {
equals(name + "." + key, value[key], expected[key]);
});
return [2 /*return*/];
}
});
}); }
});
}
var tests = blockchainData[network];
// And address test case can have any of the following:
// - balance
// - code
// - storage
// - ENS name
tests.addresses.forEach(function (test) {
if (test.balance) {
addSimpleTest("fetches account balance: " + test.address, function (provider) {
return provider.getBalance(test.address);
}, test.balance);
}
if (test.code) {
addSimpleTest("fetches account code: " + test.address, function (provider) {
return provider.getCode(test.address);
}, test.code);
}
if (test.storage) {
Object.keys(test.storage).forEach(function (position) {
addSimpleTest("fetches storage: " + test.address + ":" + position, function (provider) {
return provider.getStorageAt(test.address, bnify(position));
}, test.storage[position]);
});
}
if (test.name) {
addSimpleTest("fetches ENS name: " + test.address, function (provider) {
return provider.resolveName(test.name);
}, test.address);
}
});
tests.blocks.forEach(function (test) {
addObjectTest("fetches block (by number) #" + test.number, function (provider) {
return provider.getBlock(test.number);
}, test);
});
tests.blocks.forEach(function (test) {
addObjectTest("fetches block (by hash) " + test.hash, function (provider) {
return provider.getBlock(test.hash);
}, test, function (provider, network, test) {
return (provider === "EtherscanProvider");
});
});
tests.transactions.forEach(function (test) {
addObjectTest("fetches transaction " + test.hash, function (provider) { return __awaiter(void 0, void 0, void 0, function () {
var tx;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, provider.getTransaction(test.hash)];
case 1:
tx = _a.sent();
// This changes with every block
assert_1.default.equal(typeof (tx.confirmations), "number", "confirmations is a number");
delete tx.confirmations;
assert_1.default.equal(typeof (tx.wait), "function", "wait is a function");
delete tx.wait;
return [2 /*return*/, tx];
}
});
}); }, test, function (provider, network, test) {
return (provider === "EtherscanProvider");
});
});
tests.transactionReceipts.forEach(function (test) {
addObjectTest("fetches transaction receipt " + test.transactionHash, function (provider) { return __awaiter(void 0, void 0, void 0, function () {
var receipt;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, provider.getTransactionReceipt(test.transactionHash)];
case 1:
receipt = _a.sent();
if (test.status === null) {
assert_1.default.ok(receipt.status === undefined, "no status");
receipt.status = null;
}
// This changes with every block; so just make sure it is a number
assert_1.default.equal(typeof (receipt.confirmations), "number", "confirmations is a number");
delete receipt.confirmations;
return [2 /*return*/, receipt];
}
});
}); }, test);
});
});
(function () {
var _this = this;
function addErrorTest(code, func) {
var _this = this;
testFunctions.push({
name: "throws correct " + code + " error",
networks: ["ropsten"],
execute: function (provider) { return __awaiter(_this, void 0, void 0, function () {
var value, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, func(provider)];
case 1:
value = _a.sent();
console.log(value);
assert_1.default.ok(false, "did not throw");
return [3 /*break*/, 3];
case 2:
error_1 = _a.sent();
assert_1.default.equal(error_1.code, code, "incorrect error thrown");
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); }
});
}
addErrorTest(ethers_1.ethers.utils.Logger.errors.NONCE_EXPIRED, function (provider) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, provider.sendTransaction("0xf86480850218711a0082520894000000000000000000000000000000000000000002801ba038aaddcaaae7d3fa066dfd6f196c8348e1bb210f2c121d36cb2c24ef20cea1fba008ae378075d3cd75aae99ab75a70da82161dffb2c8263dabc5d8adecfa9447fa")];
});
}); });
addErrorTest(ethers_1.ethers.utils.Logger.errors.INSUFFICIENT_FUNDS, function (provider) { return __awaiter(_this, void 0, void 0, function () {
var txProps, wallet, tx;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
txProps = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
gasPrice: 9000000000,
gasLimit: 21000,
value: 1
};
wallet = ethers_1.ethers.Wallet.createRandom();
return [4 /*yield*/, wallet.signTransaction(txProps)];
case 1:
tx = _a.sent();
return [2 /*return*/, provider.sendTransaction(tx)];
}
});
}); });
addErrorTest(ethers_1.ethers.utils.Logger.errors.INSUFFICIENT_FUNDS, function (provider) { return __awaiter(_this, void 0, void 0, function () {
var txProps, wallet;
return __generator(this, function (_a) {
txProps = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
gasPrice: 9000000000,
gasLimit: 21000,
value: 1
};
wallet = ethers_1.ethers.Wallet.createRandom().connect(provider);
return [2 /*return*/, wallet.sendTransaction(txProps)];
});
}); });
addErrorTest(ethers_1.ethers.utils.Logger.errors.UNPREDICTABLE_GAS_LIMIT, function (provider) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, provider.estimateGas({
to: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" // ENS contract
})];
});
}); });
})();
testFunctions.push({
name: "sends a transaction",
extras: ["funding"],
timeout: 300,
networks: ["ropsten"],
execute: function (provider) { return __awaiter(void 0, void 0, void 0, function () {
var wallet, addr, b0, tx, b1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
wallet = fundWallet.connect(provider);
addr = "0x8210357f377E901f18E45294e86a2A32215Cc3C9";
return [4 /*yield*/, provider.getBalance(wallet.address)];
case 1:
b0 = _a.sent();
assert_1.default.ok(b0.gt(ethers_1.ethers.constants.Zero), "balance is non-zero");
return [4 /*yield*/, wallet.sendTransaction({
to: addr,
value: 123
})];
case 2:
tx = _a.sent();
return [4 /*yield*/, tx.wait()];
case 3:
_a.sent();
return [4 /*yield*/, provider.getBalance(wallet.address)];
case 4:
b1 = _a.sent();
assert_1.default.ok(b0.gt(b1), "balance is decreased");
return [2 /*return*/];
}
});
}); }
});
describe("Test Provider Methods", function () {
var fundReceipt = null;
var faucet = "0x8210357f377E901f18E45294e86a2A32215Cc3C9";
before(function () {
return __awaiter(this, void 0, void 0, function () {
var provider, funder;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
provider = ethers_1.ethers.getDefaultProvider("ropsten");
return [4 /*yield*/, ethers_1.ethers.utils.fetchJson("https://api.ethers.io/api/v1/?action=fundAccount&address=" + fundWallet.address.toLowerCase())];
case 1:
funder = _a.sent();
fundReceipt = provider.waitForTransaction(funder.hash);
fundReceipt.then(function (receipt) {
console.log("*** Funded: " + fundWallet.address);
});
return [2 /*return*/];
}
});
});
});
after(function () {
return __awaiter(this, void 0, void 0, function () {
var provider, gasPrice, balance;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
// Wait until the funding is complete
return [4 /*yield*/, fundReceipt];
case 1:
// Wait until the funding is complete
_a.sent();
provider = ethers_1.ethers.getDefaultProvider("ropsten");
return [4 /*yield*/, provider.getGasPrice()];
case 2:
gasPrice = _a.sent();
return [4 /*yield*/, provider.getBalance(fundWallet.address)];
case 3:
balance = _a.sent();
fundWallet.connect(provider).sendTransaction({
to: faucet,
gasLimit: 21000,
gasPrice: gasPrice,
value: balance.sub(gasPrice.mul(21000))
});
return [2 /*return*/];
}
});
});
});
providerFunctions.forEach(function (_a) {
var name = _a.name, networks = _a.networks, create = _a.create;
networks.forEach(function (network) {
var provider = create(network);
testFunctions.forEach(function (test) {
// Skip tests not supported on this network
if (test.networks.indexOf(network) === -1) {
return;
}
if (test.checkSkip && test.checkSkip(name, network, test)) {
return;
}
// How many attempts to try?
var attempts = (test.attempts != null) ? test.attempts : 3;
var timeout = (test.timeout != null) ? test.timeout : 60;
var extras = (test.extras || []).reduce(function (accum, key) {
accum[key] = true;
return accum;
}, {});
it(name + "." + (network ? network : "default") + " " + test.name, function () {
return __awaiter(this, void 0, void 0, function () {
var error, attempt, attemptError_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.timeout(timeout * 1000 * attempts);
if (!extras.funding) return [3 /*break*/, 2];
return [4 /*yield*/, fundReceipt];
case 1:
_a.sent();
_a.label = 2;
case 2:
if (!!extras.nowait) return [3 /*break*/, 4];
return [4 /*yield*/, waiter(1000)];
case 3:
_a.sent();
_a.label = 4;
case 4:
error = null;
attempt = 0;
_a.label = 5;
case 5:
if (!(attempt < attempts)) return [3 /*break*/, 10];
_a.label = 6;
case 6:
_a.trys.push([6, 8, , 9]);
return [4 /*yield*/, Promise.race([
test.execute(provider),
waiter(timeout * 1000).then(function (resolve) { throw new Error("timeout"); })
])];
case 7: return [2 /*return*/, _a.sent()];
case 8:
attemptError_1 = _a.sent();
console.log("*** Failed attempt " + (attempt + 1) + ": " + attemptError_1.message);
error = attemptError_1;
return [3 /*break*/, 9];
case 9:
attempt++;
return [3 /*break*/, 5];
case 10: throw error;
}
}); });
}); });
}); });
}
if (test.name) {
it("fetches the ENS name: " + test.name, function () {
this.timeout(60000);
return provider.resolveName(test.name).then(function (address) {
equals("ENS Name", test.address, address);
return waiter(delay);
});
});
}
});
tests.blocks.forEach(function (test) {
function checkBlock(promise) {
return promise.then(function (block) {
for (var key in test) {
equals("Block " + key, block[key], test[key]);
}
return waiter(delay);
});
}
it("fetches block (by number) #" + test.number, function () {
this.timeout(60000);
return checkBlock(provider.getBlock(test.number));
});
// Etherscan does not support getBlockByBlockhash... *sad emoji*
if (providerName === "EtherscanProvider") {
return;
}
it("fetches block (by hash) " + test.hash, function () {
this.timeout(60000);
return checkBlock(provider.getBlock(test.hash));
}); });
}); });
tests.transactions.forEach(function (test) {
function testTransaction(expected) {
var title = ("Transaction " + expected.hash.substring(0, 10) + " - ");
return provider.getTransaction(expected.hash).then(function (tx) {
// This changes with every block
assert_1.default.equal(typeof (tx.confirmations), "number", "confirmations is a number");
delete tx.confirmations;
assert_1.default.equal(typeof (tx.wait), "function", "wait is a function");
delete tx.wait;
for (var key in tx) {
equals((title + key), tx[key], expected[key]);
}
return waiter(delay);
});
}
it("fetches transaction: " + test.hash, function () {
this.timeout(60000);
return testTransaction(test);
});
});
tests.transactionReceipts.forEach(function (test) {
function testTransactionReceipt(expected) {
var title = ("Receipt " + expected.transactionHash.substring(0, 10) + " - ");
return provider.getTransactionReceipt(expected.transactionHash).then(function (receipt) {
// This changes with every block; so just make sure it is a number
assert_1.default.equal(typeof (receipt.confirmations), "number", "confirmations is a number");
delete receipt.confirmations;
for (var key in receipt) {
equals((title + key), receipt[key], expected[key]);
}
//equals(("Receipt " + expected.transactionHash.substring(0, 10)), receipt, expected);
return waiter(delay);
});
}
it("fetches transaction receipt: " + test.transactionHash, function () {
this.timeout(60000);
return testTransactionReceipt(test);
});
});
if (networkName === "ropsten") {
it("throws correct NONCE_EXPIRED errors", function () {
return __awaiter(this, void 0, void 0, function () {
var tx, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.timeout(60000);
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, provider.sendTransaction("0xf86480850218711a0082520894000000000000000000000000000000000000000002801ba038aaddcaaae7d3fa066dfd6f196c8348e1bb210f2c121d36cb2c24ef20cea1fba008ae378075d3cd75aae99ab75a70da82161dffb2c8263dabc5d8adecfa9447fa")];
case 2:
tx = _a.sent();
console.log(tx);
assert_1.default.ok(false);
return [3 /*break*/, 4];
case 3:
error_1 = _a.sent();
assert_1.default.equal(error_1.code, ethers_1.ethers.utils.Logger.errors.NONCE_EXPIRED);
return [3 /*break*/, 4];
case 4: return [4 /*yield*/, waiter(delay)];
case 5:
_a.sent();
return [2 /*return*/];
}
});
});
});
it("throws correct INSUFFICIENT_FUNDS errors", function () {
return __awaiter(this, void 0, void 0, function () {
var txProps, wallet, tx, error_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.timeout(60000);
txProps = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
gasPrice: 9000000000,
gasLimit: 21000,
value: 1
};
wallet = ethers_1.ethers.Wallet.createRandom();
return [4 /*yield*/, wallet.signTransaction(txProps)];
case 1:
tx = _a.sent();
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, provider.sendTransaction(tx)];
case 3:
_a.sent();
assert_1.default.ok(false);
return [3 /*break*/, 5];
case 4:
error_2 = _a.sent();
assert_1.default.equal(error_2.code, ethers_1.ethers.utils.Logger.errors.INSUFFICIENT_FUNDS);
return [3 /*break*/, 5];
case 5: return [4 /*yield*/, waiter(delay)];
case 6:
_a.sent();
return [2 /*return*/];
}
});
});
});
it("throws correct INSUFFICIENT_FUNDS errors (signer)", function () {
return __awaiter(this, void 0, void 0, function () {
var txProps, wallet, error_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.timeout(60000);
txProps = {
to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
gasPrice: 9000000000,
gasLimit: 21000,
value: 1
};
wallet = ethers_1.ethers.Wallet.createRandom().connect(provider);
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, wallet.sendTransaction(txProps)];
case 2:
_a.sent();
assert_1.default.ok(false);
return [3 /*break*/, 4];
case 3:
error_3 = _a.sent();
assert_1.default.equal(error_3.code, ethers_1.ethers.utils.Logger.errors.INSUFFICIENT_FUNDS);
return [3 /*break*/, 4];
case 4: return [4 /*yield*/, waiter(delay)];
case 5:
_a.sent();
return [2 /*return*/];
}
});
});
});
it("throws correct UNPREDICTABLE_GAS_LIMIT errors", function () {
return __awaiter(this, void 0, void 0, function () {
var error_4;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.timeout(60000);
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, provider.estimateGas({
to: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" // ENS; no payable fallback
})];
case 2:
_a.sent();
assert_1.default.ok(false);
return [3 /*break*/, 4];
case 3:
error_4 = _a.sent();
assert_1.default.equal(error_4.code, ethers_1.ethers.utils.Logger.errors.UNPREDICTABLE_GAS_LIMIT);
return [3 /*break*/, 4];
case 4: return [4 /*yield*/, waiter(delay)];
case 5:
_a.sent();
return [2 /*return*/];
}
});
});
});
it("sends a transaction", function () {
return __awaiter(this, void 0, void 0, function () {
var wallet, funder, addr, gasPrice, balance, tx;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.timeout(360000);
wallet = ethers_1.ethers.Wallet.createRandom().connect(provider);
return [4 /*yield*/, ethers_1.ethers.utils.fetchJson("https://api.ethers.io/api/v1/?action=fundAccount&address=" + wallet.address.toLowerCase())];
case 1:
funder = _a.sent();
return [4 /*yield*/, provider.waitForTransaction(funder.hash)];
case 2:
_a.sent();
addr = "0x8210357f377E901f18E45294e86a2A32215Cc3C9";
gasPrice = 9000000000;
return [4 /*yield*/, provider.getBalance(wallet.address)];
case 3:
balance = _a.sent();
assert_1.default.ok(balance.eq(ethers_1.ethers.utils.parseEther("3.141592653589793238")), "balance is pi after funding");
return [4 /*yield*/, wallet.sendTransaction({
to: addr,
gasPrice: gasPrice,
value: balance.sub(21000 * gasPrice)
})];
case 4:
tx = _a.sent();
return [4 /*yield*/, tx.wait()];
case 5:
_a.sent();
return [4 /*yield*/, provider.getBalance(wallet.address)];
case 6:
balance = _a.sent();
assert_1.default.ok(balance.eq(ethers_1.ethers.constants.Zero), "balance is zero after after sweeping");
return [4 /*yield*/, waiter(delay)];
case 7:
_a.sent();
return [2 /*return*/];
}
});
});
});
}
// Obviously many more cases to add here
// - getTransactionCount
// - getBlockNumber
// - getGasPrice
// - estimateGas
// - sendTransaction
// - call
// - getLogs
//
// Many of these are tLegacyParametersested in run-providers, which uses nodeunit, but
// also creates a local private key which must then be funded to
// execute the tests. I am working on a better test contract to deploy
// to all the networks to help test these.
});
}
["default", "homestead", "ropsten", "rinkeby", "kovan", "goerli"].forEach(function (networkName) {
["getDefaultProvider", "AlchemyProvider", "CloudflareProvider", "InfuraProvider", "EtherscanProvider", "NodesmithProvider", "Web3Provider"].forEach(function (providerName) {
if (providerName === "NodesmithProvider") {
return;
}
if (providerName === "CloudflareProvider") {
return;
}
if (providerName === "Web3Provider") {
return;
}
if ((networkName !== "homestead" && networkName !== "default") && providerName === "CloudflareProvider") {
return;
}
testProvider(providerName, networkName);
}); });
}); });
/* /*
@ -789,7 +876,7 @@ describe("Test extra Etherscan operations", function() {
}); });
*/ */
describe("Test Basic Authentication", function () { describe("Test Basic Authentication", function () {
this.retries(3); //this.retries(3);
function test(name, url) { function test(name, url) {
it("tests " + name, function () { it("tests " + name, function () {
this.timeout(60000); this.timeout(60000);

File diff suppressed because one or more lines are too long

@ -39,7 +39,7 @@
"scripts": { "scripts": {
"test": "exit 1" "test": "exit 1"
}, },
"tarballHash": "0xeba001b6d7814b9df776d8a5b395ba7080d99ea8a6dfc8fad70888a5f7d01f3e", "tarballHash": "0x71309e6063699613deb6d5d29f7c87963ee1d71e252f006cdd3ad930e187e47c",
"types": "./lib/index.d.ts", "types": "./lib/index.d.ts",
"version": "5.0.8" "version": "5.0.8"
} }