-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from wowica/add-ppp-mint-example
Added PPP example
- Loading branch information
Showing
4 changed files
with
167 additions
and
1 deletion.
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
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
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 |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// $ deno run -A run_ppp_emulation.ts | ||
import { | ||
Address, | ||
applyDoubleCborEncoding, | ||
applyParamsToScript, | ||
Constr, | ||
Data, | ||
Emulator, | ||
fromText, | ||
generatePrivateKey, | ||
Lucid, | ||
OutRef, | ||
PrivateKey, | ||
UTxO, | ||
} from "https://deno.land/x/lucid/mod.ts"; | ||
|
||
// Imports blueprint generated from `aiken build` | ||
// Blueprints CIP: https://cips.cardano.org/cips/cip57/ | ||
import blueprint from "./plutus.json" assert { type: "json" }; | ||
|
||
// Define wallets, balances and Custom network | ||
|
||
const privateKeyAlice = generatePrivateKey(); | ||
|
||
const addressAlice = await (await Lucid.new(undefined, "Custom")) | ||
.selectWalletFromPrivateKey(privateKeyAlice) | ||
.wallet.address(); | ||
|
||
const emulator = new Emulator([ | ||
{ | ||
address: addressAlice, | ||
assets: { lovelace: 100_000_000n }, | ||
}, | ||
]); | ||
|
||
const lucid = await Lucid.new(emulator); | ||
|
||
const nft = blueprint.validators.find((v) => v.title === "ppp_mint.nft_policy"); | ||
|
||
const tokenName = "JUNGLE-GIFT-CARD"; | ||
|
||
let policyId: string; | ||
let nftMintingPolicy: string; | ||
let assetName: string; | ||
|
||
const applyParamsToContract = (outputReference: OutRef) => { | ||
nftMintingPolicy = applyParamsToScript(nft?.compiledCode, [ | ||
outputReference, | ||
fromText(tokenName), | ||
]); | ||
|
||
policyId = lucid.utils.validatorToScriptHash({ | ||
type: "PlutusV2", | ||
script: nftMintingPolicy, | ||
}); | ||
|
||
assetName = `${policyId}${fromText(tokenName)}`; | ||
}; | ||
|
||
const mintNFT = async ( | ||
minterPrivateKey: PrivateKey, | ||
receiverAddress: Address, | ||
) => { | ||
const owner: Lucid = lucid.selectWalletFromPrivateKey(minterPrivateKey); | ||
const [utxo] = await owner.wallet.getUtxos(); | ||
|
||
const outRef: OutRef = new Constr(0, [ | ||
new Constr(0, [utxo.txHash]), | ||
BigInt(utxo.outputIndex), | ||
]); | ||
|
||
applyParamsToContract(outRef); | ||
|
||
const mintingPolicy = { | ||
type: "PlutusV2", | ||
script: applyDoubleCborEncoding(nftMintingPolicy), | ||
}; | ||
|
||
// Change this to > 1n and script will error | ||
const mintAmount = 1n; | ||
|
||
const txHash = await owner | ||
.newTx() | ||
.collectFrom([utxo]) | ||
// use the nft validator | ||
.attachMintingPolicy(mintingPolicy) | ||
// mint 1 of the asset | ||
.mintAssets({ [assetName]: mintAmount }, Data.void()) | ||
.payToAddress(receiverAddress, { [assetName]: mintAmount }) | ||
.complete() | ||
.then((tx) => tx.sign().complete()) | ||
.then((tx) => tx.submit()) | ||
.catch((e) => console.log(e)); | ||
|
||
console.log(txHash); | ||
}; | ||
|
||
console.log("Alice's balance before mint"); | ||
console.log(await getBalanceAtAddress(addressAlice)); | ||
|
||
await mintNFT(privateKeyAlice, addressAlice); | ||
emulator.awaitBlock(4); | ||
|
||
console.log("Alice's balance after mint"); | ||
console.log(await getBalanceAtAddress(addressAlice)); | ||
|
||
function getBalanceAtAddress(address: Address): Promise<UTxO> { | ||
return lucid.utxosAt(address); | ||
} |
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 |
---|---|---|
@@ -0,0 +1,26 @@ | ||
use aiken/dict.{to_pairs} | ||
use aiken/list | ||
use aiken/transaction.{Mint, OutputReference, ScriptContext, Transaction} | ||
use aiken/transaction/value.{from_minted_value, tokens} | ||
|
||
// NFT policy (same as week05's one) | ||
validator(utxo_ref: OutputReference, token_name: ByteArray) { | ||
fn nft_policy(_r: Data, ctx: ScriptContext) -> Bool { | ||
// Pattern-match to get policy_id and Fail if it's not a minting transaction | ||
expect Mint(policy_id) = ctx.purpose | ||
// Pattern-match to get the transaction inputs and minted values | ||
let ScriptContext { transaction: Transaction { inputs, mint, .. }, .. } = | ||
ctx | ||
// Pattern-match to get the minted tokens and Fail if it's not a single asset minted | ||
let asset_pairs = | ||
mint |> from_minted_value() |> tokens(policy_id) |> to_pairs() | ||
|
||
expect [Pair(asset_name, amount)] = asset_pairs | ||
|
||
// Check if the transaction consumes the utxo_ref passed as parameter | ||
let is_ouput_consumed = | ||
list.any(inputs, fn(input) { input.output_reference == utxo_ref }) | ||
// Final checks | ||
is_ouput_consumed? && (1 == amount)? && (asset_name == token_name)? | ||
} | ||
} |