Skip to content

Commit

Permalink
add localhost options to hardhat config (#27)
Browse files Browse the repository at this point in the history
* add localhost options

* fix linting errors

* add localhost setup explanation in readme
  • Loading branch information
Intizar-T authored Jun 7, 2024
1 parent 46675ae commit 4c158a6
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 123 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand Down
10 changes: 7 additions & 3 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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'
}
}
}
Expand Down
141 changes: 73 additions & 68 deletions scripts/performance-test-seq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
})
106 changes: 55 additions & 51 deletions scripts/performance-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {

Check warning on line 79 in scripts/performance-test.ts

View workflow job for this annotation

GitHub Actions / build

'delay' is defined but never used

Check warning on line 79 in scripts/performance-test.ts

View workflow job for this annotation

GitHub Actions / build

'arg0' is defined but never used
throw new Error('Function not implemented.')
throw new Error('Function not implemented.')
}

2 changes: 2 additions & 0 deletions scripts/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`)
}
Expand Down

0 comments on commit 4c158a6

Please sign in to comment.