@@ -3,25 +3,13 @@ import yargs from "yargs";
3
3
import { hideBin } from "yargs/helpers" ;
4
4
import HDWalletProvider from "@truffle/hdwallet-provider" ;
5
5
import CoinFlipAbi from "./CoinFlipAbi.json" ;
6
- import axios from "axios" ;
7
6
8
- const argv = yargs ( hideBin ( process . argv ) )
7
+ const parser = yargs ( hideBin ( process . argv ) )
9
8
. option ( "private-key" , {
10
9
description : "Private key (as a hexadecimal string) of the sender" ,
11
10
type : "string" ,
12
11
required : true ,
13
12
} )
14
- . option ( "fortuna-url" , {
15
- description : "URL of the fortuna server for your chosen provider" ,
16
- type : "string" ,
17
- default : "https://fortuna-staging.dourolabs.app" ,
18
- } )
19
- . option ( "chain-name" , {
20
- description :
21
- "The name of your blockchain (for accessing data from fortuna)" ,
22
- type : "string" ,
23
- required : true ,
24
- } )
25
13
. option ( "address" , {
26
14
description : "The address of the CoinFlip contract" ,
27
15
type : "string" ,
@@ -37,37 +25,15 @@ const argv = yargs(hideBin(process.argv))
37
25
. alias ( "help" , "h" )
38
26
. parserConfiguration ( {
39
27
"parse-numbers" : false ,
40
- } )
41
- . parseSync ( ) ;
42
-
43
- const fortunaUrl = argv . fortunaUrl ;
44
- const chainName = argv . chainName ;
45
- const coinFlipContractAddress = argv . address ;
46
- const rpc = argv . rpcUrl ;
47
- const privateKey = argv . privateKey ;
48
-
49
- async function fetchWithRetry ( url : string , maxRetries : number ) : Promise < any > {
50
- let retryCount = 0 ;
51
-
52
- async function doRequest ( ) {
53
- try {
54
- const response = await axios . get ( url ) ;
55
- return response . data ;
56
- } catch ( error ) {
57
- if ( retryCount < maxRetries ) {
58
- retryCount ++ ;
59
- setTimeout ( doRequest , 1000 ) ;
60
- } else {
61
- console . error ( "Max retry attempts reached. Exiting." ) ;
62
- throw error ;
63
- }
64
- }
65
- }
66
-
67
- return await doRequest ( ) ; // Start the initial request
68
- }
28
+ } ) ;
69
29
70
30
async function main ( ) {
31
+ const argv = await parser . argv ;
32
+
33
+ const coinFlipContractAddress = argv . address ;
34
+ const rpc = argv . rpcUrl ;
35
+ const privateKey = argv . privateKey ;
36
+
71
37
const provider = new HDWalletProvider ( {
72
38
privateKeys : [ privateKey ] ,
73
39
providerOrUrl : rpc ,
@@ -84,38 +50,52 @@ async function main() {
84
50
85
51
console . log ( "1. Generating user's random number..." ) ;
86
52
const randomNumber = web3 . utils . randomHex ( 32 ) ;
87
- const commitment = web3 . utils . keccak256 ( randomNumber ) ;
88
53
console . log ( ` number : ${ randomNumber } ` ) ;
89
- console . log ( ` commitment: ${ commitment } ` ) ;
90
54
91
55
console . log ( "2. Requesting coin flip..." ) ;
92
56
const flipFee = await coinFlipContract . methods . getFlipFee ( ) . call ( ) ;
93
57
console . log ( ` fee : ${ flipFee } wei` ) ;
94
58
95
59
const receipt = await coinFlipContract . methods
96
- . requestFlip ( commitment )
60
+ . requestFlip ( randomNumber )
97
61
. send ( { value : flipFee , from : provider . getAddress ( 0 ) } ) ;
98
62
99
63
console . log ( ` tx : ${ receipt . transactionHash } ` ) ;
100
64
const sequenceNumber = receipt . events . FlipRequest . returnValues . sequenceNumber ;
101
65
console . log ( ` sequence : ${ sequenceNumber } ` ) ;
102
66
103
- console . log ( "3. Retrieving provider's random number..." ) ;
104
- const url = `${ fortunaUrl } /v1/chains/${ chainName } /revelations/${ sequenceNumber } ` ;
105
- console . log ( ` fetch url : ${ url } ` ) ;
106
- // Note that there is a potential race condition here: the server may not have observed the request ^
107
- // before this HTTP response. Hence, we retry fetching the url a couple of times.
108
- const response = await fetchWithRetry ( url , 3 ) ;
109
- const providerRandom = `0x${ response . value . data } ` ;
110
- console . log ( ` number : ${ providerRandom } ` ) ;
111
-
112
- console . log ( "4. Revealing the result of the coin flip..." ) ;
113
- const receipt2 = await coinFlipContract . methods
114
- . revealFlip ( sequenceNumber , randomNumber , providerRandom )
115
- . send ( { from : provider . getAddress ( 0 ) } ) ;
116
- console . log ( ` tx : ${ receipt2 . transactionHash } ` ) ;
117
- const isHeads = receipt2 . events . FlipResult . returnValues . isHeads ;
118
- console . log ( ` result : ${ isHeads ? "heads" : "tails" } ` ) ;
67
+ console . log ( "3. Waiting for result..." ) ;
68
+ // Poll for new FlipResult events emitted by the CoinFlip contract. It checks if the event
69
+ // has the same sequenceNumber as the request. If it does,
70
+ // it logs the result and stops polling.
71
+ let fromBlock = receipt . blockNumber ;
72
+ const intervalId = setInterval ( async ( ) => {
73
+ const currentBlock = await web3 . eth . getBlockNumber ( ) ;
74
+
75
+ if ( fromBlock > currentBlock ) {
76
+ return ;
77
+ }
78
+
79
+ // Get 'FlipResult' events emitted by the CoinFlip contract for given block range.
80
+ const events = await coinFlipContract . getPastEvents ( "FlipResult" , {
81
+ fromBlock : fromBlock ,
82
+ toBlock : currentBlock ,
83
+ } ) ;
84
+ fromBlock = currentBlock + 1 ;
85
+
86
+ // Find the event with the same sequence number as the request.
87
+ const event = events . find (
88
+ ( event ) => event . returnValues . sequenceNumber === sequenceNumber
89
+ ) ;
90
+
91
+ // If the event is found, log the result and stop polling.
92
+ if ( event !== undefined ) {
93
+ console . log (
94
+ ` result : ${ event . returnValues . isHeads ? "Heads" : "Tails" } `
95
+ ) ;
96
+ clearInterval ( intervalId ) ;
97
+ }
98
+ } , 1000 ) ;
119
99
120
100
provider . engine . stop ( ) ;
121
101
}
0 commit comments