Skip to main content

Web2 API

Info

This API enables you to use our RNG in a Web2 context, like a React backend for example. If you need to call our RNG from a smart contract, use the Web3 API instead.

Introduction

Requesting randomness on Random.win consists of deploying a random draw request onchain.

Once the request is fulfilled and the random numbers are generated, you are automatically notified, and can export these numbers offchain to use them in your app.

1. Get an Ethereum wallet

Skip this step if you already have an Ethereum wallet.

Otherwise, choose one of the available wallets or ask us to create a wallet for you. We personnaly recommend the Rabby wallet which is quite popular and super simple to use.

2. Request randomness

The main benefit of an onchain RNG is to let the users of your app verify your randomness onchain.

This is the purpose of a blockchain explorer such as Arbiscan. Anyone can go to the Arbiscan website, search for our contract address, and verify the random numbers for a particular request.

However, we recognize that this process can seem tedious if your users are not familiar with blockchain. This is why if you prefer, we can generate a user-friendly verification page on our domain verify.win (see example). We can even customize this page with your own company logo and design. Then, the only thing you'll have to do is to share this page's URL with your users.

Learn more about verification.

Choose whether you want a verification page or not, and then proceed to the corresponding step.

info

Make sure to top up your account before making any request otherwise your request will fail.

If you choose Without a verification page, Arbitrum will also charge you about $0.01 worth of ETH on your own wallet for executing the transaction, so make sure your wallet isn't empty. This small fee does not happen if you choose With a verification page because in this case we are making the transaction on your behalf.

Without a verification page

When requesting randomness without a verification page you can directly call our smart contract.

Endpoint

The deployDraw function in our smart contract.

Parameters

  • numbers: The number of random numbers to generate. Maximum is 500. A number cannot be selected more than once, meaning that you have the guarantee that all random numbers will be different.
  • range: The maximum value of a random number. Can be up to 1,000,000. The minimum value of a random number is 1.
  • algorithm: The random draw algorithm to use. Use 0 for Ordered outcomes, 1 for Fisher-Yates, or 2 for Fisher-Yates (GLI-19 certified). If you don't know which one to choose we recommend you to use 0.
  • scheduledAt: The timestamp, in seconds, when the randomness generation will be triggered. It will take 5 more seconds after that for the randomness generation to complete. This parameter enables you to post a request onchain now but generate the randomness at a later date, which can be useful in some cases. Use 0 to ask for randomness immediately.

Response

  • cid: A unique identifier for your random draw. You can communicate this cid to your users for them to verify the random draw onchain. Learn more.

Example Code

Here's how to do it with Viem in a Typescript backend. If you're using a different programming language for your backend, please adapt the code to your language.

Typescript
import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts'
import { arbitrum } from 'viem/chains';
import mainContractAbi from './abi'; // See https://docs.random.win/faq#-what-is-an-abi-and-where-can-i-find-it-

const contractAddress = "<Our Main contract address>"; // See https://docs.random.win/contracts#main
const privateKey = "<Your Ethereum private key>"; /* This key is private,
NEVER share it with anyone, even us. If someone knows your private key,
he will have access to your funds on your Ethereum wallet AND your funds
on Random.win */

const publicClient = createPublicClient({
chain: arbitrum,
transport: http()
});

const walletClient = createWalletClient({
account: privateKeyToAccount(privateKey),
chain: arbitrum,
transport: http()
});

const numbers = 5; // We want to get 5 random numbers
const range = 100; // Ranging from 1 to 100 (included)
const algorithm = 0; // The random numbers will be displayed in ascending order
const scheduledAt = 0; // We want to trigger the randomness request now

const { request, result } = await publicClient.simulateContract({
address: contractAddress,
abi: mainContractAbi,
functionName: 'deployDraw',
args: [numbers, range, algorithm, scheduledAt],
account
});

/* As a good practice, you should always call `simulateContract` first
to make sure your request is properly made and will be accepted by the blockchain,
and then call `writeContract` to publish the request onchain.
If you don't call `writeContract` your request will never be published
and you won't get any randomness. */
await walletClient.writeContract(request);

const cid = result; // The result is your random draw identifier that we call cid
console.log(`Request ${cid} successfully published onchain. ✅`);

With a verification page

When requesting randomness with a verification page you need to make a POST request to our endpoint with the following parameters.

Endpoint

https://www.random.win/api/draw/deploy

Parameters

  • owner: Your Ethereum address
  • signature (autogenerated): The signature of your Ethereum address. A signature is a cryptographic proof which enables our API to be sure that you are the owner of this Ethereum address. It can be automaticaly generated by Viem, see code example below.
  • title: The title of the page that will be created for your draw
  • rules (optional): Description of the rules of the draw if any.
  • participants: What we call participants are the entities that you want to draw from. It can be either:
    • A list of participants with each participant separated by the delimiter \n, for example "John\nJack\nJoe" or "1\n2\n3\n4\n5\n6\n7\n8\n9". The maximum number of participants is 1,000,000.
    • Alternatively, you can set this parameter to the number of participants without specifying a list of participants, for example "3" instead of "John\nJack\nJoe", or "9" instead of "1\n2\n3\n4\n5\n6\n7\n8\n9".
  • numbers: The number of random numbers that will be generated, that is, the number of participants that will be randomly selected. Maximum is 500. Should be less or equal to the number of participants.
  • scheduledAt: The timestamp, in seconds, when the randomness generation will be triggered. It will take 5 more seconds after that for the randomness generation to complete. This parameter enables you to post a request onchain now but generate the randomness at a later date, which can be useful in some cases. Use 0 to ask for randomness immediately.
  • algorithm (optional): The random draw algorithm to use. Use 0 for Ordered outcomes, 1 for Fisher-Yates, or 2 for Fisher-Yates (GLI-19 certified). If you don't know which one to choose we recommend you to use 0. Default is 0.

