-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Based on Aiken's Hello WOrld example. TODO: I couldn't get the redeem contract to be accepted by the network. We need to figure out why and update this example. Replaces the plutus part of #307
- Loading branch information
1 parent
bf34fe4
commit 8e6cfcb
Showing
1 changed file
with
139 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
--- | ||
sidebar_position: 2 | ||
--- | ||
|
||
# Aiken's Hello World Example | ||
|
||
Using Aiken's [hello world](https://aiken-lang.org/example--hello-world/basics) example we can see how to use datums and redeemers with the transaction builder. | ||
|
||
To deploy the contract datum we need to create an output to the contract with the datum attached like so: | ||
|
||
```rust | ||
let change_addr: Address = todo!("Add your change address here"); | ||
let sk1: PrivateKey = todo!("Add your own private key here that controls the input"); | ||
let sk2: PrivateKey = todo!("Add your own private key here for the contract's datum"); | ||
|
||
let mut tx_builder = make_tx_builder(); | ||
|
||
// input needed to pay for the tx | ||
tx_builder.add_input(SingleInputBuilder::new( | ||
TransactionInput::new( | ||
TransactionHash::from_hex("1665fc34e312445884d752a557e6b3499e1fc10228de77ca712b6bda9078ced7").unwrap(), | ||
0 | ||
), | ||
TransactionOutput::new( | ||
addr.clone(), | ||
Value::from(10000000000), | ||
Some(DatumOption::new_hash(contract_datum.hash())), | ||
None | ||
), | ||
).payment_key().unwrap())?; | ||
|
||
// contract created from bytes from the Plutus.json generated by Aiken | ||
let contract = PlutusV2Script::from_cbor_bytes(&hex::decode("58f2010000323232323232323222232325333008323232533300b002100114a06644646600200200644a66602200229404c8c94ccc040cdc78010028a511330040040013014002375c60240026eb0c038c03cc03cc03cc03cc03cc03cc03cc03cc020c008c020014dd71801180400399b8f375c6002600e00a91010d48656c6c6f2c20576f726c6421002300d00114984d958c94ccc020cdc3a400000226464a66601a601e0042930b1bae300d00130060041630060033253330073370e900000089919299980618070010a4c2c6eb8c030004c01401058c01400c8c014dd5000918019baa0015734aae7555cf2ab9f5742ae881").unwrap()).unwrap(); | ||
let contract_addr = EnterpriseAddress::new( | ||
change_addr.network_id().unwrap(), | ||
StakeCredential::new_script(contract.hash()), | ||
).to_address(); | ||
|
||
// contract datum | ||
let contract_datum = PlutusData::new_constr_plutus_data( | ||
ConstrPlutusData::new(0, vec![PlutusData::new_bytes(sk2.to_public().hash().to_raw_bytes().to_vec())]) | ||
); | ||
|
||
// send funds to the contract | ||
tx_builder.add_output(SingleOutputBuilderResult::new( | ||
TransactionOutput::new(contract_addr.clone(), Value::from(5000000000), None, None) | ||
)); | ||
|
||
let mut signed_tx_builder = tx_builder.build( | ||
ChangeSelectionAlgo::Default, | ||
&addr | ||
)?; | ||
|
||
let tx_hash = hash_transaction(&signed_tx_builder.body()); | ||
signed_tx_builder.add_vkey(make_vkey_witness(&tx_hash, &sk1)); | ||
let tx = signed_tx_builder.build_checked().unwrap(); | ||
``` | ||
|
||
After we've deployed this contract it is time to redeem it. | ||
|
||
```rust | ||
// contract / tx_builder / contract_datum are same as above | ||
|
||
let redeemer_datum = PlutusData::new_constr_plutus_data( | ||
ConstrPlutusData::new(0, vec![PlutusData::new_bytes("Hello, World!".as_bytes().to_vec())]) | ||
); | ||
|
||
tx_builder.add_input(SingleInputBuilder::new( | ||
TransactionInput::new( | ||
TransactionHash::from_hex("6079e89a1eeba9ef1d6a334f8edbf6029ff5299315a3fd55fce732da6a72fd9b").unwrap(), | ||
0 | ||
), | ||
TransactionOutput::new( | ||
addr.clone(), | ||
Value::from(7500000), | ||
None, | ||
None | ||
), | ||
).plutus_script( | ||
PartialPlutusWitness::new( | ||
PlutusScriptWitness::Script(contract.into()), | ||
redeemer_datum.clone() | ||
), | ||
vec![sk1.to_public().hash(), sk2.to_public().hash()], | ||
contract_datum.clone(), | ||
).unwrap())?; | ||
|
||
// In order to run plutus contracts we must supply collateral which will only be spent if the contract does | ||
// not provide enough ADA specified via exunits to execute it. | ||
tx_builder.add_collateral(SingleInputBuilder::new( | ||
TransactionInput::new( | ||
TransactionHash::from_hex("5acebd1bc82df3d6c8f50908c1a182d5fb2ff0525066fa5a3ec44fe8df80f005").unwrap(), | ||
0, | ||
), | ||
TransactionOutput::new( | ||
addr.clone(), | ||
Value::from(5000000), | ||
None, | ||
None, | ||
), | ||
).payment_key().unwrap())?; | ||
let mut redeemer_builder = tx_builder.build_for_evaluation( | ||
ChangeSelectionAlgo::Default, | ||
&addr, | ||
)?; | ||
|
||
// We must then send this draft tx for evaluation via ogmios, blockfrost, etc | ||
// in order to figure out how many exunits are necessary to evaluate it | ||
println!("draft tx: {}", hex::encode(redeemer_builder.draft_tx()?.to_cbor_bytes())); | ||
|
||
// once we get the exunits required back we can set it and be ready to finalize the signing of the tx | ||
redeemer_builder.set_exunits( | ||
RedeemerWitnessKey::new(RedeemerTag::Spend, 0), | ||
ExUnits::new(5000000, 2000000000), | ||
); | ||
let redeemers = redeemer_builder.build()?; | ||
tx_builder.set_exunits( | ||
RedeemerWitnessKey::new(RedeemerTag::Spend, 0), | ||
ExUnits::new(5000000, 2000000000), | ||
); | ||
|
||
|
||
let mut signed_tx_builder = tx_builder.build( | ||
ChangeSelectionAlgo::Default, | ||
&addr | ||
)?; | ||
let tx_hash = hash_transaction(&signed_tx_builder.body()); | ||
signed_tx_builder | ||
.add_vkey(make_vkey_witness( | ||
&tx_hash, | ||
&sk1, | ||
)); | ||
signed_tx_builder | ||
.add_vkey(make_vkey_witness( | ||
&tx_hash, | ||
&sk2, | ||
)); | ||
let tx = signed_tx_builder.build_checked().unwrap(); | ||
``` |