-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add 3 exercises for agoric-exercises
- Loading branch information
Showing
3 changed files
with
149 additions
and
40 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,59 @@ | ||
// @ts-check | ||
import { AmountMath, AmountShape, AssetKind } from '@agoric/ertp'; | ||
import { Far } from '@endo/far'; | ||
import '@agoric/zoe/exported.js'; | ||
import { M } from '@endo/patterns'; | ||
import { atomicRearrange } from '@agoric/zoe/src/contractSupport/atomicTransfer.js'; | ||
|
||
const greet = who => `Hello, ${who}!`; | ||
const { Fail, quote: q } = assert; | ||
|
||
export const start = () => { | ||
return { | ||
publicFacet: Far('Hello', { greet }), | ||
/** | ||
* @param {ZCF<{joinPrice: Amount}>} zcf | ||
*/ | ||
export const start = async zcf => { | ||
const gameSeat = zcf.makeEmptySeatKit().zcfSeat; | ||
// TODO: convert to COPY_BAG | ||
const ticketMint = await zcf.makeZCFMint('Ticket', AssetKind.NAT); | ||
|
||
const joinShape = harden({ | ||
give: { Price: AmountShape }, | ||
want: { Tickets: AmountShape }, | ||
exit: M.any(), | ||
}); | ||
|
||
/** @param {ZCFSeat} playerSeat */ | ||
const joinHandler = playerSeat => { | ||
const { give, want } = playerSeat.getProposal(); | ||
|
||
// TODO: update the checks here once AssetKind is converted to COPY_BAG | ||
AmountMath.isGTE( | ||
AmountMath.make(ticketMint.getIssuerRecord().brand, 1n), | ||
want.Tickets, | ||
) || Fail`${q(want.Tickets)} exceeds 1n ticket`; | ||
|
||
// mintGains mints all amounts in `want` | ||
// For more, see reference: | ||
// https://docs.agoric.com/reference/zoe-api/zcfmint.html#azcfmint-mintgains-gains-zcfseat | ||
const tmp = ticketMint.mintGains(want); | ||
// atomicRearrange rearrange the assets between seats | ||
atomicRearrange( | ||
zcf, | ||
harden([ | ||
[playerSeat, gameSeat, give], | ||
// TODO: add another TransferPart below to pass the exercise 3 test | ||
[tmp, playerSeat, want], | ||
]), | ||
); | ||
|
||
playerSeat.exit(true); | ||
return 'welcome to the game'; | ||
}; | ||
|
||
const publicFacet = Far('API', { | ||
makeJoinInvitation: () => | ||
zcf.makeInvitation(joinHandler, 'join', undefined, joinShape), | ||
}); | ||
|
||
return { publicFacet }; | ||
}; | ||
harden(start); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,101 @@ | ||
/** | ||
* @file Tests for agoric-basics-contract.js | ||
*/ | ||
|
||
// @ts-check | ||
import '@endo/init'; | ||
import { E } from '@endo/far'; | ||
|
||
// eslint-disable-next-line import/no-unresolved -- https://github.com/avajs/ava/issues/2951 | ||
import test from 'ava'; | ||
import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js'; | ||
|
||
import bundleSource from '@endo/bundle-source'; | ||
import { makeZoeKitForTest } from '@agoric/zoe/tools/setup-zoe.js'; | ||
import { E, passStyleOf } from '@endo/far'; | ||
import { createRequire } from 'module'; | ||
import { AmountMath, makeIssuerKit } from '@agoric/ertp'; | ||
|
||
test('exercise 1: bundleSource bundles the contract for use with zoe', async t => { | ||
const myRequire = createRequire(import.meta.url); | ||
const contractPath = myRequire.resolve(`../src/agoric-basics-contract.js`); | ||
|
||
// bundleSource() bundles contract and all of its modules into a single artifact | ||
// and is the first thing you need to do in order to deploy a contract | ||
// For more, see reference: https://docs.agoric.com/guides/zoe/#bundling-a-contract | ||
|
||
// TODO: initialize the const `bundle` using bundleSource() to pass the test below | ||
// Tips 1: you can import bundleSource() from @endo/bundle-source | ||
// Tips 2: don't forget to use `await` to get the fulfilled value | ||
const bundle = await bundleSource(contractPath); | ||
|
||
t.is(bundle.moduleFormat, 'endoZipBase64'); | ||
t.true(bundle.endoZipBase64.length > 10_000); | ||
}); | ||
|
||
test('exercise 2: start zoe instance', async t => { | ||
const myRequire = createRequire(import.meta.url); | ||
const contractPath = myRequire.resolve(`../src/agoric-basics-contract.js`); | ||
const bundle = await bundleSource(contractPath); | ||
const { zoeService: zoe } = makeZoeKitForTest(); | ||
const installation = await E(zoe).install(bundle); | ||
t.is(passStyleOf(installation), 'remotable'); | ||
|
||
const playMoney = makeIssuerKit('PlayMoney'); | ||
const playMoneyIssuer = { Price: playMoney.issuer }; | ||
const joinPrice = AmountMath.make(playMoney.brand, 5n); | ||
|
||
// startInstance creates an instance of the installed smart contract, with terms speicific to the instance | ||
// similar to how a JavaScript object is an instance of its class | ||
const { instance } = await E(zoe).startInstance( | ||
installation, | ||
playMoneyIssuer, | ||
{ | ||
// TODO: initialize the instance with the expected joinPrice to pass the test below | ||
joinPrice: joinPrice, | ||
}, | ||
); | ||
const terms = await E(zoe).getTerms(instance); | ||
|
||
t.is(terms.joinPrice, joinPrice); | ||
}); | ||
|
||
test('exercise 3: atomicRearrange', async t => { | ||
const myRequire = createRequire(import.meta.url); | ||
const contractPath = myRequire.resolve(`../src/agoric-basics-contract.js`); | ||
const bundle = await bundleSource(contractPath); | ||
const { zoeService: zoe } = makeZoeKitForTest(); | ||
const installation = await E(zoe).install(bundle); | ||
|
||
const playMoney = makeIssuerKit('PlayMoney'); | ||
const playMoneyIssuer = { Price: playMoney.issuer }; | ||
|
||
const { instance } = await E(zoe).startInstance( | ||
installation, | ||
playMoneyIssuer, | ||
{ | ||
joinPrice: AmountMath.make(playMoney.brand, 5n), | ||
}, | ||
); | ||
const publicFacet = await E(zoe).getPublicFacet(instance); | ||
const terms = await E(zoe).getTerms(instance); | ||
const alicePurse = playMoney.issuer.makeEmptyPurse(); | ||
const amountOfMoney = AmountMath.make(playMoney.brand, 5n); | ||
const moneyPayment = playMoney.mint.mintPayment(amountOfMoney); | ||
alicePurse.deposit(moneyPayment); | ||
|
||
const { issuers, brands, joinPrice } = terms; | ||
const proposal = { | ||
give: { Price: joinPrice }, | ||
want: { Tickets: AmountMath.make(brands.Ticket, 1n) }, | ||
}; | ||
|
||
const Price = await E(alicePurse).withdraw(joinPrice); | ||
|
||
import { start } from '../src/agoric-basics-contract.js'; | ||
const toJoin = E(publicFacet).makeJoinInvitation(); | ||
|
||
test('contract greets by name', async t => { | ||
const { publicFacet } = start(); | ||
const actual = await E(publicFacet).greet('Bob'); | ||
t.is(actual, 'Hello, Bob!'); | ||
const seat = E(zoe).offer(toJoin, proposal, { Price }); | ||
const tickets = await E(seat).getPayout('Tickets'); | ||
const actual = await E(issuers.Ticket).getAmountOf(tickets); | ||
// How do we complete the trade, i.e deduct the amount from alice's purse and mint her a ticket? | ||
// Hint: use atomicRearrange() | ||
// TODO: update atomicRearrange in agoric-basics-contract.js | ||
t.deepEqual(actual, proposal.want.Tickets); | ||
}); |
This file was deleted.
Oops, something went wrong.