Created
October 3, 2022 12:48
-
-
Save TheCyberWatchers/d77ece397cb2083b722c1d47954f6fc7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//index.mjs | |
import { loadStdlib, ask } from "@reach-sh/stdlib"; | |
import * as backend from './build/index.main.mjs'; | |
const stdlib = loadStdlib(); | |
const isAlice = await ask.ask( | |
`Are you Alice?`, | |
ask.yesno | |
); | |
const who = isAlice ? 'Alice' : 'Bob' | |
console.log(`Starting Rock, Paper, Scissors! as ${Who}`); | |
let acc = null; | |
const createAcc = await ask.ask( | |
`Would you like to create an account? (only possible on devnet)`, | |
ask.yesno | |
); | |
if(createAcc){ | |
acc = await stdlib.newTestAccount(stdlib.parseCurrency(1000)); | |
} else { | |
const secret = await ask.ask( | |
`What is your account secret?`, | |
(x => x) | |
); | |
acc = await stdlib.newAccountFromSecret(secret); | |
} | |
let ctc = null; | |
if(isAlice){ | |
ctc = acc.contract(backend); | |
ctc.getInfo().then((info) => { | |
console.log(`The contract is deployed as = ${JSON.stringify(info)}`);}); | |
} else { | |
const info = await ask.ask( | |
`Please paste the contract information:`, | |
JSON.parse | |
); | |
ctc = acc.contact(backend, info) | |
} | |
const fmt = (x) => stdlib.formatCurrency(x, 4); | |
const getBalance = async () => fmt(await stdlib.balanceOf(acc)); | |
const before = await getBalance(); | |
console.log(`Your balance is ${before}`) | |
const interact = { ...stdlib.hasRandom }; | |
interact.informTimeout = () => { | |
console.log(`There was a timeout.`); | |
process.exit(1); | |
}; | |
if (isAlice) { | |
const amt = await ask.ask( | |
`How much do you want to wager?`, | |
stdlib.parseCurrency | |
); | |
interact.wager = amt; | |
interact.deadline = { ETH: 100, ALGO: 100, CFX: 1000 }[stdlib.connector]; | |
} else { | |
interact.acceptWager = async (amt) => { | |
const accepted = await ask.ask( | |
`Do you accept the wager of ${fmt(amt)}?`, | |
ask.yesno | |
); | |
if(!accepted){ | |
process.exit(0); | |
} | |
}; | |
} | |
const HAND = ['Rock', 'Paper', 'Scissors']; | |
const HANDS = { | |
'Rock': 0, 'R': 0, 'r': 0, | |
'Paper': 1, 'P': 1, 'p': 1, | |
"Scissors": 2, 'S': 2, 's': 2, | |
}; | |
interact.getHand = async () => { | |
const hand = await ask.ask(`What hand will you play?`, (x) => { | |
const hand = HANDS[x]; | |
if (hand === undefined){ | |
throw Error(`Not a valid hand ${hand}`); | |
} | |
return hand; | |
}); | |
console.log(`You played ${HAND[hand]}`); | |
return hand; | |
}; | |
const OUTCOME = ['Bob wins', 'Draw', 'Alice wins']; | |
interact.seeOutcome = async (outcome) => { | |
console.log(`The outcome is: ${OUTCOME[outcome]}`); | |
}; | |
const part = isAlice ? ctc.p.Alice : ctc.p.Bob; | |
await part(interact); | |
const after = await getBalance(); | |
console.log(`Your balance is now ${after}`); | |
ask.done(); | |
//index.rsh | |
'reach 0.1'; | |
const [ isHand, ROCK, PAPER, SCISSORS ] = makeEnum(3); | |
const [ isOutcome, B_WINS, DRAW, A_WINS ] = makeEnum(3); | |
const winner = (handAlice, handBob) => | |
((handAlice + (4 - handBob)) % 3); | |
assert(winner(ROCK, PAPER) == B_WINS); | |
assert(winner(PAPER, ROCK) == A_WINS); | |
assert(winner(ROCK, ROCK) == DRAW); | |
forall(UInt, handAlice => | |
forall(UInt, handBob => | |
assert(isOutcome(winner(handAlice, handBob))))); | |
forall(UInt, (hand) => | |
assert(winner(hand, hand) == DRAW)); | |
const Player = { | |
...hasRandom, | |
getHand: Fun([], UInt), | |
seeOutcome: Fun([UInt], Null), | |
informTimeout: Fun([], Null), | |
}; | |
export const main = Reach.App(() => { | |
const Alice = Participant('Alice', { | |
...Player, | |
wager: UInt, // atomic units of currency | |
deadline: UInt, // time delta (blocks/rounds) | |
}); | |
const Bob = Participant('Bob', { | |
...Player, | |
acceptWager: Fun([UInt], Null), | |
}); | |
init(); | |
const informTimeout = () => { | |
each([Alice, Bob], () => { | |
interact.informTimeout(); | |
}); | |
}; | |
Alice.only(() => { | |
const wager = declassify(interact.wager); | |
const deadline = declassify(interact.deadline); | |
}); | |
Alice.publish(wager, deadline) | |
.pay(wager); | |
commit(); | |
Bob.only(() => { | |
interact.acceptWager(wager); | |
}); | |
Bob.pay(wager) | |
.timeout(relativeTime(deadline), () => closeTo(Alice, informTimeout)); | |
var outcome = DRAW; | |
invariant( balance() == 2 * wager && isOutcome(outcome) ); | |
while ( outcome == DRAW ) { | |
commit(); | |
Alice.only(() => { | |
const _handAlice = interact.getHand(); | |
const [_commitAlice, _saltAlice] = makeCommitment(interact, _handAlice); | |
const commitAlice = declassify(_commitAlice); | |
}); | |
Alice.publish(commitAlice) | |
.timeout(relativeTime(deadline), () => closeTo(Bob, informTimeout)); | |
commit(); | |
unknowable(Bob, Alice(_handAlice, _saltAlice)); | |
Bob.only(() => { | |
const handBob = declassify(interact.getHand()); | |
}); | |
Bob.publish(handBob) | |
.timeout(relativeTime(deadline), () => closeTo(Alice, informTimeout)); | |
commit(); | |
Alice.only(() => { | |
const saltAlice = declassify(_saltAlice); | |
const handAlice = declassify(_handAlice); | |
}); | |
Alice.publish(saltAlice, handAlice) | |
.timeout(relativeTime(deadline), () => closeTo(Bob, informTimeout)); | |
checkCommitment(commitAlice, saltAlice, handAlice); | |
outcome = winner(handAlice, handBob); | |
continue; | |
} | |
assert(outcome == A_WINS || outcome == B_WINS); | |
transfer(2 * wager).to(outcome == A_WINS ? Alice : Bob); | |
commit(); | |
each([Alice, Bob], () => { | |
interact.seeOutcome(outcome); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment