<?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: simusud</title>
    <description>The latest articles on DEV Community by simusud (@simusud).</description>
    <link>https://dev.to/simusud</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%2F1228291%2F5c9116dc-038f-42f1-abbb-8b3147f5d490.png</url>
      <title>DEV Community: simusud</title>
      <link>https://dev.to/simusud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/simusud"/>
    <language>en</language>
    <item>
      <title>CoinFlip: A Smart Contract game built with Soroban and React</title>
      <dc:creator>simusud</dc:creator>
      <pubDate>Thu, 07 Dec 2023 13:31:33 +0000</pubDate>
      <link>https://dev.to/simusud/coinflip-a-smart-contract-game-built-with-soroban-and-react-1mgj</link>
      <guid>https://dev.to/simusud/coinflip-a-smart-contract-game-built-with-soroban-and-react-1mgj</guid>
      <description>&lt;p&gt;In this article, I will describe the steps to build a coin flip web app using Soroban and React.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Repo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/simusud/coin-flip" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;The first step you have to do is install Rust. You can follow the steps to install Rust in the following article:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Node v18 - Install here: &lt;a href="https://nodejs.org/en/download" rel="noopener noreferrer"&gt;https://nodejs.org/en/download&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rust - How to install Rust: &lt;a href="https://soroban.stellar.org/docs/getting-started/setup#install-rust" rel="noopener noreferrer"&gt;https://soroban.stellar.org/docs/getting-started/setup#install-rust&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Soroban CLI - How to install Soroban CLI: &lt;a href="https://soroban.stellar.org/docs/getting-started/setup#install-the-soroban-cli" rel="noopener noreferrer"&gt;https://soroban.stellar.org/docs/getting-started/setup#install-the-soroban-cli&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stellar Account with test tokens on TEstnet - How to create new wallet using soroban-cli &amp;amp; receive test tokens: &lt;a href="https://soroban.stellar.org/docs/getting-started/setup#configure-an-identity" rel="noopener noreferrer"&gt;https://soroban.stellar.org/docs/getting-started/setup#configure-an-identity&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Freighter Wallet - Wallet extension for interact with the app. Link: &lt;a href="https://www.freighter.app" rel="noopener noreferrer"&gt;https://www.freighter.app&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Clone, Build, and Deploy Smart contract
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Clone the repository:&lt;br&gt;
&lt;code&gt;git clone https://github.com/simusud/coin-flip.git&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;code&gt;contracts/coin_flip&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build the contract:&lt;br&gt;
&lt;code&gt;soroban contract build&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy the contract to Testnet:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soroban contract deploy \
--wasm target/wasm32-unknown-unknown/release/coin_flip.wasm \
--source alice \
--network testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the deployment is complete, you will receive a Contract Address. Save that address to be used in calling the contract functions.&lt;br&gt;
The Contract Address will begin with C..... and looks like this &lt;code&gt;CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Calling Smart Contract Function
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Contract Initialization
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn initialize(env:Env, admin:Address) {
    if Self::has_administrator(env.clone()) {
        panic!("Contract already initialized.")
    }
    let key = DataKeys::Admin;
    env.storage().instance().set(&amp;amp;key, &amp;amp;admin)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This function is called to initialize the contract with admin address as param. Upon initialization it sets a admin address&lt;/p&gt;

&lt;p&gt;After deployment, the first function we should call is initialization. Call initialize function through CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soroban contract invoke \
--id your_contract_id \
--source alice \
--network testnet \
-- \
initialize \
--admin alice 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Set native coin address
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn set_native_coin(env:Env, address:Address) {
    let admin = Self::get_admin(env.clone());
    admin.require_auth();

    let key = DataKeys::NativeCoinAddress;
    env.storage().instance().set(&amp;amp;key, &amp;amp;address)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function sets a native coin address. It can be called only by the admin.&lt;br&gt;
The native coin (XLM) address in Soroban is : &lt;code&gt;CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Set the XLM contact address through CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soroban contract invoke \
 --id your_contract_id \
 --source alice \
 --network testnet \
 -- \
 set_native_coin \
 --address CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add XLM token to your contract
The contract needs to hold double the amount of the flip. So we need to transfer some XLM to the contract depending upon the maximum limit a player can bet.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shell
   soroban contract invoke \
    --id CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC \
    --source alice \
    --network testnet \
    -- \
    transfer \
    --from alice \
    --to your_contract_id \
    --amount 1000000000 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Call flip function
This is a public function and can be called by any user. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It first checks the balance of the contract if it is sufficient to pay back the double of the flip amount, if not it reverts the transaction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let contract_balance = Self::get_balance_of_contract(env.clone());
        if contract_balance &amp;lt; (amount * 2) {
            panic!("Not enough balance in contract. Plese flip for lesser amount")
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, it transfers the the amount of bet native coin to the contract itself from the user calling the transaction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// transfer native coin to current contract from 'sender' address
        let native_coin_addr = Self::get_native_coin(env.clone());
        let flip_key = DataKeys::FlipCount;
        let flip_count: u32 = env.storage().instance().get::&amp;lt;DataKeys, u32&amp;gt;(&amp;amp;flip_key).unwrap_or(0);

        let native_coin_client = token::Client::new(&amp;amp;env, &amp;amp;native_coin_addr);
        native_coin_client.transfer(&amp;amp;sender, &amp;amp;env.current_contract_address(), &amp;amp;(amount));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, it generates the random flip choice by shuffling the list containing head and tail items.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let value = vec![
            &amp;amp;env, 
            String::from_slice(&amp;amp;env, "tail"),
            String::from_slice(&amp;amp;env, "head"),
             ];

    let random_side = value.shuffle();
    let result = random_side.first_unchecked();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It now checks the flip choice given by the sender and the choice randomly generated by the contact. If the sender's choice matches then contract sends double the bet amount to sender. And if sender's flip choice doesn't match the choice generated by contract it emits an event saying "You Lost".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if result == flip_choice {
            native_coin_client.transfer(&amp;amp;env.current_contract_address(), &amp;amp;sender, &amp;amp;(2 * amount));
            win_status = true;
            env.events().publish((sender.clone(), flip_choice.clone()), "You Won");
        } else {
            env.events().publish((sender, flip_choice.clone()), "You Lost");
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also updates the flip counter to tract the number of flips made in the app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// increase flip counter 
        env.storage().instance().set(&amp;amp;flip_key, &amp;amp;(flip_count + 1));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there are some getter functions to get addresses of admin and native coin and native coin balance of the contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build, deploy &amp;amp; run the app frontend
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Clone this repository:&lt;br&gt;
&lt;code&gt;git clone https://github.com/simusud/coin-flip.git&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;code&gt;frontend/coin_flip&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change the &lt;strong&gt;contractAddress&lt;/strong&gt; value to the contract address that you deployed in &lt;code&gt;FlipOptions.tsx&lt;/code&gt; file in line no. 52.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the app&lt;br&gt;
&lt;code&gt;npm run dev&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You will set the localhost where the app will run. Open the link.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on &lt;strong&gt;Connect Wallet&lt;/strong&gt; Botton on the top right corner of the web app.Then enter the password.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2pf0rldo1yeqberilud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2pf0rldo1yeqberilud.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter amount to flip, select flip choice and click Toss button to flip the coin.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzs5o2peaojk92nxz4psl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzs5o2peaojk92nxz4psl.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
And then wallet will pop up to approve the transaction and  click &lt;strong&gt;Approve&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Now if you win you will receive double the amount you tossed. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Coin flip is a smart contract game on Soroban Testnet. This app is created for fun. I request all users to use it responsibly will the knowledge of risks of this in mainnet. Happy Tossing!&lt;/p&gt;

</description>
      <category>soroban</category>
      <category>react</category>
      <category>smartcontract</category>
      <category>stellar</category>
    </item>
  </channel>
</rss>
