<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: truong</title>
    <description>The latest articles on DEV Community by truong (@truongnx).</description>
    <link>https://dev.to/truongnx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1215085%2F75048671-82f6-4723-a288-b2a00cf291ce.png</url>
      <title>DEV Community: truong</title>
      <link>https://dev.to/truongnx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/truongnx"/>
    <language>en</language>
    <item>
      <title>Sui basic - Managed coin</title>
      <dc:creator>truong</dc:creator>
      <pubDate>Fri, 24 Nov 2023 16:34:25 +0000</pubDate>
      <link>https://dev.to/truongnx/sui-basic-managed-coin-5foi</link>
      <guid>https://dev.to/truongnx/sui-basic-managed-coin-5foi</guid>
      <description>&lt;p&gt;Now we have peeked under the hood of the &lt;code&gt;sui::coin&lt;/code&gt; module, we can look at a simple but complete example of creating a type of custom fungible token where there is a trusted manager that has the capability to mint and burn, similar to many ERC-20 implementations. &lt;/p&gt;

&lt;h2&gt;
  
  
  Smart Contract
&lt;/h2&gt;

&lt;p&gt;You can find the complete &lt;a href="//../example_projects/fungible_tokens/sources/managed.move"&gt;Managed Coin example contract&lt;/a&gt; under the example project folder.&lt;/p&gt;

&lt;p&gt;Given what we have covered so far, this contract should be fairly easy to understand. It follows the &lt;a href="//./3_witness_design_pattern.md#one-time-witness"&gt;One Time Witness&lt;/a&gt; pattern exactly, where the &lt;code&gt;witness&lt;/code&gt; resource is named &lt;code&gt;MANAGED&lt;/code&gt;, and automatically created by the module &lt;code&gt;init&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; function then calls &lt;code&gt;coin::create_currency&lt;/code&gt; to get the &lt;code&gt;TreasuryCap&lt;/code&gt; and &lt;code&gt;CoinMetadata&lt;/code&gt; resources. The parameters passed into this function are the fields of the &lt;code&gt;CoinMetadata&lt;/code&gt; object, so include the token name, symbol, icon URL, etc. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CoinMetadata&lt;/code&gt; is immediately frozen after creation via the &lt;code&gt;transfer::freeze_object&lt;/code&gt; method, so that it becomes a &lt;a href="//../../unit-two/lessons/2_ownership.md#shared-immutable-objects"&gt;shared immutable object&lt;/a&gt; that can be read by any address. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;TreasuryCap&lt;/code&gt; &lt;a href="//../../unit-two/lessons/6_capability_design_pattern.md"&gt;Capability&lt;/a&gt; object is used as a way to control access to the &lt;code&gt;mint&lt;/code&gt; and &lt;code&gt;burn&lt;/code&gt; methods that create or destroy &lt;code&gt;Coin&amp;lt;MANAGED&amp;gt;&lt;/code&gt; objects respectively. &lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing and CLI Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Publish the Module
&lt;/h3&gt;

&lt;p&gt;Under the &lt;a href="//../example_projects/fungible_tokens/"&gt;fungible_tokens&lt;/a&gt; project folder, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    sui client publish &lt;span class="nt"&gt;--gas-budget&lt;/span&gt; 10000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see console output similar to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zL6Ro5JU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/a6a3aee1-ca0e-4ece-b2b8-19cd942a3b3a" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zL6Ro5JU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/a6a3aee1-ca0e-4ece-b2b8-19cd942a3b3a" alt="Publish Output" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two immutable objects created are respectively the package itself and the &lt;code&gt;CoinMetadata&lt;/code&gt; object of &lt;code&gt;Managed Coin&lt;/code&gt;. And the owned object passed to the transaction sender is the &lt;code&gt;TreasuryCap&lt;/code&gt; object of &lt;code&gt;Managed Coin&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Export the object IDs of the package object and the &lt;code&gt;TreasuryCap&lt;/code&gt; object to environmental variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PACKAGE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;package object ID from previous output&amp;gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TREASURYCAP_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;treasury cap object ID from previous output&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Minting Tokens
&lt;/h3&gt;

