<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Heekyun on Medium]]></title>
        <description><![CDATA[Stories by Heekyun on Medium]]></description>
        <link>https://medium.com/@heekyun?source=rss-d8432c69bef4------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*smwXXHiR1qVKFGvm.jpg</url>
            <title>Stories by Heekyun on Medium</title>
            <link>https://medium.com/@heekyun?source=rss-d8432c69bef4------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 01:19:42 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@heekyun/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Introducing Marmalade V2: Empowering the Future of NFTs]]></title>
            <link>https://medium.com/kadena-io/introducing-marmalade-v2-empowering-the-future-of-nfts-33ad2f3c94e8?source=rss-d8432c69bef4------2</link>
            <guid isPermaLink="false">https://medium.com/p/33ad2f3c94e8</guid>
            <category><![CDATA[l2]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[kadena]]></category>
            <category><![CDATA[marmalade]]></category>
            <category><![CDATA[nft]]></category>
            <dc:creator><![CDATA[Heekyun]]></dc:creator>
            <pubDate>Fri, 16 Jun 2023 12:59:51 GMT</pubDate>
            <atom:updated>2023-11-05T14:23:41.562Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zGdTSmjV4Q0BQWJ6ulpMIA.png" /></figure><p>The long-awaited release of Marmalade’s V2 standard has arrived, bringing a host of exciting updates and features to the top NFT standard in the industry! If you’ve been tracking the progress of Kadena and its NFT standards, you know we’ve been on a journey from the unstandardised on-chain metadata and single-policy token logic in V1 (KIP-13) to a far more robust and dynamic V2 (KIP-20). We’re thrilled to share the next stage of this adventure.</p><p><strong>Understanding KIP-0020: The Marmalade V2 Standard</strong></p><p>Marmalade V1 initially introduced the use of the Haber manifest model and had a policy-model token system, allowing tokens to adopt various policies, which adds extra logic into the marmalade function such as create-token, mint, burn, transfer, sale. With the V1 model, tokens could be programmed to allow whitelisted collections, fungible sales with royalties, and more.</p><p>Marmalade V2 represents a significant leap forward. It introduces an off-chain URI with a standardized metadata format, opening the door for marketplaces to easily fetch necessary data.</p><p>In our continuous pursuit of advancement and refinement, we’ve incorporated an enhanced feature in Marmalade V2: the stacking of policies. Unlike in V1, each token in V2 isn’t bound by a singular policy. Instead, tokens can accommodate N number of policies, providing an unprecedented degree of flexibility and functionality. This feature is powered by one of the most notable additions in Marmalade V2: “the policy manager”. The policy manager provides token creators with the convenience of selecting their preferred features from our comprehensive concrete policies, enabling effortless token creation. For those seeking additional rules, the immutable policies field offers the flexibility to incorporate specific requirements.</p><p>At the heart of this approach, there are three distinct types of policies: <strong>concrete-policies</strong>, <strong>immutable-policies</strong>, and <strong>adjustable-policies</strong>. Let’s dive deeper into what each of these means:</p><p>1. <strong>Concrete-Policies</strong>: These policies serve as foundational features for the token, representing its core characteristics. Stored as boolean values, they indicate whether a specific concrete-policy is in use. Importantly, these are immutable; once set, they cannot be altered. More importantly, Concrete policies are written and maintained by Kadena.</p><p>2. <strong>Immutable-Policies</strong>: These policies offer additional functionality, augmenting the capabilities of the token. Once established, these policies are also immutable, meaning they cannot be changed post-implementation.</p><p>3. <strong>Adjustable-Policies</strong>: Unlike the previous two, these policies provide flexibility, as they can be modified by the token owner. It’s crucial to note, however, that fractional tokens do not possess the capability to adjust these policies.</p><p>With respect to concrete policies, we offer five primary concrete policies which encapsulate the most commonly used functionalities in token creation. Marmalade V2 incorporates these concrete policies to simplify the process of token creation, while simultaneously ensuring that the tokens still benefit from rich, advanced features. The concrete policies are:</p><p>- <strong>Collection Policy</strong>: This policy facilitates the initiation of a collection with predefined token lists.</p><p>- <strong>Fungible Quote Policy</strong>: This policy empowers the sale of NFTs with fungibles through the use of an escrow account.</p><p>- <strong>Non-fungible Policy</strong>: This policy constrains the token supply to 1 and sets precision to 0, thereby enforcing the token’s non-fungibility.</p><p>- <strong>Royalty-policy</strong>: Dependent on the `fungible-quote-policy`, this policy designates the creator account to receive royalties upon each sale of the token using the `fungible-quote-policy`.</p><p>- <strong>Guard-policy</strong>: grants the ability to add optional guards to each marmalade action.</p><p>To incorporate these features during token minting, Marmalade users simply need to add true or false next to the respective policy fields in <strong>concrete-policies</strong>. Should projects require custom logic beyond what these concrete policies offer, they can deactivate the concrete policy and incorporate additional policies into the <strong>immutable-policies</strong>or <strong>adjustable-policies</strong> fields.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K4qJr2FaCwIjP-e78Hpc9A.png" /></figure><p><strong>Migration</strong></p><p>For those seeking to migrate from Marmalade V1 to V2, the migration-policy-v1 policy is specifically built to migrate marmalade.ledger tokens to marmalade-v2.ledger.</p><p>For projects that seek to use the v1 manifest model, they can continue using the manifest using onchain-manifest-policy-v1.</p><p>–</p><p>The evolution from V1 to V2 signifies our relentless commitment to make NFTs more secure, flexible, and beneficial for everyone involved — creators, buyers, and the broader community. While we loved the idea of everyone minting their own marketplace in V1, we realized that the true strength lies in the policy management.</p><p>As we delve into this new and exciting journey, remember that this is just the beginning. We’re looking forward to the innovative ways that you, the builders and pioneers, will harness the power of Marmalade V2 to create a dynamic, more inclusive, and ever-evolving NFT landscape.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2F9a9e56%3Fas_embed%3Dtrue&amp;dntp=1&amp;display_name=Upscribe&amp;url=https%3A%2F%2Fupscri.be%2F9a9e56&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href">https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=33ad2f3c94e8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/kadena-io/introducing-marmalade-v2-empowering-the-future-of-nfts-33ad2f3c94e8">Introducing Marmalade V2: Empowering the Future of NFTs</a> was originally published in <a href="https://medium.com/kadena-io">Kadena</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[NFT Collection Tutorial on Marmalade]]></title>
            <link>https://medium.com/kadena-io/nft-collection-tutorial-on-marmalade-e6db9ee6b538?source=rss-d8432c69bef4------2</link>
            <guid isPermaLink="false">https://medium.com/p/e6db9ee6b538</guid>
            <category><![CDATA[kadena]]></category>
            <category><![CDATA[nft]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[marmalade]]></category>
            <category><![CDATA[nft-marketplace]]></category>
            <dc:creator><![CDATA[Heekyun]]></dc:creator>
            <pubDate>Wed, 25 Jan 2023 15:30:04 GMT</pubDate>
            <atom:updated>2023-01-25T15:45:00.281Z</atom:updated>
            <content:encoded><![CDATA[<h3>The NFT Collection Tutorial on Marmalade</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0RpXuD_h3i9crcT6pRulPg.png" /></figure><p>Marmalade <em>token policies</em> allow for fine-grained customization of how NFTs are minted and sold. This article provides a tutorial demonstrating how an NFT collection supporting presale could be implemented in your NFT marketplace, using an example policy ‘simple-one-off-collection-policy`.</p><p>This tutorial will demonstrate the policy step-by-step with an example collection called muppets-v1.</p><p>Releasing the collection is accomplished in the following steps:</p><ol><li>Initiate Collection (Operator)</li><li>Reserve Whitelist (Minter)</li><li>Reveal Tokens in collection (Operator)</li><li>Create / Mint Token (Minter)</li><li>Transfer</li></ol><h3>Initiate Collection</h3><p>In order to create a collection, the operator executes a function directly on the policy, marmalade.simple-1-off-whitelist-collection-policy.init-collection, with the required fields.</p><ul><li>collection-id: id of collection.</li><li>collection-size: Total number of tokens in the collection.</li><li>collection-hash: Hash of the list of token IDs in the collection.</li><li>operator-guard: Guard that is used to reveal the tokens.</li><li>operator: existing fungible account to receive funds at mint.</li><li>fungible: the fungible to be paid at reserve_whitelist.</li><li>price: the fungible price of the whitelist to be transferred from buyer to operator.</li></ul><p>The most important field to understand in this step is the collection-hash. In order to lock in the tokens without revealing its properties, the list of tokens will be hashed, with each token-id being the hash of its manifests. The tokens will be revealed at a later step, and the token manifests will have to match the given collection-hash in order to be created/minted.</p><p>When init-collection succeeds, an event (marmalade.simple-one-off-collection-policy.INIT_COLLECTION collection-id collection-size collection-hash fungible price operator) will be emitted.</p><h4>Initiate muppets-v1</h4><ol><li>Create a token-manifest for each token:</li></ol><p>All marmalade tokens must use kip.token-manifest.create-manifest function, which will return a manifest format like this:</p><pre>{<br>  uri:object{mf-uri}<br>  hash:string<br>  data:[object{mf-datum}]<br>}</pre><p>For simplicity, each muppet token manifests will contain text of its names.</p><p>2. Use marmalade.ledger.create-token-id to generate token-ids.</p><pre>(marmalade.ledger.create-token-id (kip.token-manifest.create-manifest (uri &quot;text&quot; &quot;Kermit the Frog&quot;) [])))</pre><p>The function simply formats the manifest with t:{manifest-hash}. The token-id for Kermit the Frog muppet token will therefore be t:33vh4wJvxEkXW72Bgvd88S6HKcyxLj2WJZEydAP4CCU.</p><p>We will do the same for the 7 more tokens, and get the list of token-ids.</p><pre>(let*<br>  ( (get-manifest (lambda (muppet:string)<br>      (create-manifest (uri &quot;text&quot; muppet) [])<br>      ))<br>    (manifests:list (map get-manifest [ &quot;Kermit the Frog&quot;<br>                                        &quot;Miss Piggy&quot;<br>                                        &quot;Fozzie Bear&quot;<br>                                        &quot;Gonzo&quot;<br>                                        &quot;Rowlf the Dog&quot;<br>                                        &quot;Scooter&quot;<br>                                        &quot;Animal&quot;<br>                                        &quot;Pepe the King Prawn&quot;<br>                                        &quot;Rizzo the Rat&quot;]))<br>    (tokens:list (map (create-token-id) manifests)<br>    ))<br>   tokens<br>)</pre><p>returns</p><pre>[ &quot;t:33vh4wJvxEkXW72Bgvd88S6HKcyxLj2WJZEydAP4CCU&quot;<br>   &quot;t:UohIzpKOlpp5l7UZ-KNni2xaLu5pO67QlHLmxj65g5U&quot;<br>   &quot;t:u7u36BxiPTKp5Wuq_mXOLS7r2LFRaLeEKg2FY6ylNX0&quot;<br>   &quot;t:rj3gbsmUdcXeb0kA39meDeKoMhWOPK6XEOCQ2RKF0q8&quot;<br>   &quot;t:uOCqa9-MgFF68zyxccZKORGDk2zMRLwpKdXvr8hfE5A&quot;<br>   &quot;t:dOFBE3GdsL-5BgMCdZfQzT20G81cANzwgwIf22N8_ig&quot;<br>   &quot;t:LScEFcxVDsvZP38jO1Kp95yNu7hGmGNrzYkwCM5UWyA&quot;<br>   &quot;t:--kKualbcNt2jKUPLG0Pyp6ByLJerOS_Wtxe914_YHA&quot;<br>   &quot;t:sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4&quot;]</pre><p>3.Hash the token list.</p><p>Finally, we can hash the list and get the collection-hash, by using hash function.</p><pre>(hash<br>  [&quot;t:33vh4wJvxEkXW72Bgvd88S6HKcyxLj2WJZEydAP4CCU&quot;<br>   &quot;t:UohIzpKOlpp5l7UZ-KNni2xaLu5pO67QlHLmxj65g5U&quot;<br>   &quot;t:u7u36BxiPTKp5Wuq_mXOLS7r2LFRaLeEKg2FY6ylNX0&quot;<br>   &quot;t:rj3gbsmUdcXeb0kA39meDeKoMhWOPK6XEOCQ2RKF0q8&quot;<br>   &quot;t:uOCqa9-MgFF68zyxccZKORGDk2zMRLwpKdXvr8hfE5A&quot;<br>   &quot;t:dOFBE3GdsL-5BgMCdZfQzT20G81cANzwgwIf22N8_ig&quot;<br>   &quot;t:LScEFcxVDsvZP38jO1Kp95yNu7hGmGNrzYkwCM5UWyA&quot;<br>   &quot;t:--kKualbcNt2jKUPLG0Pyp6ByLJerOS_Wtxe914_YHA&quot;<br>   &quot;t:sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4&quot;] )</pre><p>eLbTngl8lNBPshPMohX0ILM8l7R4RV8eNm9p0Pq1W6E is our collection hash. Note that all of the steps 1-3 are not to be done on-chain, but should be done off-chain. Only the following step will be executed on-chain.</p><p>4. Run init-collection</p><p>Finally, we have our required fields to initiate our collection. The following code creates muppet-v1 collection with 9 tokens that we generated above, with k:aa5f18ed095607fbef309abd5511baaa0844e067a61ed4cf51d5333e770ed030 being the operator account in fungible, coin, with whitelist price of 5.0. This code should now be sent to the chain.</p><pre>(init-collection<br>  &quot;muppet-v1&quot; 9 &quot;eLbTngl8lNBPshPMohX0ILM8l7R4RV8eNm9p0Pq1W6E&quot;<br>  &quot;k:aa5f18ed095607fbef309abd5511baaa0844e067a61ed4cf51d5333e770ed030&quot; (read-keyset &#39;operator-guard) coin 5.0)</pre><p>We will see the following event emitted once the transaction succeeds. (marmalade.simple-one-off-collection-policy.INIT_COLLECTION &quot;muppet-v1&quot; 9 &quot;eLbTngl8lNBPshPMohX0ILM8l7R4RV8eNm9p0Pq1W6E&quot; &quot;k:aa5f18ed095607fbef309abd5511baaa0844e067a61ed4cf51d5333e770ed030&quot; coin 5.0)</p><h3>Reserve Whitelist</h3><p>Whitelists in this collection policy are on a first-come, first-served basis. This step is to be run by the minters.</p><ol><li>To reserve whitelists, minters must have a fungible account with a balance bigger than the price.</li></ol><p>In our example, muppets-v1 collection uses fungible, coin, so the mint account must be a coin account with a balance bigger than 5.0. Minters must use a principal-ed account. This can simply be a k:{public-key}, but there is an act function to generate it in code. For example, running the following code.</p><pre>(create-principal (read-keyset &#39;keyset))</pre><p>with a keyset of</p><pre>{<br>  &quot;keys&quot;: [&quot;27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot;],<br>  &quot;pred&quot;: &quot;keys-all&quot;<br>}</pre><p>will generate a k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4.</p><p>Because this transaction will transfer coin to operator, the minters must sign the capability (coin.TRANSFER &quot;k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot; &quot;k:aa5f18ed095607fbef309abd5511baaa0844e067a61ed4cf51d5333e770ed030&quot; 5.0) to send from mint account to the operator account.</p><p>2. With prepared account, minters can now run reserve-whitelist and get their slots locked in.</p><p>Successful whitelist will emit an event, (RESERVE_WHITELIST collection-id account whitelist-index). This info should be saved for the token creations and mint index.</p><p>The whitelist of the last token will generate a random index that will shift the whitelist slots. This shift index will be used to randomize the selection of NFTs within collection. By randomly setting the shift index at the end of whitelist, marmalade prevents the operator to reserve certain NFTs that may be more valuable than others.</p><h4>Whitelist a token in muppet-v1</h4><ol><li>Run reserve-whitelist with a keyset.</li></ol><pre>(marmalade.simple-one-off-collection-policy.reserve-whitelist &quot;muppet-v1&quot; (create-principal (read-keyset &#39;keyset)))</pre><p>2. Save the emitted event.</p><pre>(marmalade.simple-one-off-collection-policy.RESERVE_WHITELIST &quot;muppets-v1&quot; &quot;k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot; 0)</pre><p>3. Whitelist of the last token generates a shift-index.</p><p>Let’s assume that the last reserve-whitelist made it into block 20987. The shift-index generated will be 8, and the transaction will emit 2 events.</p><pre>(marmalade.simple-one-off-collection-policy.RESERVE_WHITELIST &quot;muppets-v1&quot; &quot;k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot; 8)<br>(marmalade.simple-one-off-collection-policy.SHIFT collection-0&quot; 8)</pre><h3>Reveal Tokens</h3><p>Once reserve-whitelist is complete, the operator can now reveal the token manifests, showing which whitelist index is dedicated to each token id.</p><h4>Reveal muppets-v1</h4><p>Operator of the muppets-v1 will prepare the token-ids, and run the function.</p><pre>(marmalade.simple-one-off-collection-policy.reveal-tokens &quot;muppets-v1&quot;<br>    [  &quot;t:33vh4wJvxEkXW72Bgvd88S6HKcyxLj2WJZEydAP4CCU&quot;<br>       &quot;t:UohIzpKOlpp5l7UZ-KNni2xaLu5pO67QlHLmxj65g5U&quot;<br>       &quot;t:u7u36BxiPTKp5Wuq_mXOLS7r2LFRaLeEKg2FY6ylNX0&quot;<br>       &quot;t:rj3gbsmUdcXeb0kA39meDeKoMhWOPK6XEOCQ2RKF0q8&quot;<br>       &quot;t:uOCqa9-MgFF68zyxccZKORGDk2zMRLwpKdXvr8hfE5A&quot;<br>       &quot;t:dOFBE3GdsL-5BgMCdZfQzT20G81cANzwgwIf22N8_ig&quot;<br>       &quot;t:LScEFcxVDsvZP38jO1Kp95yNu7hGmGNrzYkwCM5UWyA&quot;<br>       &quot;t:--kKualbcNt2jKUPLG0Pyp6ByLJerOS_Wtxe914_YHA&quot;<br>       &quot;t:sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4&quot;])</pre><p>Note that the function reveal-tokens enforces the hash of the list of the token-ids to match the collection-hash that was used in the init-collection step as shown below.</p><pre>(enforce (= collection-hash (hash token-ids)) &quot;Token manifests don&#39;t match&quot;)</pre><p>In order for minters to be able to create and mint their tokens, the operator must publish the token manifests to the whitelisters.</p><h3>Create Token / Mint Token</h3><p>create-token is an operations required for each marmalade token in the collection to add it to the marmalade ledger. Minters must use the published manifest to call create-token.</p><p>This step is ideally run together with mint transaction. mint is the final step that is required to own the token. Similar to create-token, mint is a general marmalade operation.</p><p>Collection policy enforces that the create-token and mint is done by the whitelisted account.</p><h4>Create “t:sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4” token.</h4><ol><li>Find thewhitelist-info.</li></ol><p>In the previous step, we had reserved whitelist for the account, and saw the emitted event of below.</p><pre>(marmalade.simple-one-off-collection-policy.RESERVE_WHITELIST &quot;muppets-v1&quot; &quot;k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot; 0)</pre><p>We need 4 fields for whitelist info: collection-id, account, guard, index. What&#39;s not in this event is the guard. Guard can simply be the keyset info we&#39;ve provided at (create-principal (read-keyset &#39;keyset)).</p><p>Our whitelist-info will be added to env-data of our transaction, and will look like the following:</p><pre>{<br>  &#39;whitelist-info : {<br>     &#39;collection-id: &quot;muppets-v1&quot;<br>    ,&quot;index&quot;: 0<br>    ,&quot;account&quot;: &quot;k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot;<br>    ,&quot;guard&quot;: {&quot;keys&quot;: [&quot;27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot;], &quot;pred&quot;: &quot;keys-all&quot;}}<br>}</pre><p>2. Find the token that matches the whitelist index.</p><p>Our whitelist index was 0. When the whitelist ended, the shift index was updated at 8. This means we will be able to mint the token at index 8. If our whitelist index was 1, we will be able to mint the token at index 0, and so on. The token-id at index 8 is t:sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4.</p><p>3. Receive the token-manifest from the operator.</p><p>The operator will release the token-manifest somewhere for the users to mint the tokens. The manifest that matches token t:sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4, is shown below.</p><pre>{&quot;uri&quot;:<br>  {&quot;scheme&quot;: &quot;text&quot;,&quot;data&quot;: &quot;Rizzo the Rat&quot;},<br>   &quot;hash&quot;: &quot;sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4&quot;,&quot;data&quot;: []}</pre><p>Note that above is the result of the code,</p><pre>(kip.token-manifest.create-manifest (uri &quot;text&quot; &quot;Rizzo the Rat&quot;) [])</pre><p>4. Run create-token and mint with the whitelist-info in env-data.</p><p>create-token takes in token-id, precision, token-manifest, and policy. The precision is 0, because this is a one-off collection policy. mint takes in token-id, account, guard, and amount. amount is always 1.0, because this is an one-off collection policy.</p><pre>(marmalade.ledger.create-token<br>  &quot;t:sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4&quot;<br>  0<br>  {&quot;uri&quot;:<br>    {&quot;scheme&quot;: &quot;text&quot;,&quot;data&quot;: &quot;Rizzo the Rat&quot;},<br>     &quot;hash&quot;: &quot;sQ19jh3-w3HOchpBefpKTBGj2_ARjC4xLiV0SVlokf4&quot;,&quot;data&quot;: []}<br>  marmalade.simple-one-off-collection-policy)<br>(marmalade.ledger.mint<br>  &quot;t:9mCeDcVIuQET1awDEWbYXF-HlRzhLv5VW3hXiW9m678&quot;<br>  &quot;k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot;<br>  (at &#39;guard (read-msg &#39;whitelist-info ))<br>  1.0))</pre><p>The minter needs to sign the capabilities, (marmalade.ledger.CREATE_TOKEN &quot;t:9mCeDcVIuQET1awDEWbYXF-HlRzhLv5VW3hXiW9m678&quot; &quot;k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot;), (marmalade.ledger.MINT &quot;t:9mCeDcVIuQET1awDEWbYXF-HlRzhLv5VW3hXiW9m678&quot; &quot;k:27fff7d20390142caf727cd4713d2c810839486fa2350af7e2ce980090185ce4&quot; 1.0)</p><p>create-token and mint can run separately or together on the same transaction.</p><h3>Transfer</h3><p>This collection policy uses plain transfer and transfer-create from the marmalade.ledger contract. transfer requires sender and receiver account names as well as the amount, which works with existing receiver accounts. transfer-create requires sender and receiver account names, receiver guard, and the amount, which works with existent and non-existent receivers. Sender&#39;s signature is required for both transfer and transfer-create.</p><h3>Things to consider</h3><p>We have now looked at initiating a collection to mint each token in the collection. The account designated at the mint step now owns the token in the main marmalade ledger.</p><p>There are more questions to be asked, however, including the scalability of bigger collections.</p><ul><li>How should we prevent the operator from scamming the whitelisters? The contract collects the funds of the buyers at reserve-whitelist phase, which means that without operator from providing token-mainifests, the buyers cannot mint the token.</li><li>Should the operator run reveal-tokens? If the token list is available off-chain, then the operator is not necessarily required to reveal-tokens. If not, who should run it?</li><li>If the collection holds bigger tokens, then adding the slots and token-list as a list inside a table can become a costly transaction. The alternative can be adding each whitelists and token-ids as rows in the table.</li></ul><p>We hope that you found this tutorial helpful! There will be lots of exciting development in Marmalade over the course of the year, so please follow us on our social channels to keep updated!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2F9a9e56%3Fas_embed%3Dtrue&amp;dntp=1&amp;display_name=Upscribe&amp;url=https%3A%2F%2Fupscri.be%2F9a9e56&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href">https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e6db9ee6b538" width="1" height="1" alt=""><hr><p><a href="https://medium.com/kadena-io/nft-collection-tutorial-on-marmalade-e6db9ee6b538">NFT Collection Tutorial on Marmalade</a> was originally published in <a href="https://medium.com/kadena-io">Kadena</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Token Protocol on Marmalade]]></title>
            <link>https://medium.com/kadena-io/token-protocol-on-marmalade-d899a6c17bca?source=rss-d8432c69bef4------2</link>
            <guid isPermaLink="false">https://medium.com/p/d899a6c17bca</guid>
            <category><![CDATA[nft]]></category>
            <category><![CDATA[marmalade]]></category>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[kadena]]></category>
            <dc:creator><![CDATA[Heekyun]]></dc:creator>
            <pubDate>Fri, 23 Dec 2022 18:08:35 GMT</pubDate>
            <atom:updated>2022-12-23T18:08:35.921Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PMdTOo8SNitmuC9rU75ahg.png" /></figure><p>To end 2022 with a bang, we are excited to announce our last feature upgrade of the year! The <a href="https://marmalade.art/">Marmalade</a> team at <a href="https://kadena.io/">Kadena</a> has worked hard and is now rolling out an upgrade to the Marmalade contract with a new feature: t:token protocol. This new token protocol will increase safety for our developers during the lazy minting process! Let’s dive right in.</p><p><strong>What is a Token Protocol?</strong></p><p>Token protocol code is a way to reserve token IDs that start with a single character and a colon. This should sound familiar if you’ve seen Kadena Account Procotols, or k: accounts. Just like accounts, token IDs now cannot be named as a:blahblah . The first token protocol to introduce is t: token protocol.</p><p><strong>t: Token Protocol</strong></p><p>Our first token protocol, t: , reserves token ID’s with the token manifest, specifically, the hash of the manifest.</p><p>Let’s look at the contract. All marmalade tokens uses manifest format like this:</p><pre>{<br>  uri:object{mf-uri}<br>  hash:string<br>  data:[object{mf-datum}]<br>}</pre><p>The field, hash, is the hashed content of the uri and data field, and is always verified at token creation. By using the hash in the token protocol, we can ensure that the token is created with the matching manifest.</p><p>t: tokens are formatted as t:{hash}.</p><p><strong>What does it achieve?</strong></p><p>The newly introduced token protocol will add safety to lazy minting. Marmalade policies can now safely reveal token IDs before its minting, without the possibility of being squatted. Note that the safety doesn’t apply once the entire manifest is revealed.</p><p><strong>Implementation</strong></p><p>The upgraded contract now enforces the token protocol at create-token , with a newly created function enforce-token-reserved.</p><p>enforce-token-reserved takes in token-id and manifest , and checks that the two match.</p><p>Another function available in the upgraded contract is create-token-id , which takes in manifest , and returns the t: token ID matching the supplied manifest.</p><p>Let’s look at an example.</p><p>Here’s a simple manifest with hello-world text, with</p><pre>{ <br>    &quot;uri&quot;: <br>     { <br>       &quot;scheme&quot;: &quot;text&quot;,<br>       &quot;data&quot;: &quot;hello-world&quot;<br>     }<br>   ,&quot;hash&quot;: &quot;lM-wiutct6tYae6bDuUTZ-aM359hwJ4ySHWPThbIGE0&quot;<br>   ,&quot;data&quot;: []<br>  }</pre><p>The following code will generate the token id, t:lM-wiutct6tYae6bDuUTZ-aM359hwJ4ySHWPThbIGE0</p><pre>(create-token-id <br>  { <br>    &quot;uri&quot;: <br>     { <br>       &quot;scheme&quot;: &quot;text&quot;,<br>       &quot;data&quot;: &quot;hello-world&quot;<br>     }<br>   ,&quot;hash&quot;: &quot;lM-wiutct6tYae6bDuUTZ-aM359hwJ4ySHWPThbIGE0&quot;<br>   ,&quot;data&quot;: []<br>  })</pre><p>And below will enforce that the protocol passes with provided token-id and the manifest</p><pre>(enforce-token-reserved<br>  &quot;t:lM-wiutct6tYae6bDuUTZ-aM359hwJ4ySHWPThbIGE0&quot;<br>  { <br>    &quot;uri&quot;: <br>     { <br>       &quot;scheme&quot;: &quot;text&quot;,<br>       &quot;data&quot;: &quot;hello-world&quot;<br>     }<br>   ,&quot;hash&quot;: &quot;lM-wiutct6tYae6bDuUTZ-aM359hwJ4ySHWPThbIGE0&quot;<br>   ,&quot;data&quot;: []<br>  })</pre><p><strong>Conclusion</strong></p><p>Marmalade offers rich flexibility with pluggable policies that allow customized rules for token creation, mint, burn, and transfers, and sales. <br>Token Protocols provides marmalade-universal standards across the policies.</p><p>We hope that you found this Marmalade upgrade useful. Please make sure to follow us on our socials for more upcoming releases in 2023 as we’ll be rolling out some fun and innovative content, tutorials, and policies!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2F9a9e56%3Fas_embed%3Dtrue&amp;dntp=1&amp;display_name=Upscribe&amp;url=https%3A%2F%2Fupscri.be%2F9a9e56&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href">https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d899a6c17bca" width="1" height="1" alt=""><hr><p><a href="https://medium.com/kadena-io/token-protocol-on-marmalade-d899a6c17bca">Token Protocol on Marmalade</a> was originally published in <a href="https://medium.com/kadena-io">Kadena</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Step-By-Step Guide to Writing Pact Smart Contract — Goliath Faucet]]></title>
            <link>https://medium.com/kadena-io/a-step-by-step-guide-to-writing-pact-smart-contract-goliath-faucet-d514f0629e46?source=rss-d8432c69bef4------2</link>
            <guid isPermaLink="false">https://medium.com/p/d514f0629e46</guid>
            <category><![CDATA[pact]]></category>
            <category><![CDATA[kadena]]></category>
            <category><![CDATA[developer]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <dc:creator><![CDATA[Heekyun]]></dc:creator>
            <pubDate>Tue, 04 Oct 2022 15:22:16 GMT</pubDate>
            <atom:updated>2022-10-09T12:29:20.276Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>A Step-By-Step Guide to Writing Pact Smart Contract — Goliath Faucet</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wmsX0LzHjaR7HVMUTjLqjw.png" /></figure><p>Most recently, Thomas Honeyman, <em>a senior engineer at Awake Security, </em>created a Pact developer tutorial series titled “<a href="https://github.com/thomashoneyman/real-world-pact">Real World Pact</a>”, which contains tutorials on:</p><ol><li>Goliath Faucet Contract</li><li>Goliath Wallet UI with TypeScript + React frontend</li></ol><p>The Kadena.js team has taken it upon themselves to create a step-by-step guide of the Goliath Project, including video demonstrations of the Goliath Wallet UI, summarizing a portion of Honeyman’s work, specifically with respect to the contract portion of the Goliath Project. The purpose of the step-by-step guide is to enable developers and interested individuals to start coding easily. For those interested in exploring the entire repo, please see <a href="https://github.com/thomashoneyman/real-world-pact/tree/main/01-faucet-contract#contract-overview">Goliath Faucet Contract Overview</a> and <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/faucet.pact">Goliath Faucet Main Contract</a>.</p><p>The guide will provide the following :</p><p>1. Overview</p><p>2. Introduction</p><p>3. Namespaces</p><p>4. Keysets</p><p>5. Interfaces &amp; Modules</p><p>6. Constants</p><p>7. Capabilities</p><p>8. Functions</p><h4><strong>Overview</strong></h4><p>The Goliath faucet is a simple smart contract that allows users to request KDA. Even though it’s a small contract, we’ll cover the majority of Pact’s features in the process of building it. The faucet contract is intended for use on a test network, so it will allow anyone to request funds.</p><p>We’ll implement these features in idiomatic Pact:</p><p>1. Any Goliath user can request funds from the faucet, with the faucet account signing on their behalf.</p><p>2. By default, users can request up to 20.0 KDA per call to request-funds and up to 100.0 KDA in total.</p><p>3. The faucet account can increase the per-request and per-account limits for any account (but it cannot decrease them).</p><p>4. You can return funds to the Goliath faucet, which will credit against your total account limit.</p><p>5. You can look up your account’s per-account and per-request limits and see how much KDA you can still request.</p><p>After following all the steps, you’ll be able to understand the contract behind the app, Goliath wallet.</p><h4><strong>Introduction</strong></h4><p>Welcome to the Goliath faucet smart contract!</p><p>We’re using the Pact smart contract language. A smart contract can contain a mixture of:</p><p>* Top-level Pact code that is executed on-chain when you deploy the contract</p><p>* Pact code organized into interfaces and modules, which can be called via other smart contracts or by sending Pact code to a Chainweb node at its Pact endpoint for evaluation.</p><p>A typical Pact smart contract executes some top-level setup code by defining one or more keysets and entering a namespaces. Then, it defines a module and/or interface that other modules can reference. Finally, it executes more top-level code to initialize data required by the module, such as creating new tables. Each of these steps introduces critical concepts for Pact development.</p><p>We’ll take all these steps in our smart contract. We’ll begin by exploring namespaces, keysets, interfaces, and modules. Then we’ll implement the “goliath-faucet” module and finish up by initializing some data.</p><h4><strong>Namespaces</strong></h4><p>Our contract begins by entering a namespace.</p><p>Modules, interfaces, and keysets in Pact must have unique names within a particular namespace. On a private blockchain you can define your own namespace or use the &quot;root&quot; namespace (ie. no namespace at all). On a public blockchain the root namespace is reserved for built-in contracts (like the coin contract, which we’ll see later), and on Chainweb specifically you can only define a new namespace with the approval of the Kadena team.</p><p>In short, we technically can define a namespace with (define-namespace) in our contract but, practically speaking, we can’t do this on Chainweb. So we can’t define a namespace, and we can’t use the root namespace. What are we to do?</p><p>Chainweb exposes two namespaces for public use: &quot;free&quot; and &quot;user&quot;. You can define interfaces, modules, and keysets inside either of these two interfaces.</p><p>To do that, enter the namespace with the (namespace) function. <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#namespace">#namespace</a></p><p>We’ll use the &quot;free&quot; namespace for our contract:</p><pre>(namespace &quot;free&quot;)</pre><h4><strong>Keysets</strong></h4><p>Now that we are inside the &quot;free&quot; namespace, we can begin defining keysets for use in our module.</p><p>Public-key authorization is widely used in smart contracts to ensure that only the holders of specific keys can take certain actions (such as transferring funds from their account). Pact integrates single- and multi-signature public-key authorization into smart contracts directly via the concept of <strong>keysets.</strong></p><p>Pact has other tools for authorization as well as a whole, authorization in Pact is handled via <strong>guards</strong> or <strong>capabilities </strong>(we’ll learn about both later), and a keyset is a specific kind of guard.</p><p>So what, concretely, is a keyset? A keyset pairs a set of public keys with a predicate function. In JSON form it looks like this:</p><p>{ “keys”: [ “abc123”], “pred”: “keys-all” }</p><p>Pact will check the predicate function against the set of keys when the keyset is used as a guard. If the predicate fails then access is denied. There are a few built-in predicate functions, such as the “keys-all” function above this predicate means means that all keys in the set must have signed the transaction. You can also write your own predicate functions (for example, to authorize access according to a vote). <a href="https://pact-language.readthedocs.io/en/latest/pact-reference.html#keysets-and-authorization">#keysets-and-authorization</a></p><p>Keysets are defined via the (define-keyset) function. This function takes a name and a keyset as arguments. When evaluated, Pact will either register the keyset at the given name on Chainweb or, if the name is already registered, then it will “rotate” (ie. update) the keyset to the new value. <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#define-keyset">#define-keyset</a></p><p>When registering a keyset in a smart contract it’s a common practice to send the keyset in the deployment transaction data instead of hardcoding it into the contract. That’s because keyset references can be rotated (ie. upgraded) once rotated, the keyset name won’t refer to the value written in the contract anymore. If you ever want to see the current value of a keyset reference, you can look it up by name by sending this code to a Chainweb node:</p><pre>(describe-keyset &quot;free.my-keyset&quot;)</pre><p>Let’s proceed with defining the “free.goliath-faucet-keyset” using the keyset</p><p>provided via transaction data. You can parse data from the transaction using the (read-*) family of functions: <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#read-msg">#read-msg</a><a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#read-keyset"> #read-keyset</a> <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#read-string">#read-string</a> <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#read-integer">#read-integer</a> <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#read-decimal">#read-decimal</a></p><p>Our deployment transaction will be sent with two pieces of data:</p><p>* ‘upgrade’: a boolean indicating whether we intend this as a deployment or as an upgrade to the already-deployed module if we are upgrading then we can skip the keyset definition and initialization steps.</p><p>* ‘goliath-faucet-contract’: a keyset that should be registered as the “free.goliath-faucet-keyset” keyset on-chain.</p><p>Below, we read the Goliath faucet keyset from the transaction data and register it, but only if we are deploying (not upgrading) this contract. Once the keyset is registered, our Pact module can refer to it when guarding sensitive information. To see how to provide a keyset in transaction data please refer to the <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/faucet.repl">faucet.repl file</a> and the deploy-faucet-contract.yaml file.</p><pre>(if (read-msg “upgrade”)<br>  [ (enforce-keyset (read-keyset “goliath-faucet-keyset”)) <br>    (define-keyset “free.goliath-faucet-keyset”<br>    (read-keyset “goliath-faucet-keyset”))<br>  ]<br>  &quot;Upgrading contract&quot;<br>)</pre><p>If reading the ‘upgrade’ field yields ‘true’, then this isn’t our initial deployment and therefore we should skip registering the keyset.</p><p>Otherwise, this is our initial deployment, so we should register the keyset. Just one more thing before we proceed: we should verify our keyset. There are multiple reasons to do this.</p><p>First, what if we have a typo in the keyset sent in the transaction data? The typo keyset will be registered and we’ll be unable to access anything guarded by it!</p><p>Second, you don’t have to define a keyset inside your smart contract. You may wish to reuse the same keyset reference in multiple contracts, and so you simply reuse the keyset reference in your contract. This can be dangerous, however. If you deploy a contract referring to a keyset but you forgot to register that keyset, then someone else can register the keyset with their keys and gain access to your guarded data. To prevent these risks it’s a best practice to enforce a keyset guard on the transaction that deploys the contract. This guard should ensure that any keysets passed to the contract were also used to sign the transaction that deploys the contract. If the enforcement fails, the deployment is aborted, and you can fix the keyset and try again. <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#keyset-ref-guard">#keyset-ref-guard</a></p><h4><strong>Interfaces &amp; Modules</strong></h4><p>So far we’ve been writing code at the top level. Code at the top level is ordinary Pact that Chainweb can execute. However, when you are defining a new smart contract, you need to organize your Pact code into interfaces and/or modules so that it can be referenced later from other contracts or via a Chainweb node’s Pact API. Chainweb will store your interfaces and modules within the namespace you’ve entered.</p><p>Interfaces and modules are both units for organizing Pact code, but they serve different purposes. An interface describes the API that a module will</p><p>implement and can supply constants and models for formal verification to aid in that implementation, but it doesn’t contain any implementations itself and cannot be executed on Chainweb. <a href="https://pact-language.readthedocs.io/en/stable/pact-reference.html#interfaces">#interfaces</a></p><p>Interfaces purely exist as a method of abstraction. An interface can be implemented by multiple modules (that means that the module provides an implementation for every function included in the interface), so it serves as a blueprint for implementers. Also, Pact functions take a reference to module as an argument so long as the module implements a specific interface. That means you can write a function that can be used with any module that implements the given interface — a powerful form of abstraction. <a href="https://pact-language.readthedocs.io/en/stable/pact-reference.html#module-references">#module-references</a></p><p>We don’t use interfaces in our contract because it’s quite small and no one else is expected to provide another implementation for its API. Instead, we skip straight to the implementation: the ‘goliath-faucet’ module.</p><p>A module in Pact is the primary unit of organization for Pact code. Modules can contain functions, pacts, capabilities, tables, and other Pact code. <a href="https://pact-language.readthedocs.io/en/stable/pact-reference.html#module">#module</a></p><p>Let’s define a Pact module with the code for our faucet. To define a module we must provide a module name, a module governance function, and then the module body containing the implementation.</p><p>The<strong> **module name**</strong> is used to refer to the module from other modules (or in the REPL). For example, `coin.transfer` refers to the `transfer` function defined in the `coin` module. To refer to a module it must have been deployed to Chainweb (or loaded into the REPL). We’ll name our module `goliath-faucet`.</p><p>Since we’re within the `free` namespace, that means we can refer to our module on Chainweb with the prefix `free.goliath-faucet`. The<strong> **module governance function**</strong> restricts how the contract can be upgraded.</p><p>Governance functions can be a keyset reference, which means that the contract can be upgraded so long as the upgrade transaction satisfies the keyset, or they can be a “capability” defined in the module. We’ll learn a lot more about capabilities later and will use a keyset reference as our governance. <a href="https://pact-language.readthedocs.io/en/latest/pact-reference.html#keysets-vs-governance-functions">#keysets-vs-governance-functions</a></p><pre>(module goliath-faucet &quot;free.goliath-faucet-keyset&quot;<br>  @doc<br>  &quot;&#39;goliath-faucet&#39; represents the Goliath Faucet Contract. \<br>  \ This contract  provides a small number of KDA to any    \  <br>  \ Kadena user who needs some. To request funds for        \      <br>  \ yourself (Chain 0 only):                                \<br>  \                                                         \<br>  \ &gt; (free.goliath-faucet.request-funds …)                 \<br>  \                                                         \<br>  \ To check your account’s request and total limits:       \<br>  \ &gt; (free.goliath-faucet.get-limits …)                    \<br>  \                                                         \<br>  \ To return funds to the faucet account (Chain 0 only):   \<br>  \ &gt; (free.goliath-faucet.return-funds …)&quot;</pre><p>Now, let’s implement the body of our module. We’ll begin with the two forms of metadata we can use to annotate our modules, interfaces, functions, table schemas, and other Pact code. The @doc metadata field is for documentation strings, and the @model metadata field is for formal verification. <a href="https://pact-language.readthedocs.io/en/latest/pact-reference.html#docs-and-metadata">#docs-and-metadata</a></p><h4><strong>Metadata</strong></h4><p>It’s a best practice to document interfaces, modules, functions, table schemas, and other Pact code using the @doc metadata field. We’ll do that throughout our contract, beginning with the module itself.</p><p>The second metadata type is @model. It allows us to specify properties that functions must satisfy and invariants that table schemas must satisfy. Pact, via the Z3 theorem prover, can prove that there is no possible set of variable assignments in our code that will violate the given property or invariant. Or, if it does find a violation, it can tell us so we can fix it! <a href="https://pact-language.readthedocs.io/en/stable/pact-properties.html#what-do-properties-and-schema-invariants-look-like">#what-do-properties-and-schema-invariants-look-like</a></p><p>Properties (but not invariants) can be defined at the top level of the module so they can be reused in multiple functions. <a href="https://pact-language.readthedocs.io/en/latest/pact-properties.html#defining-and-reusing-properties">#defining-and-reusing-properties</a></p><p>We have a few functions that should never succeed unless they were called in a transaction signed by the Goliath faucet keyset. We can capture that property in a reusable definition. We’ll see examples of using this property within a function later on.</p><pre>@model<br>  [ (defproperty faucet-authorized <br>      (authorized-by &quot;free.goliath-faucet-keyset&quot;))<br>  ]</pre><h4><strong>Constants</strong></h4><p>It’s useful to define constants in your interface for values that will be used in several functions, or values that other modules should be able to refer to.</p><p>Our faucet contract has a specific range of values that it will allow the per-request and per-account limits to be set to. It’s useful to capture these values in variables that our tests, module code, and other modules on Chainweb can refer to. To expose a constant value, use (defconst). <a href="https://pact-language.readthedocs.io/en/latest/pact-reference.html#defconst">#defconst</a></p><pre>(defconst FAUCET_ACCOUNT &quot;goliath-faucet<br>   @doc &quot;Account name of the faucet account that holds and disburses   funds.&quot;)<br>(defconst DEFAULT_REQUEST_LIMIT 20.0<br>   @doc &quot;Users can at minimum ask for up to 20 KDA per request.&quot;)<br>(defconst DEFAULT_ACCOUNT_LIMIT 100.0<br>   @doc &quot;Users can at minimum ask for up to 100 KDA per account.&quot;)</pre><h4><strong>Schemas &amp; Tables</strong></h4><p>When your smart contract needs to persist some data across multiple calls to functions in the contract, it should use a table. Tables in Pact are relational databases and have a key-row structure. Keys are always strings. You can define a table with `deftable`. <a href="https://pact-language.readthedocs.io/en/stable/pact-reference.html#deftable">#deftable</a></p><p>Our smart contract needs to persist four pieces of data. First, we need to record how much KDA in total each account has requested and returned so that we know when a request would exceed the per-account limit. We also need to record the per-request and per-account limits, as they can be adjusted by the faucet account at any time.</p><p>Before we define any tables, however, we should define schemas for them. The schema for a table specifies the table columns and their data types. <a href="https://pact-language.readthedocs.io/en/stable/pact-reference.html#defschema">#defschema</a></p><p>The schema will be used to verify we are using the right types when reading or writing the table. For example, Pact can typecheck our module and ensure we never try to provide a string for an integer column, or try to insert a row that’s missing a column.</p><p>By convention, we use the same name for a table and its schema, except we give the schema a -schema suffix.</p><pre>(defschema accounts-schema <br>   @model<br>   [ (invariant (&lt;= (- funds-requested funds-returned) <br>        account-limit))<br>     (invariant (&gt;= (- funds-requested funds-returned) 0.0))<br>   ] <br>   funds-requested:decimal<br>   funds-returned:decimal<br>   request-limit:decimal<br>   account-limit:decimal)</pre><p>We’ve seen @model used to define some reusable properties at the module level. Now, let’s see how to leverage invariants (ie. formal verification for table schemas) to guarantee it is never possible for an address to exceed their account limit or return more funds than they have requested. To specify an invariant, use (invariant) and provide a predicate; the Z3 theorem prover will check that the variables used in your predicate can never have values that would fail the predicate. Not all Pact functions can be used in the predicate; you can see a list of available ones here <a href="https://pact-language.readthedocs.io/en/stable/pact-properties-api.html#property-and-invariant-functions">#property-and-invariant-functions</a></p><p>The first invariant ensures that you can never receive more funds than your account limit. The second ensures you can never return more funds than you have received. Then, we define our four columns and their types.</p><p>Now that we have our schema we can define a table which uses it with the (deftable) function. <a href="https://pact-language.readthedocs.io/en/stable/pact-reference.html#deftable">#deftable</a></p><p>We’ll refer to the table by name when we need to insert, read, or update data. When our module is deployed, we’ll also need to create the table using the (create-table) function (this must be called outside the module). <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#create-table">#create-table</a></p><p>Pact supplies several data-access functions for working with tables. <a href="https://pact-language.readthedocs.io/en/latest/pact-functions.html#database">#database</a></p><p>Note that these functions can only be called by functions within the module that defined the table, or in a transaction that satisfies the module governance function. Beyond these points of access, no one can read or write to tables directly.</p><pre>(deftable accounts:{accounts-schema})</pre><h4><strong>Capabilities</strong></h4><p>Next, let’s explore a fundamental pair of concepts in Pact: guards and capabilities. A guard in Pact defines a rule that must be satisfied for the transaction to continue.</p><p>We’ve seen an example already: keysets are one type of guard. But there are others, such as pact guards (used to guard that transaction is executed within a certain multi-step transactions, such as (coin.transfer-crosschain) and user guards (arbitrary user-defined predicate functions).</p><p>In short, guards are pure predicate functions over the given environment, which can be enforced at any time with (enforce-guard).</p><p>A capability, on the other hand, implements fine-grained control over how a guard is deployed to grant some access to a user of the smart contract.</p><p>Capabilities in Pact are an entire system for managing user rights during the execution of a transaction. You can define a new capability with (defcap). A capability consists of a name, a list of arguments, optional metadata, and a function body that returns a boolean.</p><p>For example, an ADMIN capability might ensure that a specific keyset must be satisfied in order to take some action:</p><pre>(defcap ADMIN ()<br>  (enforce-guard (keyset-ref-guard &quot;free.my-keyset&quot;))</pre><p>Capabilities can implement more sophisticated rules, such as orchestrating a vote to determine whether the contract can be upgraded. You can learn more about capabilities in the Pact documentation. <a href="https://pact-language.readthedocs.io/en/latest/pact-reference.html#capabilities">#capabilities</a></p><p>There are four critical things to know about capabilities.</p><p>First, you can grant a capability to a function with (with-capability), and you can protect some sensitive code with the (require-capability) function. “Granting” a capability means that calls to (require-capability) will succeed so long as the capability is in scope. <a href="https://pact-language.readthedocs.io/en/latest/pact-functions.html#with-capability">#with-capability</a> <a href="https://pact-language.readthedocs.io/en/latest/pact-functions.html#require-capability">#require-capability</a></p><p>Second, you can only grant a capability within the module that defined the corresponding capability. That means, for example, that protecting code with (require-capability) means that code cannot be called from outside the module, because its required capability can only be granted within the module. This is a helpful way to make particular functions private.</p><p>Third, capabilities come in two flavors: unmanaged and managed. Acquiring either will let you access code protected by (require-capability). However, unmanaged capabilities are static (they only rely on their parameters and transaction data to determine whether the capability should be granted), whereas managed capabilities can be dynamic (they additionally rely on state that can change each time the capability is requested during a given transaction). By convention, unmanaged capabilities are “granted” and managed capabilities are “installed”. You can tell that a capability is managed if it uses the @managed metadata field.</p><p>We won’t use managed capabilities in this contract, but you can learn more about them here: <a href="https://pact-language.readthedocs.io/en/latest/pact-reference.html#signatures-and-managed-capabilities">#signatures-and-managed-capabilities</a> <a href="https://stackoverflow.com/questions/72746446/what-are-the-semantics-of-capability-manager-functions-in-pact">#what-are-the-semantics-of-capability-manager-functions-in-pact</a></p><p>Finally, signers of a Pact transaction can scope their signature to one or more capabilities in the module. This indicates that the signer has agreed to grant the specified capabilities if they are asked for via the (with-capability) function, but other capabilities should be denied.</p><p>Managed capabilities must always be scoped; unmanaged capabilities don’t always have to be scoped. When the signer signs with empty capability list, unmanaged capabilities required in the transaction will be signed.</p><p>You can see examples of scoping a signature to a capability in the <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/faucet.repl">faucet.repl file</a> and in the various <a href="https://github.com/thomashoneyman/real-world-pact/tree/50ce4cf19e65f4bfb7de90d8ea5f38948afbd4ce/01-faucet-contract/yaml/send">‘send’ request files</a>.</p><p>Our contract will use one capability: SET_LIMIT. It ensures that calls to change the per-request and per-account limits for a given account<strong> *must*</strong> be signed for by the goliath-faucet account.</p><p>The module’s SET_LIMIT capability will be a simple keyset guard. To grant this capability in a function in this module with (with-capability), the transaction that calls that function must be signed by the goliath-faucet private key, scoped to the SET_LIMIT capability.</p><pre>(defcap SET_LIMIT ()<br> @doc “Enforce only faucet account can raise limits.”<br> (enforce-guard (keyset-ref-guard “free.goliath-faucet-keyset”)))</pre><h4><strong>Functions</strong></h4><p>Now for the fun part! It’s time to implement the core logic of our smart contract. Each feature of the contract will be represented by a function.</p><p>We’ll implement functions for users to request and return funds and to look up their account limits. We’ll also implement two admin-only functions to adjust an account’s limits. Along the way we’ll see how to grant capabilities, prevent invalid states, read and write tables, format strings, and more.</p><p><strong>free.goliath-faucet.request-funds</strong></p><p>Our first function lets users request funds from the faucet. Specifically, we will call the (coin.transfer-create) function from the coin contract <strong>IF</strong> the requested amount is within the account limits for the receiving account. If our checks pass (the amount is valid), then we’ll transfer the funds and then update our accounts table to reflect the transfer.</p><pre>(defun request-funds:string (<br>  receiver:string <br>  receiver-guard:guard <br>  amount:decimal)<br>  @doc <br>     &quot;Request that funds are sent to the account denoted as the \    <br>    \&#39;receiver&#39;. If the account does not exist then it will be \   <br>    \ created and be guarded by the provided ‘receiver-guard’ <br>    \ keyset.&quot;</pre><p>We’ll use two properties to help ensure correct behavior for this function. First, the transaction should only succeed if the address requested a positive amount. Second, if the transaction succeeded, then the table at the ‘funds-requested’ column must have increased by the amount requested. The first property is a simple check, but the second uses a property-only function called (column-delta). <a href="https://pact-language.readthedocs.io/en/stable/pact-properties-api.html#column-delta">#column-delta</a></p><p>Recall that due to our schema invariants we have some additional checks that verify that our table writes are always within the valid bounds of our account and request limits. But they won’t stop us from forgetting to write to the table at all, or from writing a value that’s not the exact amount the user requested. (column-delta) can ensure that for us.</p><pre>@model<br>  [ (property (&gt; amount 0.0))<br>    (property (= amount (column-delta accounts “funds-requested”)))<br>  ]</pre><p>Pact’s formal verification will check that your implementation satisfies the two properties above, but we still have to write the code that <strong>*prevents*</strong> the invalid states. To abort a transaction if it fails to meet a condition, use (enforce). <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#enforce">#enforce</a></p><p>To see formal verification in action, comment out this line and re-run the REPL file.</p><pre>(enforce (&gt; amount 0.0) “Amount must be greater than 0.0”)</pre><p>We still need to verify that the amount is within the account’s limits. To do that, we must read the receiver’s limits from the accounts table if it exists there (ie. it has requested funds before), or assume the default limits if not.</p><p>There are a number of functions for reading and writing tables. One of the most common is (with-default-read), which is used to read a row from a table, with a fallback value in the case the row does not exist. <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#with-default-read">#with-default-read</a></p><p>The := operator indicates that we are storing the value of the column on the left-hand side in the variable name on the right-hand side within the scope of the (with-default-read) call.</p><pre>(with-default-read accounts receiver<br>   { “funds-requested”: 0.0<br>   , “funds-returned”: 0.0<br>   , “request-limit”: DEFAULT_REQUEST_LIMIT<br>   , “account-limit”: DEFAULT_ACCOUNT_LIMIT<br>   }<br>   { “funds-requested” := requested<br>   , “funds-returned” := returned<br>   , “request-limit” := request-limit<br>   , “account-limit” := account-limit<br>   }</pre><p>From this point on we have access to the values of the four columns associated with the receiver account in the accounts table. Let’s use them to bind a helper variable, balance, that records the difference between the total requested funds and the total returned funds.</p><p>For binding the variable, we can introduce local variables with (let). <a href="https://pact-language.readthedocs.io/en/stable/pact-reference.html#let">#let</a></p><p>This balance is what should be checked against the account limit. Now, we can finally enforce that the requested amount does not exceed the request limit.</p><pre>(let ( (balance (- requested returned)) )<br>   (enforce (&lt;= amount request-limit)<br>   (format &quot;{} exceeds the account’s per-request limit, which is {}&quot;       <br>     [ amount request-limit ]))</pre><p>We can also ensure that transferring the requested amount would not result in exceeding the total account limit.</p><pre>(enforce (&lt;= (+ amount balance) account-limit)<br>  (format &quot;{} would exceed the account’s total limit ({} remains of    {} total)&quot; <br>    [ amount (- account-limit balance) account-limit ]))</pre><p>With these checks satisfied, we know that the address has requested a valid amount and we process the transfer using the (coin.transfer-create) function: <a href="https://github.com/kadena-io/chainweb-node/blob/56e99ae421d2269a657e3bb3780c6d707e5149a0/pact/coin-contract/v5/coin-v5.pact#L358-L362">coin contract #L358–362</a></p><p>Notice that the (coin.transfer-create) function grants a capability, (coin.TRANSFER), as part of its implementation: <a href="https://github.com/kadena-io/chainweb-node/blob/56e99ae421d2269a657e3bb3780c6d707e5149a0/pact/coin-contract/v5/coin-v5.pact#L377">coin contract #L377</a></p><p>That means that a transaction that calls this (request-funds) function must be signed by the faucet account keys, and that signature must be scoped to the (coin.TRANSFER) capability. To see examples of how to do this, please see the <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/faucet.repl">faucet.repl file</a> and the request-funds.yaml request file!</p><pre>(coin.transfer-create FAUCET_ACCOUNT receiver receiver-guard amount)</pre><p>If the transfer succeeded, then we should update the accounts table to indicate the user has requested more funds. If you’d like to see our formal verification in action, try “accidentally” hardcoding the funds-requested update below to a specific number in the <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/faucet.pact">faucet.pact file</a>.</p><pre>(write accounts receiver<br>  { &quot;funds-requested&quot;: (+ amount requested)<br>  , &quot;funds-returned&quot;: returned<br>  , &quot;request-limit&quot;: request-limit<br>  , &quot;account-limit&quot;: account-limit<br>  }))))</pre><p>Our next two functions can only be called by the faucet account itself. They adjust the per-request or per-account limit for a given address. We’ll implement checks to ensure that the new limits are greater than the old limits and that the transaction executing this function was signed by the faucet account.</p><p><strong>free.goliath-faucet.set-request-limit</strong></p><pre>(defun set-request-limit:string (account:string new-limit:decimal)<br>  @doc &quot;Set a new per-request limit for requesting funds from the  faucet.&quot;</pre><p>Once again we’ll reach for property tests to ensure our function is correct.</p><p>The first property test verifies that the faucet signed this transaction — it’s referring to the (faucet-authorized) property we defined at the module level earlier in our code.</p><p>The second property test verifies that if this transaction succeeded, then the accounts table row for this account, at the “request-limit” column, has been updated to be the value provided to this function. Similarly to (column-delta), we can use this to verify that the table is written correctly. <a href="https://pact-language.readthedocs.io/en/stable/pact-properties-api.html#read">#read</a></p><pre>@model<br> [ (property faucet-authorized)<br>   (property (= new-limit (at &quot;request-limit&quot; <br>     (read accounts account   &quot;after&quot;))))<br> ]</pre><p>The primary way to enforce a condition in a function is the (enforce) function. However, we can also put enforcement logic into a capability. A function can only acquire that capability via (with-capability) if the enforcement checks in the capability succeed. Capabilities are the best tool to reach for when you want to pass a transaction only if it was signed with particular keys; in our case, we have a (SET_LIMIT) capability that enforces that the &quot;free.goliath-faucet-keyset&quot;keyset must be satisfied in order for the SET_LIMIT capability to be granted.</p><p>Since we want the (set-request-limit) to be only called by the faucet account, the SET_LIMIT capability is the perfect way to restrict access to this function. To see an example of how to sign a transaction with this capability, please refer to the <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/faucet.repl">faucet.repl file</a> or the <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/yaml/send/set-user-request-limit.yaml">set-user-request-limit.yaml request file</a>.</p><p>We used (with-default-read) before because we wanted to provide a fallback value in case the account had never requested funds before. This function is different: it should not be possible to update the limits for an account that hasn’t yet requested anything. (with-read) will fail the transaction if the given account does not exist in the table, and read the row otherwise. <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#with-read">#with-read</a></p><p>Note that when using (with-read) it is not necessary to bind variables to every column in the table. You can just use the columns you want.</p><pre>(with-capability (SET_LIMIT)      <br>  (with-read accounts account { <br>     &quot;account-limit&quot; := old-account-limit }        <br>    (enforce (&gt; new-limit old-account-limit)          <br>      (format &quot;The new account limit {} must be a value greater than the old limit ({})&quot; <br>        [ new-limit, old-account-limit ]))        <br>    (update accounts account { &quot;account-limit&quot;: new-limit }))))</pre><p>We used (write) before because we were inserting a new row into the table if the account didn’t yet exist. To update one or more columns in an existing row you can use (update). <a href="https://pact-language.readthedocs.io/en/stable/pact-functions.html#update">#update</a></p><p>Like (with-read), it’s only necessary to include the columns that you are updating, not all the columns.</p><p><strong>free.goliath-faucet.set-account-limit</strong></p><p>The (set-account-limit) function is almost identical to the (set-request-limit) function, just targeting a different field.</p><pre>(defun set-account-limit:string (account:string new-limit:decimal)  <br>  @doc &quot;Set a new per-account limit for requesting funds from   \      <br>  \ the faucet.&quot;    <br>  @model      <br>    [ (property faucet-authorized)        <br>      (property (= new-limit <br>        (at &quot;account-limit&quot; (read accounts account &quot;after&quot;))))        <br>    ]     <br>  (with-capability (SET_LIMIT)      <br>    (with-read accounts account { <br>      &quot;account-limit&quot; := old-account-limit <br>    }        <br>      (enforce (&gt; new-limit old-account-limit)          <br>        (format &quot;The new account limit {} must be a value greater than the old limit ({})&quot; <br>          [ new-limit, old-account-limit ]))  <br>      (update accounts account { &quot;account-limit&quot;: new-limit }))))</pre><p>Our next function is a little helper that lets users look up their account limits from our table. Remember: tables cannot be accessed outside your module for security reasons. If you want to provide access to specific data, write a function that performs the table read.</p><p><strong>free.goliath-faucet.get-limits</strong></p><pre>(defun get-limits:object (account:string)<br>  @doc &quot;Read the limits for your account and see how much KDA you can request.&quot;<br>  (with-read accounts account { <br>     &quot;account-limit&quot; := account-limit<br>   , &quot;request-limit&quot; := request-limit<br>   , &quot;funds-requested&quot; := requested<br>   , &quot;funds-returned&quot; := returned<br>   } { <br>     &quot;account-limit&quot;: account-limit<br>   , &quot;request-limit&quot;: request-limit<br>   , &quot;account-limit-remaining&quot;: <br>       (- account-limit (- requested  returned))<br>   }<br> ))</pre><p>Our final function allows users to transfer funds back to the faucet account and credit it against their account limit. The property tests, enforcements, table reads and writes, and let bindings should start looking familiar!</p><p><strong>free.goliath-faucet.return-funds</strong></p><pre>(defun return-funds:string (account:string amount:decimal)<br>  @doc “Return funds to the faucet (returned funds credit against your limits).”<br>  @model<br>   [ (property (&gt; amount 0.0))<br>     (property (= amount (column-delta accounts “funds-returned”)))<br>   ]<br>   (enforce (&gt; amount 0.0) “Amount must be greater than 0.0”)<br>   (with-read accounts account { <br>     “funds-requested” := requested<br>   , “funds-returned” := returned <br>   } <br>   (let ((balance (- requested returned )) <br>         (new-returned (+ returned amount )) )</pre><p>We didn’t implement a property for this because our table invariants already verify that the funds returned can never exceed the funds requested. You can verify that removing this enforcement check will make the model checker yell at us.</p><pre>(enforce (&lt;= amount balance)<br>  (format &quot;{} exceeds the amount this account can return to the faucet, which is {}.&quot;<br>    [ amount balance ]))</pre><p>Next, we transfer from the user account to the faucet account. To transfer funds from the user to the faucet account the user must have signed the transaction and scoped their signature to the (coin.TRANSFER) capability. For examples, please see the <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/faucet.repl">faucet.repl file</a> and the <a href="https://github.com/thomashoneyman/real-world-pact/blob/main/01-faucet-contract/yaml/send/return-funds.yaml">return-funds.yaml</a> request file.</p><pre>(coin.transfer account FAUCET_ACCOUNT amount)<br>  (update accounts account { &quot;funds-returned&quot;: new-returned }))))<br>)</pre><h4><strong>Initialization</strong></h4><p>At this point we’ve established our smart contract: we entered a namespace, defined a keyset, and implemented a module. Now it’s time to initialize data.</p><p>For a typical smart contract, that simply means creating any tables we defined in the contract. However, more complex contracts may perform other steps, such as calling functions from the module.</p><p>Tables are defined in modules, but they are created after them. This ensures that the module can be redefined (ie. upgraded) later without necessarily having to re-create the table.</p><p>Speaking of: it’s a common practice to implement the initialization step as an ‘if’ statement that differentiates between an initial deployment and an upgrade. As with our keyset definition at the beginning of the contract, this can be done by sending an “upgrade” field with a boolean value as part of the transaction data</p><pre>(if (read-msg &quot;upgrade&quot;)<br>  &quot;Upgrade complete&quot;<br>  (create-table free.goliath-faucet.accounts))</pre><p>We have completed writing a faucet contract that can be deployed on devnet. The next steps will be running a devnet on your local machine, and running the faucet application that calls the functions from the contract.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dpZhDOpRAA0tZwdI" /></figure><p>You can start by following the instructions here: <a href="https://github.com/thomashoneyman/real-world-pact/tree/main/02-goliath-wallet">https://github.com/thomashoneyman/real-world-pact/tree/main/02-goliath-wallet</a></p><p>The Kadena.js team hopes that this step-by-step guide was practical and helpful.</p><p>Make sure you follow us on our social accounts for more exciting developer updates to come!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2F9a9e56%3Fas_embed%3Dtrue&amp;dntp=1&amp;display_name=Upscribe&amp;url=https%3A%2F%2Fupscri.be%2F9a9e56&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href">https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d514f0629e46" width="1" height="1" alt=""><hr><p><a href="https://medium.com/kadena-io/a-step-by-step-guide-to-writing-pact-smart-contract-goliath-faucet-d514f0629e46">A Step-By-Step Guide to Writing Pact Smart Contract — Goliath Faucet</a> was originally published in <a href="https://medium.com/kadena-io">Kadena</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kadena.js — PactNumber]]></title>
            <link>https://medium.com/kadena-io/kadena-js-pactnumber-1444580eeda8?source=rss-d8432c69bef4------2</link>
            <guid isPermaLink="false">https://medium.com/p/1444580eeda8</guid>
            <category><![CDATA[kadena]]></category>
            <category><![CDATA[dapps]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <dc:creator><![CDATA[Heekyun]]></dc:creator>
            <pubDate>Fri, 09 Sep 2022 13:30:02 GMT</pubDate>
            <atom:updated>2022-09-09T13:30:02.791Z</atom:updated>
            <content:encoded><![CDATA[<h3>Kadena.js — <strong>PactNumber has been Released</strong></h3><p>We are thrilled to announce that PactNumber is now released in Kadena.js.</p><p>What is PactNumber and how is it used?</p><p>PactNumber is a typescript class that provides useful number functions for frontend builders to generate Pact Code conveniently with accuracy. In this article, we’ll take a look at the use of numbers in KDA transfer functions and introduce the usage of PactNumber.</p><h3><strong>Integer vs Decimal vs String</strong></h3><p>Pact functions often require numbers to be typed as integers or decimals. The amount in KDA transfer functions are typed as decimal. Therefore, the sample code below will receive a type error, “<em>expected decimal, found integer”.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qs22V2P_u_iaBpko" /><figcaption>Example 1) KDA transfer function — expect type error</figcaption></figure><p>PactNumber now provides the functions toInteger() and toDecimal(), so builders can forget about number type errors, just like the code below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DkkvLGWCCH3Fm1iwopfX6w.png" /><figcaption>Example 2) PactNumber.toDecimal()</figcaption></figure><p>There are also cases when we want to read numbers as strings. One example is the Chain IDs that are used in KDA’s cross chain transfers. Builders need to be aware that even though Kadena chains consist of integers ranging from 0..19, the Kadena chains are specified as strings. The 4th argument in the below example specifies the target chain as chain 10.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-AE07uZ5ThBF44WdpuU39Q.png" /><figcaption>Example 3) KDA Cross Chain Transfer to chain 10.</figcaption></figure><p>PactNumber now provides the functions to stringify any type of numbers with toStringifiedInteger() and toStringifiedDecimal()</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AGstOaBTKIbod9l-Jp9jgg.png" /><figcaption>Example 3) PactNumber.toStringifiedInteger()</figcaption></figure><h4><strong>Pact native functions</strong></h4><p>We have looked composing Pact codes with different number types from Javascript with PactNumber. There also exists Pact native functions to read numbers from data field: read-msg , read-decimal , read-integer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Q73fcLyJ23dnn1Vi" /><figcaption>Example 4) KDA transfer function — using read-decimal</figcaption></figure><p>Above code is one example of writing the KDA transfer function with read-decimal, where amount is passed into data field as a string. This way, amount is always read as decimals, and the type error shown in example 1 is prevented.</p><p>read-msg is also a function to read from data field, regardless of the type. Below are examples that depict how the numbers are formatted differently to be read as different types in Pact.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XhMjw9Mq1iYhZa8mgINXRw.png" /><figcaption>Example 5) Typing numbers in transaction data field — (read-msg)</figcaption></figure><p>PactNumber provides the functions to format numbers in decimal or integer objects that Pact expects in the data field: toPactDecimal() and toPactInteger() .</p><h3>Big Number</h3><p>Lastly, PactNumber solves a big issue that builders often struggle with —operating with numbers in Javascript that are out of safe number range.</p><p>Number operations in smart contracts often involve big decimal points that Javascript cannot safely handle. PactNumber uses bignumber.js library and allow users to store and handle big number values safely.</p><h3>What’s coming next?</h3><p>Coming next with PactNumber is number operations.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1444580eeda8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/kadena-io/kadena-js-pactnumber-1444580eeda8">Kadena.js — PactNumber</a> was originally published in <a href="https://medium.com/kadena-io">Kadena</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Getting Started with Chainweb Relay App]]></title>
            <link>https://medium.com/kadena-io/getting-started-with-chainweb-relay-app-7e7a01fe79c8?source=rss-d8432c69bef4------2</link>
            <guid isPermaLink="false">https://medium.com/p/7e7a01fe79c8</guid>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[crypto]]></category>
            <category><![CDATA[blockchain-technology]]></category>
            <category><![CDATA[defi]]></category>
            <dc:creator><![CDATA[Heekyun]]></dc:creator>
            <pubDate>Wed, 25 Aug 2021 15:45:02 GMT</pubDate>
            <atom:updated>2021-08-25T15:45:02.194Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bmXFrJ6AX3NxWty7Au7sVg.jpeg" /></figure><h3>Getting Started with Kadena Relay App in Testnet</h3><p>Part 1: Create and fund a testnet KDA account</p><p>Part 2: Create a Bond on Kadena Testnet</p><p>Part 3: Install and Run Kadena Relay App on Testnet</p><p>Part 4 (bonus): Rotate, renew, and unbond your bonds.</p><h3>Part 1: Create and fund a testnet KDA account</h3><p>You’ll first create a testnet KDA account (will be referred to tKDA account in this article) in order to create a bond on Kadena testnet. If you have a Zelcore or Chainweaver account, you can use the account from Zelcore. Otherwise, you can generate a keypair from <a href="https://transfer.chainweb.com/">kadena-transfer-tool</a> to create the account.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/552/1*ZvEmzVsDfAUTuAR4nJ90aA.png" /><figcaption>kadena-transfer-tool</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qqE5owAzNukpZB7EE0ofsA.png" /><figcaption>Zelcore Wallet — Kadena</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5mefJQ__uzqP1kpqL3Ifmg.png" /><figcaption>Zelcore Wallet — Receive</figcaption></figure><ol><li>Visit the <a href="https://transfer.chainweb.com/">kadena-transfer-tool</a> and click on “Generate KeyPair.” A file that contains a set of public key and a private key will be downloaded. For Zelcore users, click on “Receive” to find your account name and the public key.</li><li>Visit <a href="https://faucet.testnet.chainweb.com/">Kadena Testnet Faucet</a> and click on “Create and Fund New Account”. If you already have a tKDA, click on “Add Funds to Existing Account.”</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/624/1*jH2o3B1BjKJvbqH6ZE2q-g.png" /><figcaption>Step 3,4,5 — Kadena Testnet Faucet</figcaption></figure><p>3. Paste in the public key from Step 1 and add to keysets by clicking “+”.</p><p>4. Fill in the account name. We recommend using the public key as the account name.</p><p>5. Click on “Create and Fund Account”</p><p>You now have a testnet KDA account with a balance of 20 tKDA.</p><h3>Part 2: Create a Bond on Kadena Testnet</h3><ol><li>Visit the <a href="https://relay.chainweb.com/testnet/">Testnet Chainweb Relay Website</a>. This website allows you to manually create a new bond, and manage existing bonds.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gmagyJ4Di-B_ZW4iXXfZbQ.png" /></figure><p>2 . Click on “Connect Wallet” on the top right, and paste in your account name. Then set the signing option to preferred method.</p><p>3. Paste in the public key in “Bond Guard” that you will use to manage the bond, and add to the keyset by clicking “+” button.</p><p>4. Click on “New Bond”.</p><p>Once the transaction is complete, you’ll see the bond details after refreshing the page.</p><h3>Part 3: Install and Run Relay App</h3><p>Before running app, you should have a <strong>relay bond</strong> and an <strong>infura</strong> <strong>project.</strong> Follow this <a href="https://blog.infura.io/getting-started-with-infura-28e41844cc89/">guide</a> to create an infura project.</p><ol><li>Set up Bond Details.</li></ol><p>Create an .env file with the template below and fill in the details.</p><pre>DEFAULT_ENV=kovan</pre><pre># Infura project ID<br>INFURA_API_TOKEN=<br><br># Relay-app settings (always required)<br>BOND_NAME=<br>PACT_PRIVATE_KEY=</pre><p><strong>INFURA_API_TOKEN — </strong>the project ID of your infura project.<br><strong>BOND_NAME</strong> — the bond name that will be listed under “Your Bonds” in <a href="https://relay.chainweb.com/testnet/">Chainweb Relay Testnet</a> website. <br><strong>PACT_PRIVATE_KEY</strong> — the private key of keypair used in the bond.</p><p>If you used the public key from Zelcore, or want to use a separate keypair to manage the bond, look at <strong>part 4: Rotate</strong> to rotate your bond guard to a separate keypair.</p><p>2. Install and run the Relay App.</p><p>The software listens to Ethereum Testnet for transfer activities to a “lockup” account and propose or endorse the header information on Kadena Testnet. If the header is proposed, the Kadena Testnet emits PROPOSE events, which the app will listen and endorse. When the app succeeds in endorsing the proposal, then the bond will have earned a new <strong>activity</strong>.</p><p>There are two ways to run this software: <strong>Docker</strong> or <strong>npm</strong>.</p><p>Run via Docker:</p><pre>docker run -v &quot;$PWD/.env:/app/.env:ro&quot; kadena/relay-app</pre><p>Run via npm:</p><pre>npm install --global @kadena/relay-app:latest<br>relay-app</pre><h4>Advanced: Generate lockup events on Ethereum testnet</h4><p>In order to create the headers to propose or endorse, there needs to be transfer activity to lockup account on Ethereum Testnet (We default to Kovan network). You can learn about creating these events <a href="https://github.com/kadena-io/chainweb-relay#generating-test-lockup-transfers">here</a>.</p><h3>Part 4(bonus): Rotate, renew, and unbond your bonds.</h3><h3>Rotate</h3><p>Although bond guards can be identical to tKDA account guard, user can use a separate keypair to guard the bonds. This is to allow the wallet users to use a keypair to be used in the bond software.</p><p>To Rotate, go to the <a href="https://relay.chainweb.com/testnet/">testnet chainweb relay website.</a></p><ol><li>Click on Bond Name, and then click on “Rotate”</li><li>Paste in the public key of the keypair that the bond guard to be rotated to. You can create a new keypair using the <a href="https://transfer.chainweb.com/">kadena-transfer-tool</a> .</li><li>Sign with the preferred method with the tKDA account guard.</li><li>Click “Confirm”</li></ol><h3>Renew / Unbond</h3><p>The bonds need to be renewed after the lockup period (10 days). Once the renew period ends (10 days), then the bond can be unbonded. The buttons will be active once the renew / unbond period begins. The steps are similar to ROTATE, with only one difference — it needs to be signed with the bond guard, not tKDA account guard.</p><p>1. Click on Bond Name, and then click on “Renew” or “Unbond”</p><p>2. Sign with the preferred method with the bond guard</p><p>3. Click Confirm</p><p>You now have a bond on Kadena Testnet and a way to earn activity using the Kadena Relay App! Join our <a href="http://discord.io/kadena">Discord channel</a> for any technical questions regarding the relay app!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2F9a9e56%3Fas_embed%3Dtrue&amp;dntp=1&amp;display_name=Upscribe&amp;url=https%3A%2F%2Fupscri.be%2F9a9e56&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href">https://medium.com/media/78d30e3fd5fc84191dd13999e9cedfc2/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7e7a01fe79c8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/kadena-io/getting-started-with-chainweb-relay-app-7e7a01fe79c8">Getting Started with Chainweb Relay App</a> was originally published in <a href="https://medium.com/kadena-io">Kadena</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>