Implementing Transferable Witness Pattern in Sui
In this tutorial, we will demonstrate how to implement the Transferable Witness pattern in the Sui ecosystem. This pattern is based on a combination of two other patterns: Capability and Witness. Transferable Witness pattern can be useful when type authorization by one module is needed to be used in another module or when authorization should be performed after some time.
Here are the steps to implement the Transferable Witness pattern:
- Create the transferable_witness module: Define a new module
examples::transferable_witness
that will implement the Transferable Witness pattern.
module examples::transferable_witness {
use sui::transfer;
use sui::object::{Self, UID};
use sui::tx_context::{Self, TxContext};
}
- Define the WITNESS type: Create a
WITNESS
type that hasstore
anddrop
abilities. Thestore
ability allows storing the witness inside a wrapper.
struct WITNESS has store, drop {}
- Define the WitnessCarrier type: Create a
WitnessCarrier
type that has thekey
ability and carries theWITNESS
type. TheWitnessCarrier
can be used only once to get aWITNESS
.
struct WitnessCarrier has key { id: UID, witness: WITNESS }
- Initialize the module: Create an
init
function that sends aWitnessCarrier
to the module publisher. This function will be called once on module publish.
fun init(ctx: &mut TxContext) {
transfer::transfer(
WitnessCarrier { id: object::new(ctx), witness: WITNESS {} },
tx_context::sender(ctx)
)
}
- Create the get_witness function: Define a public function
get_witness
that takes aWitnessCarrier
as an argument and returns the innerWITNESS
type. The function unwraps the carrier and deletes the carrier'sid
before returning thewitness
.
public fun get_witness(carrier: WitnessCarrier): WITNESS {
let WitnessCarrier { id, witness } = carrier;
object::delete(id);
witness
}
By following these steps, you can implement the Transferable Witness pattern in the Sui ecosystem. This pattern combines the Capability and Witness patterns to allow type authorization by one module to be used in another module or to perform authorization after some time.