latency_entropy_with_callback.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import yargs from "yargs";
  2. import { hideBin } from "yargs/helpers";
  3. import {
  4. DefaultStore,
  5. EvmChain,
  6. EvmEntropyContract,
  7. PrivateKey,
  8. toPrivateKey,
  9. } from "../src";
  10. import { COMMON_DEPLOY_OPTIONS, findEntropyContract } from "./common";
  11. const parser = yargs(hideBin(process.argv))
  12. .usage(
  13. "Requests a random number from an entropy contract and measures the\n" +
  14. "latency between request submission and fulfillment by the Fortuna keeper service.\n" +
  15. "Usage: $0 --private-key <private-key> --chain <chain-id> | --all-chains <testnet|mainnet>"
  16. )
  17. .options({
  18. chain: {
  19. type: "string",
  20. desc: "test latency for the contract on this chain",
  21. conflicts: "all-chains",
  22. },
  23. "all-chains": {
  24. type: "string",
  25. conflicts: "chain",
  26. choices: ["testnet", "mainnet"],
  27. desc: "test latency for all entropy contracts deployed either on mainnet or testnet",
  28. },
  29. "private-key": COMMON_DEPLOY_OPTIONS["private-key"],
  30. });
  31. async function testLatency(
  32. contract: EvmEntropyContract,
  33. privateKey: PrivateKey
  34. ) {
  35. const provider = await contract.getDefaultProvider();
  36. const userRandomNumber = contract.generateUserRandomNumber();
  37. const requestResponse = await contract.requestRandomness(
  38. userRandomNumber,
  39. provider,
  40. privateKey,
  41. true // with callback
  42. );
  43. console.log(`Request tx hash : ${requestResponse.transactionHash}`);
  44. // Read the sequence number for the request from the transaction events.
  45. const sequenceNumber =
  46. requestResponse.events.RequestedWithCallback.returnValues.sequenceNumber;
  47. console.log(`sequence : ${sequenceNumber}`);
  48. const startTime = Date.now();
  49. const fromBlock = requestResponse.blockNumber;
  50. const web3 = contract.chain.getWeb3();
  51. const entropyContract = contract.getContract();
  52. // eslint-disable-next-line no-constant-condition
  53. while (true) {
  54. await new Promise((resolve) => setTimeout(resolve, 1000));
  55. const currentBlock = await web3.eth.getBlockNumber();
  56. if (fromBlock > currentBlock) {
  57. continue;
  58. }
  59. const events = await entropyContract.getPastEvents("RevealedWithCallback", {
  60. fromBlock: fromBlock,
  61. toBlock: currentBlock,
  62. });
  63. const event = events.find(
  64. (event) => event.returnValues.request[1] == sequenceNumber
  65. );
  66. if (event !== undefined) {
  67. console.log(`Random number : ${event.returnValues.randomNumber}`);
  68. const endTime = Date.now();
  69. console.log(`Fortuna Latency : ${endTime - startTime}ms`);
  70. console.log(
  71. `Revealed after : ${
  72. currentBlock - requestResponse.blockNumber
  73. } blocks`
  74. );
  75. break;
  76. }
  77. if (Date.now() - startTime > 60000) {
  78. console.log("Timeout: 60s passed without the callback being called.");
  79. break;
  80. }
  81. }
  82. }
  83. async function main() {
  84. const argv = await parser.argv;
  85. if (!argv.chain && !argv["all-chains"]) {
  86. throw new Error("Must specify either --chain or --all-chains");
  87. }
  88. const privateKey = toPrivateKey(argv.privateKey);
  89. if (argv["all-chains"]) {
  90. for (const contract of Object.values(DefaultStore.entropy_contracts)) {
  91. if (
  92. contract.getChain().isMainnet() ===
  93. (argv["all-chains"] === "mainnet")
  94. ) {
  95. console.log(`Testing latency for ${contract.getId()}...`);
  96. await testLatency(contract, privateKey);
  97. }
  98. }
  99. } else if (argv.chain) {
  100. const chain = DefaultStore.getChainOrThrow(argv.chain, EvmChain);
  101. const contract = findEntropyContract(chain);
  102. await testLatency(contract, privateKey);
  103. }
  104. }
  105. main();