-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support multiple api keys in hardhat-etherscan
The config has been extended to allow both a string as api key or an object that can contain multiple api keys, keyed by network. Relates to #1448.
- Loading branch information
Showing
8 changed files
with
183 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { NomicLabsHardhatPluginError } from "hardhat/src/plugins"; | ||
import { pluginName } from "./constants"; | ||
import { Networks, EtherscanConfig } from "./types"; | ||
|
||
const isNetworkKey = (network: string): network is Networks => { | ||
return network in Networks; | ||
}; | ||
|
||
const checkKey = (key: string | undefined): string => { | ||
if (key === undefined || key === "") { | ||
throw new NomicLabsHardhatPluginError( | ||
pluginName, | ||
`Please provide an Etherscan API token via hardhat config. | ||
E.g.: { [...], etherscan: { apiKey: 'an API key' }, [...] } | ||
See https://etherscan.io/apis` | ||
); | ||
} | ||
|
||
return key; | ||
}; | ||
|
||
const resolveEtherscanApiKey = ( | ||
etherscan: EtherscanConfig, | ||
network: string | ||
): string => { | ||
if (etherscan.apiKey === undefined || typeof etherscan.apiKey === "string") { | ||
return checkKey(etherscan.apiKey); | ||
} | ||
|
||
const apiKeys = etherscan.apiKey; | ||
|
||
if (!isNetworkKey(network)) { | ||
throw new NomicLabsHardhatPluginError( | ||
pluginName, | ||
`Unrecognized network: ${network}` | ||
); | ||
} | ||
|
||
const key = apiKeys[network]; | ||
|
||
return checkKey(key); | ||
}; | ||
|
||
export default resolveEtherscanApiKey; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,16 @@ | ||
export enum Networks { | ||
mainnet = "mainnet", | ||
rinkeby = "rinkeby", | ||
ropsten = "ropsten", | ||
polygon = "polygon", | ||
optimism = "optimism", | ||
optimismTestnet = "optimismTestnet", | ||
} | ||
|
||
export type EtherscanApiKeys = { | ||
[Network in Networks]?: string; | ||
}; | ||
|
||
export interface EtherscanConfig { | ||
apiKey?: string; | ||
apiKey?: string | EtherscanApiKeys; | ||
} |
2 changes: 2 additions & 0 deletions
2
...ardhat-etherscan/test/fixture-projects/hardhat-project-multiple-apikeys-config/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/cache | ||
/artifacts-dir |
12 changes: 12 additions & 0 deletions
12
.../test/fixture-projects/hardhat-project-multiple-apikeys-config/contracts/TestContract.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
pragma solidity 0.5.15; | ||
|
||
contract TestContract { | ||
|
||
uint amount; | ||
|
||
string message = "placeholder"; | ||
|
||
constructor(uint _amount) public { | ||
amount = _amount + 20; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
...etherscan/test/fixture-projects/hardhat-project-multiple-apikeys-config/hardhat.config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
require("../../../src/index"); | ||
|
||
module.exports = { | ||
etherscan: { | ||
apiKey: { | ||
mainnet: "mainnet-testtoken", | ||
ropsten: "ropsten-testtoken", | ||
}, | ||
}, | ||
solidity: { | ||
version: "0.5.15", | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { assert } from "chai"; | ||
import resolveEtherscanApiKey from "../src/resolveEtherscanApiKey"; | ||
import { EtherscanConfig } from "../src/types"; | ||
|
||
describe("Etherscan API Key resolution", () => { | ||
describe("provide one api key", () => { | ||
it("returns the api key no matter the network", () => { | ||
assert.equal( | ||
resolveEtherscanApiKey({ apiKey: "testtoken" }, "mainnet"), | ||
"testtoken" | ||
); | ||
|
||
assert.equal( | ||
resolveEtherscanApiKey({ apiKey: "testtoken" }, "rinkeby"), | ||
"testtoken" | ||
); | ||
}); | ||
}); | ||
|
||
describe("provide multiple api keys", () => { | ||
it("can retrieve different keys depending on --network", () => { | ||
const etherscanConfig: EtherscanConfig = { | ||
apiKey: { | ||
mainnet: "mainnet-testtoken", | ||
rinkeby: "rinkeby-testtoken", | ||
}, | ||
}; | ||
|
||
assert.equal( | ||
resolveEtherscanApiKey(etherscanConfig, "mainnet"), | ||
"mainnet-testtoken" | ||
); | ||
assert.equal( | ||
resolveEtherscanApiKey(etherscanConfig, "rinkeby"), | ||
"rinkeby-testtoken" | ||
); | ||
}); | ||
|
||
it("should throw if api key is for unrecognized network", () => { | ||
assert.throws(() => | ||
resolveEtherscanApiKey( | ||
// @ts-expect-error | ||
{ apiKey: { newthing: "testtoken" } }, | ||
"newthing" | ||
) | ||
); | ||
}); | ||
}); | ||
|
||
describe("provide no api key", () => { | ||
it("should throw if api key root is undefined", () => { | ||
assert.throws(() => | ||
resolveEtherscanApiKey({ apiKey: undefined }, "rinkeby") | ||
); | ||
}); | ||
|
||
it("should throw if api key root is empty string", () => { | ||
assert.throws(() => resolveEtherscanApiKey({ apiKey: "" }, "rinkeby")); | ||
}); | ||
|
||
it("should throw if network subkey is undefined", () => { | ||
assert.throws(() => | ||
resolveEtherscanApiKey({ apiKey: { rinkeby: undefined } }, "rinkeby") | ||
); | ||
}); | ||
|
||
it("should throw if network subkey is empty string", () => { | ||
assert.throws(() => | ||
resolveEtherscanApiKey({ apiKey: { rinkeby: "" } }, "rinkeby") | ||
); | ||
}); | ||
}); | ||
}); |