UNPKG

@agoric/zoe

Version:

Zoe: the Smart Contract Framework for Offer Enforcement

124 lines (113 loc) 3.79 kB
import { assert } from '@endo/errors'; import { makeIssuerKit, AssetKind, AmountMath } from '@agoric/ertp'; import { E } from '@endo/eventual-send'; import { Far } from '@endo/marshal'; import { notForProductionUse } from '@agoric/internal/src/magic-cookie-test-only.js'; /** * This contract mints non-fungible tokens and creates a selling contract * instance to sell the tokens in exchange for some sort of money. * * startInstance() returns a creatorFacet which is a * ticketMaker with a `.sellTokens()` method. `.sellTokens()` takes a * specification of what is being sold, such as: * { * customValueProperties: { ...arbitrary }, * count: 3n, * moneyIssuer: moolaIssuer, * sellItemsInstallationHandle, * pricePerItem: AmountMath.make(moolaBrand, 20n), * } * The payouts are returned as an offerResult in the `outcome`, and an API that * allows selling the tickets that were produced. You can reuse the ticket maker * to mint more tickets (e.g. for a separate show.) * * @param {ZCF<{ * tokenName: string, * }>} zcf */ const start = zcf => { notForProductionUse(); const { tokenName = 'token' } = zcf.getTerms(); // Create the internal token mint // makeIssuerKit fails upgrade, this contract is for demo only const { issuer, mint, brand } = makeIssuerKit(tokenName, AssetKind.SET); const zoeService = zcf.getZoeService(); /** * @param {object} obj * @param {Installation<import('./sellItems.js').start>} obj.sellItemsInstallation * @param {*} obj.customValueProperties * @param {number} obj.count * @param {*} obj.moneyIssuer * @param {*} obj.pricePerItem */ const sellTokens = ({ customValueProperties, count, moneyIssuer, sellItemsInstallation, pricePerItem, }) => { const tokenAmount = AmountMath.make( brand, harden( Array(count) .fill(undefined) .map((_, i) => { const tokenNumber = i + 1; return { ...customValueProperties, number: tokenNumber, }; }), ), ); const tokenPayment = mint.mintPayment(harden(tokenAmount)); // Note that the proposal `want` is empty // This is due to a current limitation in proposal // expressiveness: // https://github.com/Agoric/agoric-sdk/issues/855 // It's impossible to know in advance how many tokens will be // sold, so it's not possible to say `want: moola(3*22)` // In a future version of Zoe, it will be possible to express: // "I want n times moolas where n is the number of sold tokens" const proposal = harden({ give: { Items: tokenAmount }, }); const paymentKeywordRecord = harden({ Items: tokenPayment }); const issuerKeywordRecord = harden({ Items: issuer, Money: moneyIssuer, }); const sellItemsTerms = harden({ pricePerItem, }); const instanceRecordP = E(zoeService).startInstance( sellItemsInstallation, issuerKeywordRecord, sellItemsTerms, ); return instanceRecordP.then( ({ creatorInvitation, creatorFacet, instance, publicFacet }) => { assert(creatorInvitation); return E(zoeService) .offer(creatorInvitation, proposal, paymentKeywordRecord) .then(sellItemsCreatorSeat => { return harden({ sellItemsCreatorSeat, sellItemsCreatorFacet: creatorFacet, sellItemsInstance: instance, sellItemsPublicFacet: publicFacet, }); }); }, ); }; /** @type {MintAndSellNFTCreatorFacet} */ const creatorFacet = Far('creatorFacet', { sellTokens, getIssuer: () => issuer, }); return harden({ creatorFacet }); }; harden(start); export { start };