From 6c42c4d045db6af6875aab5130cbd4fea973c98e Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 13 Feb 2025 14:38:26 -0600 Subject: [PATCH 1/3] chore: rename sell contract to .ts --- ...ncert-tickets.contract.js => sell-concert-tickets.contract.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename contract/src/{sell-concert-tickets.contract.js => sell-concert-tickets.contract.ts} (100%) diff --git a/contract/src/sell-concert-tickets.contract.js b/contract/src/sell-concert-tickets.contract.ts similarity index 100% rename from contract/src/sell-concert-tickets.contract.js rename to contract/src/sell-concert-tickets.contract.ts From 7bdeb6778344a07a3b1d2d840bcc639054bcf98f Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 13 Feb 2025 14:21:25 -0600 Subject: [PATCH 2/3] chore: port sell-concert-tickets contract to .ts (WIP) feat: Convert JSDoc types to TypeScript in sell-concert-tickets.contract.ts refactor: Add Typescript type for Inventory and improve type annotations refactor: Convert JSDoc typedef to TypeScript type definition feat: Add comment to convert JSDoc types to TypeScript refactor: Convert JSDoc types to TypeScript in sell-concert-tickets contract --- contract/src/sell-concert-tickets.contract.ts | 81 ++++++++----------- 1 file changed, 35 insertions(+), 46 deletions(-) diff --git a/contract/src/sell-concert-tickets.contract.ts b/contract/src/sell-concert-tickets.contract.ts index aa6f6180..978f0132 100644 --- a/contract/src/sell-concert-tickets.contract.ts +++ b/contract/src/sell-concert-tickets.contract.ts @@ -17,57 +17,55 @@ * @see {@link https://docs.agoric.com/guides/js-programming/hardened-js.html|Hardened JavaScript} * for background on `harden` and `assert`. */ -// @ts-check import { Far } from '@endo/far'; -import { M, getCopyBagEntries, makeCopyBag } from '@endo/patterns'; +import { CopyBag, M, getCopyBagEntries, makeCopyBag } from '@endo/patterns'; import { AssetKind } from '@agoric/ertp/src/amountMath.js'; import { atomicRearrange } from '@agoric/zoe/src/contractSupport/atomicTransfer.js'; import { AmountMath, AmountShape } from '@agoric/ertp'; -/** - * @import {Amount, NatValue, Brand} from '@agoric/ertp/src/types.js'; - */ +/// + +import type { Amount, NatValue, Brand } from '@agoric/ertp/src/types.js'; + +type Inventory = { + [key: string]: { + tradePrice: { brand: Brand<'copyBag'>; value: CopyBag }; + maxTickets: NatValue; + }; +}; + const { Fail, quote: q } = assert; // #region bag utilities -/** - * - * @param {Amount} amount - * @param {number} n - * @returns {Amount} - */ -const multiply = (amount, n) => { +const multiply = (amount: Amount, n: number): Amount => { const arr = Array.from({ length: n }); return arr.reduce( - (sum, _) => AmountMath.add(amount, sum), + (sum: Amount, _) => AmountMath.add(amount, sum), AmountMath.make(amount.brand, 0n), ); }; -/** - * - * @param {Amount} sum - * @param {[string, bigint]} entry - * @param {Inventory} inventory - * @returns {Amount} - */ -const addMultiples = (sum, entry, inventory) => { - const multiple = multiply(inventory[entry[0]].tradePrice, Number(entry[1])); +const addMultiples = ( + sum: Amount<'nat'>, + entry: [string, bigint], + inventory: Inventory, +): Amount<'nat'> => { + const multiple = multiply( + inventory[entry[0]].tradePrice, + Number(entry[1]), + ) as Amount<'nat'>; return AmountMath.add(multiple, sum); }; -/** - * - * @param {import('@endo/patterns').CopyBag} bag - * @param {Inventory} inventory - * @returns {Amount} - */ -export const bagPrice = (bag, inventory) => { - const entries = /** @type {[string, bigint][]} */ (getCopyBagEntries(bag)); +export const bagPrice = ( + bag: import('@endo/patterns').CopyBag, + inventory: Inventory, +): Amount => { + const entries = getCopyBagEntries(bag) as [string, bigint][]; const values = Object.values(inventory); const brand = values[0].tradePrice.brand; - let finalAmount = /** @type {Amount} */ (AmountMath.makeEmpty(brand)); + let finalAmount = /** @type {Amount} */ AmountMath.makeEmpty(brand); for (const entry of entries) { finalAmount = addMultiples(finalAmount, entry, inventory); } @@ -85,22 +83,15 @@ harden(bagPrice); * maxTickets: 3n, * }, * } - * - * @typedef {{[key: string]: {tradePrice: {brand: Brand<"copyBag">, value: any}, maxTickets: NatValue}}} Inventory */ const InventoryShape = M.recordOf(M.string(), { tradePrice: AmountShape, maxTickets: M.nat(), }); -/** - * In addition to the standard `issuers` and `brands` terms, - * this contract is parameterized by terms for inventory - * - * @typedef {{ - * inventory: Inventory - * }} SellConcertTicketsTerms - */ +type SellConcertTicketsTerms = { + inventory: Inventory; +}; export const meta = harden({ customTermsShape: { inventory: InventoryShape }, @@ -114,10 +105,9 @@ harden(customTermsShape); * Start a contract that * - creates a new semi-fungible asset type for Tickets, and * - handles offers to buy as many tickets as inventory allows - * - * @param {ZCF} zcf + * @param zcf */ -export const start = async zcf => { +export const start = async (zcf: ZCF) => { const { inventory } = zcf.getTerms(); const inventoryValues = Object.values(inventory); @@ -174,8 +164,7 @@ export const start = async zcf => { /** a seat for allocating proceeds of sales */ const proceeds = zcf.makeEmptySeatKit().zcfSeat; - /** @type {OfferHandler} */ - const tradeHandler = buyerSeat => { + const tradeHandler: OfferHandler = buyerSeat => { // give and want are guaranteed by Zoe to match proposalShape const { give, want } = buyerSeat.getProposal(); From 91a5bca1cfcfb037614e17370727412868714ccf Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Thu, 13 Feb 2025 14:35:05 -0600 Subject: [PATCH 3/3] test: update test to use .ts contract (WIP) importing from the contract isn't working --- contract/test/test-sell-concert-tickets-contract.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contract/test/test-sell-concert-tickets-contract.js b/contract/test/test-sell-concert-tickets-contract.js index 2a152ea9..25c25f02 100644 --- a/contract/test/test-sell-concert-tickets-contract.js +++ b/contract/test/test-sell-concert-tickets-contract.js @@ -44,7 +44,7 @@ import { extract } from '@agoric/vats/src/core/utils.js'; const myRequire = createRequire(import.meta.url); const contractPath = myRequire.resolve( - `../src/sell-concert-tickets.contract.js`, + `../src/sell-concert-tickets.contract.ts`, ); const test = /** @type {TestFn}} */ (anyTest);