Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/pas/Move.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@
/// 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;

use pas::namespace::Namespace;
use pas::policy::{Self, Policy, PolicyCap};
use pas::request::Request;
use pas::send_funds::SendFunds;
use pas::templates::Templates;
module pas::demo_usd;

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<u8> = b"Any amount over 10K is not allowed in this demo.";
Expand Down Expand Up @@ -97,7 +96,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()],
);

Expand All @@ -115,7 +114,7 @@ public fun use_v2(
type_name::with_defining_ids<DEMO_USD>().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[],
);

Expand Down
3 changes: 3 additions & 0 deletions packages/pas/sources/templates.move
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use sui::{derived_object, dynamic_field};
#[error(code = 0)]
const ETemplateNotSet: vector<u8> = b"Template not set for this action.";

/// Namespacing type for `ext_input`'s.
public struct PAS {}

public struct Templates has key {
id: UID,
}
Expand Down
4 changes: 2 additions & 2 deletions packages/ptb/Move.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
41 changes: 34 additions & 7 deletions packages/ptb/sources/ptb.move
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ use std::bcs;
use std::string::String;
use std::type_name;

// TODO: what should be a standard delimiter for namespaces?
const OBJECT_BY_ID_EXT: vector<u8> = b"object_by_id:";
const OBJECT_BY_TYPE_EXT: vector<u8> = b"object_by_type:";
const RECEIVING_BY_ID_EXT: vector<u8> = 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<CallArg>,
commands: vector<Command>,
}

Expand Down Expand Up @@ -110,7 +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`.
Ext(String),
///
/// 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(String, String),
}

/// Defines a simplified `ObjectArg` type for the `Transaction`.
Expand Down Expand Up @@ -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 ===
Expand All @@ -158,6 +168,15 @@ 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()) }

/// 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.
Expand Down Expand Up @@ -248,8 +267,16 @@ 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<T>(name: String): Argument {
Argument::Input(
CallArg::Ext((*type_name::with_original_ids<T>().as_string()).to_string(), name),
)
}

/// Create an external input handler for a given type T.
/// 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
Expand Down Expand Up @@ -337,7 +364,7 @@ public fun upgrade(

/// Create an `Ext` command.
public fun ext(data: vector<u8>): Command {
Command(7, data)
Command(EXT_TAG, data)
}

// === Test Features ===
Expand Down
159 changes: 150 additions & 9 deletions packages/ptb/tests/ptb_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -18,27 +26,160 @@ 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(
@0x0.to_string(),
"demo_usd",
"resolve_transfer",
vector[
ptb::ext_input("request"), // TODO: consider namespaces here?
ptb::ext_input("policy_arg"),
ptb::clock(),
],
vector[ptb::ext_input<PAS>("request"), ptb::ext_input<PAS>("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<NFT>().as_string()).to_string();

let paid = ptb.command(
ptb::move_call(
@0x2.to_string(),
"transfer_policy",
"paid",
vector[ptb::ext_input<Kiosk>("request")],
vector[nft_type],
),
);

// TODO: compiler panic!
// std::debug::print(&_mc);
let fee_amount = ptb.command(
ptb::move_call(
"@mysten/kiosk",
"royalty_rule",
"fee_amount",
vector[ptb::ext_input<Kiosk>("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(
"@mysten/kiosk",
"royalty_rule",
"pay",
vector[
ptb::ext_input<Kiosk>("policy"),
ptb::ext_input<Kiosk>("request"),
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<Kiosk>("buyer_kiosk"), ptb::ext_input<Kiosk>("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<Kiosk>("request"), ptb::ext_input<Kiosk>("buyer_kiosk")],
vector[nft_type],
),
);

// confirm the request
ptb.command(
ptb::move_call(
@0x2.to_string(),
"transfer_policy",
"confirm_request",
vector[ptb::ext_input<Kiosk>("policy"), ptb::ext_input<Kiosk>("request")],
vector[nft_type],
),
);
}
35 changes: 0 additions & 35 deletions packages/testing/demo_usd/Move.lock

This file was deleted.

Loading