From 4c158a62344170db79e9550630386b436f120404 Mon Sep 17 00:00:00 2001 From: Intizar Tashov Date: Fri, 7 Jun 2024 15:27:26 +0900 Subject: [PATCH] add localhost options to hardhat config (#27) * add localhost options * fix linting errors * add localhost setup explanation in readme --- README.md | 3 +- hardhat.config.ts | 10 ++- scripts/performance-test-seq.ts | 141 +++++++++++++++++--------------- scripts/performance-test.ts | 106 ++++++++++++------------ scripts/utils.ts | 2 + 5 files changed, 139 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index 0892b35..e3bf91d 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ yarn compile npx hardhat deploy --network baobab ``` +If you are using [orakl-repository](https://github.com/Bisonai/orakl/) to run a local node, you can also deploy this `VRFConsumer` on your local node. The `Prepayment` and `VRFCoordinator` addresses in [hardhat.config.ts](hardhat.config.ts) `namedAccounts` and `keyHash` in [utils.ts](scripts/utils.ts) are configured properly to be used locally. + ## Get Estimated Service Fee Prior to creating an account, you have the option to retrieve the estimated service fee for a single VRF request. To do this, you can run the provided script using the following command: @@ -105,7 +107,6 @@ After setting the `ACC_ID` in `.env` file, you can move to the next step **Reque If you'd like to use your existing prepayment account, set your account id in the `.env` file and add your deployed consumer to your account by executing the hardhat `addConsumer` task (described in more detail below). Note that providing `account-id` parameter is optional if your account id is already in the `.env` file and `consumer` parameter is also optional if you've deployed your consumer using hardhat under this repository. - ## Request & Read VRF Before running following scripts, one must deploy `VRFConsumer` smart contract. diff --git a/hardhat.config.ts b/hardhat.config.ts index 5e54357..b2be353 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -37,7 +37,9 @@ const config: HardhatUserConfig = { networks: { localhost: { gas: 1_400_000, - gasPrice: 250_000_000_000 + gasPrice: 250_000_000_000, + ...commonConfig, + url: process.env.PROVIDER || 'http://127.0.0.1:8545' }, baobab: { url: process.env.PROVIDER || 'https://api.baobab.klaytn.net:8651', @@ -57,11 +59,13 @@ const config: HardhatUserConfig = { }, prepayment: { baobab: '0x8d3A1663d10eEb0bC9C9e537e1BBeA69383194e7', - cypress: '0xc2C88492Cf7e5240C3EB49353539E75336960600' + cypress: '0xc2C88492Cf7e5240C3EB49353539E75336960600', + localhost: '0x5FbDB2315678afecb367f032d93F642f64180aa3' }, vrfCoordinator: { baobab: '0xDA8c0A00A372503aa6EC80f9b29Cc97C454bE499', - cypress: '0x3F247f70DC083A2907B8E76635986fd09AA80EFb' + cypress: '0x3F247f70DC083A2907B8E76635986fd09AA80EFb', + localhost: '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512' } } } diff --git a/scripts/performance-test-seq.ts b/scripts/performance-test-seq.ts index b8c4a05..6f1a87d 100644 --- a/scripts/performance-test-seq.ts +++ b/scripts/performance-test-seq.ts @@ -7,88 +7,93 @@ const TOTAL_NUM_CALLS = 100 const RATE_LIMIT_PER_SECOND = 100 function delay(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)) } async function main() { - const vrfConsumer = await ethers.getContract('VRFConsumer') + const vrfConsumer = await ethers.getContract('VRFConsumer') - const keyHash = '0x47ede773ef09e40658e643fe79f8d1a27c0aa6eb7251749b268f829ea49f2024' - const callbackGasLimit = 500_000 - const numWords = 1 - const value = ethers.utils.parseEther('1.0') + const keyHash = '0x47ede773ef09e40658e643fe79f8d1a27c0aa6eb7251749b268f829ea49f2024' + const callbackGasLimit = 500_000 + const numWords = 1 + const value = ethers.utils.parseEther('1.0') - const providerUrl = 'https://baobab01.fautor.app' - const provider = new ethers.providers.JsonRpcProvider(providerUrl) + const providerUrl = 'https://baobab01.fautor.app' + const provider = new ethers.providers.JsonRpcProvider(providerUrl) - const signer = new ethers.Wallet('0d3046f718bad9413a30559bcb36e10c2c257ce83f760cb5f83bb676bb51a65b', provider) - const signerWithProvider = signer.connect(provider) - const nonceManager = new NonceManager(signerWithProvider) + const signer = new ethers.Wallet( + '0d3046f718bad9413a30559bcb36e10c2c257ce83f760cb5f83bb676bb51a65b', + provider + ) + const signerWithProvider = signer.connect(provider) + const nonceManager = new NonceManager(signerWithProvider) - const vrfConsumerNonce = new ethers.Contract( - vrfConsumer.address, - vrfConsumer.interface, - nonceManager - ) + const vrfConsumerNonce = new ethers.Contract( + vrfConsumer.address, + vrfConsumer.interface, + nonceManager + ) - const limiter = new Bottleneck({ - maxConcurrent: RATE_LIMIT_PER_SECOND, - minTime: 1000 / RATE_LIMIT_PER_SECOND - }) + const limiter = new Bottleneck({ + maxConcurrent: RATE_LIMIT_PER_SECOND, + minTime: 1000 / RATE_LIMIT_PER_SECOND + }) - const txResults = [] - for (let i = 1; i <= TOTAL_NUM_CALLS; i++) { - console.log(`Call ${i}`) - try { - await limiter.schedule(async () => { - const tx = await vrfConsumerNonce.requestRandomWordsDirect( - keyHash, - callbackGasLimit, - numWords, - { - value, - } - ) - const receipt = await tx.wait() - console.log(`Transaction ${i} mined: ${receipt.transactionHash}`) - // const requestId = await vrfConsumerNonce.sLastRequestId() - // console.log(`requestId for transaction ${i}: ${requestId}`) - // let attempts = 0 - // let randomWord - // while (attempts < 5) { - // try { - // randomWord = await vrfConsumerNonce.getRandomWord(requestId) - // if (randomWord != 0) { - // break - // } - // } catch (e) { - // console.log(`Attempt ${attempts + 1} failed: ${e.message}`) - // attempts++ - // await delay(20000) // wait 2 seconds before retrying - // } - // } - // console.log(`Random word for transaction ${i}: ${randomWord}`) - txResults.push({status: 'fulfilled', value: tx}) - }) - } catch (error) { - console.error(`Error in loop ${i}:`, error) - txResults.push({status: 'rejected', reason: error}) - } + const txResults = [] + for (let i = 1; i <= TOTAL_NUM_CALLS; i++) { + console.log(`Call ${i}`) + try { + await limiter.schedule(async () => { + const tx = await vrfConsumerNonce.requestRandomWordsDirect( + keyHash, + callbackGasLimit, + numWords, + { + value + } + ) + const receipt = await tx.wait() + console.log(`Transaction ${i} mined: ${receipt.transactionHash}`) + // const requestId = await vrfConsumerNonce.sLastRequestId() + // console.log(`requestId for transaction ${i}: ${requestId}`) + // let attempts = 0 + // let randomWord + // while (attempts < 5) { + // try { + // randomWord = await vrfConsumerNonce.getRandomWord(requestId) + // if (randomWord != 0) { + // break + // } + // } catch (e) { + // console.log(`Attempt ${attempts + 1} failed: ${e.message}`) + // attempts++ + // await delay(20000) // wait 2 seconds before retrying + // } + // } + // console.log(`Random word for transaction ${i}: ${randomWord}`) + txResults.push({ status: 'fulfilled', value: tx }) + }) + } catch (error) { + console.error(`Error in loop ${i}:`, error) + txResults.push({ status: 'rejected', reason: error }) + } - if (i < TOTAL_NUM_CALLS) { - await delay(WAIT_TIME_MS) - } + if (i < TOTAL_NUM_CALLS) { + await delay(WAIT_TIME_MS) } + } - const successfulTxs = txResults.filter((result) => result.status === 'fulfilled').map((result) => result.value) - const tps = successfulTxs.length / (TOTAL_NUM_CALLS * WAIT_TIME_MS / 1000) + const successfulTxs = txResults + .filter((result) => result.status === 'fulfilled') + .map((result) => result.value) + const tps = successfulTxs.length / ((TOTAL_NUM_CALLS * WAIT_TIME_MS) / 1000) - console.log(`Total transactions: ${TOTAL_NUM_CALLS}`) - console.log(`Successful transactions: ${successfulTxs.length}`) - console.log(`TPS: ${tps}`) + console.log(`Total transactions: ${TOTAL_NUM_CALLS}`) + console.log(`Successful transactions: ${successfulTxs.length}`) + console.log(`TPS: ${tps}`) } main().catch((error) => { - console.error(error) - process.exitCode = 1 + console.error(error) + process.exitCode = 1 }) diff --git a/scripts/performance-test.ts b/scripts/performance-test.ts index ed07111..ce69cdf 100644 --- a/scripts/performance-test.ts +++ b/scripts/performance-test.ts @@ -7,71 +7,75 @@ const TOTAL_NUM_CALLS = 300 const RATE_LIMIT_PER_SECOND = 200 async function main() { - const vrfConsumer = await ethers.getContract('VRFConsumer') + const vrfConsumer = await ethers.getContract('VRFConsumer') - const keyHash = '0x47ede773ef09e40658e643fe79f8d1a27c0aa6eb7251749b268f829ea49f2024' - const callbackGasLimit = 500_000 - const numWords = 1 - const value = ethers.utils.parseEther('1.0') + const keyHash = '0x47ede773ef09e40658e643fe79f8d1a27c0aa6eb7251749b268f829ea49f2024' + const callbackGasLimit = 500_000 + const numWords = 1 + const value = ethers.utils.parseEther('1.0') - const providerUrl = 'https://api.baobab.klaytn.net:8651' - const provider = new ethers.providers.JsonRpcProvider(providerUrl) + const providerUrl = 'https://api.baobab.klaytn.net:8651' + const provider = new ethers.providers.JsonRpcProvider(providerUrl) - const signer = new ethers.Wallet('0d3046f718bad9413a30559bcb36e10c2c257ce83f760cb5f83bb676bb51a65b', provider) - const signerWithProvider = signer.connect(provider) - const nonceManager = new NonceManager(signerWithProvider) + const signer = new ethers.Wallet( + '0d3046f718bad9413a30559bcb36e10c2c257ce83f760cb5f83bb676bb51a65b', + provider + ) + const signerWithProvider = signer.connect(provider) + const nonceManager = new NonceManager(signerWithProvider) - const vrfConsumerNonce = new ethers.Contract( - vrfConsumer.address, - vrfConsumer.interface, - nonceManager - ) + const vrfConsumerNonce = new ethers.Contract( + vrfConsumer.address, + vrfConsumer.interface, + nonceManager + ) - const limiter = new Bottleneck({ - maxConcurrent: RATE_LIMIT_PER_SECOND, - minTime: 1000 / RATE_LIMIT_PER_SECOND - }) + const limiter = new Bottleneck({ + maxConcurrent: RATE_LIMIT_PER_SECOND, + minTime: 1000 / RATE_LIMIT_PER_SECOND + }) - const txPromises = [] + const txPromises = [] - for (let i = 1; i <= TOTAL_NUM_CALLS; i++) { - console.log(`Call ${i}`) - try { - const txPromise = limiter.schedule(async () => { - const tx = await vrfConsumerNonce.requestRandomWordsDirect( - keyHash, - callbackGasLimit, - numWords, - { - value, - } - ) - return tx.wait() - }) - txPromises.push(txPromise) - } catch (error) { - console.error(`Error in loop ${i}:`, error) - } + for (let i = 1; i <= TOTAL_NUM_CALLS; i++) { + console.log(`Call ${i}`) + try { + const txPromise = limiter.schedule(async () => { + const tx = await vrfConsumerNonce.requestRandomWordsDirect( + keyHash, + callbackGasLimit, + numWords, + { + value + } + ) + return tx.wait() + }) + txPromises.push(txPromise) + } catch (error) { + console.error(`Error in loop ${i}:`, error) + } - if (i < TOTAL_NUM_CALLS) { - await new Promise((resolve) => setTimeout(resolve, WAIT_TIME_MS)) - } + if (i < TOTAL_NUM_CALLS) { + await new Promise((resolve) => setTimeout(resolve, WAIT_TIME_MS)) } + } - const txResults = await Promise.allSettled(txPromises) - const successfulTxs = txResults.filter((result) => result.status === 'fulfilled').map((result) => result.value) - const tps = successfulTxs.length / (TOTAL_NUM_CALLS * WAIT_TIME_MS / 1000) + const txResults = await Promise.allSettled(txPromises) + const successfulTxs = txResults + .filter((result) => result.status === 'fulfilled') + .map((result) => result.value) + const tps = successfulTxs.length / ((TOTAL_NUM_CALLS * WAIT_TIME_MS) / 1000) - console.log(`Total transactions: ${TOTAL_NUM_CALLS}`) - console.log(`Successful transactions: ${successfulTxs.length}`) - console.log(`TPS: ${tps}`) + console.log(`Total transactions: ${TOTAL_NUM_CALLS}`) + console.log(`Successful transactions: ${successfulTxs.length}`) + console.log(`TPS: ${tps}`) } main().catch((error) => { - console.error(error) - process.exitCode = 1 + console.error(error) + process.exitCode = 1 }) function delay(arg0: number) { - throw new Error('Function not implemented.') + throw new Error('Function not implemented.') } - diff --git a/scripts/utils.ts b/scripts/utils.ts index 443e848..76cf5dd 100644 --- a/scripts/utils.ts +++ b/scripts/utils.ts @@ -4,6 +4,8 @@ export function getKeyHash() { return '0xd9af33106d664a53cb9946df5cd81a30695f5b72224ee64e798b278af812779c' } else if (networkName == 'cypress') { return '0x6cff5233743b3c0321a19ae11ab38ae0ddc7ddfe1e91b162fa8bb657488fb157' + } else if (networkName == 'localhost') { + return '0xeaec8ebbc75ec18c1d761e4e11d2eab84392a55786264a3aa7385ab4532db1e4' } else { throw new Error(`Key Hash is not defined for network: ${networkName}`) }