Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #4400 from trufflesuite/hdwallet-constructor
Browse files Browse the repository at this point in the history
Accept url and provider arguments in hdwallet-provider constructor
  • Loading branch information
gnidan authored Nov 18, 2021
2 parents b250432 + 14f7213 commit dee370e
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 41 deletions.
3 changes: 2 additions & 1 deletion packages/hdwallet-provider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"ganache-core": "2.13.0",
"mocha": "8.1.2",
"ts-node": "^9.0.0",
"typescript": "^4.1.4"
"typescript": "^4.1.4",
"web3": "1.5.3"
},
"keywords": [
"etheruem",
Expand Down
6 changes: 5 additions & 1 deletion packages/hdwallet-provider/src/constructor/Constructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type {
Mnemonic,
MnemonicPhrase,
PrivateKey,
Provider,
ProviderUrl,
ProviderOrUrl,
AddressIndex,
NumberOfAddresses,
Expand Down Expand Up @@ -38,7 +40,9 @@ export type InputSigningAuthority =
| PrivateKeysSigningAuthority;

export interface CommonOptions {
providerOrUrl: ProviderOrUrl;
providerOrUrl?: ProviderOrUrl;
provider?: Provider;
url?: ProviderUrl;
addressIndex?: AddressIndex;
numberOfAddresses?: NumberOfAddresses;
shareNonce?: ShareNonce;
Expand Down
2 changes: 1 addition & 1 deletion packages/hdwallet-provider/src/constructor/getOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ const matchesNewInputOptions = (

// beyond that, determine based on property inclusion check for required keys
return (
"providerOrUrl" in options &&
("providerOrUrl" in options || "provider" in options || "url" in options) &&
("privateKeys" in options || "mnemonic" in options)
);
};
Expand Down
9 changes: 8 additions & 1 deletion packages/hdwallet-provider/src/constructor/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ export interface Mnemonic {
phrase: MnemonicPhrase;
password?: MnemonicPassword;
}
import type { Provider as LegacyProvider } from "web3/providers";
type Eip1193Provider = {
request: (options: {
method: string;
params?: unknown[] | object;
}) => Promise<any>;
};
export type PrivateKey = string;
export type Provider = any;
export type Provider = LegacyProvider | Eip1193Provider;
export type ProviderUrl = string;
export type ProviderOrUrl = Provider | ProviderUrl;
export type AddressIndex = number;
Expand Down
42 changes: 29 additions & 13 deletions packages/hdwallet-provider/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ class HDWalletProvider {

constructor(...args: ConstructorArguments) {
const {
providerOrUrl, // required
provider,
url,
providerOrUrl,
addressIndex = 0,
numberOfAddresses = 10,
shareNonce = true,
Expand All @@ -78,11 +80,21 @@ class HDWalletProvider {
pollingInterval
});

if (!HDWalletProvider.isValidProvider(providerOrUrl)) {
let providerToUse;
if (HDWalletProvider.isValidProvider(provider)) {
providerToUse = provider;
} else if (HDWalletProvider.isValidProvider(url)) {
providerToUse = url;
} else {
providerToUse = providerOrUrl;
}

if (!HDWalletProvider.isValidProvider(providerToUse)) {
throw new Error(
[
`Malformed provider URL: '${providerOrUrl}'`,
"Please specify a correct URL, using the http, https, ws, or wss protocol.",
`No provider or an invalid provider was specified: '${providerToUse}'`,
"Please specify a valid provider or URL, using the http, https, " +
"ws, or wss protocol.",
""
].join("\n")
);
Expand Down Expand Up @@ -219,8 +231,8 @@ class HDWalletProvider {
: this.engine.addProvider(singletonNonceSubProvider);

this.engine.addProvider(new FiltersSubprovider());
if (typeof providerOrUrl === "string") {
const url = providerOrUrl;
if (typeof providerToUse === "string") {
const url = providerToUse;

const providerProtocol = (
Url.parse(url).protocol || "http:"
Expand All @@ -235,8 +247,7 @@ class HDWalletProvider {
this.engine.addProvider(new RpcProvider({ rpcUrl: url }));
}
} else {
const provider = providerOrUrl;
this.engine.addProvider(new ProviderSubprovider(provider));
this.engine.addProvider(new ProviderSubprovider(providerToUse));
}

// Required by the provider engine.
Expand Down Expand Up @@ -356,15 +367,20 @@ class HDWalletProvider {
return this.addresses;
}

public static isValidProvider(provider: string | any): boolean {
const validProtocols = ["http:", "https:", "ws:", "wss:"];

public static isValidProvider(provider: any): boolean {
if (!provider) return false;
if (typeof provider === "string") {
const validProtocols = ["http:", "https:", "ws:", "wss:"];
const url = Url.parse(provider.toLowerCase());
return !!(validProtocols.includes(url.protocol || "") && url.slashes);
} else if ("request" in provider) {
// provider is an 1193 provider
return true;
} else if ("send" in provider) {
// provider is a "legacy" provider
return true;
}

return true;
return false;
}
}

Expand Down
71 changes: 51 additions & 20 deletions packages/hdwallet-provider/test/provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ describe("HD Wallet Provider", function () {
mnemonic: {
phrase: mnemonicPhrase
},
providerOrUrl: `http://localhost:${port}`
url: `http://localhost:${port}`
});

assert.deepEqual(provider.getAddresses(), truffleDevAccounts);
Expand Down Expand Up @@ -168,7 +168,7 @@ describe("HD Wallet Provider", function () {
"candy maple cake sugar pudding cream honey rich smooth crumble sweet treat";
provider = new HDWalletProvider({
mnemonic: mnemonicPhrase,
providerOrUrl: `http://localhost:${port}`
url: `http://localhost:${port}`
});

assert.deepEqual(provider.getAddresses(), truffleDevAccounts);
Expand Down Expand Up @@ -198,7 +198,7 @@ describe("HD Wallet Provider", function () {
phrase: mnemonicPhrase,
password: "yummy"
},
providerOrUrl: `http://localhost:${port}`
url: `http://localhost:${port}`
});

assert.deepEqual(provider.getAddresses(), accounts);
Expand All @@ -208,28 +208,14 @@ describe("HD Wallet Provider", function () {
assert(number === 0);
});

it("throws on invalid mnemonic", () => {
try {
provider = new HDWalletProvider({
mnemonic: {
phrase: "I am not a crook"
},
providerOrUrl: "http://localhost:8545"
});
assert.fail("Should throw on invalid mnemonic");
} catch (e) {
assert(e.message.includes("Mnemonic invalid or undefined"));
}
});

it("provides for a default polling interval", () => {
const mnemonicPhrase =
"candy maple cake sugar pudding cream honey rich smooth crumble sweet treat";
provider = new HDWalletProvider({
mnemonic: {
phrase: mnemonicPhrase
},
providerOrUrl: `http://localhost:${port}`,
url: `http://localhost:${port}`,
// polling interval is unspecified
});
assert.ok(provider.engine,
Expand All @@ -249,7 +235,7 @@ describe("HD Wallet Provider", function () {
mnemonic: {
phrase: mnemonicPhrase
},
providerOrUrl: `http://localhost:${port}`,
url: `http://localhost:${port}`,
// double the default value, for less chatty JSON-RPC
pollingInterval: 8000,
});
Expand Down Expand Up @@ -278,7 +264,7 @@ describe("HD Wallet Provider", function () {

provider = new HDWalletProvider({
privateKeys,
providerOrUrl: `http://localhost:${port}`
url: `http://localhost:${port}`
});
web3.setProvider(provider);

Expand All @@ -304,5 +290,50 @@ describe("HD Wallet Provider", function () {
const number = await web3.eth.getBlockNumber();
assert(number === 0);
});

describe("instantiation errors", () => {
it("throws on invalid providers", () => {
try {
provider = new HDWalletProvider({
mnemonic: {
phrase: "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat"
},
// @ts-ignore we gotta do the bad thing here to get the test right
provider: { junk: "in", an: "object" }
});
assert.fail("Should throw on invalid provider");
} catch (e) {
assert(e.message.includes("invalid provider was specified"));
}
});

it("throws on invalid urls", () => {
try {
provider = new HDWalletProvider({
mnemonic: {
phrase: "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat"
},
url: "justABunchOfJunk"
});
assert.fail("Should throw on invalid url");
} catch (e) {
assert(e.message.includes("invalid provider was specified"));
}
});

it("throws on invalid mnemonic", () => {
try {
provider = new HDWalletProvider({
mnemonic: {
phrase: "I am not a crook"
},
url: "http://localhost:8545"
});
assert.fail("Should throw on invalid mnemonic");
} catch (e) {
assert(e.message.includes("Mnemonic invalid or undefined"));
}
});
});
});
});
17 changes: 13 additions & 4 deletions packages/hdwallet-provider/test/urlValidation.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import assert from "assert";
import WalletProvider from "../dist";
import Ganache from "ganache-core";
import { describe, it } from "mocha";

const { isValidProvider } = WalletProvider;
Expand All @@ -20,8 +21,8 @@ describe("HD Wallet Provider Validator", () => {
assert.fail("did not throw!");
} catch (e) {
const expectedMessage = [
`Malformed provider URL: '${badUrl}'`,
"Please specify a correct URL, using the http, https, ws, or wss protocol.",
`No provider or an invalid provider was specified: '${badUrl}'`,
"Please specify a valid provider or URL, using the http, https, ws, or wss protocol.",
""
].join("\n");
assert.equal(e.message, expectedMessage);
Expand All @@ -35,8 +36,8 @@ describe("HD Wallet Provider Validator", () => {
assert.fail("did not throw!");
} catch (e) {
const expectedMessage = [
`Malformed provider URL: '${badUrl}'`,
"Please specify a correct URL, using the http, https, ws, or wss protocol.",
`No provider or an invalid provider was specified: '${badUrl}'`,
"Please specify a valid provider or URL, using the http, https, ws, or wss protocol.",
""
].join("\n");
assert.equal(e.message, expectedMessage);
Expand Down Expand Up @@ -80,5 +81,13 @@ describe("HD Wallet Provider Validator", () => {
"Good WSS Url should pass validation"
);
});

it("a provider", () => {
const provider = Ganache.provider();
assert.ok(
isValidProvider(provider),
"Good provider should pass validation."
);
});
});
});

0 comments on commit dee370e

Please sign in to comment.