How to Generate Randomness Using Chainlink with the Hyperverse

April 11, 2022

What is Chainlink and why should I care?

Chainlink is one of the most popular oracles in the ecosystem. Oracles are entities that connect blockchains to external systems, enabling smart contracts to access real-world data. Essentially, an oracle provides a bridge between on-chain and off-chain data to view stock/crypto prices, weather, sporting event scores, etc. One of the most important features it allows us to implement is randomness. Randomness is not possible to do on-chain without an oracle since the blockchain is deterministic by nature. So I will be showing you how to implement the random pick smart module within your Dapp to choose a random number!

What is Chainlink?

What is an Oracle?

Step 0: Build authentication in your Dapp and get hooked up to the Hyperverse

Step 1: Import the smart module

{

     bundle: RandomPick,

     tenantId: TENANT_ID,

}

Your end result should look something like this:

import "../styles/globals.css";

import type { AppProps } from "next/app";

import { initialize, Provider, Network } from "@decentology/hyperverse";

import { Ethereum } from "@decentology/hyperverse-ethereum";

import * as RandomPick from "@decentology/hyperverse-ethereum-randompick";

const TENANT_ID = "0x62a7aa79a52591Ccc62B71729329A80a666fA50f";

function MyApp({ Component, pageProps }: AppProps) {

   const hyperverse = initialize({

      blockchain: Ethereum,

      network: Network.Testnet,

     modules: [

        {

            bundle: RandomPick,

            tenantId: TENANT_ID,

        },

     ],

});

return (

    <Provider initialState={hyperverse}>

        <Component {...pageProps} />

    </Provider>

   );

}

export default MyApp;

Step 2: Import useRandomPick

In your index.tsx file we will import the useRandomPick hook to get access to all the smart module functionality.

Add this line of code to the top of the file:

import { useRandomPick } from "@decentology/hyperverse-ethereum-randompick";

Step 3: Extract the functionality we want

Add these lines of code right before the return:

const { StartRandomPick, GetRandomPick } = useRandomPick();

const {

   mutate: randomMutate,

   data: requestId,

   isLoading: randomNumber,

} = StartRandomPick();

let { data: randomNumberPick, isLoading: loadingWinner } = GetRandomPick(requestId);

randomMutate function takes in an array of integers which will set off the request to Chainlink

randomNumberPick will hold the value of the returned random number

Step 4: Set up the random number winner structure

Add these lines before the return:

const [winner, setWinner] = useState<any>(null);

const isLoading = randomNumber || loadingWinner;

We will be using winner to display the random number that was chosen and we will be using isLoading to display to the user that we are waiting for the function to return a random number

If you have done all the steps so far, this is what your index.tsx file should look like:

import { useEthereum } from "@decentology/hyperverse-ethereum";

import { useRandomPick } from "@decentology/hyperverse-ethereum-randompick";

import type { NextPage } from "next";

import Head from "next/head";

import Image from "next/image";

import styles from "../styles/Home.module.css";

const Home: NextPage = () => {

   const { address, disconnect, connect, error } = useEthereum();

   const [winner, setWinner] = useState<any>(null);

   const { StartRandomPick, GetRandomPick } = useRandomPick();

   const {

      mutate: randomMutate,

      data: requestId,

      isLoading: randomNumber,

} = StartRandomPick();

let { data: randomNumberPick, isLoading: loadingWinner } = GetRandomPick(requestId);

const isLoading = randomNumber || loadingWinner;

return (

   <div className={styles.container}>

      <Head>

          <title>Create Next App</title>

          <meta name="description" content="Generated by create next app" />

          <link rel="icon" href="/favicon.ico" />

      </Head>

      <main className={styles.main}>

          <h1 className={styles.title}>

              Welcome to <a href="<https://nextjs.org>">Next.js!</a>

          </h1>

         {!address ? (

            <button onClick={connect}>Connect Wallet</button>

         ) : (

            <button onClick={disconnect}>

               <span>{address}</span>

            </button>

         )}

     </main>

     <footer className={styles.footer}>

          <a

               href="<https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app>"

               target="_blank"

               rel="noopener noreferrer"

           >

               Powered by{" "}

                  <span className={styles.logo}>

                      <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />

                 </span>

           </a>

       </footer>

    </div>

   );

};

export default Home;

Step 5: Add the onClick functionality

Add these lines of code after the address button:

{!isLoading ? (

   <button

        onClick={() => fetchRandomNumber()}

        disabled={!address}

    >

        Start Random Picker

     </button>

) : (

      <button>Processing...</button>

)}

Here we are using HTML to build a button that says “Start Random Picker” when isLoading is false and otherwise shows “Processing...” We are also disabling the user from clicking the button unless they have connected their wallet to the Dapp.

Add this function before the return:

const fetchNFTs = async () => {

    setWinner(null);

    randomMutate([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

};

This function simply sets the winner to null and calls the randomMutate function passing in 10 integers.

Step 6: Show the random number

Add this before the fetchNFTs function:

useEffect(() => {

   if (randomNumberPick) {

      setWinner(randomNumberPick);

   }

}, [randomNumberPick]);

This sets the winner to the random number that is returned from GetRandomPick()

No we can simply add this line of code after the button we created above to show the random number if it exists:

{winner || null}

Step 7: Run yarn dev to see it in action!

Note: Make sure you are on the Rinkeby Test Network for it to work

The end result code should look something like this:

import { useEthereum } from "@decentology/hyperverse-ethereum";

import { useRandomPick } from "@decentology/hyperverse-ethereum-randompick";

import type { NextPage } from "next";

import Head from "next/head";

import Image from "next/image";

import styles from "../styles/Home.module.css";

const Home: NextPage = () => {

   const { address, disconnect, connect, error } = useEthereum();

   const [winner, setWinner] = useState<any>(null);

   const { StartRandomPick, GetRandomPick } = useRandomPick();

   const {

      mutate: randomMutate,

      data: requestId,

      isLoading: randomNumber,

} = StartRandomPick();

let { data: randomNumberPick, isLoading: loadingWinner } = GetRandomPick(requestId);

const isLoading = randomNumber || loadingWinner;

useEffect(() => {

   if (randomNumberPick) {

      setWinner(randomNumberPick);

   }

}, [randomNumberPick]);

const fetchNFTs = async () => {

   setWinner(null);

   randomMutate([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

};

return (

   <div className={styles.container}>

      <Head>

          <title>Create Next App</title>

          <meta name="description" content="Generated by create next app" />

          <link rel="icon" href="/favicon.ico" />

      </Head>

      <main className={styles.main}>

          <h1 className={styles.title}>

              Welcome to <a href="<https://nextjs.org>">Next.js!</a>

          </h1>

         {!address ? (

            <button onClick={connect}>Connect Wallet</button>

         ) : (

            <button onClick={disconnect}>

               <span>{address}</span>

            </button>

         )}

     </main>

     <footer className={styles.footer}>

          <a

               href="<https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app>"

               target="_blank"

               rel="noopener noreferrer"

           >

               Powered by{" "}

                  <span className={styles.logo}>

                      <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />

                 </span>

           </a>

       </footer>

    </div>

   );

};

export default Home;

LFG! 🚀  You should give yourself a pat on the back for completing this because that was a lot of reading

Next Steps: Build something of your own using this module and share it with us!

Inspiration: Here is a fully functional Dapp that shows a random NFT from the connected user’s wallet built using this smart module and OpenSea’s API!

GitHub Repo: https://github.com/ShainDholakiya/HyperverseStarterDapp-RandomPick