From ebe7c90799f41be1eb8ec01bb742591ecb6c7920 Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 14:15:59 +0300 Subject: [PATCH 01/11] adds namespaces and tests --- packages/ptb/sources/ptb.move | 36 ++++++-- packages/ptb/tests/ptb_tests.move | 135 ++++++++++++++++++++++++++++-- 2 files changed, 158 insertions(+), 13 deletions(-) diff --git a/packages/ptb/sources/ptb.move b/packages/ptb/sources/ptb.move index d953a04..958caab 100644 --- a/packages/ptb/sources/ptb.move +++ b/packages/ptb/sources/ptb.move @@ -3,15 +3,22 @@ module ptb::ptb; use std::bcs; use std::string::String; -use std::type_name; +use std::type_name::{Self, TypeName}; // TODO: what should be a standard delimiter for namespaces? const OBJECT_BY_ID_EXT: vector = b"object_by_id:"; const OBJECT_BY_TYPE_EXT: vector = b"object_by_type:"; const RECEIVING_BY_ID_EXT: vector = b"receiving_by_id:"; +/// Tag for extended arguments. Intentionally offset to not be mistaken for a +/// command tag. +const EXT_TAG: u8 = 100; + +/// Defines a PTB template. Unlike the canonical Sui PTB, this one does not have inputs. +/// Instead, the inputs are passed in as arguments to the commands directly. And +/// while this is a bit more verbose and less optimized storage wise, it is more +/// flexible format for off-chain handling. public struct Transaction has copy, drop, store { - inputs: vector, commands: vector, } @@ -110,7 +117,10 @@ public enum CallArg has copy, drop, store { }, /// Extended arguments for off-chain resolution. /// Can be created and registered in a transaction through `ext_input`. - Ext(String), + /// Extended arguments are namespaced by TypeName associated with them. In an + /// application, this can be the root object, or a special type used for off + /// chain resolution. + Ext(TypeName, String), } /// Defines a simplified `ObjectArg` type for the `Transaction`. @@ -144,7 +154,7 @@ public enum WithdrawFrom has copy, drop, store { /// Create a new Transaction builder. public fun new(): Transaction { - Transaction { inputs: vector[], commands: vector[] } + Transaction { commands: vector[] } } // === System Objects === @@ -158,6 +168,12 @@ public fun random(): Argument { object_by_id(@0x8.to_id()) } /// Shorthand for `object_by_id` with `0xD` (DisplayRegistry). public fun display(): Argument { object_by_id(@0xD.to_id()) } +/// Shorthand for `object_by_id` with `0x403` (DenyList). +public fun deny_list(): Argument { object_by_id(@0x403.to_id()) } + +/// Shorthand for `object_by_id` with `0xC` (CoinRegistry). +public fun coin_registry(): Argument { object_by_id(@0xC.to_id()) } + // === Inputs === /// Create a gas coin input. @@ -248,8 +264,14 @@ public fun receiving_object_by_id(id: ID): Argument { /// Create an external input handler. /// Expected to be understood by the off-chain tooling. -public fun ext_input(name: String): Argument { - Argument::Input(CallArg::Ext(name)) +public fun ext_input(name: String): Argument { + Argument::Input(CallArg::Ext(type_name::with_original_ids(), name)) +} + +/// Create an external input handler for a given type T. +/// This can be used in a case where the builder does not have access to the `T`. +public fun ext_input_raw(type_name: TypeName, name: String): Argument { + Argument::Input(CallArg::Ext(type_name, name)) } /// Register a command in the Transaction builder. Returns the Argument, which @@ -337,7 +359,7 @@ public fun upgrade( /// Create an `Ext` command. public fun ext(data: vector): Command { - Command(7, data) + Command(EXT_TAG, data) } // === Test Features === diff --git a/packages/ptb/tests/ptb_tests.move b/packages/ptb/tests/ptb_tests.move index 26756fc..f09179f 100644 --- a/packages/ptb/tests/ptb_tests.move +++ b/packages/ptb/tests/ptb_tests.move @@ -2,7 +2,15 @@ module ptb::ptb_tests; use ptb::ptb; +use std::type_name; use std::unit_test::assert_eq; +use sui::kiosk::Kiosk; + +/// Keeping this for testing purposes. +public struct PAS {} + +/// NFT type for kiosk example. +public struct NFT has key, store { id: UID } #[test] fun ptb() { @@ -18,13 +26,77 @@ fun ptb() { ), ); - let coin = ptb.command(ptb::split_coins(ptb::gas(), vector[arg])); + // split twice + let coins = ptb.command(ptb::split_coins(ptb::gas(), vector[arg, arg])); - ptb.command(ptb::transfer_objects(vector[coin], ptb::pure(@0))); + ptb.command(ptb::transfer_objects(vector[coins.nested(0), coins.nested(1)], ptb::pure(@0))); assert_eq!(arg.idx(), 0); } +#[test] +fun simple_option_and_vec_operations() { + let mut ptb = ptb::new(); + + let some_arg = ptb.command( + ptb::move_call( + @0x1.to_string(), + "option", + "some", + vector[ptb::pure(100u64)], + vector["u64"], + ), + ); + + // dummy bool result + let _ = ptb.command( + ptb::move_call( + @0x1.to_string(), + "option", + "is_some", + vector[some_arg], + vector["u64"], + ), + ); + + let u64_val = ptb.command( + ptb::move_call( + @0x1.to_string(), + "option", + "swap", + vector[some_arg, ptb::pure(200u64)], + vector["u64"], + ), + ); + + let vec = ptb.command( + ptb::make_move_vec(option::some("u64"), vector[u64_val, ptb::pure(300u64)]), + ); + + 2u8.do!( + |_| ptb.command( + ptb::move_call( + @0x1.to_string(), + "vector", + "pop_back", + vector[vec], + vector["u64"], + ), + ), + ); + + // lastly, destroy empty vector + ptb.command( + ptb::move_call( + @0x1.to_string(), + "vector", + "destroy_empty", + vector[vec], + vector["u64"], + ), + ); +} + #[test] fun pas_command_with_ext_inputs() { ptb::move_call( @@ -32,13 +104,64 @@ fun pas_command_with_ext_inputs() { "demo_usd", "resolve_transfer", vector[ - ptb::ext_input("request"), // TODO: consider namespaces here? - ptb::ext_input("policy_arg"), + ptb::ext_input("request"), + ptb::ext_input("policy_arg"), ptb::clock(), ], vector["magic::usdc_app::DEMO_USDC"], ); +} + +#[test] +fun kiosk_transaction_with_rules_resolution() { + let mut ptb = ptb::new(); + let nft_type = (*type_name::with_original_ids().as_string()).to_string(); + + // pay royalty + ptb.command( + ptb::move_call( + "@mysten/kiosk", + "royalty_rule", + "pay", + vector[ + ptb::ext_input("policy"), + ptb::ext_input("request"), + ptb::ext_input("royalty_payment"), + ], + vector[nft_type], + ), + ); + + // lock item in the buyer kiosk + ptb.command( + ptb::move_call( + @0x2.to_string(), + "kiosk", + "lock", + vector[ptb::ext_input("buyer_kiosk"), ptb::ext_input("item")], + vector[nft_type], + ), + ); + + // prove that the item is locked + ptb.command( + ptb::move_call( + "@mysten/kiosk", + "kiosk_lock_rule", + "prove", + vector[ptb::ext_input("request"), ptb::ext_input("buyer_kiosk")], + vector[nft_type], + ), + ); - // TODO: compiler panic! - // std::debug::print(&_mc); + // confirm the request + ptb.command( + ptb::move_call( + @0x2.to_string(), + "policy", + "confirm_request", + vector[ptb::ext_input("policy"), ptb::ext_input("request")], + vector[nft_type], + ), + ); } From 9adda0ab71f09acd981e2cd2ed9b15785ecc9ea1 Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 14:22:55 +0300 Subject: [PATCH 02/11] remove redundant comment --- packages/ptb/sources/ptb.move | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ptb/sources/ptb.move b/packages/ptb/sources/ptb.move index 958caab..f1bc8cb 100644 --- a/packages/ptb/sources/ptb.move +++ b/packages/ptb/sources/ptb.move @@ -5,7 +5,6 @@ use std::bcs; use std::string::String; use std::type_name::{Self, TypeName}; -// TODO: what should be a standard delimiter for namespaces? const OBJECT_BY_ID_EXT: vector = b"object_by_id:"; const OBJECT_BY_TYPE_EXT: vector = b"object_by_type:"; const RECEIVING_BY_ID_EXT: vector = b"receiving_by_id:"; From bb565db872ed53d899fda2a58e957562306ffcce Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 14:26:15 +0300 Subject: [PATCH 03/11] extend kiosk test sample --- packages/ptb/tests/ptb_tests.move | 32 ++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/ptb/tests/ptb_tests.move b/packages/ptb/tests/ptb_tests.move index f09179f..ea850bf 100644 --- a/packages/ptb/tests/ptb_tests.move +++ b/packages/ptb/tests/ptb_tests.move @@ -103,11 +103,7 @@ fun pas_command_with_ext_inputs() { @0x0.to_string(), "demo_usd", "resolve_transfer", - vector[ - ptb::ext_input("request"), - ptb::ext_input("policy_arg"), - ptb::clock(), - ], + vector[ptb::ext_input("request"), ptb::ext_input("policy_arg"), ptb::clock()], vector["magic::usdc_app::DEMO_USDC"], ); } @@ -117,6 +113,28 @@ fun kiosk_transaction_with_rules_resolution() { let mut ptb = ptb::new(); let nft_type = (*type_name::with_original_ids().as_string()).to_string(); + let paid = ptb.command( + ptb::move_call( + @0x2.to_string(), + "transfer_policy", + "paid", + vector[ptb::ext_input("request")], + vector[nft_type], + ), + ); + + let fee_amount = ptb.command( + ptb::move_call( + "@mysten/kiosk", + "royalty_rule", + "fee_amount", + vector[ptb::ext_input("policy"), paid], + vector[nft_type], + ), + ); + + let royalty_payment = ptb.command(ptb::split_coins(ptb::gas(), vector[fee_amount])); + // pay royalty ptb.command( ptb::move_call( @@ -126,7 +144,7 @@ fun kiosk_transaction_with_rules_resolution() { vector[ ptb::ext_input("policy"), ptb::ext_input("request"), - ptb::ext_input("royalty_payment"), + royalty_payment, ], vector[nft_type], ), @@ -158,7 +176,7 @@ fun kiosk_transaction_with_rules_resolution() { ptb.command( ptb::move_call( @0x2.to_string(), - "policy", + "transfer_policy", "confirm_request", vector[ptb::ext_input("policy"), ptb::ext_input("request")], vector[nft_type], From ef33f66a9548fa41c4bc5f8e94f930d2b8626f9c Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 14:34:44 +0300 Subject: [PATCH 04/11] fix build --- packages/pas/sources/templates.move | 3 +++ packages/ptb/sources/ptb.move | 17 ++++++++++------- packages/testing/demo_usd/sources/demo_usd.move | 6 +++--- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/pas/sources/templates.move b/packages/pas/sources/templates.move index 54b90ac..979b457 100644 --- a/packages/pas/sources/templates.move +++ b/packages/pas/sources/templates.move @@ -12,6 +12,9 @@ use sui::{derived_object, dynamic_field}; #[error(code = 0)] const ETemplateNotSet: vector = b"Template not set for this action."; +/// Namespacing type for `ext_input`'s. +public struct PAS {} + public struct Templates has key { id: UID, } diff --git a/packages/ptb/sources/ptb.move b/packages/ptb/sources/ptb.move index f1bc8cb..2b6b27c 100644 --- a/packages/ptb/sources/ptb.move +++ b/packages/ptb/sources/ptb.move @@ -3,7 +3,7 @@ module ptb::ptb; use std::bcs; use std::string::String; -use std::type_name::{Self, TypeName}; +use std::type_name; const OBJECT_BY_ID_EXT: vector = b"object_by_id:"; const OBJECT_BY_TYPE_EXT: vector = b"object_by_type:"; @@ -116,10 +116,11 @@ public enum CallArg has copy, drop, store { }, /// Extended arguments for off-chain resolution. /// Can be created and registered in a transaction through `ext_input`. - /// Extended arguments are namespaced by TypeName associated with them. In an + /// + /// Extended arguments are namespaced by Type associated with them. In an /// application, this can be the root object, or a special type used for off /// chain resolution. - Ext(TypeName, String), + Ext(String, String), } /// Defines a simplified `ObjectArg` type for the `Transaction`. @@ -264,13 +265,15 @@ public fun receiving_object_by_id(id: ID): Argument { /// Create an external input handler. /// Expected to be understood by the off-chain tooling. public fun ext_input(name: String): Argument { - Argument::Input(CallArg::Ext(type_name::with_original_ids(), name)) + Argument::Input( + CallArg::Ext((*type_name::with_original_ids().as_string()).to_string(), name), + ) } /// Create an external input handler for a given type T. -/// This can be used in a case where the builder does not have access to the `T`. -public fun ext_input_raw(type_name: TypeName, name: String): Argument { - Argument::Input(CallArg::Ext(type_name, name)) +/// This can be used to hardcode the namespace value without having access to `T`. +public fun ext_input_raw(namespace: String, name: String): Argument { + Argument::Input(CallArg::Ext(namespace, name)) } /// Register a command in the Transaction builder. Returns the Argument, which diff --git a/packages/testing/demo_usd/sources/demo_usd.move b/packages/testing/demo_usd/sources/demo_usd.move index 9c969d7..eeed684 100644 --- a/packages/testing/demo_usd/sources/demo_usd.move +++ b/packages/testing/demo_usd/sources/demo_usd.move @@ -12,7 +12,7 @@ use pas::namespace::Namespace; use pas::policy::{Self, Policy, PolicyCap}; use pas::request::Request; use pas::send_funds::SendFunds; -use pas::templates::Templates; +use pas::templates::{PAS, Templates}; use ptb::ptb; use std::type_name; use sui::balance::Balance; @@ -97,7 +97,7 @@ entry fun setup(namespace: &mut Namespace, templates: &mut Templates, faucet: &m type_name.address_string().to_string(), "demo_usd", "approve_transfer", - vector[ptb::ext_input("pas:request"), ptb::object_by_id(@0x6.to_id())], + vector[ptb::ext_input("pas:request"), ptb::object_by_id(@0x6.to_id())], vector[(*type_name.as_string()).to_string()], ); @@ -115,7 +115,7 @@ public fun use_v2( type_name::with_defining_ids().address_string().to_string(), "demo_usd", "approve_transfer_v2", - vector[ptb::ext_input("pas:request"), ptb::object_by_id(object::id(faucet))], + vector[ptb::ext_input("pas:request"), ptb::object_by_id(object::id(faucet))], vector[], ); From ebb49d9ce5f219c63ddbc335b5256f19f7c0b59e Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 14:46:33 +0300 Subject: [PATCH 05/11] updates deps --- packages/testing/demo_usd/Move.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/testing/demo_usd/Move.lock b/packages/testing/demo_usd/Move.lock index 2054416..177dc62 100644 --- a/packages/testing/demo_usd/Move.lock +++ b/packages/testing/demo_usd/Move.lock @@ -5,13 +5,13 @@ version = 4 [pinned.testnet.MoveStdlib] -source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "868c226359ef914f1f3b080518f27eb13d8967f5" } +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "b38bca86f0323b3fe8b6b7f4ca0cd7ae7faebe4b" } use_environment = "testnet" manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" deps = {} [pinned.testnet.Sui] -source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "868c226359ef914f1f3b080518f27eb13d8967f5" } +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "b38bca86f0323b3fe8b6b7f4ca0cd7ae7faebe4b" } use_environment = "testnet" manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" deps = { MoveStdlib = "MoveStdlib" } From ede01399216708110f7d032e46b665bc8573f54a Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 15:05:08 +0300 Subject: [PATCH 06/11] update type definitions in the SDK --- sdk/pas/README.md | 2 +- sdk/pas/src/contracts/ptb/ptb.ts | 8 +++++++- sdk/pas/src/resolution.ts | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sdk/pas/README.md b/sdk/pas/README.md index a21f4ce..0944bfb 100644 --- a/sdk/pas/README.md +++ b/sdk/pas/README.md @@ -1 +1 @@ -# Permissioned Assets Standard sdk +# Permissioned Assets Standard SDK diff --git a/sdk/pas/src/contracts/ptb/ptb.ts b/sdk/pas/src/contracts/ptb/ptb.ts index 3821768..5d17d78 100644 --- a/sdk/pas/src/contracts/ptb/ptb.ts +++ b/sdk/pas/src/contracts/ptb/ptb.ts @@ -87,7 +87,13 @@ export const CallArg = new MoveEnum({ * Extended arguments for off-chain resolution. Can be created and registered in a * transaction through `ext_input`. */ - Ext: bcs.string(), + Ext: new MoveStruct({ + name: `CallArg.Ext`, + fields: { + namespace: bcs.string(), + value: bcs.string(), + }, + }), }, }); export const Command = new MoveTuple({ diff --git a/sdk/pas/src/resolution.ts b/sdk/pas/src/resolution.ts index 7fa75f8..ac728f1 100644 --- a/sdk/pas/src/resolution.ts +++ b/sdk/pas/src/resolution.ts @@ -196,7 +196,7 @@ export function buildMoveCallCommandFromTemplate( ); } } else if (arg.Input.Ext) { - resolvedArgs.push(resolveRawPasRequest(args, arg.Input.Ext)); + resolvedArgs.push(resolveRawPasRequest(args, arg.Input.Ext.value)); } else { throw new PASClientError(`Unsupported input kind: ${arg.Input.$kind}`); } From 7e5b8eb1113f664f3af5cd8e3674ceb3ede75198 Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 15:06:54 +0300 Subject: [PATCH 07/11] fix deps lockfiles --- packages/pas/Move.lock | 4 ++-- packages/ptb/Move.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/pas/Move.lock b/packages/pas/Move.lock index b300e81..e6ea47d 100644 --- a/packages/pas/Move.lock +++ b/packages/pas/Move.lock @@ -5,13 +5,13 @@ version = 4 [pinned.testnet.MoveStdlib] -source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "563c15820b27dec9cbe75f826a3b6243ef44da1a" } +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "b38bca86f0323b3fe8b6b7f4ca0cd7ae7faebe4b" } use_environment = "testnet" manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" deps = {} [pinned.testnet.Sui] -source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "563c15820b27dec9cbe75f826a3b6243ef44da1a" } +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "b38bca86f0323b3fe8b6b7f4ca0cd7ae7faebe4b" } use_environment = "testnet" manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" deps = { MoveStdlib = "MoveStdlib" } diff --git a/packages/ptb/Move.lock b/packages/ptb/Move.lock index 4ab5128..fa5d7d6 100644 --- a/packages/ptb/Move.lock +++ b/packages/ptb/Move.lock @@ -5,13 +5,13 @@ version = 4 [pinned.testnet.MoveStdlib] -source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "563c15820b27dec9cbe75f826a3b6243ef44da1a" } +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "b38bca86f0323b3fe8b6b7f4ca0cd7ae7faebe4b" } use_environment = "testnet" manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" deps = {} [pinned.testnet.Sui] -source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "563c15820b27dec9cbe75f826a3b6243ef44da1a" } +source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "b38bca86f0323b3fe8b6b7f4ca0cd7ae7faebe4b" } use_environment = "testnet" manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" deps = { MoveStdlib = "MoveStdlib" } From bef52eaff2f7ed7dc186cdb9db3df79bc318ce9a Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 15:09:20 +0300 Subject: [PATCH 08/11] patch e2e test sample --- sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move b/sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move index f731906..379c29e 100644 --- a/sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move +++ b/sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move @@ -12,7 +12,7 @@ use pas::namespace::Namespace; use pas::policy::{Self, Policy, PolicyCap}; use pas::request::Request; use pas::send_funds::SendFunds; -use pas::templates::Templates; +use pas::templates::{PAS, Templates}; use ptb::ptb; use std::type_name; use sui::balance::Balance; @@ -97,7 +97,7 @@ entry fun setup(namespace: &mut Namespace, templates: &mut Templates, faucet: &m type_name.address_string().to_string(), "demo_usd", "approve_transfer", - vector[ptb::ext_input("pas:request"), ptb::object_by_id(@0x6.to_id())], + vector[ptb::ext_input("pas:request"), ptb::object_by_id(@0x6.to_id())], vector[(*type_name.as_string()).to_string()], ); @@ -115,7 +115,7 @@ public fun use_v2( type_name::with_defining_ids().address_string().to_string(), "demo_usd", "approve_transfer_v2", - vector[ptb::ext_input("pas:request"), ptb::object_by_id(object::id(faucet))], + vector[ptb::ext_input("pas:request"), ptb::object_by_id(object::id(faucet))], vector[], ); From 3aeba7415a0f3ea15e2c35475c1ed4584a28e0cc Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 15:15:45 +0300 Subject: [PATCH 09/11] nits and bits - no longer pas: prefix - move demo_usd as example - little type magic --- .../sources => pas/examples}/demo_usd.move | 6 ++-- packages/testing/demo_usd/Move.lock | 35 ------------------- packages/testing/demo_usd/Move.toml | 7 ---- sdk/pas/src/resolution.ts | 19 +++++----- .../e2e/data/demo_usd/sources/demo_usd.move | 4 +-- 5 files changed, 16 insertions(+), 55 deletions(-) rename packages/{testing/demo_usd/sources => pas/examples}/demo_usd.move (95%) delete mode 100644 packages/testing/demo_usd/Move.lock delete mode 100644 packages/testing/demo_usd/Move.toml diff --git a/packages/testing/demo_usd/sources/demo_usd.move b/packages/pas/examples/demo_usd.move similarity index 95% rename from packages/testing/demo_usd/sources/demo_usd.move rename to packages/pas/examples/demo_usd.move index eeed684..2762a78 100644 --- a/packages/testing/demo_usd/sources/demo_usd.move +++ b/packages/pas/examples/demo_usd.move @@ -6,7 +6,7 @@ /// This module defines a DEMO_USD witness type that gets registered in the PAS system /// during package initialization. It sets up a Policy with resolution commands for /// SendFunds and UnlockFunds actions. -module demo_usd::demo_usd; +module pas::demo_usd; use pas::namespace::Namespace; use pas::policy::{Self, Policy, PolicyCap}; @@ -97,7 +97,7 @@ entry fun setup(namespace: &mut Namespace, templates: &mut Templates, faucet: &m type_name.address_string().to_string(), "demo_usd", "approve_transfer", - vector[ptb::ext_input("pas:request"), ptb::object_by_id(@0x6.to_id())], + vector[ptb::ext_input("request"), ptb::object_by_id(@0x6.to_id())], vector[(*type_name.as_string()).to_string()], ); @@ -115,7 +115,7 @@ public fun use_v2( type_name::with_defining_ids().address_string().to_string(), "demo_usd", "approve_transfer_v2", - vector[ptb::ext_input("pas:request"), ptb::object_by_id(object::id(faucet))], + vector[ptb::ext_input("request"), ptb::object_by_id(object::id(faucet))], vector[], ); diff --git a/packages/testing/demo_usd/Move.lock b/packages/testing/demo_usd/Move.lock deleted file mode 100644 index 177dc62..0000000 --- a/packages/testing/demo_usd/Move.lock +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by move; do not edit -# This file should be checked in. - -[move] -version = 4 - -[pinned.testnet.MoveStdlib] -source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "b38bca86f0323b3fe8b6b7f4ca0cd7ae7faebe4b" } -use_environment = "testnet" -manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363" -deps = {} - -[pinned.testnet.Sui] -source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "b38bca86f0323b3fe8b6b7f4ca0cd7ae7faebe4b" } -use_environment = "testnet" -manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C" -deps = { MoveStdlib = "MoveStdlib" } - -[pinned.testnet.demo_usd] -source = { root = true } -use_environment = "testnet" -manifest_digest = "F42F13A0483640C91598349E0E0C125899BD5635A850639255F6EC2E598ADAF8" -deps = { pas = "pas", ptb = "ptb", std = "MoveStdlib", sui = "Sui" } - -[pinned.testnet.pas] -source = { local = "../../pas" } -use_environment = "testnet" -manifest_digest = "38AA62656ABE7551C444DA427ADBAA7751CB67250663D39FCDE36E938138EA7D" -deps = { ptb = "ptb", std = "MoveStdlib", sui = "Sui" } - -[pinned.testnet.ptb] -source = { local = "../../ptb" } -use_environment = "testnet" -manifest_digest = "5745706258F61D6CE210904B3E6AE87A73CE9D31A6F93BE4718C442529332A87" -deps = { std = "MoveStdlib", sui = "Sui" } diff --git a/packages/testing/demo_usd/Move.toml b/packages/testing/demo_usd/Move.toml deleted file mode 100644 index f727418..0000000 --- a/packages/testing/demo_usd/Move.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "demo_usd" -edition = "2024.beta" - -[dependencies] -pas = { local = "../../pas" } -ptb = { local = "../../ptb" } diff --git a/sdk/pas/src/resolution.ts b/sdk/pas/src/resolution.ts index ac728f1..52ce10f 100644 --- a/sdk/pas/src/resolution.ts +++ b/sdk/pas/src/resolution.ts @@ -196,7 +196,7 @@ export function buildMoveCallCommandFromTemplate( ); } } else if (arg.Input.Ext) { - resolvedArgs.push(resolveRawPasRequest(args, arg.Input.Ext.value)); + resolvedArgs.push(resolveRawPasRequest(args, arg.Input.Ext)); } else { throw new PASClientError(`Unsupported input kind: ${arg.Input.$kind}`); } @@ -221,22 +221,25 @@ export function buildMoveCallCommandFromTemplate( }); } -function resolveRawPasRequest(args: RawCommandBuildArgs, value: string): Argument { - switch (value) { - case 'pas:request': +function resolveRawPasRequest(args: RawCommandBuildArgs, extInput: { _namespace: string, value: string }): Argument { + // do the logic on `namespace` here + // return error if it's not PAS + + switch (extInput.value) { + case 'request': if (!args.request) throw new PASClientError(`Request is not set in the context.`); return args.request; - case 'pas:policy': + case 'policy': if (!args.policy) throw new PASClientError(`Policy is not set in the context.`); return args.policy; - case 'pas:sender_chest': + case 'sender_chest': if (!args.senderChest) throw new PASClientError(`Sender chest is not set in the context.`); return args.senderChest; - case 'pas:receiver_chest': + case 'receiver_chest': if (!args.receiverChest) throw new PASClientError(`Receiver chest is not set in the context.`); return args.receiverChest; default: - throw new PASClientError(`Unknown pas request: ${value}`); + throw new PASClientError(`Unknown pas request: ${extInput.value}`); } } diff --git a/sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move b/sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move index 379c29e..6fdef81 100644 --- a/sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move +++ b/sdk/pas/test/e2e/data/demo_usd/sources/demo_usd.move @@ -97,7 +97,7 @@ entry fun setup(namespace: &mut Namespace, templates: &mut Templates, faucet: &m type_name.address_string().to_string(), "demo_usd", "approve_transfer", - vector[ptb::ext_input("pas:request"), ptb::object_by_id(@0x6.to_id())], + vector[ptb::ext_input("request"), ptb::object_by_id(@0x6.to_id())], vector[(*type_name.as_string()).to_string()], ); @@ -115,7 +115,7 @@ public fun use_v2( type_name::with_defining_ids().address_string().to_string(), "demo_usd", "approve_transfer_v2", - vector[ptb::ext_input("pas:request"), ptb::object_by_id(object::id(faucet))], + vector[ptb::ext_input("request"), ptb::object_by_id(object::id(faucet))], vector[], ); From 9730418612ed2373288e3d4fb94f40ecfd6c2133 Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 15:17:11 +0300 Subject: [PATCH 10/11] adds accumulator root --- packages/ptb/sources/ptb.move | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/ptb/sources/ptb.move b/packages/ptb/sources/ptb.move index 2b6b27c..85df124 100644 --- a/packages/ptb/sources/ptb.move +++ b/packages/ptb/sources/ptb.move @@ -174,6 +174,9 @@ public fun deny_list(): Argument { object_by_id(@0x403.to_id()) } /// Shorthand for `object_by_id` with `0xC` (CoinRegistry). public fun coin_registry(): Argument { object_by_id(@0xC.to_id()) } +/// Shorthand for `object_by_id` with `0xACC` (AccumulatorRoot). +public fun accumulator_root(): Argument { object_by_id(@0xacc.to_id()) } + // === Inputs === /// Create a gas coin input. From 140322d6e115c4dfab55a4ceb489a8f51ff8482a Mon Sep 17 00:00:00 2001 From: Damir Shamanaev Date: Tue, 10 Mar 2026 15:18:36 +0300 Subject: [PATCH 11/11] patch formatting --- packages/pas/examples/demo_usd.move | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/pas/examples/demo_usd.move b/packages/pas/examples/demo_usd.move index 2762a78..dd68575 100644 --- a/packages/pas/examples/demo_usd.move +++ b/packages/pas/examples/demo_usd.move @@ -8,17 +8,16 @@ /// SendFunds and UnlockFunds actions. module pas::demo_usd; -use pas::namespace::Namespace; -use pas::policy::{Self, Policy, PolicyCap}; -use pas::request::Request; -use pas::send_funds::SendFunds; -use pas::templates::{PAS, Templates}; +use pas::{ + namespace::Namespace, + policy::{Self, Policy, PolicyCap}, + request::Request, + send_funds::SendFunds, + templates::{PAS, Templates} +}; use ptb::ptb; use std::type_name; -use sui::balance::Balance; -use sui::clock::Clock; -use sui::coin::TreasuryCap; -use sui::coin_registry::{Self, MetadataCap}; +use sui::{balance::Balance, clock::Clock, coin::TreasuryCap, coin_registry::{Self, MetadataCap}}; #[error(code = 0)] const EInvalidAmount: vector = b"Any amount over 10K is not allowed in this demo.";