Response

  • cid: A unique identifier for your random draw. You can communicate this cid to your users for them to verify the random draw. Learn more.

Example Code

Typescript
import { privateKeyToAccount } from 'viem/accounts'

const ethereumAddress = "<Your Ethereum address>";
const privateKey = "<Your Ethereum private key>"; /* This key is private,
NEVER share it with anyone, even us. If someone knows your private key,
he will have access to your funds on your Ethereum wallet AND your funds
on Random.win */

// Signature
const account = privateKeyToAccount(privateKey);
const signature = await account.signMessage({
message: ethereumAddress
});

// Request parameters
const params = {
owner: ethereumAddress,
signature: signature,
title: "Draw title",
participants: "John\nLara\nHugo",
numbers: 1,
scheduledAt: Math.floor(Date.now() / 1000) + 5*60, // trigger in 5 minutes
};

// Request
fetch("https://www.random.win/api/draw/deploy", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(params)
})
.then(res => res.json())
.then(data => {

// Response
const cid = data.response.cid;

if (cid) {
console.log("Successful deploy:", cid);
// Verification page accessible at https://verify.win/<cid>
}

if (data.error) {
console.error(data.error.message);
}

})
.catch(err => console.error(err));

3. Retrieve the randomness

Random numbers

Once a request is completed, meaning when the randomness has been generated and the random numbers are available for export, our smart contract will emit an event called DrawCompleted.

By listening to this event, you will be notified when your request is completed and will be able to retrieve the random numbers by calling the read-only function checkRandomNumbers(cid).

This transaction is free

A read-only function in an Ethereum contract can only read the state of the contract, and cannot make any changes to it. Therefore, they do not require any gas to be executed, and can be called by anyone for free.

Here's how to do it with Viem in a Typescript frontend. If you're using a different programming language for your frontend, please adapt the code to your language.

Typescript
import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
import mainContractAbi from './abi'; // See https://docs.random.win/faq#-what-is-an-abi-and-where-can-i-find-it-

const mainContractAddress = "<Our Main contract address>"; // See https://docs.random.win/contracts#main
const cid = "<Your random draw CID>";
const participants = ["John", "Lara", "Jack", "Joe", "Danny"]; // Let's say you requested 2 random numbers to randomly select 2 winners from this list of participants

// A client to interact with the Ethereum blockchain
const publicClient = createPublicClient({
chain: arbitrum,
transport: http()
});

// We wait until the request is completed
// This shouldn't take more than 5 seconds after the randomness generation was triggered onchain, which is the `scheduledAt` parameter you used when making the request
const unwatch = publicClient.watchContractEvent({
address: mainContractAddress,
abi: mainContractAbi,
eventName: 'DrawCompleted',
args: { cid: cid },
onLogs: (logs: any) => {
console.log(logs);
getRandomNumbers();
}
});

// `watchContractEvent` will only watch for future events
// So if your request was just completed a few seconds ago you won't be notified
// That's why you also have to call the function `isCompleted` to check if your request was completed in the past
const isCompleted = await publicClient.readContract({
address: mainContractAddress,
abi: mainContractAbi,
functionName: 'isCompleted',
args: [cid]
});


if (isCompleted as boolean) {

// If our request is already completed we can get the randomness now
getRandomNumbers();

}

async function getRandomNumbers(): Promise<void> {

unwatch(); // A request can only be completed once so we can stop listening for new events after it is completed

const response = await publicClient.readContract({
address: mainContractAddress,
abi: mainContractAbi,
functionName: 'checkRandomNumbers',
args: [cid]
});

const randomNumbers: number[] = response as number[]; // Convert the response to a number array type
console.log(`The random numbers for request ${cid} are: ${randomNumbers.join(", ")}`);
console.log(`The winners for this random draw are: ${randomNumbers.map(n => participants[n - 1]).join(", ")}`); // The minimum value of a random number is 1 so you need "n-1" to convert the number to an array index
// If randomNumbers = [2,4] then output will be "The winners are: Lara, Joe"
}
tip

If you know your request is already completed, you can just call checkRandomNumbers without listening to the DrawCompleted event and without calling isCompleted.

Raw randomness

Instead of getting the random numbers you can get the raw randomness for your request by calling the checkRawRandomness function.

Typescript
const rawRandomness = await publicClient.readContract({
address: mainContractAddress,
abi: mainContractAbi,
functionName: 'checkRawRandomness',
args: [cid]
});

console.log(`Raw randomness for CID ${cid} is ${rawRandomness as string}`);

Learn more about raw randomness.