Get a Random Value from API
This section showcases how to get a random value inside a smart contract using Oraichain VRF 2.0

Prerequisite

Before integrating Oraichain VRF 2.0 into your tech stack, you need to install Oraichain cosmosjs library. Kindly follow the steps as demonstrated here.

Integration steps

For Back-end Usage

Step 1: Import Oraichain cosmosjs library

1
const Cosmos = require("@oraichain/cosmosjs").default;
2
3
const lcdUrl = "https://lcd.orai.io";
4
const chainId = "Oraichain";
5
const mnemonic = "foo bar";
6
const requestFees =100;
7
8
const message = Cosmos.message;
9
const cosmos = new Cosmos(lcdUrl, chainId);
10
const childKey = cosmos.getChildKey(mnemonic);
11
const sender = cosmos.getAddress(mnemonic);
12
13
cosmos.setBech32MainPrefix('orai');
Copied!

Step 2: Request a random transaction

1
const input = Buffer.from(
2
JSON.stringify({
3
request_random: {
4
input: btoa(userInput),
5
},
6
})
7
);
8
9
const txBody = getHandleMessage(contract, input, sender, requestFees);
10
const response = await cosmos.submit(childKey, txBody, "BROADCAST_MODE_BLOCK", isNaN(fees) ? 0 : parseInt(fees), gas);
Copied!
Enter a string value of your preference at userInput. You will see the fee for your request at requestFees. Also, maximum gas and tx fee need to be decided before each request.
In the unlikely case that your request takes too long to respond, try switching "BROADCAST_MODE_BLOCK" to "BROADCAST_MODE_SYNC", and use tx hash to query until it is included on-chain.
Regarding how to query tx hash, please refer to this example or this.

Step 3: Get a random round number

1
const round = response.tx_response.logs[0].events[1].attributes[3].value;
Copied!

Step 4: Get the information from a round

1
const queryRoundInput = JSON.stringify({
2
get_round: {round: parseInt(round)},
3
});
4
5
const roundOutput = await cosmos.get(`/wasm/v1beta1/contract
6
/${contract}/smart/${Buffer.from(queryRoundInput).toString("base64")}`);
Copied!
contract is the contract address of the VRF issued by Oraichain and can be reviewed on Oraiscan any time**.**
If the round result has not displayed the randomness output, you just need to wait for some time before querying again.

For browser usage

Step 1: Import Oraichain cosmosjs library

1
import Cosmos from "@oraichain/cosmosjs";
2
const lcdUrl = "https://lcd.orai.io";
3
const chainId = "Oraichain";
4
const requestFees = “100”;
5
6
const message = Cosmos.message;
7
const cosmos = new Cosmos(lcdUrl, chainId);
Copied!

Step 2: Import keystation for wallet use by creating a new js file

