diff --git a/crates/tx3-cardano/src/compile/mod.rs b/crates/tx3-cardano/src/compile/mod.rs index fcf441c2..106831bd 100644 --- a/crates/tx3-cardano/src/compile/mod.rs +++ b/crates/tx3-cardano/src/compile/mod.rs @@ -76,20 +76,7 @@ fn compile_struct(ir: &ir::StructExpr) -> Result } fn compile_data_expr(ir: &ir::Expression) -> Result { - match ir { - ir::Expression::Bytes(x) => Ok(x.as_data()), - ir::Expression::Number(x) => Ok(x.as_data()), - ir::Expression::Bool(x) => Ok(x.as_data()), - ir::Expression::String(x) => Ok(x.as_str().as_data()), - ir::Expression::Struct(x) => compile_struct(x), - ir::Expression::Map(x) => x.try_as_data(), - ir::Expression::Address(x) => Ok(x.as_data()), - ir::Expression::List(x) => x.try_as_data(), - _ => Err(Error::CoerceError( - format!("{ir:?}"), - "DataExpr".to_string(), - )), - } + ir.try_as_data() } fn compile_native_asset_for_output( diff --git a/crates/tx3-cardano/src/compile/plutus_data.rs b/crates/tx3-cardano/src/compile/plutus_data.rs index 3d67b479..fa320487 100644 --- a/crates/tx3-cardano/src/compile/plutus_data.rs +++ b/crates/tx3-cardano/src/compile/plutus_data.rs @@ -1,7 +1,8 @@ pub use pallas::codec::utils::Int; -use pallas::codec::utils::KeyValuePairs; +use pallas::{codec::utils::KeyValuePairs, ledger::addresses}; pub use pallas::ledger::primitives::{BigInt, BoundedBytes, Constr, MaybeIndefArray, PlutusData}; use tx3_lang::ir; +use std::collections::HashMap; pub trait IntoData { fn as_data(&self) -> PlutusData; @@ -148,10 +149,70 @@ impl TryIntoData for ir::Expression { ir::Expression::Hash(x) => Ok(x.as_data()), ir::Expression::List(x) => x.try_as_data(), ir::Expression::Map(x) => x.try_as_data(), - x => Err(super::Error::CoerceError( - format!("{x:?}"), + ir::Expression::AdHocDirective(x) => match x.name.as_str() { + "cardano_address_payment_part" => address_payment_part(&x.data), + "cardano_address_staking_part" => address_staking_part(&x.data), + _ => Ok(().as_data()), + }, + _ => Err(super::Error::CoerceError( + format!("{self:?}"), "PlutusData".to_string(), )), } } } + +fn extract_address(data: &HashMap) -> Result { + data.get("address") + .ok_or_else(|| super::Error::CoerceError( + "Address field not found in data".to_string(), + "Address".to_string(), + )) + .and_then(|expr| match expr { + ir::Expression::Address(bytes) => { + addresses::Address::from_bytes(bytes) + .map_err(|_| super::Error::CoerceError( + "Invalid address bytes".to_string(), + "Address".to_string(), + )) + } + _ => Err(super::Error::CoerceError( + format!("Expected Address expression, found {:?}", expr), + "Address".to_string(), + )), + }) +} + +fn address_payment_part(data: &HashMap) -> Result { + let addr = extract_address(data)?; + + match addr { + addresses::Address::Shelley(shelley_addr) => { + Ok(shelley_addr.payment().to_vec().as_data()) + } + addresses::Address::Byron(byron_addr) => { + Ok(byron_addr.to_vec().as_data()) + } + _ => Err(super::Error::CoerceError( + "Address type does not support payment parts".to_string(), + "Payment credential".to_string(), + )), + } +} + +fn address_staking_part(data: &HashMap) -> Result { + let addr = extract_address(data)?; + + match addr { + addresses::Address::Shelley(shelley_addr) => { + Ok(shelley_addr.delegation().to_vec().as_data()) + } + addresses::Address::Stake(stake_addr) => { + Ok(stake_addr.to_vec().as_data()) + } + _ => Err(super::Error::CoerceError( + "Address type does not support staking parts".to_string(), + "Staking credential".to_string(), + )), + } +} \ No newline at end of file diff --git a/crates/tx3-lang/src/analyzing.rs b/crates/tx3-lang/src/analyzing.rs index 120d6366..50549a7c 100644 --- a/crates/tx3-lang/src/analyzing.rs +++ b/crates/tx3-lang/src/analyzing.rs @@ -703,6 +703,8 @@ impl Analyzable for DataExpr { DataExpr::SlotToTime(x) => x.analyze(parent), DataExpr::TimeToSlot(x) => x.analyze(parent), DataExpr::ConcatOp(x) => x.analyze(parent), + DataExpr::AddressPaymentPart(x) => x.analyze(parent), + DataExpr::AddressStakingPart(x) => x.analyze(parent), _ => AnalyzeReport::default(), } } @@ -723,6 +725,8 @@ impl Analyzable for DataExpr { DataExpr::SlotToTime(x) => x.is_resolved(), DataExpr::TimeToSlot(x) => x.is_resolved(), DataExpr::ConcatOp(x) => x.is_resolved(), + DataExpr::AddressPaymentPart(x) => x.is_resolved(), + DataExpr::AddressStakingPart(x) => x.is_resolved(), _ => true, } } diff --git a/crates/tx3-lang/src/ast.rs b/crates/tx3-lang/src/ast.rs index b8620754..8b92ddb5 100644 --- a/crates/tx3-lang/src/ast.rs +++ b/crates/tx3-lang/src/ast.rs @@ -752,6 +752,8 @@ pub enum DataExpr { NegateOp(NegateOp), PropertyOp(PropertyOp), UtxoRef(UtxoRef), + AddressPaymentPart(crate::cardano::AddressPaymentPart), + AddressStakingPart(crate::cardano::AddressStakingPart), } impl DataExpr { @@ -787,6 +789,8 @@ impl DataExpr { DataExpr::UtxoRef(_) => Some(Type::UtxoRef), DataExpr::MinUtxo(_) => Some(Type::AnyAsset), DataExpr::ComputeTipSlot => Some(Type::Int), + DataExpr::AddressPaymentPart(_) => Some(Type::Bytes), + DataExpr::AddressStakingPart(_) => Some(Type::Bytes), DataExpr::SlotToTime(_) => Some(Type::Int), DataExpr::TimeToSlot(_) => Some(Type::Int), } diff --git a/crates/tx3-lang/src/cardano.rs b/crates/tx3-lang/src/cardano.rs index 77cd5861..a26b531b 100644 --- a/crates/tx3-lang/src/cardano.rs +++ b/crates/tx3-lang/src/cardano.rs @@ -724,6 +724,34 @@ impl IntoLower for CardanoPublishBlock { } } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct AddressPaymentPart { + pub address: Box, + pub span: Span, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct AddressStakingPart { + pub address: Box, + pub span: Span, +} + +pub fn parse_cardano_function(pair: Pair) -> Result { + let mut inner = pair.into_inner(); + let function_pair = inner.next().unwrap(); + + match function_pair.as_rule() { + Rule::cardano_address_payment_part => { + Ok(DataExpr::AddressPaymentPart(AddressPaymentPart::parse(function_pair)?)) + } + Rule::cardano_address_staking_part => { + Ok(DataExpr::AddressStakingPart(AddressStakingPart::parse(function_pair)?)) + } + x => unreachable!("Unexpected rule in cardano_functions: {:?}", x), + } +} + + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum CardanoBlock { VoteDelegationCertificate(VoteDelegationCertificate), @@ -735,6 +763,38 @@ pub enum CardanoBlock { Publish(CardanoPublishBlock), } +impl AstNode for AddressPaymentPart { + const RULE: Rule = Rule::cardano_address_payment_part; + + fn parse(pair: Pair) -> Result { + let span = pair.as_span().into(); + let mut inner = pair.into_inner(); + let address = DataExpr::parse(inner.next().unwrap())?.into(); + + Ok(AddressPaymentPart { address, span }) + } + + fn span(&self) -> &Span { + &self.span + } +} + +impl AstNode for AddressStakingPart { + const RULE: Rule = Rule::cardano_address_staking_part; + + fn parse(pair: Pair) -> Result { + let span = pair.as_span().into(); + let mut inner = pair.into_inner(); + let address = DataExpr::parse(inner.next().unwrap())?.into(); + + Ok(AddressStakingPart { address, span }) + } + + fn span(&self) -> &Span { + &self.span + } +} + impl AstNode for CardanoBlock { const RULE: Rule = Rule::cardano_block; @@ -781,6 +841,26 @@ impl AstNode for CardanoBlock { } } +impl Analyzable for AddressPaymentPart { + fn analyze(&mut self, parent: Option>) -> AnalyzeReport { + self.address.analyze(parent) + } + + fn is_resolved(&self) -> bool { + self.address.is_resolved() + } +} + +impl Analyzable for AddressStakingPart { + fn analyze(&mut self, parent: Option>) -> AnalyzeReport { + self.address.analyze(parent) + } + + fn is_resolved(&self) -> bool { + self.address.is_resolved() + } +} + impl Analyzable for CardanoBlock { fn analyze(&mut self, parent: Option>) -> AnalyzeReport { match self { @@ -807,6 +887,40 @@ impl Analyzable for CardanoBlock { } } +impl IntoLower for AddressPaymentPart { + type Output = ir::AdHocDirective; + + fn into_lower( + &self, + ctx: &crate::lowering::Context, + ) -> Result { + let address_expr = self.address.into_lower(ctx)?; + let mut data = std::collections::HashMap::new(); + data.insert("address".to_string(), address_expr); + Ok(ir::AdHocDirective { + name: "cardano_address_payment_part".to_string(), + data, + }) + } +} + +impl IntoLower for AddressStakingPart { + type Output = ir::AdHocDirective; + + fn into_lower( + &self, + ctx: &crate::lowering::Context, + ) -> Result { + let address_expr = self.address.into_lower(ctx)?; + let mut data = std::collections::HashMap::new(); + data.insert("address".to_string(), address_expr); + Ok(ir::AdHocDirective { + name: "cardano_address_staking_part".to_string(), + data, + }) + } +} + impl IntoLower for CardanoBlock { type Output = ir::AdHocDirective; diff --git a/crates/tx3-lang/src/lowering.rs b/crates/tx3-lang/src/lowering.rs index 32abf290..9c531a03 100644 --- a/crates/tx3-lang/src/lowering.rs +++ b/crates/tx3-lang/src/lowering.rs @@ -491,6 +491,12 @@ impl IntoLower for ast::DataExpr { ast::DataExpr::ComputeTipSlot => { ir::Expression::EvalCompiler(Box::new(ir::CompilerOp::ComputeTipSlot)) } + ast::DataExpr::AddressPaymentPart(x) => { + ir::Expression::AdHocDirective(Box::new(x.into_lower(ctx)?)) + } + ast::DataExpr::AddressStakingPart(x) => { + ir::Expression::AdHocDirective(Box::new(x.into_lower(ctx)?)) + } ast::DataExpr::SlotToTime(x) => ir::Expression::EvalCompiler(Box::new( ir::CompilerOp::ComputeSlotToTime(x.into_lower(ctx)?), )), @@ -961,4 +967,6 @@ mod tests { test_lowering!(donation); test_lowering!(list_concat); + + test_lowering!(party_serialization); } diff --git a/crates/tx3-lang/src/parsing.rs b/crates/tx3-lang/src/parsing.rs index 50a5ebba..ebf59e5f 100644 --- a/crates/tx3-lang/src/parsing.rs +++ b/crates/tx3-lang/src/parsing.rs @@ -12,10 +12,8 @@ use pest::{ }; use pest_derive::Parser; -use crate::{ - ast::*, - cardano::{PlutusWitnessBlock, PlutusWitnessField}, -}; +use crate::ast::*; + #[derive(Parser)] #[grammar = "tx3.pest"] pub(crate) struct Tx3Grammar; @@ -1252,6 +1250,7 @@ impl AstNode for DataExpr { Rule::concat_constructor => DataExpr::concat_constructor_parse(x), Rule::min_utxo => DataExpr::min_utxo_parse(x), Rule::tip_slot => DataExpr::tip_slot_parse(x), + Rule::cardano_functions => crate::cardano::parse_cardano_function(x), Rule::slot_to_time => DataExpr::slot_to_time_parse(x), Rule::time_to_slot => DataExpr::time_to_slot_parse(x), Rule::data_expr => DataExpr::parse(x), @@ -1295,6 +1294,8 @@ impl AstNode for DataExpr { DataExpr::PropertyOp(x) => &x.span, DataExpr::UtxoRef(x) => x.span(), DataExpr::MinUtxo(x) => x.span(), + DataExpr::AddressPaymentPart(x) => x.span(), + DataExpr::AddressStakingPart(x) => x.span(), DataExpr::SlotToTime(x) => x.span(), DataExpr::TimeToSlot(x) => x.span(), DataExpr::ComputeTipSlot => &Span::DUMMY, // TODO @@ -2749,11 +2750,11 @@ mod tests { #[test] fn test_spans_are_respected() { let program = parse_well_known_example("lang_tour"); - assert_eq!(program.span, Span::new(0, 1560)); + assert_eq!(program.span, Span::new(0, 2370)); - assert_eq!(program.parties[0].span, Span::new(47, 61)); + assert_eq!(program.parties[0].span, Span::new(92, 106)); - assert_eq!(program.types[0].span, Span::new(63, 158)); + assert_eq!(program.types[0].span, Span::new(108, 232)); } fn make_snapshot_if_missing(example: &str, program: &Program) { @@ -2822,4 +2823,6 @@ mod tests { test_parsing!(donation); test_parsing!(list_concat); + + test_parsing!(party_serialization); } diff --git a/crates/tx3-lang/src/tx3.pest b/crates/tx3-lang/src/tx3.pest index 43ef45c1..a7af9a13 100644 --- a/crates/tx3-lang/src/tx3.pest +++ b/crates/tx3-lang/src/tx3.pest @@ -161,6 +161,7 @@ data_expr = { data_prefix* ~ data_primary ~ data_postfix* ~ (data_infix ~ data_p string | min_utxo | tip_slot | + cardano_functions | slot_to_time | time_to_slot | struct_constructor | @@ -402,6 +403,17 @@ cardano_publish_block = { "}" } +cardano_address_payment_part = { "payment_part" ~ "(" ~ data_expr ~ ")" } +cardano_address_staking_part = { "staking_part" ~ "(" ~ data_expr ~ ")" } + +cardano_functions = { + "cardano" ~ "::" ~ ( + cardano_address_payment_part | + cardano_address_staking_part + ) +} + + cardano_block = { "cardano" ~ "::" ~ ( cardano_stake_delegation_certificate | diff --git a/examples/cardano_witness.mint_from_plutus.tir b/examples/cardano_witness.mint_from_plutus.tir index 8ff6e2e2..c0f4530f 100644 --- a/examples/cardano_witness.mint_from_plutus.tir +++ b/examples/cardano_witness.mint_from_plutus.tir @@ -202,6 +202,9 @@ { "name": "plutus_witness", "data": { + "version": { + "Number": 3 + }, "script": { "Bytes": [ 81, @@ -223,9 +226,6 @@ 174, 105 ] - }, - "version": { - "Number": 3 } } } diff --git a/examples/lang_tour.my_tx.tir b/examples/lang_tour.my_tx.tir index 80d3416f..77278c6b 100644 --- a/examples/lang_tour.my_tx.tir +++ b/examples/lang_tour.my_tx.tir @@ -666,15 +666,6 @@ { "name": "withdrawal", "data": { - "redeemer": { - "Struct": { - "constructor": 0, - "fields": [] - } - }, - "amount": { - "Number": 100 - }, "credential": { "EvalParam": { "ExpectValue": [ @@ -682,6 +673,15 @@ "Address" ] } + }, + "amount": { + "Number": 100 + }, + "redeemer": { + "Struct": { + "constructor": 0, + "fields": [] + } } } }, diff --git a/examples/party_serialization.ast b/examples/party_serialization.ast new file mode 100644 index 00000000..fb0b638d --- /dev/null +++ b/examples/party_serialization.ast @@ -0,0 +1,410 @@ +{ + "env": null, + "txs": [ + { + "name": { + "value": "transfer", + "span": { + "dummy": false, + "start": 68, + "end": 76 + } + }, + "parameters": { + "parameters": [ + { + "name": { + "value": "quantity", + "span": { + "dummy": false, + "start": 82, + "end": 90 + } + }, + "type": "Int" + } + ], + "span": { + "dummy": false, + "start": 76, + "end": 97 + } + }, + "locals": null, + "references": [], + "inputs": [ + { + "name": "source", + "many": false, + "fields": [ + { + "From": { + "Identifier": { + "value": "Sender", + "span": { + "dummy": false, + "start": 133, + "end": 139 + } + } + } + }, + { + "MinAmount": { + "StaticAssetConstructor": { + "type": { + "value": "Ada", + "span": { + "dummy": false, + "start": 161, + "end": 164 + } + }, + "amount": { + "Identifier": { + "value": "quantity", + "span": { + "dummy": false, + "start": 165, + "end": 173 + } + } + }, + "span": { + "dummy": false, + "start": 161, + "end": 174 + } + } + } + } + ], + "span": { + "dummy": false, + "start": 104, + "end": 181 + } + } + ], + "outputs": [ + { + "name": null, + "optional": false, + "fields": [ + { + "To": { + "Identifier": { + "value": "Receiver", + "span": { + "dummy": false, + "start": 208, + "end": 216 + } + } + } + }, + { + "Amount": { + "StaticAssetConstructor": { + "type": { + "value": "Ada", + "span": { + "dummy": false, + "start": 234, + "end": 237 + } + }, + "amount": { + "Identifier": { + "value": "quantity", + "span": { + "dummy": false, + "start": 238, + "end": 246 + } + } + }, + "span": { + "dummy": false, + "start": 234, + "end": 247 + } + } + } + } + ], + "span": { + "dummy": false, + "start": 187, + "end": 254 + } + }, + { + "name": null, + "optional": false, + "fields": [ + { + "To": { + "Identifier": { + "value": "Sender", + "span": { + "dummy": false, + "start": 281, + "end": 287 + } + } + } + }, + { + "Amount": { + "SubOp": { + "lhs": { + "SubOp": { + "lhs": { + "Identifier": { + "value": "source", + "span": { + "dummy": false, + "start": 305, + "end": 311 + } + } + }, + "rhs": { + "StaticAssetConstructor": { + "type": { + "value": "Ada", + "span": { + "dummy": false, + "start": 314, + "end": 317 + } + }, + "amount": { + "Identifier": { + "value": "quantity", + "span": { + "dummy": false, + "start": 318, + "end": 326 + } + } + }, + "span": { + "dummy": false, + "start": 314, + "end": 327 + } + } + }, + "span": { + "dummy": false, + "start": 312, + "end": 313 + } + } + }, + "rhs": { + "Identifier": { + "value": "fees", + "span": { + "dummy": false, + "start": 330, + "end": 334 + } + } + }, + "span": { + "dummy": false, + "start": 328, + "end": 329 + } + } + } + }, + { + "Datum": { + "StructConstructor": { + "type": { + "value": "Datum", + "span": { + "dummy": false, + "start": 351, + "end": 356 + } + }, + "case": { + "name": { + "value": "Default", + "span": { + "dummy": true, + "start": 0, + "end": 0 + } + }, + "fields": [ + { + "name": { + "value": "owner", + "span": { + "dummy": false, + "start": 369, + "end": 374 + } + }, + "value": { + "AddressPaymentPart": { + "address": { + "Identifier": { + "value": "Sender", + "span": { + "dummy": false, + "start": 398, + "end": 404 + } + } + }, + "span": { + "dummy": false, + "start": 385, + "end": 405 + } + } + }, + "span": { + "dummy": false, + "start": 369, + "end": 405 + } + } + ], + "spread": null, + "span": { + "dummy": false, + "start": 357, + "end": 416 + } + }, + "span": { + "dummy": false, + "start": 351, + "end": 416 + } + } + } + } + ], + "span": { + "dummy": false, + "start": 260, + "end": 423 + } + } + ], + "validity": null, + "mints": [], + "burns": [], + "signers": null, + "adhoc": [], + "span": { + "dummy": false, + "start": 65, + "end": 425 + }, + "collateral": [], + "metadata": null + } + ], + "types": [ + { + "name": { + "value": "Datum", + "span": { + "dummy": false, + "start": 6, + "end": 11 + } + }, + "cases": [ + { + "name": { + "value": "Default", + "span": { + "dummy": true, + "start": 0, + "end": 0 + } + }, + "fields": [ + { + "name": { + "value": "owner", + "span": { + "dummy": false, + "start": 16, + "end": 21 + } + }, + "type": "Bytes", + "span": { + "dummy": false, + "start": 16, + "end": 28 + } + } + ], + "span": { + "dummy": false, + "start": 1, + "end": 31 + } + } + ], + "span": { + "dummy": false, + "start": 1, + "end": 31 + } + } + ], + "aliases": [], + "assets": [], + "parties": [ + { + "name": { + "value": "Sender", + "span": { + "dummy": false, + "start": 39, + "end": 45 + } + }, + "span": { + "dummy": false, + "start": 33, + "end": 46 + } + }, + { + "name": { + "value": "Receiver", + "span": { + "dummy": false, + "start": 54, + "end": 62 + } + }, + "span": { + "dummy": false, + "start": 48, + "end": 63 + } + } + ], + "policies": [], + "span": { + "dummy": false, + "start": 0, + "end": 425 + } +} \ No newline at end of file diff --git a/examples/party_serialization.transfer.tir b/examples/party_serialization.transfer.tir new file mode 100644 index 00000000..124b3de2 --- /dev/null +++ b/examples/party_serialization.transfer.tir @@ -0,0 +1,189 @@ +{ + "fees": { + "EvalParam": "ExpectFees" + }, + "references": [], + "inputs": [ + { + "name": "source", + "utxos": { + "EvalParam": { + "ExpectInput": [ + "source", + { + "address": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + }, + "min_amount": { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] + }, + "ref": "None", + "many": false, + "collateral": false + } + ] + } + }, + "redeemer": "None" + } + ], + "outputs": [ + { + "address": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } + }, + "datum": "None", + "amount": { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] + }, + "optional": false + }, + { + "address": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + }, + "datum": { + "Struct": { + "constructor": 0, + "fields": [ + { + "AdHocDirective": { + "name": "cardano_address_payment_part", + "data": { + "address": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + } + } + } + } + ] + } + }, + "amount": { + "EvalBuiltIn": { + "Sub": [ + { + "EvalBuiltIn": { + "Sub": [ + { + "EvalCoerce": { + "IntoAssets": { + "EvalParam": { + "ExpectInput": [ + "source", + { + "address": { + "EvalParam": { + "ExpectValue": [ + "sender", + "Address" + ] + } + }, + "min_amount": { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] + }, + "ref": "None", + "many": false, + "collateral": false + } + ] + } + } + } + }, + { + "Assets": [ + { + "policy": "None", + "asset_name": "None", + "amount": { + "EvalParam": { + "ExpectValue": [ + "quantity", + "Int" + ] + } + } + } + ] + } + ] + } + }, + { + "EvalParam": "ExpectFees" + } + ] + } + }, + "optional": false + } + ], + "validity": null, + "mints": [], + "burns": [], + "adhoc": [], + "collateral": [], + "signers": null, + "metadata": [] +} \ No newline at end of file diff --git a/examples/party_serialization.tx3 b/examples/party_serialization.tx3 new file mode 100644 index 00000000..431c66ee --- /dev/null +++ b/examples/party_serialization.tx3 @@ -0,0 +1,30 @@ + +type Datum { + owner: Bytes, +} + +party Sender; + +party Receiver; + +tx transfer( + quantity: Int +) { + input source { + from: Sender, + min_amount: Ada(quantity), + } + + output { + to: Receiver, + amount: Ada(quantity), + } + + output { + to: Sender, + amount: source - Ada(quantity) - fees, + datum: Datum { + owner: cardano::payment_part(Sender), + }, + } +} \ No newline at end of file diff --git a/examples/reference_script.publish_native.tir b/examples/reference_script.publish_native.tir index 90fdd3b9..e10857b5 100644 --- a/examples/reference_script.publish_native.tir +++ b/examples/reference_script.publish_native.tir @@ -137,6 +137,9 @@ { "name": "cardano_publish", "data": { + "version": { + "Number": 0 + }, "script": { "Bytes": [ 130, @@ -147,6 +150,14 @@ 0 ] }, + "to": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } + }, "amount": { "Assets": [ { @@ -162,17 +173,6 @@ } } ] - }, - "to": { - "EvalParam": { - "ExpectValue": [ - "receiver", - "Address" - ] - } - }, - "version": { - "Number": 0 } } } diff --git a/examples/reference_script.publish_plutus.tir b/examples/reference_script.publish_plutus.tir index f1291c1f..3b1fb060 100644 --- a/examples/reference_script.publish_plutus.tir +++ b/examples/reference_script.publish_plutus.tir @@ -137,9 +137,6 @@ { "name": "cardano_publish", "data": { - "version": { - "Number": 3 - }, "amount": { "Assets": [ { @@ -156,13 +153,8 @@ } ] }, - "to": { - "EvalParam": { - "ExpectValue": [ - "receiver", - "Address" - ] - } + "version": { + "Number": 3 }, "script": { "Bytes": [ @@ -185,6 +177,14 @@ 174, 105 ] + }, + "to": { + "EvalParam": { + "ExpectValue": [ + "receiver", + "Address" + ] + } } } } diff --git a/examples/withdrawal.transfer.tir b/examples/withdrawal.transfer.tir index facdbb3c..ec19f1e1 100644 --- a/examples/withdrawal.transfer.tir +++ b/examples/withdrawal.transfer.tir @@ -165,6 +165,9 @@ { "name": "withdrawal", "data": { + "amount": { + "Number": 0 + }, "credential": { "EvalParam": { "ExpectValue": [ @@ -173,9 +176,6 @@ ] } }, - "amount": { - "Number": 0 - }, "redeemer": { "Struct": { "constructor": 0,