&lt;p&gt;To mint some &lt;code&gt;MNG&lt;/code&gt; tokens, we can use the following CLI command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    sui client call &lt;span class="nt"&gt;--function&lt;/span&gt; mint &lt;span class="nt"&gt;--module&lt;/span&gt; managed &lt;span class="nt"&gt;--package&lt;/span&gt; &lt;span class="nv"&gt;$PACKAGE_ID&lt;/span&gt; &lt;span class="nt"&gt;--args&lt;/span&gt; &lt;span class="nv"&gt;$TREASURYCAP_ID&lt;/span&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&amp;lt;amount to mint&amp;gt;&lt;span class="se"&gt;\"&lt;/span&gt; &amp;lt;recipient address&amp;gt; &lt;span class="nt"&gt;--gas-budget&lt;/span&gt; 10000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;💡Note: as of Sui binary version 0.21.0, &lt;code&gt;u64&lt;/code&gt; inputs must be escaped as strings, thus the above CLI command format. This might change in a future version.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dWchevEH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/c8c40802-1b00-4a5a-9fc5-c60e592d4295" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dWchevEH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/c8c40802-1b00-4a5a-9fc5-c60e592d4295" alt="Minting" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Export the object ID of the newly minted &lt;code&gt;COIN&amp;lt;MANAGED&amp;gt;&lt;/code&gt; object to a bash variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;COIN_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;coin object ID from previous output&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that the &lt;code&gt;Supply&lt;/code&gt; field under the &lt;code&gt;TreasuryCap&amp;lt;MANAGED&amp;gt;&lt;/code&gt; object should be increased by the amount minted. &lt;/p&gt;

&lt;h3&gt;
  
  
  Burning Tokens
&lt;/h3&gt;

&lt;p&gt;To burn an existing &lt;code&gt;COIN&amp;lt;MANAGED&amp;gt;&lt;/code&gt; object, we use the following CLI command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    sui client call &lt;span class="nt"&gt;--function&lt;/span&gt; burn &lt;span class="nt"&gt;--module&lt;/span&gt; managed &lt;span class="nt"&gt;--package&lt;/span&gt; &lt;span class="nv"&gt;$PACKAGE_ID&lt;/span&gt; &lt;span class="nt"&gt;--args&lt;/span&gt; &lt;span class="nv"&gt;$TREASURYCAP_ID&lt;/span&gt; &lt;span class="nv"&gt;$COIN_ID&lt;/span&gt; &lt;span class="nt"&gt;--gas-budget&lt;/span&gt; 10000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that the &lt;code&gt;Supply&lt;/code&gt; field under the &lt;code&gt;TreasuryCap&amp;lt;MANAGED&amp;gt;&lt;/code&gt; object should be back to &lt;code&gt;0&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Exercise: What other commonly used functions do fungible tokens need? You should know enough about programming in Move now to try to implement some of these functions.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Part 7: &lt;a href="https://dev.to/truongnx/sui-basic-generics-2c64"&gt;Generics&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sui</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Sui basic - Generics</title>
      <dc:creator>truong</dc:creator>
      <pubDate>Fri, 24 Nov 2023 16:27:11 +0000</pubDate>
      <link>https://dev.to/truongnx/sui-basic-generics-2c64</link>
      <guid>https://dev.to/truongnx/sui-basic-generics-2c64</guid>
      <description>&lt;h2&gt;
  
  
  Intro to Generics
&lt;/h2&gt;

&lt;p&gt;Generics are abstract stand-ins for concrete types or other properties. They work similarly to &lt;a href="https://doc.rust-lang.org/stable/book/ch10-00-generics.html"&gt;generics in Rust&lt;/a&gt;, and can be used to allow greater flexibility and avoid logic duplication while writing Sui Move code.&lt;/p&gt;

&lt;p&gt;Generics are a key concept in Sui Move, and it's important to understand and have an intuition for how they work, so take your time with this section and understand every part fully. &lt;/p&gt;

&lt;h2&gt;
  
  
  Generics Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using Generics in Structs
&lt;/h3&gt;

&lt;p&gt;Let's look at a basic example of how to use generics to create a container &lt;code&gt;Box&lt;/code&gt; that can hold any type in Sui Move.&lt;/p&gt;

&lt;p&gt;First, without generics, we can define a &lt;code&gt;Box&lt;/code&gt; that holds a &lt;code&gt;u64&lt;/code&gt; type as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;module&lt;/span&gt;  &lt;span class="nn"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this type will only be able to hold a value of type &lt;code&gt;u64&lt;/code&gt;. To make our &lt;code&gt;Box&lt;/code&gt; able to hold any generic type, we will need to use generics. The code would be modified as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;module&lt;/span&gt;  &lt;span class="nn"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Ability Constraints
&lt;/h4&gt;

