Skip to content

SIP: PTB Type Argument Interpolation - #68

Open
92GC wants to merge 4 commits into
sui-foundation:mainfrom
92GC:sip-ptb-type-interpolation
Open

SIP: PTB Type Argument Interpolation#68
92GC wants to merge 4 commits into
sui-foundation:mainfrom
92GC:sip-ptb-type-interpolation

Conversation

@92GC

@92GC 92GC commented Jan 5, 2026

Copy link
Copy Markdown

Summary

Extend PTBs so later commands can reference both:

  1. types defined by an earlier Publish command; and
  2. functions inside the newly published package.

Currently package IDs must be known when the PTB is constructed. This prevents atomic workflows that publish a package,
initialize its assets, and register those assets with existing protocols such as PAS or Govex.

The Problem

const ptb = new Transaction();
const publication = ptb.publish({ modules, dependencies });

// FAILS: cannot call a function in the newly published package.
const [treasuryCap] = ptb.moveCall({
  target: `${???}::my_coin::create_currency`,
  arguments: [coinRegistry],
});

// FAILS: cannot use the newly published type with an existing package.
ptb.moveCall({
  target: `${pasPackage}::policy::new_for_currency`,
  typeArguments: [`${???}::my_coin::MY_COIN`],
  arguments: [namespace, treasuryCap, false],
});

This is particularly relevant to PAS.

PAS creates a policy for an existing currency type:

policy::new_for_currency<C>(
    namespace,
    treasury_cap: &mut TreasuryCap<C>,
    clawback_allowed,
)

A JIT workflow therefore needs to:

  1. publish the module defining C;
  2. call that module to create and return TreasuryCap<C>;
  3. pass C and its TreasuryCap<C> to PAS;
  4. register the asset with Govex and create the proposal.

Type-argument interpolation solves step 3, but calling the newly published currency factory also requires target-package
interpolation.

The Solution

const publication = ptb.publish({ modules, dependencies });

const coinType = ptb.typeFromResult(
  publication,
  "my_coin",
  "MY_COIN",
);

const [treasuryCap] = ptb.moveCall({
  target: ptb.targetFromResult(
    publication,
    "my_coin",
    "create_currency",
  ),
  arguments: [coinRegistry],
});

const [policy, policyCap] = ptb.moveCall({
  target: `${pasPackage}::policy::new_for_currency`,
  typeArguments: [coinType],
  arguments: [namespace, treasuryCap, false],
});

ptb.moveCall({
  target: `${govexPackage}::proposal::register_conditional_asset`,
  typeArguments: [coinType],
  arguments: [proposal, treasuryCap, policy],
});

This enables a single PTB to:

  • create its currency and TreasuryCap;
  • create its PAS policy;
  • register it with Govex; and
  • create the proposal.

92GC and others added 4 commits January 5, 2026 21:22
Enables type arguments in PTB commands to reference Results from prior commands,
allowing publish-and-use in a single transaction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant