import { useEffect, useState } from "preact/hooks"; import { Blockfrost, Constr, Data, fromText, Lucid } from "lucid/mod.ts"; import { Input } from "~/components/Input.tsx"; import { Button } from "~/components/Button.tsx"; import { AppliedValidators, applyParams, LocalCache, Validators, } from "~/utils.ts"; export interface AppProps { validators: Validators; } export default function App({ validators }: AppProps) { const [lucid, setLucid] = useState(null); const [blockfrostAPIKey, setBlockfrostAPIKey] = useState(""); const [tokenName, setTokenName] = useState(""); const [giftADA, setGiftADA] = useState(); const [lockTxHash, setLockTxHash] = useState(undefined); const [waitingLockTx, setWaitingLockTx] = useState(false); const [unlockTxHash, setUnlockTxHash] = useState( undefined, ); const [waitingUnlockTx, setWaitingUnlockTx] = useState(false); const [parameterizedContracts, setParameterizedContracts] = useState< AppliedValidators | null >(null); const setupLucid = async (e: Event) => { e.preventDefault(); const lucid = await Lucid.new( new Blockfrost( "https://cardano-preprod.blockfrost.io/api/v0", blockfrostAPIKey, ), "Preprod", ); const cache = localStorage.getItem("cache"); if (cache) { const { tokenName, giftADA, parameterizedValidators, lockTxHash, }: LocalCache = JSON.parse(cache); setTokenName(tokenName); setGiftADA(giftADA); setParameterizedContracts(parameterizedValidators); setLockTxHash(lockTxHash); } setLucid(lucid); }; useEffect(() => { if (lucid) { window.cardano .eternl .enable() .then((wallet) => { lucid.selectWallet(wallet); }); } }, [lucid]); const submitTokenName = async (e: Event) => { e.preventDefault(); const utxos = await lucid?.wallet.getUtxos()!; const utxo = utxos[0]; const outputReference = { txHash: utxo.txHash, outputIndex: utxo.outputIndex, }; const contracts = applyParams( tokenName, outputReference, validators, lucid!, ); setParameterizedContracts(contracts); }; const createGiftCard = async (e: Event) => { e.preventDefault(); setWaitingLockTx(true); try { const lovelace = Number(giftADA) * 1000000; const assetName = `${parameterizedContracts!.policyId}${ fromText(tokenName) }`; // Action::Mint const mintRedeemer = Data.to(new Constr(0, [])); const utxos = await lucid?.wallet.getUtxos()!; const utxo = utxos[0]; const tx = await lucid! .newTx() .collectFrom([utxo]) .attachMintingPolicy(parameterizedContracts!.giftCard) .mintAssets( { [assetName]: BigInt(1) }, mintRedeemer, ) .payToContract( parameterizedContracts!.lockAddress, { inline: Data.void() }, { "lovelace": BigInt(lovelace) }, ) .complete(); const txSigned = await tx.sign().complete(); const txHash = await txSigned.submit(); const success = await lucid!.awaitTx(txHash); // Wait a little bit longer so ExhaustedUTxOError doesn't happen // in the next Tx setTimeout(() => { setWaitingLockTx(false); if (success) { localStorage.setItem( "cache", JSON.stringify({ tokenName, giftADA, parameterizedValidators: parameterizedContracts, lockTxHash: txHash, }), ); setLockTxHash(txHash); } }, 3000); } catch { setWaitingLockTx(false); } }; const redeemGiftCard = async (e: Event) => { e.preventDefault(); setWaitingUnlockTx(true); try { const utxos = await lucid!.utxosAt(parameterizedContracts!.lockAddress); const assetName = `${parameterizedContracts!.policyId}${ fromText(tokenName) }`; // Action::Burn const burnRedeemer = Data.to(new Constr(1, [])); const tx = await lucid! .newTx() .collectFrom(utxos, Data.void()) .attachMintingPolicy(parameterizedContracts!.giftCard) .attachSpendingValidator(parameterizedContracts!.redeem) .mintAssets( { [assetName]: BigInt(-1) }, burnRedeemer, ) .complete(); const txSigned = await tx.sign().complete(); const txHash = await txSigned.submit(); const success = await lucid!.awaitTx(txHash); setWaitingUnlockTx(false); if (success) { localStorage.removeItem("cache"); setUnlockTxHash(txHash); } } catch { setWaitingUnlockTx(false); } }; return (
{!lucid ? (
setBlockfrostAPIKey(e.currentTarget.value)} > Blockfrost API Key
) : (
setTokenName(e.currentTarget.value)} > Token Name {tokenName && ( )}
)} {lucid && parameterizedContracts && ( <>

Redeem

            {parameterizedContracts.redeem.script}
          

Gift Card

            {parameterizedContracts.giftCard.script}
          
setGiftADA(e.currentTarget.value)} > ADA Amount {lockTxHash && ( <>

ADA Locked

{lockTxHash} )} {unlockTxHash && ( <>

ADA Unlocked

{unlockTxHash} )}
)}
); }