&lt;p&gt;We can add conditions to enforce that the type passed into the generic must have certain abilities. The syntax looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;module&lt;/span&gt;  &lt;span class="nn"&gt;generics&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// T must be copyable and droppable &lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;drop&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡It's important to note here that the inner type &lt;code&gt;T&lt;/code&gt; in the above example must meet certain ability constraints due to the outer container type. In this example, &lt;code&gt;T&lt;/code&gt; must have &lt;code&gt;store&lt;/code&gt;, as &lt;code&gt;Box&lt;/code&gt; has &lt;code&gt;store&lt;/code&gt; and &lt;code&gt;key&lt;/code&gt;. However, &lt;code&gt;T&lt;/code&gt; can also have abilities that the container doesn't have, such as &lt;code&gt;drop&lt;/code&gt; in this example.&lt;/p&gt;

&lt;p&gt;The intuition is that if the container is allowed to contain a type that does not follow the same rules that it does, the container would violate its own ability. How can a box be storeable if its content isn't also storeable?&lt;/p&gt;

&lt;p&gt;We will see in the next section that there is a way to get around this rule in certain cases using a special keyword, called &lt;code&gt;phantom&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;💡See the &lt;a href="//./sources/generics.move"&gt;generics project&lt;/a&gt; under &lt;code&gt;example_projects&lt;/code&gt; for some examples of generic types.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Generics in Functions
&lt;/h3&gt;

&lt;p&gt;To write a function that returns an instance of &lt;code&gt;Box&lt;/code&gt; that can accept a parameter of any type for the &lt;code&gt;value&lt;/code&gt; field, we also have to use generics in the function definition. The function can be defined as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;create_box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to restrict the function to only accept a specific type for &lt;code&gt;value&lt;/code&gt;, we simply specify that type in the function signature as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;create_box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will only accept inputs of the type &lt;code&gt;u64&lt;/code&gt; for the &lt;code&gt;create_box&lt;/code&gt; method, while still using the same generic &lt;code&gt;Box&lt;/code&gt; struct. &lt;/p&gt;

&lt;h4&gt;
  
  
  Calling Functions with Generics
&lt;/h4&gt;

&lt;p&gt;To call a function with a signature that contains generics, we must specify the type in angle brackets, as in the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// value will be of type storage::Box&amp;lt;bool&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;bool_box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;create_box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// value will be of the type storage::Box&amp;lt;u64&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;u64_box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;create_box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Calling Functions with Generics using Sui CLI
&lt;/h4&gt;

&lt;p&gt;To call a function with generics in its signature from the Sui CLI, you must define the argument's type using the flag &lt;code&gt;--type-args&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following is an example that calls the &lt;code&gt;create_box&lt;/code&gt; function to create a box that contains a coin of the type &lt;code&gt;0x2::sui::SUI&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sui client call &lt;span class="nt"&gt;--package&lt;/span&gt; 0xbff5d0f3202e3b19e622b13819f269ae9aad904436cc557bace358266938e2ec &lt;span class="nt"&gt;--module&lt;/span&gt; generics &lt;span class="nt"&gt;--function&lt;/span&gt; create_box &lt;span class="nt"&gt;--args&lt;/span&gt; &lt;span class="nv"&gt;$OBJECT_ID&lt;/span&gt; &lt;span class="nt"&gt;--type-args&lt;/span&gt; 0x2::sui::SUI &lt;span class="nt"&gt;--gas-budget&lt;/span&gt; 10000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: tạo 1 object simple_box then put it into a box&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Generics Syntax
&lt;/h2&gt;

&lt;p&gt;For more advanced syntax involving the use of generics in Sui Move, such as multiple generic types, please refer to the excellent &lt;a href="https://move-book.com/advanced-topics/understanding-generics.html"&gt;section on generics in the Move Book&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;But for our current lesson on fungible tokens, you already know enough about how generics work to proceed. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Here is example &lt;a href="https://github.com/truonggau/sui-tutorial/blob/main/sui_coin_demo/sources/generics.move"&gt;code&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Part 6: &lt;a href="https://dev.to/truongnx/sui-basic-events-1gh5"&gt;Events&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sui</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Sui basic - events</title>
      <dc:creator>truong</dc:creator>
      <pubDate>Thu, 23 Nov 2023 03:36:25 +0000</pubDate>
      <link>https://dev.to/truongnx/sui-basic-events-1gh5</link>
      <guid>https://dev.to/truongnx/sui-basic-events-1gh5</guid>
      <description>&lt;h1&gt;
  
  
  Events
&lt;/h1&gt;

&lt;p&gt;Events are important for Sui Move smart contracts, as it is the main way for indexers to track actions on-chain. You can understand it as logging on server backends, and indexers as parsers.&lt;/p&gt;