1
// @ts-nocheck
2
/* eslint-disable eqeqeq */
3
// Find Left Boundry of the Screen/Monitor
4
function FindLeftScreenBoundry() {
5
// Check if the window is off the primary monitor in a positive axis
6
// X,Y X,Y S = Screen, W = Window
7
// 0,0 ---------- 1280,0 ----------
8
// | | | --- |
9
// | | | | W | |
10
// | S | | --- S |
11
// ---------- ----------
12
if (window.leftWindowBoundry() > window.screen.width) {
13
return window.leftWindowBoundry() - (window.leftWindowBoundry() - window.screen.width);
14
}
15
16
// Check if the window is off the primary monitor in a negative axis
17
// X,Y X,Y S = Screen, W = Window
18
// 0,0 ---------- -1280,0 ----------
19
// | | | --- |
20
// | | | | W | |
21
// | S | | --- S |
22
// ---------- ----------
23
// This only works in Firefox at the moment due to a bug in Internet Explorer opening new windows into a negative axis
24
// However, you can move opened windows into a negative axis as a workaround
25
if (window.leftWindowBoundry() < 0 && window.leftWindowBoundry() > window.screen.width * -1) {
26
return window.screen.width * -1;
27
}
28
29
// If neither of the above, the monitor is on the primary monitor whose's screen X should be 0
30
return 0;
31
}
32
33
window.leftScreenBoundry = FindLeftScreenBoundry;
34
35
function PopupCenter(url, title, w, h) {
36
const newWindow = window.open(
37
url,
38
title,
39
"resizable=1, scrollbars=1, fullscreen=0, height=" +
40
h +
41
", width=" +
42
w +
43
", screenX=" +
44
window.leftScreenBoundry +
45
" , left=" +
46
window.leftScreenBoundry +
47
", toolbar=0, menubar=0, status=1"
48
);
49
return newWindow;
50
}
51
52
function openWindowV1(type, payload, account = "", self) {
53
console.log(`open ${self.client}`);
54
55
// The account parameter is required for users having multiple keychain accounts.
56
let apiUrl = "";
57
switch (type) {
58
case "signin":
59
apiUrl = "signin";
60
break;
61
case "transaction":
62
apiUrl = "tx";
63
break;
64
default:
65
apiUrl = "signin";
66
break;
67
}
68
69
return PopupCenter(
70
self.keystationUrl +
71
"/" +
72
apiUrl +
73
"?account=" +
74
encodeURIComponent(account) +
75
"&client=" +
76
encodeURIComponent(self.client) +
77
"&lcd=" +
78
encodeURIComponent(self.lcd) +
79
"&path=" +
80
encodeURIComponent(self.path) +
81
"&payload=" +
82
encodeURIComponent(JSON.stringify(payload)),
83
"",
84
"470",
85
"760"
86
);
87
}
88
89
function openWindowV2(type, payload, account = "", self) {
90
console.log(`open ${self.client}`);
91
92
// The account parameter is required for users having multiple keychain accounts.
93
let apiUrl = "";
94
switch (type) {
95
case "signin":
96
apiUrl = "signin";
97
break;
98
case "transaction":
99
apiUrl = "transaction";
100
break;
101
case "ai-request":
102
apiUrl = "ai_request/set";
103
break;
104
default:
105
apiUrl = "auth";
106
break;
107
}
108
109
const network = "Oraichain";
110
return PopupCenter(
111
self.keystationUrl +
112
"/" +
113
apiUrl +
114
"?lcd=" +
115
encodeURIComponent(self.lcd) +
116
"&raw_message=" +
117
encodeURIComponent(JSON.stringify(payload)) +
118
"&signInFromScan=true" +
119
"&network=" +
120
network,
121
"",
122
"470",
123
"760"
124
);
125
}
126
127
export default class Keystation {
128
constructor(params) {
129
if (!params) {
130
return;
131
}
132
const { client, lcd, path, keystationUrl } = params;
133
this.client = client;
134
this.lcd = lcd;
135
this.path = path;
136
137
this.keystationUrl = keystationUrl;
138
}
139
140
openWindow(type, payload, account = "") {
141
const self = this;
142
return process.env.REACT_APP_WALLET_VERSION == 2 ? openWindowV2(type, payload, account, self) : openWindowV1(type, payload, account, self);
143
}
144
}
145
146
export const myKeystation = new Keystation({
147
client: "https://api.wallet.orai.io",
148
lcd: "https://lcd.orai.io",
149
path: "44/118/0/0/0",
150
keystationUrl: "https://api.wallet.orai.io",
151
});
Copied!

Step 3: Create a randomness request

1
const input = Buffer.from(
2
JSON.stringify({
3
request_random: {
4
input: btoa(userInput),
5
},
6
})
7
);
8
9
const {privateKey, chainCode, network} = await getChildKey();
10
const childKey = fromPrivateKey(Buffer.from(privateKey), Buffer.from(chainCode), network);
11
12
const sender = cosmos.getAddress(childKey);
13
14
15
const txBody = getHandleMessage(contract, input, sender, requestFees);
16
const response = await cosmos.submit(childKey, txBody, "BROADCAST_MODE_BLOCK", isNaN(fees) ? 0 : parseInt(fees), gas);
Copied!
Function getChildKey() is as follow:
1
// const popup = window.open(`${config.walletapi}/auth?signInFromScan=true`, "", "resizable=1, scrollbars=1, fullscreen=0, width=470, height=760");
2
const popup = myKeystation.openWindow("auth", "");
3
4
return new Promise((resolve, reject) => {
5
const loop = setInterval(function() {
6
if (!popup) {
7
clearInterval(loop);
8
reject("window-blocked");
9
} else if (popup.closed) {
10
clearInterval(loop);
11
reject("window-closed");
12
}
13
}, 500);
14
const handler = e => {
15
if (e.data.privateKey && e.data.chainCode && e.data.network) {
16
clearInterval(loop);
17
window.removeEventListener("message", handler);
18
resolve(e.data);
19
}
20
};
21
window.addEventListener("message", handler);
22
});
23
};
Copied!

Step 4: Repeat the previously mentioned step 3 and 4 to get the random value and round information