April 11, 2022
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!
{
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;
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";
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
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;
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.
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}
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