mod common;
use mesmo::Mesmo;
use common::*;
use serde_json::json;
#[test]
fn test_integration_managed_account_handle_sign_submit() {
if skip_if_no_devkit() {
return;
}
use mesmo::accounts::SigningRole;
let lib = Mesmo::new().expect("create lib");
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let utxos = devkit_get_utxos(INTENT_SENDER);
let pp = devnet_pp();
let built = lib
.quicktx()
.build(&read_fixture("stake_registration.yaml"), &utxos, &pp, None, 1)
.expect("build");
let acct = lib
.accounts()
.from_mnemonic(INTENT_MNEMONIC, mesmo::Network::Testnet, 0, 0)
.expect("open account");
let signed = acct
.sign_tx(&built.tx_cbor, SigningRole::PAYMENT | SigningRole::STAKE)
.expect("handle sign");
devkit_try_submit(&signed).expect("submit");
}
#[test]
fn test_integration_stake_registration() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
build_sign_submit(&lib, "stake_registration.yaml", None, &["payment", "stake"]);
}
#[test]
fn test_integration_drep_registration() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
build_sign_submit(&lib, "drep_registration.yaml", None, &["payment", "drep"]);
}
#[test]
fn test_integration_drep_key_required() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let u = devkit_get_utxos(INTENT_SENDER);
let built = lib
.quicktx()
.build(&read_fixture("drep_registration.yaml"), &u, &pp, None, 1)
.expect("build");
let signed_payment_only = intent_sign(&lib, &built.tx_cbor, &["payment"]);
if devkit_try_submit(&signed_payment_only).is_ok() {
panic!(
"the node accepted a DRep registration signed with the payment key only; \
expected rejection (MissingVKeyWitnessesUTXOW)"
);
}
}
#[test]
fn test_integration_donation() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let lib = Mesmo::new().expect("create lib");
let utxos = devkit_get_utxos(INTENT_SENDER);
let pp = devnet_pp();
let base_yaml = read_fixture("donation.yaml");
let mut treasury = String::from("0");
let mut last_err = String::new();
for _ in 0..5 {
let yaml = base_yaml.replace(
"current_treasury_value: 0",
&format!("current_treasury_value: {}", treasury),
);
let result = lib.quicktx().build(&yaml, &utxos, &pp, None, 0).expect("build");
let signed = intent_sign(&lib, &result.tx_cbor, &["payment"]);
match devkit_try_submit(&signed) {
Ok(tx_hash) => {
assert!(!tx_hash.is_empty(), "empty tx hash from submit");
return; }
Err(e) => {
last_err = e;
match parse_expected_treasury(&last_err) {
Some(v) => treasury = v,
None => panic!("unexpected submit error: {}", last_err),
}
}
}
}
panic!("donation submit failed after retries: {}", last_err);
}
#[test]
fn test_integration_info_proposal() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let utxos = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("stake_registration.yaml"), &utxos, &pp, None, &["payment", "stake"]);
wait_for_block();
let utxos2 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("governance_proposal.yaml"), &utxos2, &pp, None, &["payment"]);
}
#[test]
fn test_integration_metadata() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
build_sign_submit(&lib, "metadata.yaml", None, &["payment"]);
}
#[test]
fn test_integration_native_mint() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
build_sign_submit(&lib, "minting.yaml", None, &["payment"]);
assert_minted_asset_at(MINT_RECEIVER);
}
#[test]
fn test_integration_plutus_mint() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
let exec = plutus_exec_units();
build_sign_submit(&lib, "plutus/script_minting.yaml", Some(&exec), &["payment"]);
assert_minted_asset_at(MINT_RECEIVER);
}
#[test]
fn test_integration_voting_delegation() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
setup_then_submit(
&lib,
"stake_registration.yaml",
&["payment", "stake"],
"voting_delegation.yaml",
&["payment", "stake"],
);
}
#[test]
fn test_integration_drep_update() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
setup_then_submit(
&lib,
"drep_registration.yaml",
&["payment", "drep"],
"drep_update.yaml",
&["payment", "drep"],
);
}
#[test]
fn test_integration_drep_deregistration() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
setup_then_submit(
&lib,
"drep_registration.yaml",
&["payment", "drep"],
"drep_deregistration.yaml",
&["payment", "drep"],
);
}
#[test]
fn test_integration_stake_withdrawal() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let u = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("stake_registration.yaml"), &u, &pp, None, &["payment", "stake"]);
wait_for_block();
let u2 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("voting_delegation.yaml"), &u2, &pp, None, &["payment", "stake"]);
wait_for_block();
let u3 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("stake_withdrawal.yaml"), &u3, &pp, None, &["payment", "stake"]);
}
#[test]
fn test_integration_voting() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let u = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("drep_registration.yaml"), &u, &pp, None, &["payment", "drep"]);
wait_for_block();
let u2 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("stake_registration.yaml"), &u2, &pp, None, &["payment", "stake"]);
wait_for_block();
let u3 = devkit_get_utxos(INTENT_SENDER);
let proposal = lib
.quicktx()
.build(&read_fixture("governance_proposal.yaml"), &u3, &pp, None, 0)
.expect("build proposal");
let action_tx_hash = proposal.tx_hash.clone();
let signed_proposal = intent_sign(&lib, &proposal.tx_cbor, &["payment"]);
if let Err(e) = devkit_try_submit(&signed_proposal) {
panic!("submit proposal: {}", e);
}
wait_for_block();
let u4 = devkit_get_utxos(INTENT_SENDER);
let vote_yaml = read_fixture("voting.yaml").replace(GOV_ACTION_PLACEHOLDER, &action_tx_hash);
sign_submit(&lib, &vote_yaml, &u4, &pp, None, &["payment", "drep"]);
}
#[test]
fn test_integration_stake_delegation() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let u = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("stake_registration.yaml"), &u, &pp, None, &["payment", "stake"]);
wait_for_block();
let u2 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("pool_registration.yaml"), &u2, &pp, None, &["payment", "stake"]);
wait_for_block();
let u3 = devkit_get_utxos(INTENT_SENDER);
let deleg_yaml = read_fixture("stake_delegation.yaml").replace(POOL_PLACEHOLDER, ACCOUNT_POOL_ID);
sign_submit(&lib, &deleg_yaml, &u3, &pp, None, &["payment", "stake"]);
}
#[test]
fn test_integration_pool_registration() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
setup_then_submit(
&lib,
"stake_registration.yaml",
&["payment", "stake"],
"pool_registration.yaml",
&["payment", "stake"],
);
}
#[test]
fn test_integration_plutus_spend() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let utxos = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("plutus/plutus_lock.yaml"), &utxos, &pp, None, &["payment"]);
wait_for_block();
let script_utxos = devkit_get_utxos(SCRIPT_ADDR);
let locked = script_utxos
.as_array()
.and_then(|a| a.first())
.unwrap_or_else(|| panic!("no locked UTXO at script address"));
let lock_hash = locked["tx_hash"].as_str().expect("locked tx_hash").to_string();
let lock_idx = locked["output_index"].as_u64().unwrap_or(0);
let mut spend_yaml = read_fixture("plutus/script_collect_from.yaml").replace(SCRIPT_TX_HASH, &lock_hash);
if lock_idx != 0 {
spend_yaml = spend_yaml.replacen("output_index: 0", &format!("output_index: {}", lock_idx), 1);
}
let fee_utxos = devkit_get_utxos(INTENT_SENDER);
let mut spend_utxos = json!([{
"tx_hash": lock_hash,
"output_index": lock_idx,
"address": SCRIPT_ADDR,
"amount": [{"unit": "lovelace", "quantity": "10000000"}],
"data_hash": SCRIPT_DATUM_HASH,
}]);
if let (Some(arr), Some(fees)) = (spend_utxos.as_array_mut(), fee_utxos.as_array()) {
for f in fees {
arr.push(f.clone());
}
}
let exec = plutus_exec_units();
sign_submit(&lib, &spend_yaml, &spend_utxos, &pp, Some(&exec), &["payment"]);
assert_utxo_consumed(SCRIPT_ADDR, &lock_hash);
}
#[test]
fn test_integration_stake_deregistration() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
setup_then_submit(
&lib,
"stake_registration.yaml",
&["payment", "stake"],
"stake_deregistration.yaml",
&["payment", "stake"],
);
}
#[test]
fn test_integration_pool_retirement() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let u = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("stake_registration.yaml"), &u, &pp, None, &["payment", "stake"]);
wait_for_block();
let u2 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("pool_registration.yaml"), &u2, &pp, None, &["payment", "stake"]);
wait_for_block();
let epoch = devkit_current_epoch();
let retire_yaml = read_fixture("pool_retirement.yaml")
.replace(POOL_PLACEHOLDER, ACCOUNT_POOL_ID)
.replace("retirement_epoch: 500", &format!("retirement_epoch: {}", epoch + 2));
let u3 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &retire_yaml, &u3, &pp, None, &["payment", "stake"]);
}
#[test]
fn test_integration_aiken_mint_accepts() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
let exec = plutus_exec_units();
build_sign_submit(&lib, "plutus/aiken_mint_pass.yaml", Some(&exec), &["payment"]);
assert_minted_asset_at(MINT_RECEIVER);
}
#[test]
fn test_integration_aiken_mint_rejects() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let utxos = devkit_get_utxos(INTENT_SENDER);
let exec = plutus_exec_units();
let result = lib
.quicktx()
.build(&read_fixture("plutus/aiken_mint_fail.yaml"), &utxos, &pp, Some(&exec), 0)
.expect("build");
let signed = intent_sign(&lib, &result.tx_cbor, &["payment"]);
assert!(
devkit_try_submit(&signed).is_err(),
"the node accepted a mint whose validator must reject (redeemer 0); \
expected a phase-2 script validation failure"
);
}
#[test]
fn test_integration_stake_deposit_round_trip() {
if skip_if_no_devkit() {
return;
}
let pp = reset_and_fund(6000);
let key_deposit = pp_lovelace(&pp, "key_deposit");
let lib = Mesmo::new().expect("create lib");
let start = balance_at(INTENT_SENDER);
let u = devkit_get_utxos(INTENT_SENDER);
let fee1 = sign_submit_fee(&lib, &read_fixture("stake_registration.yaml"), &u, &pp, None, &["payment", "stake"]);
wait_for_block();
assert_eq!(balance_at(INTENT_SENDER), start - fee1 - key_deposit);
let u2 = devkit_get_utxos(INTENT_SENDER);
let fee2 = sign_submit_fee(&lib, &read_fixture("stake_deregistration.yaml"), &u2, &pp, None, &["payment", "stake"]);
wait_for_block();
assert_eq!(balance_at(INTENT_SENDER), start - fee1 - fee2); }
#[test]
fn test_integration_drep_deposit_effect() {
if skip_if_no_devkit() {
return;
}
let pp = reset_and_fund(6000);
let drep_deposit = pp_lovelace(&pp, "drep_deposit");
let lib = Mesmo::new().expect("create lib");
let start = balance_at(INTENT_SENDER);
let u = devkit_get_utxos(INTENT_SENDER);
let fee = sign_submit_fee(&lib, &read_fixture("drep_registration.yaml"), &u, &pp, None, &["payment", "drep"]);
wait_for_block();
assert_eq!(balance_at(INTENT_SENDER), start - fee - drep_deposit);
}
#[test]
fn test_integration_proposal_deposit_effect() {
if skip_if_no_devkit() {
return;
}
let pp = reset_and_fund(6000);
let key_deposit = pp_lovelace(&pp, "key_deposit");
let gov_deposit = pp_lovelace(&pp, "gov_action_deposit");
let lib = Mesmo::new().expect("create lib");
let start = balance_at(INTENT_SENDER);
let u = devkit_get_utxos(INTENT_SENDER);
let fee1 = sign_submit_fee(&lib, &read_fixture("stake_registration.yaml"), &u, &pp, None, &["payment", "stake"]);
wait_for_block();
let u2 = devkit_get_utxos(INTENT_SENDER);
let fee2 = sign_submit_fee(&lib, &read_fixture("governance_proposal.yaml"), &u2, &pp, None, &["payment"]);
wait_for_block();
assert_eq!(balance_at(INTENT_SENDER), start - fee1 - key_deposit - fee2 - gov_deposit);
}
#[test]
fn test_integration_pool_deposit_effect() {
if skip_if_no_devkit() {
return;
}
let pp = reset_and_fund(6000);
let key_deposit = pp_lovelace(&pp, "key_deposit");
let pool_deposit = pp_lovelace(&pp, "pool_deposit");
let lib = Mesmo::new().expect("create lib");
let start = balance_at(INTENT_SENDER);
let u = devkit_get_utxos(INTENT_SENDER);
let fee1 = sign_submit_fee(&lib, &read_fixture("stake_registration.yaml"), &u, &pp, None, &["payment", "stake"]);
wait_for_block();
let u2 = devkit_get_utxos(INTENT_SENDER);
let fee2 = sign_submit_fee(&lib, &read_fixture("pool_registration.yaml"), &u2, &pp, None, &["payment", "stake"]);
wait_for_block();
assert_eq!(balance_at(INTENT_SENDER), start - fee1 - key_deposit - fee2 - pool_deposit);
}
#[test]
fn test_integration_collect_from() {
if skip_if_no_devkit() {
return;
}
let pp = reset_and_fund(6000);
let lib = Mesmo::new().expect("create lib");
let utxos = devkit_get_utxos(INTENT_SENDER);
let target_hash = utxos[0]["tx_hash"].as_str().expect("utxo tx_hash").to_string();
let target_idx = utxos[0]["output_index"].as_i64().unwrap_or(0);
let mut yaml = read_fixture("collect_from.yaml").replace(&"a".repeat(64), &target_hash);
if target_idx != 0 {
yaml = yaml.replacen("output_index: 0", &format!("output_index: {}", target_idx), 1);
}
sign_submit(&lib, &yaml, &utxos, &pp, None, &["payment"]);
}
#[test]
fn test_integration_reference_input() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
devkit_topup(INTENT_SENDER2, 5);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let ref_utxos = devkit_get_utxos(INTENT_SENDER2);
let ref_hash = ref_utxos[0]["tx_hash"].as_str().expect("ref tx_hash").to_string();
let ref_balance = total_lovelace(&ref_utxos);
let yaml = read_fixture("reference_input.yaml").replace(&"c".repeat(64), &ref_hash);
let utxos = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &yaml, &utxos, &pp, None, &["payment"]);
wait_for_block();
assert_eq!(balance_at(INTENT_SENDER2), ref_balance); }
#[test]
fn test_integration_native_script_spend() {
if skip_if_no_devkit() {
return;
}
let pp = reset_and_fund(6000);
let lib = Mesmo::new().expect("create lib");
let info: serde_json::Value =
serde_json::from_str(&lib.address().info(INTENT_SENDER).expect("address info"))
.expect("parse info");
let key_hash = info["payment_credential_hash"].as_str().expect("payment cred");
let script: serde_json::Value = serde_json::from_str(
&lib
.script()
.native_from_json(&format!(r#"{{"type":"sig","keyHash":"{}"}}"#, key_hash))
.expect("native script"),
)
.expect("parse script");
let script_hash = script["script_hash"].as_str().expect("script_hash");
let cbor_hex = &script["cbor_hex"].as_str().expect("cbor_hex")[2..];
let script_address = lib
.address()
.from_bytes(&format!("70{}", script_hash)) .expect("script address");
let lock_yaml = format!(
r#"
version: 1.0
transaction:
- tx:
from: {sender}
change_address: {sender}
intents:
- type: payment
address: {script_address}
amounts:
- unit: lovelace
quantity: "5000000"
"#,
sender = INTENT_SENDER,
script_address = script_address
);
let u = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &lock_yaml, &u, &pp, None, &["payment"]);
wait_for_block();
let script_utxos = devkit_get_utxos(&script_address);
let lock_hash = script_utxos[0]["tx_hash"].as_str().expect("lock hash").to_string();
let lock_idx = script_utxos[0]["output_index"].as_i64().unwrap_or(0);
let spend_yaml = format!(
r#"
version: 1.0
context:
fee_payer: {sender}
transaction:
- tx:
from: {sender}
change_address: {sender}
inputs:
- type: collect_from
utxo_refs:
- tx_hash: {lock_hash}
output_index: {lock_idx}
intents:
- type: payment
address: {sender}
amounts:
- unit: lovelace
quantity: "3000000"
scripts:
- type: native_script
script_hex: {cbor_hex}
"#,
sender = INTENT_SENDER,
lock_hash = lock_hash,
lock_idx = lock_idx,
cbor_hex = cbor_hex
);
let mut spend_utxos = script_utxos.as_array().expect("utxos array").clone();
spend_utxos.extend(
devkit_get_utxos(INTENT_SENDER)
.as_array()
.expect("utxos array")
.clone(),
);
let spend_utxos = serde_json::Value::Array(spend_utxos);
sign_submit_n(&lib, &spend_yaml, &spend_utxos, &pp, None, &["payment"], 1);
assert_utxo_consumed(&script_address, &lock_hash);
}
#[test]
fn test_integration_pool_update() {
if skip_if_no_devkit() {
return;
}
let pp = reset_and_fund(6000);
let lib = Mesmo::new().expect("create lib");
let u = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("stake_registration.yaml"), &u, &pp, None, &["payment", "stake"]);
wait_for_block();
let u2 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("pool_registration.yaml"), &u2, &pp, None, &["payment", "stake"]);
wait_for_block();
let u3 = devkit_get_utxos(INTENT_SENDER);
sign_submit(&lib, &read_fixture("pool_update.yaml"), &u3, &pp, None, &["payment", "stake"]);
}
#[test]
fn test_integration_compose_two_senders() {
if skip_if_no_devkit() {
return;
}
devkit_reset();
wait_for_block();
devkit_topup(INTENT_SENDER, 6000);
devkit_topup(INTENT_SENDER2, 6000);
wait_for_block();
let pp = devnet_pp();
let lib = Mesmo::new().expect("create lib");
let mut utxos = devkit_get_utxos(INTENT_SENDER)
.as_array()
.expect("utxos array")
.clone();
utxos.extend(
devkit_get_utxos(INTENT_SENDER2)
.as_array()
.expect("utxos array")
.clone(),
);
let utxos = serde_json::Value::Array(utxos);
let result = lib
.quicktx()
.build(&read_fixture("compose.yaml"), &utxos, &pp, None, 0)
.expect("build");
let once = intent_sign(&lib, &result.tx_cbor, &["payment"]);
let twice = intent_sign_at(&lib, 1, &once, &["payment"]);
devkit_try_submit(&twice).expect("submit");
wait_for_block();
assert_eq!(balance_at(MINT_RECEIVER), 8_000_000);
}
#[test]
fn test_integration_scalus_computed_units() {
if skip_if_no_devkit() {
return;
}
let lib = Mesmo::new().expect("create lib");
build_sign_submit(&lib, "plutus/script_minting.yaml", None, &["payment"]);
assert_minted_asset_at(MINT_RECEIVER);
}