diff --git a/examples/one_shot/islands/App.tsx b/examples/one_shot/islands/App.tsx index e09bfc56..46fc4e05 100644 --- a/examples/one_shot/islands/App.tsx +++ b/examples/one_shot/islands/App.tsx @@ -1,10 +1,21 @@ import { useEffect, useState } from "preact/hooks"; -import { Blockfrost, Lucid } from "~/vendor/lucid@0.9.4/mod.ts"; +import { + Blockfrost, + Constr, + Data, + fromText, + Lucid, +} from "~/vendor/lucid@0.9.4/mod.ts"; import { Input } from "~/components/Input.tsx"; import { Button } from "~/components/Button.tsx"; -import { applyParams, Validators } from "~/utils.ts"; +import { + AppliedValidators, + applyParams, + LocalCache, + Validators, +} from "~/utils.ts"; export interface AppProps { validators: Validators; @@ -13,8 +24,15 @@ export interface AppProps { export default function App({ validators }: AppProps) { const [lucid, setLucid] = useState(null); 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< - { lock: string; mint: string } | null + AppliedValidators | null >(null); const setupLucid = async (blockfrostApiKey: string) => { @@ -26,6 +44,22 @@ export default function App({ validators }: AppProps) { "Mainnet", ); + 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); }; @@ -45,8 +79,6 @@ export default function App({ validators }: AppProps) { const utxos = await lucid?.wallet.getUtxos()!; - console.log(utxos); - const utxo = utxos[0]; const outputReference = { txHash: utxo.txHash, @@ -63,6 +95,105 @@ export default function App({ validators }: AppProps) { setParameterizedContracts(contracts); }; + const submitADAGift = async (e: Event) => { + e.preventDefault(); + + setWaitingLockTx(true); + + 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!.mint) + .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 ExhuastedUTxOError 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); + }; + + const submitRedeemADAGift = async (e: Event) => { + e.preventDefault(); + + setWaitingUnlockTx(true); + + 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!.mint) + .attachSpendingValidator(parameterizedContracts!.lock) + .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); + } + }; + return (
{!lucid @@ -88,6 +219,7 @@ export default function App({ validators }: AppProps) { type="text" name="tokenName" id="tokenName" + value={tokenName} onInput={(e) => setTokenName(e.currentTarget.value)} > Token Name @@ -100,17 +232,75 @@ export default function App({ validators }: AppProps) { )} )} - {parameterizedContracts && ( + {lucid && parameterizedContracts && ( <>

Lock

-            {parameterizedContracts.lock}
+            {parameterizedContracts.lock.script}
           

Mint

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

ADA Locked

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

ADA Unlocked

+ + + {unlockTxHash} + + + )} +
)}
diff --git a/examples/one_shot/utils.ts b/examples/one_shot/utils.ts index 94583ddd..0d68f0eb 100644 --- a/examples/one_shot/utils.ts +++ b/examples/one_shot/utils.ts @@ -1,9 +1,7 @@ import { applyDoubleCborEncoding, applyParamsToScript, - C, Constr, - Data, fromText, Lucid, MintingPolicy, @@ -18,6 +16,13 @@ export type Validators = { mint: MintingPolicy; }; +export type LocalCache = { + tokenName: string; + giftADA: string; + lockTxHash: string; + parameterizedValidators: AppliedValidators; +}; + export async function readValidators(): Promise { const blueprint: Blueprint = JSON.parse( await Deno.readTextFile("plutus.json"), @@ -47,12 +52,19 @@ export async function readValidators(): Promise { }; } +export type AppliedValidators = { + lock: SpendingValidator; + mint: MintingPolicy; + policyId: string; + lockAddress: string; +}; + export function applyParams( tokenName: string, outputReference: OutRef, validators: Validators, lucid: Lucid, -): { lock: string; mint: string } { +): AppliedValidators { const outRef = new Constr(0, [ new Constr(0, [outputReference.txHash]), BigInt(outputReference.outputIndex), @@ -63,15 +75,25 @@ export function applyParams( outRef, ]); - const policyId = lucid.utils.validatorToScriptHash(validators.mint); + const policyId = lucid.utils.validatorToScriptHash({ + type: "PlutusV2", + script: mint, + }); const lock = applyParamsToScript(validators.lock.script, [ fromText(tokenName), policyId, ]); + const lockAddress = lucid.utils.validatorToAddress({ + type: "PlutusV2", + script: lock, + }); + return { - lock: applyDoubleCborEncoding(lock), - mint: applyDoubleCborEncoding(mint), + lock: { type: "PlutusV2", script: applyDoubleCborEncoding(lock) }, + mint: { type: "PlutusV2", script: applyDoubleCborEncoding(mint) }, + policyId, + lockAddress, }; }