&lt;p&gt;Events on Sui are also represented as objects. There are several types of system level events in Sui, including Move event, Publish event, Transfer object event, and so on. For the full list of system event types, please refer to the &lt;a href="https://docs.sui.io/build/event_api"&gt;Sui Events API page here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The event details of a transaction can be viewed on the &lt;a href="https://suiexplorer.com/"&gt;Sui Explorer&lt;/a&gt; under the &lt;code&gt;Events&lt;/code&gt; tab:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---67K1vnL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/b3292df5-1180-4807-b38f-440d916407f3" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---67K1vnL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/b3292df5-1180-4807-b38f-440d916407f3" alt="Screenshot 2023-11-16 at 16 30 48" width="800" height="208"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Custom Events
&lt;/h2&gt;

&lt;p&gt;Developers can also define custom events on Sui. We can define a custom event marking when a transcript has been requested in the following way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="cd"&gt;/// Event marking when a transcript has been requested&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;TranscriptRequestEvent&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;drop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// The Object ID of the transcript wrapper&lt;/span&gt;
        &lt;span class="n"&gt;wrapper_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// The requester of the transcript&lt;/span&gt;
        &lt;span class="n"&gt;requester&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// The intended address of the transcript&lt;/span&gt;
        &lt;span class="n"&gt;intended_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The type representing an event has the abilities &lt;code&gt;copy&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt;. Event objects aren't representing assets, and we are only interested in the data contained within, so they can be duplicated, and dropped at the end of scopes.&lt;/p&gt;

&lt;p&gt;To emit an event in Sui, you just need to use the &lt;a href="https://github.com/MystenLabs/sui/blob/main/crates/sui-framework/docs/event.md#function-emit"&gt;&lt;code&gt;sui::event::emit&lt;/code&gt; method&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's modify our &lt;code&gt;request_transcript&lt;/code&gt; method to emit this event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;request_transcript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WrappableTranscript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intended_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TxContext&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;folderObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Folder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;intended_address&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nn"&gt;event&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TranscriptRequestEvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;wrapper_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;uid_to_inner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;folderObject&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;requester&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;tx_context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;intended_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="c1"&gt;//We transfer the wrapped transcript object directly to the intended address&lt;/span&gt;
        &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folderObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intended_address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Sui explorer, we can see the event emitted displayed as the following, showing the three data fields that we defined in the &lt;code&gt;TranscriptRequestEvent&lt;/code&gt; event:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zwbDOZ_0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/b7378a85-456e-43b3-a3cb-974b6d20cde4" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zwbDOZ_0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/b7378a85-456e-43b3-a3cb-974b6d20cde4" alt="Screenshot 2023-11-16 at 16 29 52" width="800" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Here is example code: &lt;a href="https://github.com/truonggau/sui-tutorial/blob/main/basic_example/basic_example/build/basic_example/sources/transcript_4.move"&gt;sui&lt;/a&gt; and &lt;a href="https://github.com/truonggau/sui-tutorial/blob/main/basic_example/js/main.js"&gt;js&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Try out creating, requesting and unpacking transcripts using the Sui CLI client and the Sui explorer to check the result. &lt;/p&gt;

&lt;p&gt;That's the end of basic example, great job!&lt;/p&gt;

&lt;h2&gt;
  
  
  Referent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Part 5: &lt;a href="https://dev.to/truongnx/sui-basic-capability-design-pattern-22mn"&gt;Capability Design Pattern&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 7: &lt;a href="https://dev.to/truongnx/sui-basic-generics-2c64"&gt;Generics&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sui</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Sui basic - Capability Design Pattern</title>
      <dc:creator>truong</dc:creator>
      <pubDate>Thu, 23 Nov 2023 03:26:51 +0000</pubDate>
      <link>https://dev.to/truongnx/sui-basic-capability-design-pattern-22mn</link>
      <guid>https://dev.to/truongnx/sui-basic-capability-design-pattern-22mn</guid>
      <description>&lt;h2&gt;
  
  
  Capability Design Pattern
&lt;/h2&gt;

&lt;p&gt;Now we have the basics of a transcript publishing system, we want to add some access control to our smart contract. &lt;/p&gt;

&lt;p&gt;Capability is a commonly used pattern in Move that allows fine-tuned access control using an object-centric model. Let's take a look at how we can define this capability object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Type that marks the capability to create, update, and delete transcripts&lt;/span&gt;
  &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;TeacherCap&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UID&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define a new struct &lt;code&gt;TeacherCap&lt;/code&gt; that marks the capability to perform privileged actions on transcripts. If we want the capability to be non-transferrable, we simply do not add the &lt;code&gt;storage&lt;/code&gt; ability to the struct. &lt;/p&gt;

&lt;p&gt;*💡Note: This is also how the equivalent of soulbound tokens (SBT) can be easily implemented in Move. You simply define a struct that has the &lt;code&gt;key&lt;/code&gt; ability, but not the &lt;code&gt;store&lt;/code&gt; ability. &lt;/p&gt;

&lt;h2&gt;
  
  
  Passing and Consuming Capability Objects
&lt;/h2&gt;

&lt;p&gt;Next, we need to modify the methods which should be callable by someone with the &lt;code&gt;TeacherCap&lt;/code&gt; capability object to take in the capability as an extra parameter and consume it immediately. &lt;/p&gt;

&lt;p&gt;For example, for the &lt;code&gt;create_wrappable_transcript_object&lt;/code&gt; method, we can modify it as the follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;create_wrappable_transcript_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;TeacherCap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TxContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;wrappableTranscript&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WrappableTranscript&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wrappableTranscript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;tx_context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We pass in a reference to &lt;code&gt;TeacherCap&lt;/code&gt; capability object and consume it immediately with the &lt;code&gt;_&lt;/code&gt; notation for unused variables and parameters. Note that because we are only passing in a reference to the object, consuming the reference has no effect on the original object. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Quiz: What happens if try to pass in &lt;code&gt;TeacherCap&lt;/code&gt; by value?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This means only an address that has a &lt;code&gt;TeacherCap&lt;/code&gt; object can call this method, effectively implementing access control on this method.&lt;/p&gt;

&lt;p&gt;We make similar modifications to all other methods in the contract that perform privileged actions on transcripts. &lt;/p&gt;

&lt;h2&gt;
  
  
  Initializer Function
&lt;/h2&gt;

&lt;p&gt;A module's initializer function is called once upon publishing the module. This is useful for initializing the state of the smart contract, and is used often to send out the initial set of capability objects. &lt;/p&gt;

&lt;p&gt;In our example, we can define the &lt;code&gt;init&lt;/code&gt; method as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="cd"&gt;/// Module initializer is called only once on module publish.&lt;/span&gt;
    &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TxContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TeacherCap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nn"&gt;tx_context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create one copy of the &lt;code&gt;TeacherCap&lt;/code&gt; object and send it to the publisher's address when the module is first published. &lt;/p&gt;

&lt;p&gt;We can see the publish transaction's effects on the &lt;a href="https://suiscan.xyz/devnet/home"&gt;Sui Explorer&lt;/a&gt; as below:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jkf9rM8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/8dad4d2b-2d72-40bf-ae9b-d1c36eee1ab1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jkf9rM8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/8dad4d2b-2d72-40bf-ae9b-d1c36eee1ab1" alt="Screenshot 2023-11-16 at 11 39 50" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second object created from the above transaction is an instance of the &lt;code&gt;TeacherCap&lt;/code&gt; object, and sent to the publisher address:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wouOspcK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/42daee3d-256e-4d24-95cc-85184d236dc7" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wouOspcK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/truonggau/sui-tutorial/assets/87189382/42daee3d-256e-4d24-95cc-85184d236dc7" alt="Screenshot 2023-11-16 at 11 36 24" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Quiz: What was the first object created?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Add Additional Teachers or Admins
&lt;/h2&gt;

&lt;p&gt;In order to give additional addresses admin access, we can simply define a method to create and send additional &lt;code&gt;TeacherCap&lt;/code&gt; objects as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;add_additional_teacher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;TeacherCap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_teacher_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TxContext&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;TeacherCap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;new_teacher_address&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method re-uses the &lt;code&gt;TeacherCap&lt;/code&gt; to control access, but if needed, you can also define a new capability struct indicating sudo access. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;💡Note: You can find some example in &lt;a href="https://github.com/truonggau/sui-tutorial/blob/main/basic_example/basic_example/build/basic_example/sources/transcript_3.move"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Part 4: &lt;a href="https://dev.to/truongnx/sui-basic-object-wrapping-4a7k"&gt;object wrapping&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 6: &lt;a href="https://dev.to/truongnx/sui-basic-events-1gh5"&gt;Event&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sui</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Sui basic - object wrapping</title>
      <dc:creator>truong</dc:creator>
      <pubDate>Thu, 23 Nov 2023 03:16:08 +0000</pubDate>
      <link>https://dev.to/truongnx/sui-basic-object-wrapping-4a7k</link>
      <guid>https://dev.to/truongnx/sui-basic-object-wrapping-4a7k</guid>
      <description>&lt;h2&gt;
  
  
  Object Wrapping
&lt;/h2&gt;

&lt;p&gt;There are multiple ways of nesting an object inside of another object in Sui Move. The first way we will introduce is called object wrapping. &lt;/p&gt;

&lt;p&gt;Let's continue our transcript example. We define a new &lt;code&gt;WrappableTranscript&lt;/code&gt; type, and the associated wrapper type &lt;code&gt;Folder&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;WrappableTranscript&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Folder&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WrappableTranscript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, &lt;code&gt;Folder&lt;/code&gt; wraps &lt;code&gt;WrappableTranscript&lt;/code&gt;, and &lt;code&gt;Folder&lt;/code&gt; is addressable through its id as it has the &lt;code&gt;key&lt;/code&gt; ability. &lt;/p&gt;

&lt;h2&gt;
  
  
  Object Wrapping Properties
&lt;/h2&gt;

&lt;p&gt;For a struct type to be capable of being embedded in a Sui object struct, which will generally have the &lt;code&gt;key&lt;/code&gt; ability, the embedded struct type must have the &lt;code&gt;store&lt;/code&gt; ability.&lt;/p&gt;

&lt;p&gt;When an object is wrapped, the wrapped object is no longer accessible independently via object ID. Instead it would just be parts of the wrapper object itself. More importantly, the wrapped object can no longer be passed as an argument in Move calls, and the only access point is through the wrapper object. &lt;/p&gt;

&lt;p&gt;Because of this property, object wrapping can be used as a way to make an object inaccessible outside of specific contract calls. For further info about Object wrapping, go check out &lt;a href="https://docs.sui.io/devnet/build/programming-with-objects/ch4-object-wrapping"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Object Wrapping Example
&lt;/h2&gt;

&lt;p&gt;We will implement an example of object wrapping to our transcript example, so that &lt;code&gt;WrappableTranscript&lt;/code&gt; is wrapped by a &lt;code&gt;Folder&lt;/code&gt; object, and so that the &lt;code&gt;Folder&lt;/code&gt; object can only be unpacked by, and thus the transcript inside only accessible by an intended address/viewer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Modify &lt;code&gt;WrappableTranscript&lt;/code&gt; and &lt;code&gt;Folder&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;First, we need to make some adjustments to our two custom types &lt;code&gt;WrappableTranscript&lt;/code&gt; and &lt;code&gt;Folder&lt;/code&gt; from the previous section&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We need to add the &lt;code&gt;key&lt;/code&gt; ability to our type definitions for &lt;code&gt;WrappableTranscript&lt;/code&gt;, so that they become assets and are transferrable. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember that custom types with the abilities &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;store&lt;/code&gt; are considered to be assets in Sui Move.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;WrappableTranscript&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;We need to add an additional field &lt;code&gt;intended_address&lt;/code&gt; to the &lt;code&gt;Folder&lt;/code&gt; struct that indicates the address of the intended viewer of the wrapped transcript.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Folder&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WrappableTranscript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;intended_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Request Transcript Method
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;request_transcript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WrappableTranscript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intended_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TxContext&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;folderObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Folder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;intended_address&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;//We transfer the wrapped transcript object directly to the intended address&lt;/span&gt;
    &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folderObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intended_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method simply takes in a &lt;code&gt;WrappableTranscript&lt;/code&gt; object and wraps it in a &lt;code&gt;Folder&lt;/code&gt; object, and transfers the wrapped transcript to the intended address of the transcript. &lt;/p&gt;

&lt;h2&gt;
  
  
  Unwrap Transcript Method
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;unpack_wrapped_transcript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TxContext&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;// Check that the person unpacking the transcript is the intended viewer&lt;/span&gt;
    &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="py"&gt;.intended_address&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;tx_context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;Folder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;intended_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;tx_context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="c1"&gt;// Deletes the wrapper Folder object&lt;/span&gt;
    &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method unwraps the &lt;code&gt;WrappableTranscript&lt;/code&gt; object from the &lt;code&gt;Folder&lt;/code&gt; wrapper object if the method caller is the intended viewer of the transcript, and sends it to the method caller. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Quiz: Why do we need to delete the wrapper object here manually? What happens if we don't delete it?&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Assert
&lt;/h3&gt;

&lt;p&gt;We used the &lt;code&gt;assert!&lt;/code&gt; syntax to verify that the address sending the transaction to unpack the transcript is the same as the &lt;code&gt;intended_address&lt;/code&gt; field of the &lt;code&gt;Folder&lt;/code&gt; wrapper object. &lt;/p&gt;

&lt;p&gt;the &lt;code&gt;assert!&lt;/code&gt; macro takes in two parameters of the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assert!(&amp;lt;bool expression&amp;gt;, &amp;lt;code&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where the boolean expression must evaluate to true, otherwise it will abort with error code &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Errors
&lt;/h3&gt;

&lt;p&gt;We are using a default 0 for our error code above, but we can also define a custom error constant in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ENotIntendedAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This error code then can be consumed at the application level and handled appropriately. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can find detail code &lt;a href="https://github.com/truonggau/sui-tutorial/blob/main/basic_example/basic_example/build/basic_example/sources/transcript_2.move"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Part 3: &lt;a href="https://dev.to/truongnx/sui-basic-parameter-2fj4"&gt;parameters&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 5: &lt;a href="https://dev.to/truongnx/sui-basic-capability-design-pattern-22mn"&gt;Capability Design Pattern&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sui</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Sui basic - parameter</title>
      <dc:creator>truong</dc:creator>
      <pubDate>Tue, 21 Nov 2023 16:15:56 +0000</pubDate>
      <link>https://dev.to/truongnx/sui-basic-parameter-2fj4</link>
      <guid>https://dev.to/truongnx/sui-basic-parameter-2fj4</guid>
      <description>&lt;h2&gt;
  
  
  Parameter Passing and Object Deletion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Parameter Passing (by &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;mut ref&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;If you are familiar with rustlang, then you are probably familiar with the Rust ownership system. One advantage of movelang compared to Solidity is that you can get a sense of what a function call might do to the asset that you used for the function interaction. Here are some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;sui&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// You are allowed to retrieve the score but cannot modify it&lt;/span&gt;
&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;view_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcriptObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;TranscriptObject&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;transcriptObject&lt;/span&gt;&lt;span class="py"&gt;.literature&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// You are allowed to view and edit the score but not allowed to delete it&lt;/span&gt;
&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;update_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcriptObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TranscriptObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="n"&gt;transcriptObject&lt;/span&gt;&lt;span class="py"&gt;.literature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// You are allowed to do anything with the score, including view, edit, or delete the entire transcript itself.&lt;/span&gt;
&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;delete_transcript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcriptObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TranscriptObject&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;TranscriptObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transcriptObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Object Deletion and Struct Unpacking
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;delete_transcript&lt;/code&gt; method from the example above illustrates how to delete an object on Sui. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In order to delete an object, you must first unpack the object and retrieve its object ID. Unpacking can only be done inside the module that defines the object due to Move's privileged struct operation rules:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Struct types can only be created ("packed"), destroyed ("unpacked") inside the module that defines the struct&lt;/li&gt;
&lt;li&gt;The fields of a struct are only accessible inside the module that defines the struct&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following these rules, if you want to modify your struct outside its defining module, you will need to provide public methods for these operations. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After unpacking the struct and retrieving its ID, the object can be deleted by simply calling the &lt;code&gt;object::delete&lt;/code&gt; framework method on its object ID. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;💡Note: the, &lt;code&gt;_&lt;/code&gt;, underscore in the above method denotes unused variables or parameters. This will consume the variable or parameter immediately.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;💡Note: You can find some example in [here](&lt;a href="https://github.com/truonggau/sui-tutorial/blob/main/basic_example/basic_example/build/basic_example/sources/transcript_3.move"&gt;https://github.com/truonggau/sui-tutorial/blob/main/basic_example/basic_example/build/basic_example/sources/transcript_3.move&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Part 2: &lt;a href="https://dev.to/truongnx/sui-basic-ownership-jdb"&gt;ownership&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 4: &lt;a href="https://dev.to/truongnx/sui-basic-object-wrapping-4a7k"&gt;object wrapping&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sui</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Sui basic - ownership</title>
      <dc:creator>truong</dc:creator>
      <pubDate>Tue, 21 Nov 2023 16:00:39 +0000</pubDate>
      <link>https://dev.to/truongnx/sui-basic-ownership-jdb</link>
      <guid>https://dev.to/truongnx/sui-basic-ownership-jdb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Each object in Sui has an owner field that indicates how this object is being owned. In Sui Move, there are a total of four types of ownership.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Owned

&lt;ul&gt;
&lt;li&gt;Owned by an address&lt;/li&gt;
&lt;li&gt;Owned by another object &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Shared

&lt;ul&gt;
&lt;li&gt;Shared immutable&lt;/li&gt;
&lt;li&gt;Shared mutable&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Owned Objects
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;The first two types of ownership fall under the &lt;code&gt;Owned Objects&lt;/code&gt; category. Owned objects in Sui are processed differently from shared objects and do not require global ordering. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Owned by an Address
&lt;/h3&gt;

&lt;p&gt;Let's continue using our &lt;code&gt;transcript&lt;/code&gt; example here. This type of ownership is pretty straightforward as the object is owned by an address to which the object is transferred upon object creation, such as in the above example at this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcriptObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;tx_context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// where tx_context::sender(ctx) is the recipient&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where the &lt;code&gt;transcriptObject&lt;/code&gt; is transferred to the address of the transaction sender upon creation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Owned by an Object
&lt;/h3&gt;

&lt;p&gt;In order for an object to be owned by another object, it is done using &lt;code&gt;dynamic_object_field&lt;/code&gt;, which we will explore in a future section. Basically, when an object is owned by another object, we will call it a child object. A child object is able to be looked up in global storage using its object ID.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared Objects
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A shared object is an object that is shared using the sui::transfer::share_object function and is accessible to everyone. Unlike owned objects, anyone can access shared ones on the network. Extended functionality and accessibility of this kind of objects requires additional effort by securing access, if needed.&lt;br&gt;
Shared objects require the key ability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Shared Immutable Objects
&lt;/h3&gt;

&lt;p&gt;Certain objects in Sui cannot be mutated by anyone, and because of this, these objects do not have an exclusive owner. All published packages and modules in Sui are immutable objects. &lt;/p&gt;

&lt;p&gt;To make an object immutable manually, one can call the following special function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;freeze_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Shared Mutable Objects
&lt;/h3&gt;

&lt;p&gt;Shared objects in Sui can be read or mutated by anyone. Shared object transactions require global ordering through a consensus layer protocol, unliked owned objects. &lt;/p&gt;

&lt;p&gt;To create a shared object, one can call this method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;share_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once an object is shared, it stays mutable and can be accessed by anyone to send a transaction to mutate the object. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;💡Note: You can find some example in &lt;a href="https://github.com/truonggau/sui-tutorial/blob/main/basic_example/basic_example/build/basic_example/sources/transcript_2.move"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Part 1: &lt;a href="https://dev.to/truongnx/sui-move-basic-object-18cn"&gt;object&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 3: &lt;a href="https://dev.to/truongnx/sui-basic-parameter-2fj4"&gt;parameters&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sui</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Sui basic - Object</title>
      <dc:creator>truong</dc:creator>
      <pubDate>Tue, 21 Nov 2023 10:21:56 +0000</pubDate>
      <link>https://dev.to/truongnx/sui-move-basic-object-18cn</link>
      <guid>https://dev.to/truongnx/sui-move-basic-object-18cn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Sui Move is a fully object-centric language. Transactions on Sui are expressed as operations where the inputs and outputs are both objects. Sui objects are the basic unit of storage in Sui. It all starts from the &lt;code&gt;struct&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;Let's first start with an example that represents a transcript recording a student's grades:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Transcript&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above definition is a regular Move struct, but it is not a Sui object. In order to make a custom Move type instantiate a Sui object in global storage, we need to add the &lt;code&gt;key&lt;/code&gt; ability, and a globally unique &lt;code&gt;id: UID&lt;/code&gt; field inside the struct definition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;sui&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;UID&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;TranscriptObject&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create a Sui Object
&lt;/h2&gt;

&lt;p&gt;Creating a Sui object requires a unique ID. We use the &lt;code&gt;sui::object::new&lt;/code&gt; function to create a new ID passing in the current &lt;code&gt;TxContext&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In Sui, every object must have an owner, which can be either an address, another object, or "shared". In our examples, we decided to make our new &lt;code&gt;transcriptObject&lt;/code&gt; owned by the transaction sender. It is done using the &lt;code&gt;transfer&lt;/code&gt; function of the Sui framework and using &lt;code&gt;tx_context::sender&lt;/code&gt; function to get the current entry call's sender's address.  &lt;/p&gt;

&lt;p&gt;We will discuss object ownership more in-depth in the next section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;sui&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;sui&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;tx_context&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TxContext&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;sui&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;create_transcript_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;TxContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;transcriptObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TranscriptObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;literature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nn"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcriptObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;tx_context&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;💡Note: Move supports field punning, which allows us to skip the field values if the field name happens to be the same as the name of the value variable it is bound to.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;💡Note: You can find some example in &lt;a href="https://github.com/truonggau/sui-tutorial/blob/main/basic_example/basic_example/build/basic_example/sources/transcript.move"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referent
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Part 2: &lt;a href="https://dev.to/truongnx/sui-basic-ownership-jdb"&gt;ownership&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sui</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
