JSPM

@randomizer.ai/realtime-client

0.1.6
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 8
  • Score
    100M100P100Q63342F
  • License GPL-3.0-or-later

Listen for Randomizer's VRF result previews in real-time

Package Exports

  • @randomizer.ai/realtime-client
  • @randomizer.ai/realtime-client/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@randomizer.ai/realtime-client) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Randomizer Sequencer Client

Listen for Randomizer VRF result previews in real-time, before they're verified on-chain.

You can update your user's interface using the real-time preview (e.g. show the result of a game, update balances, or show the NFT they're minting).

Result previews are extremely likely to be the final on-chain result, since the sequencer can submit the result if the beacon does not submit it in time.

Installation

npm i @randomizer.ai/realtime-client

Example

For a full example, see Realtime Coinflip Example Game.

Front-end

import { listenForPreview } from "@randomizer.ai/realtime-client";
import ethers from "ethers";

// See https://randomizer.ai/docs for contract addresses
// Using Randomizer's Arbitrum Goerli contract address here:
const RANDOMIZER_ADDRESS = "0x923096Da90a3b60eb7E12723fA2E1547BA9236Bc";

// Get the event fired by Randomizer that returns the request ID
// headsOrTails is a boolean
const flip = (headsOrTails) => {

  // Flip for tails
  await contract.flip(headsOrTails);
  const receipt = await tx.wait();

  // Get request ID from the transaction event emitted by the Randomizer contract
  let requestId;
  for (const event of receipt.events) {
    if (event.address === RANDOMIZER_ADDRESS) {
      // Convert event.args[0] (id) to number
      requestId = parseInt(event.topics[1]);
    }
  }

  // Listen for the real-time preview result fired by Randomizer's sequencer (returns a hex string)
  const seed = await listenForPreview(requestId);

  // Forward the result hex as a BigNumber to previewResult
  const result = (await $contracts.coinflip.previewResult(ethers.BigNumber.from(seed)));

  if(headsOrTails === result) {
    // Player won
  } else {
    // Player lost
  }

}

/* Additionally the UI should listen for on-chain FlipResult event and update the state accordingly */

Contract

interface IRandomizer {
    function request(uint256 callbackGasLimit) external returns (uint256);

    function clientWithdrawTo(address to, uint256 amount) external;
}

contract CoinFlip {
    struct CoinFlipGame {
        address player;
        bool prediction;
        bool result;
        uint256 seed;
    }

    event Flip(address indexed player, uint256 indexed id, bool prediction);

    event FlipResult(
        address indexed player,
        uint256 indexed id,
        uint256 seed,
        bool prediction,
        bool result
    );

    mapping(uint256 => CoinFlipGame) coinFlipGames;
    mapping(address => uint256[]) userToGames;
    mapping(uint256 => bool) gameToHeadsTails;

    IRandomizer private randomizer;

    constructor(address _randomizer) {
        randomizer = IRandomizer(_randomizer);
    }

    // Called by player to initiate a coinflip
    // Using randomizer's request id as the game id
    function flip(bool prediction) external {
        uint256 id = IRandomizer(randomizer).request(100000);
        userToGames[msg.sender].push(id);
        coinFlipGames[id] = CoinFlipGame(msg.sender, prediction, false, 0);
        emit Flip(msg.sender, id, prediction);
    }

    // Previews the outcome of a game based on the seed, used for realtime result previews sent by Randomizer Sequencer.
    function previewResult(bytes32 value) external pure returns (bool) {
        bool headsOrTails = (uint256(value) % 2 == 0);
        return headsOrTails;
    }

    // The callback function called by randomizer when the random bytes are ready
    function randomizerCallback(uint256 _id, bytes32 _value) external {
        require(
            msg.sender == address(randomizer),
            "Only the randomizer contract can call this function"
        );
        CoinFlipGame memory game = coinFlipGames[_id];
        uint256 seed = uint256(_value);
        game.seed = seed;
        bool headsOrTails = (seed % 2 == 0);
        game.result = headsOrTails;
        emit FlipResult(game.player, _id, seed, game.prediction, headsOrTails);
    }
}