update hello world codes
This commit is contained in:
parent
c3b07dfe83
commit
0b007b4405
|
@ -2,3 +2,5 @@ artifacts/
|
||||||
build/
|
build/
|
||||||
*.sk
|
*.sk
|
||||||
*.addr
|
*.addr
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
|
@ -1,33 +1,54 @@
|
||||||
# Hello, World!
|
# Hello, World!
|
||||||
|
|
||||||
An example of an Hello, World! contract using Aiken and [Lucid](https://github.com/spacebudz/lucid).
|
An example of an Hello, World! contract using Aiken and [Mesh](https://meshjs.dev/).
|
||||||
|
|
||||||
See the [full tutorial on aiken-lang.org](https://aiken-lang.org/getting-started/hello-world).
|
See the [full tutorial on aiken-lang.org](https://aiken-lang.org/example--hello-world/end-to-end/mesh).
|
||||||
|
|
||||||
## Building
|
## Setup
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
```
|
```
|
||||||
aiken build
|
aiken build
|
||||||
```
|
```
|
||||||
|
|
||||||
## Generating Credentials
|
### Initializing workspace
|
||||||
|
|
||||||
```
|
```
|
||||||
deno run --allow-net --allow-write generate-credentials.ts
|
npm init -y
|
||||||
|
npm install @meshsdk/core tsx
|
||||||
```
|
```
|
||||||
|
|
||||||
## Locking Funds
|
### Setup environment variables
|
||||||
|
|
||||||
|
```
|
||||||
|
export BLOCKFROST_PROJECT_ID=preprod...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Generating Credentials
|
||||||
|
|
||||||
|
```
|
||||||
|
npx tsx generate-credentials.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Locking Funds
|
||||||
|
|
||||||
> **Warning** Require `BLOCKFROST_API_KEY` environment variable to be set.
|
> **Warning** Require `BLOCKFROST_API_KEY` environment variable to be set.
|
||||||
|
|
||||||
```
|
```
|
||||||
deno run --allow-net --allow-read --allow-env hello_world-lock.ts
|
npx tsx lock.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
## Unlocking Funds
|
Successful transaction hash: `bfa4818940831dff961a2f097e1aef9bf626de744fd96abfd2be7d6b61afb270` (preprod)
|
||||||
|
|
||||||
|
### Unlocking Funds
|
||||||
|
|
||||||
> **Warning** Require `BLOCKFROST_API_KEY` environment variable to be set.
|
> **Warning** Require `BLOCKFROST_API_KEY` environment variable to be set.
|
||||||
|
|
||||||
```
|
```
|
||||||
deno run --allow-net --allow-read --allow-env hello_world-unlock.ts TRANSACTION_ID_FROM_LOCK
|
npx tsx unlock.ts TRANSACTION_ID_FROM_LOCK
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Successful transaction hash: `1f8f3abac70c3a71c6aa943b4b9a6ac002e63a69225eb59305c3cd663cda3dd7` (preprod)
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import fs from "node:fs";
|
||||||
|
import {
|
||||||
|
BlockfrostProvider,
|
||||||
|
MeshTxBuilder,
|
||||||
|
MeshWallet,
|
||||||
|
serializePlutusScript,
|
||||||
|
UTxO,
|
||||||
|
} from "@meshsdk/core";
|
||||||
|
import { applyParamsToScript } from "@meshsdk/core-csl";
|
||||||
|
import blueprint from "./plutus.json";
|
||||||
|
|
||||||
|
const blockchainProvider = new BlockfrostProvider(process.env.BLOCKFROST_PROJECT_ID!);
|
||||||
|
|
||||||
|
// wallet for signing transactions
|
||||||
|
export const wallet = new MeshWallet({
|
||||||
|
networkId: 0,
|
||||||
|
fetcher: blockchainProvider,
|
||||||
|
submitter: blockchainProvider,
|
||||||
|
key: {
|
||||||
|
type: "root",
|
||||||
|
bech32: fs.readFileSync("me.sk").toString(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export function getScript() {
|
||||||
|
const scriptCbor = applyParamsToScript(
|
||||||
|
blueprint.validators[0].compiledCode,
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const scriptAddr = serializePlutusScript(
|
||||||
|
{ code: scriptCbor, version: "V3" },
|
||||||
|
).address;
|
||||||
|
|
||||||
|
return { scriptCbor, scriptAddr };
|
||||||
|
}
|
||||||
|
|
||||||
|
// reusable function to get a transaction builder
|
||||||
|
export function getTxBuilder() {
|
||||||
|
return new MeshTxBuilder({
|
||||||
|
fetcher: blockchainProvider,
|
||||||
|
submitter: blockchainProvider,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// reusable function to get a UTxO by transaction hash
|
||||||
|
export async function getUtxoByTxHash(txHash: string): Promise<UTxO> {
|
||||||
|
const utxos = await blockchainProvider.fetchUTxOs(txHash);
|
||||||
|
if (utxos.length === 0) {
|
||||||
|
throw new Error("UTxO not found");
|
||||||
|
}
|
||||||
|
return utxos[0];
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import { Lucid } from "https://deno.land/x/lucid@0.8.3/mod.ts";
|
import { MeshWallet } from '@meshsdk/core';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
|
||||||
const lucid = await Lucid.new(undefined, "Preview");
|
const secret_key = MeshWallet.brew(true) as string;
|
||||||
|
|
||||||
const privateKey = lucid
|
fs.writeFileSync('me.sk', secret_key);
|
||||||
.utils
|
|
||||||
.generatePrivateKey();
|
|
||||||
await Deno.writeTextFile("key.sk", privateKey);
|
|
||||||
|
|
||||||
const address = await lucid
|
const wallet = new MeshWallet({
|
||||||
.selectWalletFromPrivateKey(privateKey)
|
networkId: 0,
|
||||||
.wallet
|
key: {
|
||||||
.address();
|
type: 'root',
|
||||||
await Deno.writeTextFile("key.addr", address);
|
bech32: secret_key,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync('me.addr', wallet.getUnusedAddresses()[0]);
|
|
@ -1,72 +0,0 @@
|
||||||
import {
|
|
||||||
Blockfrost,
|
|
||||||
Constr,
|
|
||||||
Data,
|
|
||||||
fromHex,
|
|
||||||
Lucid,
|
|
||||||
SpendingValidator,
|
|
||||||
toHex,
|
|
||||||
TxHash,
|
|
||||||
} from "https://deno.land/x/lucid@0.8.3/mod.ts";
|
|
||||||
import * as cbor from "https://deno.land/x/cbor@v1.4.1/index.js";
|
|
||||||
|
|
||||||
const lucid = await Lucid.new(
|
|
||||||
new Blockfrost(
|
|
||||||
"https://cardano-preview.blockfrost.io/api/v0",
|
|
||||||
Deno.env.get("BLOCKFROST_API_KEY"),
|
|
||||||
),
|
|
||||||
"Preview",
|
|
||||||
);
|
|
||||||
|
|
||||||
lucid.selectWalletFromPrivateKey(await Deno.readTextFile("./key.sk"));
|
|
||||||
|
|
||||||
const validator = await readValidator();
|
|
||||||
|
|
||||||
// --- Supporting functions
|
|
||||||
|
|
||||||
async function readValidator(): Promise<SpendingValidator> {
|
|
||||||
const validator = JSON
|
|
||||||
.parse(await Deno.readTextFile("plutus.json"))
|
|
||||||
.validators[0];
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: "PlutusV2",
|
|
||||||
script: toHex(cbor.encode(fromHex(validator.compiledCode))),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const publicKeyHash = lucid.utils
|
|
||||||
.getAddressDetails(await lucid.wallet.address())
|
|
||||||
.paymentCredential
|
|
||||||
?.hash;
|
|
||||||
|
|
||||||
const datum = Data.to(new Constr(0, [publicKeyHash]));
|
|
||||||
|
|
||||||
const txHash = await lock(1000000n, { into: validator, owner: datum });
|
|
||||||
|
|
||||||
await lucid.awaitTx(txHash);
|
|
||||||
|
|
||||||
console.log(`1 tADA locked into the contract at:
|
|
||||||
Tx ID: ${txHash}
|
|
||||||
Datum: ${datum}
|
|
||||||
`);
|
|
||||||
|
|
||||||
// --- Supporting functions
|
|
||||||
|
|
||||||
async function lock(
|
|
||||||
lovelace: bigint,
|
|
||||||
{ into, owner }: { into: SpendingValidator; owner: string },
|
|
||||||
): Promise<TxHash> {
|
|
||||||
const contractAddress = lucid.utils.validatorToAddress(into);
|
|
||||||
|
|
||||||
const tx = await lucid
|
|
||||||
.newTx()
|
|
||||||
.payToContract(contractAddress, { inline: owner }, { lovelace })
|
|
||||||
.complete();
|
|
||||||
|
|
||||||
const signedTx = await tx
|
|
||||||
.sign()
|
|
||||||
.complete();
|
|
||||||
|
|
||||||
return signedTx.submit();
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
import {
|
|
||||||
Blockfrost,
|
|
||||||
Constr,
|
|
||||||
Data,
|
|
||||||
fromHex,
|
|
||||||
Lucid,
|
|
||||||
OutRef,
|
|
||||||
Redeemer,
|
|
||||||
SpendingValidator,
|
|
||||||
toHex,
|
|
||||||
TxHash,
|
|
||||||
utf8ToHex,
|
|
||||||
} from "https://deno.land/x/lucid@0.8.3/mod.ts";
|
|
||||||
import * as cbor from "https://deno.land/x/cbor@v1.4.1/index.js";
|
|
||||||
|
|
||||||
const lucid = await Lucid.new(
|
|
||||||
new Blockfrost(
|
|
||||||
"https://cardano-preview.blockfrost.io/api/v0",
|
|
||||||
Deno.env.get("BLOCKFROST_API_KEY"),
|
|
||||||
),
|
|
||||||
"Preview",
|
|
||||||
);
|
|
||||||
|
|
||||||
lucid.selectWalletFromPrivateKey(await Deno.readTextFile("./key.sk"));
|
|
||||||
|
|
||||||
const validator = await readValidator();
|
|
||||||
|
|
||||||
const utxo: OutRef = { txHash: Deno.args[0], outputIndex: 0 };
|
|
||||||
|
|
||||||
const redeemer = Data.to(new Constr(0, [utf8ToHex("Hello, World!")]));
|
|
||||||
|
|
||||||
const unlockTxHash = await unlock(utxo, {
|
|
||||||
from: validator,
|
|
||||||
using: redeemer,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
await lucid.awaitTx(unlockTxHash);
|
|
||||||
|
|
||||||
console.log(`1 tADA unlocked from the contract
|
|
||||||
Tx ID: ${unlockTxHash}
|
|
||||||
Redeemer: ${redeemer}
|
|
||||||
`);
|
|
||||||
|
|
||||||
// --- Supporting functions
|
|
||||||
|
|
||||||
async function unlock(
|
|
||||||
ref: OutRef,
|
|
||||||
{ from, using }: { from: SpendingValidator; using: Redeemer },
|
|
||||||
): Promise<TxHash> {
|
|
||||||
const [utxo] = await lucid.utxosByOutRef([ref]);
|
|
||||||
|
|
||||||
const tx = await lucid
|
|
||||||
.newTx()
|
|
||||||
.collectFrom([utxo], using)
|
|
||||||
.addSigner(await lucid.wallet.address())
|
|
||||||
.attachSpendingValidator(from)
|
|
||||||
.complete();
|
|
||||||
|
|
||||||
const signedTx = await tx
|
|
||||||
.sign()
|
|
||||||
.complete();
|
|
||||||
|
|
||||||
return signedTx.submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readValidator(): Promise<SpendingValidator> {
|
|
||||||
const validator = JSON
|
|
||||||
.parse(await Deno.readTextFile("plutus.json"))
|
|
||||||
.validators[0];
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: "PlutusV2",
|
|
||||||
script: toHex(cbor.encode(fromHex(validator.compiledCode))),
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { Asset, deserializeAddress, mConStr0 } from "@meshsdk/core";
|
||||||
|
import { getScript, getTxBuilder, wallet } from "./common";
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// these are the assets we want to lock into the contract
|
||||||
|
const assets: Asset[] = [
|
||||||
|
{
|
||||||
|
unit: "lovelace",
|
||||||
|
quantity: "1000000",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// get utxo and wallet address
|
||||||
|
const utxos = await wallet.getUtxos();
|
||||||
|
const walletAddress = (await wallet.getUsedAddresses())[0];
|
||||||
|
|
||||||
|
const { scriptAddr } = getScript();
|
||||||
|
|
||||||
|
// hash of the public key of the wallet, to be used in the datum
|
||||||
|
const signerHash = deserializeAddress(walletAddress).pubKeyHash;
|
||||||
|
|
||||||
|
// build transaction with MeshTxBuilder
|
||||||
|
const txBuilder = getTxBuilder();
|
||||||
|
await txBuilder
|
||||||
|
.txOut(scriptAddr, assets) // send assets to the script address
|
||||||
|
.txOutDatumHashValue(mConStr0([signerHash])) // provide the datum where `"constructor": 0`
|
||||||
|
.changeAddress(walletAddress) // send change back to the wallet address
|
||||||
|
.selectUtxosFrom(utxos)
|
||||||
|
.setNetwork('preprod')
|
||||||
|
.complete();
|
||||||
|
const unsignedTx = txBuilder.txHex;
|
||||||
|
|
||||||
|
const signedTx = await wallet.signTx(unsignedTx);
|
||||||
|
const txHash = await wallet.submitTx(signedTx);
|
||||||
|
console.log(`1 tADA locked into the contract at Tx ID: ${txHash}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import {
|
||||||
|
deserializeAddress,
|
||||||
|
mConStr0,
|
||||||
|
stringToHex,
|
||||||
|
} from "@meshsdk/core";
|
||||||
|
import { getScript, getTxBuilder, getUtxoByTxHash, wallet } from "./common";
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// get utxo, collateral and address from wallet
|
||||||
|
const utxos = await wallet.getUtxos();
|
||||||
|
const walletAddress = (await wallet.getUsedAddresses())[0];
|
||||||
|
const collateral = (await wallet.getCollateral())[0];
|
||||||
|
|
||||||
|
const { scriptCbor } = getScript();
|
||||||
|
|
||||||
|
// hash of the public key of the wallet, to be used in the datum
|
||||||
|
const signerHash = deserializeAddress(walletAddress).pubKeyHash;
|
||||||
|
// redeemer value to unlock the funds
|
||||||
|
const message = "Hello, World!";
|
||||||
|
|
||||||
|
// get the utxo from the script address of the locked funds
|
||||||
|
const txHashFromDesposit = process.argv[2];
|
||||||
|
const scriptUtxo = await getUtxoByTxHash(txHashFromDesposit);
|
||||||
|
|
||||||
|
// build transaction with MeshTxBuilder
|
||||||
|
const txBuilder = getTxBuilder();
|
||||||
|
await txBuilder
|
||||||
|
.spendingPlutusScript("V3") // we used plutus v3
|
||||||
|
.txIn( // spend the utxo from the script address
|
||||||
|
scriptUtxo.input.txHash,
|
||||||
|
scriptUtxo.input.outputIndex,
|
||||||
|
scriptUtxo.output.amount,
|
||||||
|
scriptUtxo.output.address
|
||||||
|
)
|
||||||
|
.txInScript(scriptCbor)
|
||||||
|
.txInRedeemerValue(mConStr0([stringToHex(message)])) // provide the required redeemer value `Hello, World!`
|
||||||
|
.txInDatumValue(mConStr0([signerHash])) // only the owner of the wallet can unlock the funds
|
||||||
|
.requiredSignerHash(signerHash)
|
||||||
|
.changeAddress(walletAddress)
|
||||||
|
.txInCollateral(
|
||||||
|
collateral.input.txHash,
|
||||||
|
collateral.input.outputIndex,
|
||||||
|
collateral.output.amount,
|
||||||
|
collateral.output.address
|
||||||
|
)
|
||||||
|
.selectUtxosFrom(utxos)
|
||||||
|
.setNetwork('preprod')
|
||||||
|
.complete();
|
||||||
|
const unsignedTx = txBuilder.txHex;
|
||||||
|
|
||||||
|
const signedTx = await wallet.signTx(unsignedTx);
|
||||||
|
const txHash = await wallet.submitTx(signedTx);
|
||||||
|
console.log(`1 tADA unlocked from the contract at Tx ID: ${txHash}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
Loading…
Reference in New Issue