<?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 Christophe Verdot on Medium]]></title>
        <description><![CDATA[Stories by Christophe Verdot on Medium]]></description>
        <link>https://medium.com/@crashartifacts?source=rss-e835c6bb39e1------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*mSURh8NefIR5nkZXRMue-A.jpeg</url>
            <title>Stories by Christophe Verdot on Medium</title>
            <link>https://medium.com/@crashartifacts?source=rss-e835c6bb39e1------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 20:24:06 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@crashartifacts/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[Waves DA (Dapp Abstraction) Account: a pragmatic “Account Abstraction-like” UX on Waves]]></title>
            <link>https://medium.com/@crashartifacts/waves-da-dapp-abstraction-account-a-pragmatic-account-abstraction-like-ux-on-waves-8ce89142f925?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/8ce89142f925</guid>
            <category><![CDATA[wavesprotocol]]></category>
            <category><![CDATA[waves]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Thu, 29 Jan 2026 13:29:22 GMT</pubDate>
            <atom:updated>2026-01-29T16:37:12.427Z</atom:updated>
            <content:encoded><![CDATA[<p>Most UX friction in crypto apps isn’t about throughput or block time.<br>It’s about <strong>how often users must sign a transaction</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7jiirM-3rTl5jNeANSAgag.png" /></figure><p>On Waves, just like on many chains, interactive apps (games, social, automation) quickly hit a wall:</p><ul><li>users have to confirm a wallet popup constantly</li><li>users pay fees for every action</li><li>onboarding becomes painful</li></ul><p>This article introduces <strong>Waves DA (Dapp Abstraction)</strong> — a <strong>smart-contract pattern</strong> built with Waves primitives (dApps + data storage) that dramatically reduces user signatures while keeping users in control.</p><blockquote>This is a composable pattern: <strong>smart account + registry + relayer</strong>.</blockquote><h3>1) Core concept: separate ownership from execution</h3><p>Waves DA introduces one idea:</p><blockquote><strong><em>Users own the account. Relayers execute actions. The blockchain sees the user’s account as the caller.</em></strong></blockquote><p>Instead of calling dApps directly from an EOA (eg: Keeper etc), the user calls through a <strong>DA Wallet</strong>:</p><ul><li>a DA Account is a proxy dApp</li><li>deployed per user</li><li>controlled by the user (owner stored on-chain)</li><li>can authorize one or more relayers to call target dApps and methods through a generic proxy</li></ul><p>So when a relayer executes something, the <strong>target dApp sees the DA Wallet as </strong><strong>caller</strong>, not the backend or relayer.</p><pre>        (User-controlled)                             (Project-controlled)<br>┌───────────────────────────────┐               ┌────────────────────────────┐<br>│  EOA Wallet (Keeper / Signer) │               │      Relayer Backend       │<br>│  - signs init &amp; permission txs│               │  - can sponsors fees           │<br>│  - never shares DA seed       │               │  - never owns user account │<br>└───────────────┬───────────────┘               └────────────┬───────────────┘<br>                │                                            │<br>                │ (EOA invokes)                              │ (Relayer invokes)<br>                v                                            v<br>      ┌───────────────────┐                     ┌─────────────────────────┐<br>      │ DA Wallet (dApp)  │&lt;--------------------│  Global Registry (dApp) │<br>      │ - proxy + perms   │    resolve EOA→DA   │  activeDA_&lt;EOA&gt; = &lt;DA&gt;  │<br>      │ - owner stored    │--------------------&gt;│  single source of truth │<br>      └─────────┬─────────┘                     └─────────────────────────┘<br>                │<br>                │ (DA invokes target dApps)<br>                v<br>       ┌──────────────────┐<br>       │   Target dApps   │<br>       │   caller == DA   │<br>       └──────────────────┘</pre><h3>2) The three building blocks</h3><h3>A) The DA Wallet (proxy smart contract/ dApp)</h3><p>This is deployed on the user’s DA address and provides:</p><ul><li>proxy()a generic “forward call to any dApp” entrypoint</li><li>permission system scoped by:<br>- relayer + dApp + method (with optional expiry)<br>- or relayer + dApp (allow all methods on that dApp)</li><li>payment caps per relayer + dApp + method, including per-asset caps</li><li>pause / unpause (owner-only)</li><li>emergency withdraw (owner-only)</li><li>optional fee reimbursement to the relayer (requested per call, enforced by the DA script and backend policy)</li></ul><h3>B) The global registry (single dApp)</h3><p>A single registry stores the canonical mapping:</p><pre>activeDA_&lt;EOA_ADDRESS&gt; =&gt; &lt;DA_ADDRESS&gt;</pre><p>This matters because:</p><ul><li>backends must <strong>never trust</strong> a DA address coming from the frontend</li><li>the registry becomes the source of truth for all relayers and apps</li><li>The registry verifies the EOA→DA link using i.originCaller and the DA’s pendingOwner stored on-chain.</li></ul><h3>C) Relayers (backends)</h3><p>Relayers:</p><ul><li>read EOA→DA mapping from the registry</li><li>build &amp; broadcast proxy() calls on DA</li><li>sponsor fees or;</li><li>receive fee refunds from the DA</li></ul><p>The backend also includes a safety check (refundGuard) to validate (via node validation) that the DA will refund the expected fee before broadcasting if needed.</p><h3>3) The most important security detail: preventing init frontrun</h3><p>The DA Wallet is generic: it should not have a hardcoded owner address in the script.</p><p>So ownership is stored in data storage (e.g. owner = &quot;&lt;EOA&gt;&quot;), and initialization sets it.</p><p>But there’s a well-known risk:</p><blockquote><em>After </em><em>setScript, the account becomes invocable by anyone.<br>If initialization simply sets </em><em>owner = i.caller, a third party could invoke first and become owner.</em></blockquote><p>That’s a classic “first-in wins” initialization frontrun scenario.</p><h3>The solution: pendingOwner written before setScript</h3><p>The deployment flow solves this by writing a <strong>Data Transaction</strong> <em>before</em> deploying the script:</p><ol><li>Generate DA seed locally (frontend only)</li><li>Fund the DA</li><li>Write on the DA Wallet data storage:</li></ol><pre>pendingOwner = &quot;&lt;EOA address&gt;&quot;</pre><p>(signed by the DA seed, since the DA account doesn’t exist as a dApp yet)</p><p>4. Deploy the proxy script (setScript, signed by DA seed)</p><p>Now, even if someone tries to frontrun an init call, the script requires:</p><ul><li>i.caller == pendingOwner</li></ul><p>So only the intended EOA can initialize.</p><p>This keeps the proxy script <strong>generic</strong> (no hardcoded EOA), while still safe.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7H58XiDSXB6WDZz5F4XDCg.png" /></figure><h3>4) One-click setup: Init + Register in a single EOA transaction</h3><p>Once the proxy script is deployed, the user does <strong>one single EOA-signed transaction</strong>:</p><pre>EOA → invoke DA.initAndRegister(registryDapp)</pre><p>This callable does two things atomically:</p><ol><li>initialize DA (set owner, set initialized, delete pendingOwner)</li><li>register in the global registry via <strong>dApp → dApp</strong> call</li></ol><p>Example of the initAndRegister() call:</p><pre>@Callable(i)<br>func initAndRegister(registryDapp: String) = {<br>  # Read pendingOwner and bind ownership to the EOA caller<br>  let eoaStr = toBase58String(i.caller.bytes)<br>  let p = match getString(this, &quot;pendingOwner&quot;) {<br>      case s:String =&gt; s<br>      case _        =&gt; throw(&quot;pendingOwner missing&quot;)<br>    }<br>    if (p != eoaStr) then throw(&quot;Only pendingOwner can init&quot;) else {<br>      let reg = Address(fromBase58String(registryDapp))<br>      # Register EOA &gt; DA on global registry<br>      strict regCall = invoke(reg, &quot;registerFromDA&quot;, [], [])<br>      [<br>        StringEntry(&quot;owner&quot;, eoaStr),<br>        BooleanEntry(&quot;initialized&quot;, true),<br>        DeleteEntry(&quot;pendingOwner&quot;)<br>      ]<br>    }<br>}</pre><p>Result: one tx initializes and links the DA.</p><h3>5) How the registry safely links EOA → DA (without trusting frontend)</h3><p>The registry callable used by this flow is registerFromDA().</p><p>It receives:</p><ul><li>the originating EOA as i.originCaller</li><li>the DA as i.caller</li></ul><p>The registry does not trust originCaller alone; it also checks the DA’s on-chain pendingOwner.</p><pre>@Callable(i)<br>func registerFromDA() = {<br>  let eoaStr = toBase58String(i.originCaller.bytes)<br>  let da     = i.caller<br>  let existing = match getString(this, &quot;activeDA_&quot; + eoaStr) {<br>      case s:String =&gt; s<br>      case _        =&gt; &quot;&quot;<br>    }<br>    if (existing != &quot;&quot;) then throw(&quot;DA already linked&quot;) else {<br>      let p = match getString(da, &quot;pendingOwner&quot;) {<br>        case s:String =&gt; s<br>        case _        =&gt; throw(&quot;DA pendingOwner missing&quot;)<br>      }<br>      if (p != eoaStr) then throw(&quot;DA pendingOwner mismatch&quot;)<br>      else [<br>        StringEntry(&quot;activeDA_&quot; + eoaStr, toBase58String(da.bytes))<br>      ]<br>    }<br>}</pre><p>This is the key:<br>✅ registry is global and canonical<br>✅ relayers can trust it<br>✅ linking is on-chain verified (not frontend claims)</p><h3>6) Calling target dApps through the proxy (without user signatures each time)</h3><p>After initialization + registration, the user can authorize a relayer:</p><ul><li>approveMethod(relayer, dapp, fn, expireHeight)</li><li>or allowAllOnDapp(relayer, dapp, expireHeight)</li><li>and set payment limits per call / asset</li></ul><p>Permissions are set by the DA owner (EOA) via owner-only callables.</p><p>Then the relayer can execute:</p><pre>Relayer → invoke DA.proxy(...)</pre><p>The DA:</p><ul><li>checks permissions and limits</li><li>forwards the call to the target dApp using invoke(target, fn, args, payments)</li><li>optionally refunds fees to the relayer (if required)</li></ul><p>Here a simplified proxy outline:</p><pre>@Callable(i)<br>func proxy(target: String, fn: String, args: List[Int], reimburse: Boolean) = {<br>  if (!match getBoolean(this, &quot;initialized&quot;) { case b:Boolean =&gt; b case _ =&gt; false }) then<br>    throw(&quot;Not initialized&quot;)<br>  else {<br>    # permission checks omitted for simplification<br>    let targetAddr = Address(fromBase58String(target))<br><br>    # args decoding omitted for simplification<br>    strict call = invoke(targetAddr, fn, decodeArgs(args), [])<br>    # Optional fee refund (exact fee amount + asset id)<br>    if (reimburse) then<br>      [ ScriptTransfer(i.caller, i.fee, i.feeAssetId) ]<br>    else<br>      []<br>  }<br>}</pre><h3>The “caller identity” property (critical)</h3><p>In the example target dApp below:</p><pre>{-# STDLIB_VERSION 6 #-}<br>{-# SCRIPT_TYPE ACCOUNT #-}<br>{-# CONTENT_TYPE DAPP #-}<br><br>func callerStr(i: Invocation) = toBase58String(i.caller.bytes)<br><br>@Callable(i)<br>func YYY3(a: Int, s: String, b: Boolean) = [<br>  StringEntry(&quot;YYY3_caller&quot;, callerStr(i)),<br>  IntegerEntry(&quot;YYY3_a&quot;, a),<br>  StringEntry(&quot;YYY3_s&quot;, s),<br>  BooleanEntry(&quot;YYY3_b&quot;, b)<br>]</pre><p>It store:</p><ul><li>caller = i.caller</li></ul><p>When the relayer calls through DA proxy:</p><ul><li>the target dApp sees i.caller = DA, not the relayer.</li></ul><p>That’s exactly what makes this pattern powerful:<br>the DA Wallet is the on-chain actor.</p><p>Permissions are managed by the DA owner (EOA) via owner-only callables like approveMethod / allowAllOnDapp.</p><h3>7) Relayer safety: refund guard</h3><p>A practical problem: relayers don’t want to sponsor calls if refunds are misconfigured or revoked.</p><p>The backend includes a refundGuard step:</p><ul><li>validates (via node simulation/validate) that the call will include the expected refund transfer to the relayer</li><li>only broadcasts if the refund is guaranteed by script execution</li></ul><p>This makes fee sponsorship robust and predictable.</p><p>Optional hardening: registry could store proxyVersion/scriptHash to ensure DA runs expected code, hence why we do not want store any address in the code.</p><h3>8) Threat model</h3><p>This pattern doesn’t pretend seeds are magic.</p><ul><li>If the DA seed is compromised during setup, that’s critical (like any wallet).</li><li>The goal is: <strong>backends are never owners</strong>, and delegation stays revocable.</li></ul><p>Strong properties:</p><ul><li>relayers are scoped and revocable (no global allow-all relayer)</li><li>registry is the source of truth (no frontend spoofing)</li><li>init cannot be frontrun due to pendingOwner</li><li>permissions are per relayer + dApp (+ method) with optional expiry</li><li>emergency pause + withdraw exists</li></ul><h3>9) Why this matters for Waves</h3><p>Waves DA enables “AA-like” UX patterns on Waves:</p><ul><li>Sponsored interactions if project/ relayer want to.</li><li>game loops and micro-actions without constant signing</li><li>backend automation with clear, revocable permissions</li><li>target dApps seeing DA identity as caller (not backend identity)</li></ul><p>All without protocol changes.</p><h3>Closing</h3><p>Dapp Abstraction is not a theoretical pitch.<br>It’s a working end-to-end PoC using Waves-native primitives:</p><ul><li>DA Wallet proxy smart account</li><li>registry mapping EOA→DA</li><li>safe init (pendingOwner written before setScript)</li><li>one-click init + register</li><li>relayer execution through proxy with optional refunds</li></ul><p>If you’re building interactive apps on Waves, this pattern can significantly improve UX while keeping user control intact.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8ce89142f925" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[NFT Standard on Waves Blockchain]]></title>
            <link>https://medium.com/@crashartifacts/nft-standard-on-waves-blockchain-ee4f3371ce35?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/ee4f3371ce35</guid>
            <category><![CDATA[wavesprotocol]]></category>
            <category><![CDATA[waves]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[nft]]></category>
            <category><![CDATA[evm]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Tue, 09 Jan 2024 06:14:11 GMT</pubDate>
            <atom:updated>2024-01-10T09:58:01.003Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yaEmGaJXo1TtCAhFYwfX0g.png" /></figure><p><em>NFTs on the Waves blockchain currently suffer from a lack of a standard, preventing the unification of all NFTs across different platforms and tools supporting Non-Fungible Tokens.</em></p><p><em>At the moment, projects like SIGN Art, Puzzle Market, Waves Keeper, etc., if they want to support new NFT collections issued outside of their platform/dApp, have to write wrapper code for each one, making it a tedious and non-scalable task.</em></p><h3><strong>WHY IS IT THAT WAY?</strong></h3><p>Let’s keep it short, but basically, it is mostly due to the very cheap cost on Waves to store data on-chain. Therefore, all projects issuing NFTs decided to store data directly on-chain with their own “standard” key/value, which is different for each project.</p><p>Let’s take the example of SIGN Art; adding a new NFT will create a set of data entries on-chain, such as:</p><pre>&quot;art_maxmint_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: 100<br>&quot;art_price_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: 150000000<br>&quot;art_royalties_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: 400<br>&quot;art_licence_cid_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: &quot;bafybeifuyo4pqu54ismqgtb6e4h6kkvgx7zg4u3zibh2r7y6mb64i7bzza/licence.pdf&quot;<br>&quot;art_licence_hash_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: &quot;a87758c354e30a9e78fb84fa3a0010a5090ab20df0be11ad45b5720cc187e639&quot;<br>&quot;art_export_hash_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: &quot;6bc24b3e7e8cb14ddb0045b4b9fa1794c0bd77aff45b45ec06ec30de7e8d399f&quot;<br>&quot;art_export_cid_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: &quot;bafybeihx75xsirilentjh4gzcwgqrfrm3l3m2boflp5wtae5mefks5p5wq/exported.png&quot;<br>&quot;art_display_cid_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: &quot;bafybeihbkmsqhenkuongrckkpcnmqr45m4ljs54swptjpo2ofzdhudisaq/display.png&quot;<br>&quot;art_desc_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: &quot;test&quot;<br>&quot;art_name_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: &quot;Hydden&quot;<br>&quot;art_date_Hv7muNhZnCLD47J9tYkURiLwmq1MKyitAidBtmk8RJhB_3NB22KNd6CsjzLyWRQxKg2CVnLfWZRD3pNX&quot;: 1696994137141<br>etc…</pre><p>On the other hand, Puzzle Market will create a different set:</p><pre>&quot;nft_8yPbzhadExk2HnwsuSHeXPydqY49qmA4Y9Zp7HkNDoCM_issuer&quot;: &quot;3PKVgd6ds1xervK6bPXbEHBqg8ibTcf5HZk&quot;<br>&quot;nft_8yPbzhadExk2HnwsuSHeXPydqY49qmA4Y9Zp7HkNDoCM_image&quot;: &quot;https://ipfs.io/ipfs/QmTJsdn6ETpdHDyP2SbR49uciqpy9fq5sn27WPWoiM9kC6&quot;<br>&quot;nft_8yPbzhadExk2HnwsuSHeXPydqY49qmA4Y9Zp7HkNDoCM_data&quot;: &quot;{&#39;collection&#39;: &#39;3PKVgd6ds1xervK6bPXbEHBqg8ibTcf5HZk_ania&#39;, &#39;num&#39;: 3}&quot;<br>&quot;nft_Gnpy5nVajPP3XQQVxrHboMAsXtjnyWAxybMDdKrbr8sD_original&quot;: &quot;https://ipfs.io/ipfs/bafybeifiikpgay7dayc2spiite27fcpvpcnlxmwefnnskg35zmrvk2d54q/original.png&quot;<br>etc…</pre><p>The same applies to any other NFT project on Waves. To change this, we need to follow the most-used standard that all other networks follow, from all EVM Chains to Solana and more. The standard is the following:</p><p>All data is stored in a JSON file on IPFS, while only the hash (called a CID on IPFS) to access this JSON is stored on-chain. This standard makes sense, as NFTs started on Ethereum, and storing a lot of data on-chain with the high gas cost it implies was not a good idea.</p><p>All media are also stored on IPFS, and their CIDs are included in the JSON. Here’s a simple example of such JSON:</p><pre>{<br>  &quot;name&quot;: &quot;Name of NFT&quot;,<br>  &quot;description&quot;: &quot;Description of NFT&quot;,<br>  &quot;external_url&quot;: &quot;https://marketplace.io/id_of_the_nft&quot;,<br>  &quot;image&quot;: &quot;ipfs://CID_GOES_HERE&quot;,<br>  &quot;attributes&quot;: [{}]<br>}</pre><p>There is basically a set of predefined properties recognized by most platforms:</p><pre>name:<br>Name of the item.<br><br>description:<br>A human-readable description of the item.<br><br>image:<br>This is the URL to the preview/ display image of the item. Can be just about any type of image, stored on IPFS starting with ipfs:// (recommended) or HTTPS paths starting with https://.<br><br>external_url:<br>This is the URL that will allow the displaying platform to send the visitor to the origin platform, for example if the NFT is sold on Puzzle Market and was issued on SIGN Art, this is the link to the initial NFT drop on SIGN Art.<br><br>animation_url:<br>This is the URL to a multi-media attachment for the item. This file extension could be anything from MP4 to GLB or MP3 but not all platform will support all extensions.<br><br>animation_type:<br>This is the file format of the multi-media attachment provided from animation_url, this allow to quickly identify the media type.<br><br>attributes:<br>These are all the custom attributes for the item</pre><p>Any other needed data is generally added as “attributes/traits”:</p><pre><br>  &quot;attributes&quot;: [<br>    {<br>      &quot;trait_type&quot;: &quot;Base&quot;, <br>      &quot;value&quot;: &quot;Starfish&quot;<br>    }, <br>    {<br>      &quot;trait_type&quot;: &quot;Eyes&quot;, <br>      &quot;value&quot;: &quot;Big&quot;<br>    }, <br>    {<br>      &quot;trait_type&quot;: &quot;Mouth&quot;, <br>      &quot;value&quot;: &quot;Surprised&quot;<br>    }, <br>    {<br>      &quot;trait_type&quot;: &quot;Level&quot;, <br>      &quot;value&quot;: 5<br>    },<br>    {<br>      &quot;display_type&quot;: &quot;boost_number&quot;, <br>      &quot;trait_type&quot;: &quot;Aqua Power&quot;, <br>      &quot;value&quot;: 40<br>    }, <br>    {<br>      &quot;display_type&quot;: &quot;boost_percentage&quot;, <br>      &quot;trait_type&quot;: &quot;Stamina Increase&quot;, <br>      &quot;value&quot;: 10<br>    }, <br>  ]<br></pre><h3>HOW DO WE MOVE TO A SIMILAR STANDARD?</h3><p>With the upcoming launch of SIGN Art V2, which comes with a lot of changes, including the removal of the “curated only” access and the support of NFTs issued on any other platform (complying with the standard) to be sold in our secondary market, such a standard is required.</p><p>It will be up to each project to align with such a standard or not, but we propose a way to do the transition that will allow anyone to follow the standard, even old existing projects, while not having to drop what they implemented already, as both can coexist on-chain. Also, with the upcoming WAVES 2.0 using EVM and a good number of EVM projects potentially moving to Waves, this is even more important to start having a standard.</p><p>Of course, SIGN Art will also comply with this standard, and it will be done as follows:</p><p>To easily retrieve the CID leading to the JSON containing the data of any given NFT, we will simply query the data storage of the issuer account looking for a data entry with a key using the following structure:</p><pre>`std_nft_${nft_id}_metadata`</pre><p>If this returns a CID, then we can request the associated JSON on IPFS.</p><pre>// Here an example how you could validate that the json have your platform requirement properties<br>const isValidMetadata = function(metadata){<br>  let is_valid = false<br>  if(Object.hasOwn(metadata, &#39;name&#39;) &amp;&amp; Object.hasOwn(metadata, &#39;description&#39;) &amp;&amp; Object.hasOwn(metadata, &#39;image&#39;) &amp;&amp; Object.hasOwn(metadata, &#39;external_url&#39;)){<br>    is_valid = true<br>  }<br>  return is_valid<br>}<br><br>// Here an example how to retrieve the NFT metadata on IPFS base on the NFT ID and ISSUER address<br>const get_nft_metadata = async function(nft_id, issuer){<br>  let data_entry_regex = `std_nft_${nft_id}_metadata`<br>  let metadata = null<br>  let nft_is_valid = false<br>  let nft_is_valid_msg = &quot;&quot;<br>  try{<br>    let get_link = await fetch(nodeURL+&quot;/addresses/data/&quot;+issuer+&quot;?key=&quot;+data_entry_regex)<br>    let get_link_json = await get_link.json()<br>    if(get_link_json.length){<br>      const get_json_from_ipfs = await fetch(&quot;https://cloudflare-ipfs.com/ipfs/&quot;+get_link_json[0].value)<br>      const result_json = await get_json_from_ipfs.json()<br>      if(isValidMetadata(result_json)){<br>        metadata = result_json<br>        nft_is_valid = true<br>      }else{<br>        nft_is_valid_msg=&quot;This NFT metadata don&#39;t follow the required standards&quot;<br>      }<br>    }else{<br>      nft_is_valid_msg=&quot;This NFT don&#39;t follow the required metadata standards&quot;<br>    }<br>  }catch(err){<br>    console.log(err)<br>  }<br>  if(!nft_is_valid){<br>    console.log(&quot;nft_is_valid_msg&quot;, nft_is_valid_msg)<br>  }else{<br>    console.log(&quot;metadata&quot;, metadata)<br>  }<br>}<br><br>get_nft_metadata(&quot;CnrsX8Gdsr2LFWTbeWd52KrJFhtHTuxtzEpkWpguZ1aC&quot;, &quot;3N9o4fNhKnVigxGjWv4MuiGXwK94SiQhomm&quot;)</pre><p>You can find the data entry of the NFT from this example on the issuer testnet address:</p><p><a href="https://testnet.w8.io/3N9o4fNhKnVigxGjWv4MuiGXwK94SiQhomm/data/CnrsX8Gdsr2LFWTbeWd52KrJFhtHTuxtzEpkWpguZ1aC">w8 · 3N9o4f···homm</a></p><p>And the JSON on IPFS from the returned CID:<br><a href="https://cloudflare-ipfs.com/ipfs/bafkreiaoncqchjss5yjizg2eljm5q66suprnud535jplfaoeofcvkjijpq">https://cloudflare-ipfs.com/ipfs/bafkreiaoncqchjss5yjizg2eljm5q66suprnud535jplfaoeofcvkjijpq</a></p><p>On the issuer side, generally the project dapp, the only requirement is to add the new STD entry when creating new NFTs.</p><p>For their existing NFTs/Entries, they can run a script that will retrieve the data from their dapp storage for each issued NFT and then do two things:</p><ol><li>Structure a JSON following the standard and add it to IPFS (remember to pin the file to ensure that they are not removed later by the garbage collector.)</li><li>From the CID received from adding the JSON to IPFS, add a new data entry on the dapp storage with “std_nft_{nft_id}_metadata” as the key and the CID as the value:</li></ol><pre>&quot;std_nft_CnrsX8Gdsr2LFWTbeWd52KrJFhtHTuxtzEpkWpguZ1aC_metadata&quot;: &quot;bafkreiaoncqchjss5yjizg2eljm5q66suprnud535jplfaoeofcvkjijpq&quot;,</pre><p>Here’s another example of a JavaScript code getting all the issued NFT data from a given issuer/dapp, generating each JSON, adding them to IPFS, and then adding the std entries to the issuer dapp with the CIDs as values:</p><pre>const encodeUrl = require(&#39;encodeurl&#39;);<br>const ipfs = require(&quot;./ipfs&quot;)<br>const {data, broadcast} = require(&#39;@waves/waves-transactions&#39;)<br><br>require(&quot;dotenv&quot;).config();<br><br>const node_url = process.env.node_url<br>const dapp_seed =process.env.dapp_seed<br>const chain_id = process.env.chain_id<br><br>const key_image = &quot;displayCid_&quot;<br>const key_title = &quot;name_&quot;<br>const key_description = &quot;desc_&quot;<br><br>const get_nft_data_from_event = async function(issuer, key){<br>  let obj = {<br>    name: &quot;&quot;,<br>    description: &quot;&quot;,<br>    image: &quot;&quot;,<br>    external_url: &quot;&quot;,<br>    attributes: [<br>     /*  {<br>        &quot;trait_type&quot;:&quot;Rarity Class&quot;,<br>        &quot;value&quot;:&quot;Normal&quot;<br>     } */<br>    ],<br>    //animation_url: &quot;https://signart.infura-ipfs.io/ipfs/bafybeibkgflciimyuwlmgffeiqriokoebfa7upurn2lpmdfxv7facfkm3u/exported.mp4&quot;,<br>    //animation_type: &quot;MP4&quot;<br>  }<br>  let regex = encodeUrl(`${key_title}${key}|${key_description}${key}|${key_image}${key}`)<br>  try{<br>    let get_link = await fetch(node_url+&quot;/addresses/data/&quot;+issuer+&quot;?matches=&quot;+regex)<br>    let get_link_json = await get_link.json()<br>    <br>    for(const i of get_link_json){<br>      if(i.key.includes(&quot;name&quot;)){<br>        obj.name = i.value<br>      }<br>      if(i.key.includes(&quot;desc&quot;)){<br>        obj.description = i.value<br>      }<br>      if(i.key.includes(&quot;displayCid&quot;)){<br>        obj.image = &quot;ipfs://&quot;+i.value<br>      }<br>    }<br>  }catch(err){<br>    console.log(err)<br>  }<br><br>  return obj<br>}<br><br>const add_to_ipfs = async function(json) {<br>  try{<br>    const add = await ipfs.upload(json)<br>    return add<br>  }catch(err){<br>    console.log(err)<br>    return err<br>  }<br>}<br><br>const add_meta_entry_to_dapp = async function(key, cid){<br>  const signDataEntry = await data(<br>    {<br>      data: [<br>          { key: key, value: cid }<br>      ],<br>      fee: 500000,<br>      chainId: chain_id<br>    }, <br>    dapp_seed<br>  )<br><br>  try{<br>    const broadcast_entry = await broadcast(signDataEntry, node_url)<br>    console.log(broadcast_entry)<br>    return {error: false, result: broadcast_entry}<br>  }catch(err){<br>    console.log(err)<br>    return {error: true, result: err}<br>  }<br>}<br><br>// retrieve all NFT data on the issuer dapp<br>const get_event_id_from_nft_id = async function(issuer){<br>    // here we query the name_(.*) keys for each issued NFT to get each NFT ID that is included in this key<br>    const regex_key_on_dapp = `name_(.*)`<br>    try{<br>      const get_link = await fetch(node_url+&quot;/addresses/data/&quot;+issuer+&quot;?matches=&quot;+regex_key_on_dapp)<br>      const get_link_json = await get_link.json()<br>      for(const i of get_link_json){<br>        // we split the key ex: &quot;name_CnrsX8Gdsr2LFWTbeWd52KrJFhtHTuxtzEpkWpguZ1aC&quot; to get the NFT ID<br>        const data = i.key.split(&quot;_&quot;)<br>        const nft_id = data[1]<br>        <br>        try{<br>          // check if NFT metadata standard exist already on issuer dapp<br>          const regex_key_meta_on_dapp = `std_nft_${nft_id}_metadata`  <br>          const have_metadata = await fetch(node_url+&quot;/addresses/data/&quot;+issuer+&quot;?matches=&quot;+regex_key_meta_on_dapp)<br>          const have_metadata_json = await have_metadata.json()<br>          // if not, get the data from issuer dapp storage<br>          if(!have_metadata_json.length){<br>            // once we get the event key, we query the event data<br>            const res = await get_nft_data_from_event(issuer, nft_id)<br>            res.external_url = &quot;https://anything.org/&quot;+data[1]<br>            const ipfs_result = await add_to_ipfs(res)<br>            const add_to_dapp = await add_meta_entry_to_dapp(regex_key_meta_on_dapp, ipfs_result.path)<br>            if(add_to_dapp.error){<br>              console.log(&quot;Error happened&quot;, add_to_dapp.result)<br>            }else{<br>              console.log(&quot;add_to_dapp&quot;, add_to_dapp.result)<br>            }<br>          }else{<br>            console.log(&quot;metadata already found for &quot;+nft_id)<br>          }<br>        }catch(err){<br>          console.log(err)<br>        }<br>      }<br>    }catch(err){<br>      console.log(err)<br>    }<br>  <br>  return<br>}<br><br>get_event_id_from_nft_id(&quot;3N9o4fNhKnVigxGjWv4MuiGXwK94SiQhomm&quot;)</pre><p>Here’s the ipfs.js file required by the example:</p><pre>let ipfsClient = null<br>let ipfs_client_dynamic_import = async function(lib){<br>  ipfsClient = await import(lib)<br>}<br>ipfs_client_dynamic_import(&#39;kubo-rpc-client&#39;)<br><br>// signart-external on infura<br>let host = &quot;ipfs.infura.io&quot;;<br>const projectId = &quot;******&quot;;<br>const projectSecret = &quot;*****&quot;;<br>const auth = &#39;Basic &#39; + Buffer.from(projectId + &#39;:&#39; + projectSecret).toString(&#39;base64&#39;)<br><br>const upload = async function(json){<br>  let result = null<br>  let ipfs = ipfsClient.create({<br>    host: host,<br>    port: &quot;5001&quot;,<br>    protocol: &quot;https&quot;,<br>    timeout: &#39;10m&#39;,<br>    headers: {<br>      authorization: auth<br>    }<br>  });<br><br>  let progress_func = function(len) {<br>    console.log(len)<br>  }; <br><br>  try {<br>    result = await ipfs.add(JSON.stringify(json), { progress: progress_func, pin: true, wrapWithDirectory: false, cidVersion: 1 })<br>  } catch (err) {<br>    console.log(&quot;catched err&quot;);<br>    console.log(err);<br>  }<br>  return result<br>}<br><br>module.exports = {<br>  upload<br>};</pre><p>We believe this standard is needed, and it will be added soon to SIGN Art with the upcoming Version 2.</p><p>It is already implemented on the testnet and heavily tested on our side.</p><p>We are, of course, open to any feedback, especially from any NFT issuer project.</p><p><strong>[UPDATE — January 10, 2024]</strong></p><p>Based on some feedback received, it was suggested to not only enforce IPFS, even though it is the standard and will remain the preferred option for us. We will adjust the proposed standard as follows:</p><p>std_nft_${nft_id}_metadata will become std_nft_${nft_id}_cid and still return the JSON file CID to retrieve it from IPFS. Alternatively, the JSON following the same standard as the IPFS version could be directly stored on the chain as a stringified JSON under std_nft_${nft_id}_json.</p><p>Example:</p><pre>&quot;std_nft_HmKzrrdrznFcZmfhigjTLhjrPXxGyR8fQn1h3eE5HCbV_json&quot;: &quot;{&quot;name&quot;:&quot;Summer Party DJ Pyrex&quot;,&quot;description&quot;:&quot;Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33.&quot;,&quot;image&quot;:&quot;ipfs://bafybeibcgaw3fkfddakkaf4hpnjw3v2uikhkskyym7fo2uadw5hgajrfpa/display.jpg&quot;,&quot;external_url&quot;:&quot;https://waveshack.sign-art.app/event/J9ALgp2FbeDGCkqVBsgbUq2BV29LtUZww426V4TQGCrL&quot;,&quot;attributes&quot;:[]}&quot;,<br>&quot;std_nft_HmKzrrdrznFcZmfhigjTLhjrPXxGyR8fQn1h3eE5HCbV_cid&quot;: &quot;bafkreifnoed6xstsvsc4w2yclo3hy5jd35nne73334nvah4kk5jwe65k6i&quot;,</pre><p>NFT Platforms will then have the choice to decide to support only the preferred standard or both. Here are the pros and cons we identified:</p><h3><strong>std_nft_${nft_id}_cid</strong></h3><p>Pros:</p><ul><li>It is the universally used standard.</li><li>Since NFT media should already be stored on IPFS, this should be easy.</li><li>NFT following this can be transferred to other chains.</li></ul><p>Cons:</p><ul><li>Projects need to use IPFS if they are not doing it yet.</li></ul><h3><strong>std_nft_${nft_id}_json</strong></h3><p>Pros:</p><ul><li>Does not require IPFS.</li><li>Accessible from other dApps.</li></ul><p>Cons:</p><ul><li>Data entries are limited to 5 Kbytes.</li><li>Does not follow the universal standard (Ethereum, BSC, Solana, etc.).</li><li>It can quickly add a lot of entries with duplicated value on dapp storage (ex: NFT with 10 000 editions).</li></ul><p>We would still prioritize the use of the IPFS option as it is more universal, it doesn’t add a lot of unnecessary data on-chain, and it is not limited in size. Also, when SIGN Art Ethereum Gateway (<a href="https://gate.sign-art.app/">https://gate.sign-art.app</a>) eventually accepts any Waves NFT in the future, the JSON on IPFS will be required, as it is needed to send a valid NFT to another Blockchain.</p><p>We are still open to any feedback as we will continue to implement and test the standard.</p><p><strong>Christophe</strong></p><p>https://www.sign-art.app<br><a href="https://t.me/SIGNArtApp">https://telegram.me/SIGNArtApp</a><br><a href="https://twitter.com/signArtApp">https://twitter.com/signArtApp</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ee4f3371ce35" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[NFTs help protect digital art’s value]]></title>
            <link>https://medium.com/@crashartifacts/nfts-help-protect-digital-arts-value-940c73920e80?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/940c73920e80</guid>
            <category><![CDATA[blockchain-technology]]></category>
            <category><![CDATA[digital-art]]></category>
            <category><![CDATA[cryptoart]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Tue, 06 Oct 2020 11:58:02 GMT</pubDate>
            <atom:updated>2020-10-06T11:58:02.146Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DRv7oXIyav1VT2r8pVeDmA.png" /></figure><p><em>In this article, Christophe Verdot, founder of Signature Chain, explains how non-fungible tokens (NFTs) can make a difference in the digital art market.</em></p><p>Fine art is a multibillion dollar market, which, in recent years, thanks to the rise of internet and digital technology, has been drifting from art galleries and auction houses to the web.</p><p><strong>Fraud in a digital age</strong></p><p>On the one hand, this shift makes art accessible to a much wider audience. However, on the other hand, it raises the issues of authenticity and copyright protection.</p><p>Due to digital technology advances, art replication and forgery have, unsurprisingly, become more sophisticated, triggering concerns among sellers and buyers alike. The art market is full of replicas and forgeries that can fool not just your average Joe, but also a seasoned enthusiast. Fraud has been on the rise globally, hitting physical as well as digital art.</p><p>To respond to this challenge, artists have begun to certify their digital works on blockchain and distribute them over a peer-to-peer, InterPlanetary File System (IPFS) network. Crypto art, as it’s been referred to, has been gaining prominence thanks to the immutability and decentralization of blockchain.</p><p>However, another issue comes up. If a digital image is freely available for viewing or downloading, what value does it have? Producing or buying digital art becomes an uncertain prospect for artists and collectors, respectively, as images can be easily duplicated and plagiarized.</p><p>If an art work can be replicated for free, it has a lower market value or none at all. Watermarking authentic works has been a common practice for artists, but advancements in technology are making this measure less effective.</p><p><strong>NFT as a solution</strong></p><p>To maintain the value of digital items, the blockchain-based concept of “digital scarcity” has been introduced, which is exercised through non-fungible tokens (NFTs). NFT is a cryptographic token representing a unique object or part of it.</p><p>An NFT is created as a blockchain transaction that permanently links the token to a unique digital fingerprint or hash on an open, distributed and permanent ledger. The possession of an artwork and a corresponding NFT signifies a verified and undisputable ownership.</p><p>NFTs can operate as provenance assuring that an artwork is genuine and providing accurate information on past ownerships.</p><p>While online art auctions are notorious for bad provenance due to unscrupulous sellers claiming to have documented ownership of fraudulent art, NFTs emerge as a vital alternative. If an official blockchain address for a specific piece of digital art is published on relevant websites and social media, any user can verify the authenticity of the work.</p><p>The immutability of blockchain ensures that an NFT as art documentation has not been altered or falsified.</p><p>Tokenized art works are generally presented and shared as HD files, which might be intimidating for some artists and buyers. However, what gives value and scarcity to digital art is not a file itself but the ownership of a “license” in the form of an NFT.</p><p>The owning of an NFT gives a buyer or collector the right to display and resell a connected work, but not the creation copyright nor the right to duplicate it commercially. The creator retains all intellectual property rights.</p><p><strong>Due diligence still required</strong></p><p>Of course, blockchain technology is no magic. Nothing can prevent scam artists from replicating someone else’s piece of digital art, tokenizing it and selling as their own, just like it is the case with physical art.</p><p>Still, digital art is available on the internet for the entire world to see and critique. Therefore, fraud can be easily detected. Social media, in particular, have become a powerful tool in that respect. By engaging in fraud, artists put their reputation, public image and potential sales a risk.</p><p>On the users’ or buyers’ side, it is still necessary to do minimal due diligence to avoid falling for fraud. Buying blindly from random and anonymous artists is not advisable. Artists should be able to display their portfolio and background, as well as their blockchain address.</p><p><strong>SIGN Art solution</strong></p><p>On the Waves blockchain, a project called SIGN Art is currently being developed by Signature Chain. The project aims to bring the Waves protocol’s advantages to digital art creators and collectors.</p><p>Thanks to its instant transactions and low fixed transaction fees, the Waves blockchain is a perfect fit for NFT issuance.</p><p>The current crypto art market is heavily dominated by Ethereum. But the Ethereum blockchain is burdened by up-and-down gas costs, which has been a major source of complaints from collectors and artists.</p><p>Over the past year, Signature Chain has developed <a href="https://www.sign-web.app/">a certification platform</a> allowing anyone to certify any file or document on the Waves blockchain.</p><p>On SIGN Art, the file certification feature will be available soon, allowing creators to certify their works with an option of tokenizing art for selling. SIGN Art could also be used as a portfolio of certified works and/or a digital art marketplace. A beta version of the service is already available on the testnet here: <a href="https://beta.sign-art.app./">https://beta.sign-art.app.</a></p><p>Read <a href="https://t.me/wavesnews?source=post_page---------------------------">Waves News channel<br></a>Follow <a href="https://twitter.com/wavesprotocol">Waves Twitter</a><br>Watch <a href="https://www.youtube.com/channel/UCYDQN4Fo4rGnOZ22L5plNIw?source=post_page---------------------------">Waves Youtube<br></a>Subscribe to <a href="https://www.reddit.com/r/Wavesplatform/?source=post_page---------------------------">Waves Subreddit</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=940c73920e80" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How SIGN solves Ownership Rights in Real Estate]]></title>
            <link>https://medium.com/@crashartifacts/how-sign-solves-ownership-rights-in-real-estate-15dd06625411?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/15dd06625411</guid>
            <category><![CDATA[signature-chain]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[dapps]]></category>
            <category><![CDATA[wave-protocol]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Tue, 21 Jul 2020 12:13:23 GMT</pubDate>
            <atom:updated>2020-07-21T12:17:35.942Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Case study in Vietnam: property purchased with full ownership certificates turned out to be a fraud.</strong></p><p><a href="https://tuoitre.vn/chuyen-oai-am-mua-nha-ra-so-hong-ten-minh-roi-van-khong-duoc-la-chu-nha-20200531223454997.htm">Chuyện oái oăm: mua nhà, ra sổ hồng tên mình rồi vẫn không được là chủ nhà</a></p><h3><strong>1. Problematic Scenario:</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fuw4-NXRL85rv2fTFSPzxw.png" /></figure><p>• An individual who has been impersonating the true owner with fake documents. Mr. Ut, the real owner of the house, has lost the property ownership certificate (assuming it could be lost or stolen by the unknown person), he only reports this to a regulator to get a new one without making a request to prevent all ownership transfer transactions related to the house =&gt; Traditional identity verification and current property management systems have critical vulnerabilities.</p><p>• Notary offices are the authenticator but do not detect the types of documents that have been falsified from the impersonator (<em>falsifying the local police certificate of the impersonator’s ID card number and the number of Mr. Ut’s ID card shown on the property ownership certificate to that from the same person, it is possible that the person pretending to have changed for a new ID card to bypass the buyer and NOTARY OFFICE</em>) caused Mr. Thien (home buyer) to lose trust in the NOTARY OFFICE =&gt; The trusted NOTARY OFFICE was proven not to be reliable.</p><p>• The court restored ownership of Mr. Ut because he was the real owner of the house and had all the valid proof. When Mr. Thien handed over the money to buy a house from the seller (the person impersonating Mr. Ut), he did not make a notarized delivery document to prove that the payment is valid for the dispute that happened later, so there was no way to claim compensation for the lost money at the NOTARY OFFICE.</p><h3><strong>2. Comprehensive Solution with Blockchain:</strong></h3><p><strong>2.1 Why Blockchain?</strong></p><p>According to the basic definition of blockchain cited from John Nguyen’s Blockchain Economy book:</p><p>“Blockchain is similar to a ledger, which records the history of valid transactions that occur in a system. However, blockchain is a digital ledger, jointly held by multiple parties (each with a copy). Once data has been validated and recorded on the blockchain thanks to the consensus of all computer nodes in the system, there is no way to change it.</p><p>The term <strong>‘’blockchain’’</strong> is made up of <strong>‘’block’’</strong> and <strong>‘’chain’’</strong>, which is derived from how the system’s design, so that valid transactions occurring in the network will be arranged in the order of the timeline (<strong>time-stamp</strong>) and is put into a block, then this block is encoded into a hash to close when it meets the conditions set by the system. Then from the hash, it is taken as the basis for connecting to the next new block. Such a system continues to form <strong>a chain of blocks</strong> that extends to infinity.”</p><p>Note, because the blockchain can’t store Blob (big size files), in our solution that we’ll introduce in the next part, blockchain <strong>does not store data content directly</strong>, but rather <strong>records hash as unique encrypted representations for the data’s content</strong> into a digital ledger.</p><p>For example, a property ownership certificate file of any size (assuming 1 MB) will be hashed by the SHA-256 algorithm into a unique piece of code (hash) that always has a length of 64 alphanumeric characters and alternating numbers, a random fixed size of 256 bits. The hash from two different files will never be the same, any alteration will result in a new hash.</p><p>SHA-256 is a one-way cryptographic hashing algorithm that creates irreversible hash back to the original hashed content with whatever computer power we have today. So, there’s no way to directly decode it because the whole purpose of this SHA-256 hash is to be irreversible, making data extremely secure and impossible to be faked.</p><p><strong>2.2 Process of the solution</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/717/1*CgTjsxjdikJe_DUPQp1IIQ.png" /></figure><p>With such superior features, we can offer an effective solution when applying blockchain to data security, anti-tampering and ownership of the right for individuals thanks to certification directly on the blockchain by the competent authority. The process will take place as followed:</p><p><strong>Step 1:</strong> First of all</p><p>• The Land Administrative Management Agency must register its ID address on the WAVES blockchain, this ID address is unique and acts as a digital signature which will be used to digitally sign and issue the property ownership certificate files. This ID address of the Land Administrative Management Agency must be publicly notified to the users to help them determine the validity of the property ownership certificate file(s) when checking licensing information on the blockchain.</p><p>• Users also need to create an ID address of their own on the WAVES blockchain. They’ll have to register personal information (KYC) which is associated with this ID address in order to use it to digitally sign a number to purchase and to transfer contracts to prove they’re the rightful owner. This personal ID address of the user will also be shown in the content of the property ownership certificate file issued by the Land Administrative Management Agency.</p><p><strong>Step 2:</strong> Through a decentralized application, let’s call it the SIGN DApp, built on the WAVES blockchain Protocol, the Land Administrative Management Agency will log in to the SIGN DApp and use their ID address to sign for certificates / validity of the property ownership certificate files.</p><p><strong>Step 3:</strong> On the SIGN DApp, the Land Administrative Management Agency will receive a “Proof of Certification” file containing the following information:</p><p>• Their (LAMA) ID (address) which was used to certify the property ownership certificate file.</p><p>• Property ownership certificate file name.</p><p>• The time-stamp at which the property ownership certificate file was validated on the WAVES blockchain.</p><p>• The hash representing the encryption for the property ownership certificate file(s) that has been recorded in the WAVES blockchain.</p><p>• A link so the user can immediately look up the validity of this information directly on the blockchain explorer of the WAVES blockchain.</p><p>• A link that allows users to download property ownership certificate files from a decentralized storage system (IPFS) whenever they need it.</p><p>The Land Administrative Management Agency then only needs to send <strong>the property ownership certificate file</strong> and <strong>the “Proof of Certification” file</strong> to the rightful owner to keep it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KySnZUguCw_vVv8CRMLKwA.png" /></figure><p><strong>Proof of Certification file of a property ownership certificate issued by the Land Administrative Management Agency.</strong></p><p><strong>Step 4:</strong> When a buyer wants to verify the validity of a property ownership certificate, confirming who the real owner of a real estate is, he only needs to know the exact ID address of the Land Administrative Management Agency (this information is publicly disclosed by the government) for collation. This requires the owner to provide 1 of the 4 following details to be easily checked on the WAVES blockchain explorer or authentication lookup (verification explorer) of the SIGN DApp:</p><p>• The file of property ownership certificate issued by the Land Administrative Management Agency</p><p>• “Proof of Certification” file</p><p>• The TxID (the code of <strong>the property ownership certificate file</strong> authentication transaction on the WAVES blockchain)</p><p>• The Hash of the property ownership certificate file</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/945/1*aRyfJ0NtKGmq3s45WE81-Q.png" /></figure><p><strong>When users use the TxID of a Proof of Certification file to check the WAVES blockchain explorer, they will see the authentication information as shown above.</strong></p><p>To determine whether a person is the rightful owner of a real estate property, the buyer only needs to do two things:</p><p>• Ask the owner to provide 1 of the 4 details listed above to check the authenticity of the property ownership certificate file on the WAVES blockchain explorer or verification explorer of SIGN DApp. Check whether or not the ID address of the current owner is being shown in the content of the property ownership certificate file.</p><p>• The buyer uses their ID address to log in and upload the file of the real estate sale and purchase agreement between the two parties onto the WAVES blockchain through <strong>the Mutual Agreement feature (a multi-party contract function)</strong> on the SIGN DApp (is an application built on the WAVES blockchain Protocol). Next, the buyer enters his ID address, owner’s ID address and ID address of the Land Administrative Management Agency, then signs the sale of contract electronically. The system will then automatically send a request to the ID address of the Land Administrative Management Agency and the ID address of the seller for both parties to sign a confirmation agreement of their purchase agreement.</p><p><strong>* Note:</strong> only the real owner of the real estate can have the private key of the ID address recorded in the content of the property ownership certificate. They can use their private key to log into the blockchain system and use their ID address to digitally sign real estate sales contracts that they own. So, it is impossible for crooks to impersonate the owner to sell a house and the buyer cannot be deceived by forging papers as the case mentioned at the top of this article.</p><p><strong>2.3 Transfer of ownership</strong></p><p>When the Land Administrative Management Agency, as a witness, participates in the signing of a real estate sale contract, they also record the transfer in ownership of that real estate. From this facility they will issue <strong>new property ownership certificate files</strong> and <strong>Proof of Certification files</strong> to the new owners (the buyers).</p><p>In order to prevent the former owner of the property from using <strong>the expired property ownership certificate</strong> and <strong>the invalidated Proof of Certification files</strong> to deceive other buyers; avoid the situation of a single property being sold to different buyers at the same time, the Land Administrative Management Agency must:</p><p>• Use the revoke function for invalidated Proof of Verification they have issued.</p><p>• Add a “revoked” tag to these invalidated Proof of Verification files and a “revoked” tag will be displayed when the user checks them in the WAVES blockchain explorer or verification explorer of the SIGN DApp.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wmbtJxnNi9_YI40LezCW-w.png" /></figure><p><strong>After the certificate has been revoked, a REVOKED tag will have been attached to the Proof of Certification file, when users look it up on the verification explorer of the SIGN DApp they can click directly on the card to check the certificate on the WAVES blockchain explorer as shown below.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/947/1*9_acCuDeirM-NCgGWpq4Cw.png" /></figure><p><strong>In the Call field displayed on blockchain explorer B, the user can see the revoked certification. This proves that the WAVES blockchain has recorded the REVOKED command into the system and the previous Proof of Certification file TxID: 5cXQg8xhDW6Qjm7rWqPWKRYgjhMTnZdunkxZZUfCzaKE is no longer valid.</strong></p><p><em>How can a buyer search for the list of previous eligible owners of the property? Or how can a buyer search for the Proof of Certification files related to a real estate in the past?</em> — This requires the Land Administrative Management Agency when issuing new property ownership certificate files and new Proof of Certification files to be able to attach the information (hash, TxID) of the previous version to the newest version.</p><p><strong>3. Summary</strong></p><p><strong><em>How to verify the identity of who the owner of a real estate is:</em></strong></p><p>• The buyer will require the seller to provide the property ownership certificate file and a Proof of Certification file.</p><p><strong><em>How to know if the seller is the owner of the real estate:</em></strong></p><p>• The buyer has to create a three-party contract and uploads the sale contract to the SIGN DApp through the Mutual Agreement feature.</p><p>• The buyer first signs digitally, then asks the digital signature (ID address) of the Land Administrative Management Agency in the contract and requires the seller to use the exact ID address recorded in the property ownership certificate file to sign the contract digitally.</p><p><strong><em>To prevent the ex-owner of the property from using previous property ownership certificates and Proof of Certifications which are expired to conduct a fraud transaction:</em></strong></p><p>• The Land Administrative Management Agency must use the revoke functions for invalidated Proof of Verification files they have issued.</p><p>• The Land Administrative Management Agency issues new property ownership certificate files and new Proof of Verification files to the new owner.</p><p>• The newest Proof of Verification version of a property must refer to its most previous Proof of Verification file.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=15dd06625411" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to build a Web App using Blockchain — Part 4]]></title>
            <link>https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-4-b53059709dbc?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/b53059709dbc</guid>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[dapps]]></category>
            <category><![CDATA[wavesplatform]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <category><![CDATA[wave-protocol]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Sun, 19 Apr 2020 07:49:29 GMT</pubDate>
            <atom:updated>2020-04-25T09:05:13.779Z</atom:updated>
            <content:encoded><![CDATA[<p><em>In the previous articles, we saw together how to build all our Web App component, here we will work on our dApp and create our Smart Contract using the RIDE language on Waves Blockchain. If you didn’t read the part 1,</em><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-1-e3dab7bbdeb"><em> please start there</em></a><em>.</em></p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-1-e3dab7bbdeb"><strong>PART 1</strong></a><strong><br></strong>a) Define the project <br>b) Why use Blockchain? <br>c) Initiate the project</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-2-9d64a8de8e0f"><strong>PART 2</strong></a><strong><br></strong>d) Create the HTML for your INDEX views<br>e) Create a GetData and Settings Classes<br>f) Create the Index javascript logics</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-3-af611a08c558"><strong>PART 3 </strong></a><strong><br></strong>g) Create the HTML for your ADMIN views<br>h) Create the Admin javascript logic<br>i) Integrate Waves Signer</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-4-b53059709dbc"><strong>PART 4</strong></a><br>j) Create the Smart Contract <br>k) Deploy the Smart Contract<br>l) Conclustion</p><h3>J) CREATE YOUR SMART CONTRACT</h3><p>To get the full code of the Smart Contract <a href="https://github.com/christopheSeeka/covstats-tuto/blob/step4/ride/dapp.ride">click here</a>.</p><p><strong>On Waves Blockchain, there is 3 types of Smart Contract:</strong></p><p><strong>The Smart Account</strong><br>This is a Smart Contract attached to a Waves Account and the script logic of this contract will check every outgoing transaction (not incoming one)</p><p><strong>The Smart Asset</strong><br>This is a Smart Contract attached to a Waves Asset and the script will process every outgoing transactions that are using this asset.</p><p><strong>The dApp</strong><br>This is a Smart Contract attached to a Waves Account, similar to the Smart Account but the script logic will also includes @Callable function that you will be able to call from outside using the invokeScript transaction</p><p><strong>In our project, we use a dApp account, this account will have two Callable functions:</strong></p><ul><li><strong>updateInfos() </strong><br>To update the title and description our our page</li><li><strong>addUpdateCase() </strong><br>To add or update entry on our data storage</li></ul><p>To create your dApp go to <a href="http://ide.wavesplatform.com/">ide.wavesplatform.com</a>, this is a convenient online ide for Waves Protocol, a very easy way to start for front end web developers.</p><p>From there click on the + on the bottom left:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/273/1*qEfMViAg12u66k1oTZdKiQ.png" /></figure><p>It will create a dApp Smart Contract template as follow:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f86b6d3eef26fe912fc3737c836809a6/href">https://medium.com/media/f86b6d3eef26fe912fc3737c836809a6/href</a></iframe><p>You see the 3 first lines these are directives needed to identify the version and type of the contract, don’t touch it. You can remove the 2 commented lines at the bottom (we wont see the Verifier today).</p><p><strong>THE “UPDATEINFOS” FUNCTION</strong></p><p>We are left with a @Callable function named foo in this new file, all function we want to be able to call from outside of our contract needs to start with a @Callable(i), the i is a global variable accessible inside the function and giving access to the transaction fields, you could call it differently if you wanted.</p><p>Be aware that local function, the one you would not allow to be called from outside, should be declared before all the @Callable one’s and without the @Callable on top of it.</p><p>Function in RIDE are declared with the key word <strong>“func” </strong>followed by the name of the function<strong>. </strong>Please change the function name from <strong>“foo”</strong> to “<strong>updateInfos”, </strong>and include two parameters, name and intro:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2297c850ac104a9318034d87dfb82a34/href">https://medium.com/media/2297c850ac104a9318034d87dfb82a34/href</a></iframe><p>Make sure to give types to the parameters, here both are :String. <br>From there we want get the address of the account calling this function, to do that we will declare a new ownerAddress variable with key word “let” and use the global variable “i” to access the caller address with “caller” key word:</p><pre>let ownerAddress = i.caller</pre><p>Now that we have the address of the calling account, the title and the description as well, we will write these data on the data storage of the dApp account.</p><p>In the current empty WriteSet([]) add the two following DataEntry:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eb1b65984e846533f77fc598d6de43f6/href">https://medium.com/media/eb1b65984e846533f77fc598d6de43f6/href</a></iframe><p>Each DataEntry line will write (or update if the key already exist) a new key/value entry in the dApp data storage, the parameter here are the key (a string) and the value (string, boolean, integer or byteVector) ex: DataEntry(key, value)</p><p>When we retrieved our address with i.caller we received the address in byteVector format, key in our data storage needs to be in string format, this is why we use <strong>toString()</strong> method to convert the address into string.</p><p>And thats it, our first @Callable function to update the general infos of the page of the calling account is ready! Was quite easy no?</p><p><strong>THE “ADDUPDATECASE” FUNCTION<br></strong>This function will add just a bit more logics, as you can see, it have a bit more parameter, some as :String and others as :Int, here the full code then we will discuss it:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ef627d71f588fb0b8acb6e1a7b1289ed/href">https://medium.com/media/ef627d71f588fb0b8acb6e1a7b1289ed/href</a></iframe><p>Same as for the previous function, we declare the ownerAddress.<br>We also declare a counterNum variable to get the last identifiant used for this calling account, for that we are using what we call a Pattern Matching with the key word “match” followed by a “getter” method.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d1eecc6307ad0641006c60ddeec5da7c/href">https://medium.com/media/d1eecc6307ad0641006c60ddeec5da7c/href</a></iframe><p>Here, this.getInteger(address+”_counterNum”) is looking into the data Storage of the dApp for an entry with the key “{address}_counterNum” and that is an Integer, in RIDE dApp Smart Contract, the key word “this” is a reference to the address of the current dApp account, you could also use it that way:</p><pre><em>getInteger</em>(this, ownerAddress + &quot;_counterNum&quot;)</pre><p>if you want get data from another account, you would use it as follow:</p><pre><em>getInteger</em>(&quot;3nHuJg...&quot;, ownerAddress + &quot;_counterNum&quot;)</pre><p>Back to our code, if the getInteger() “match”, meaning if the entry exist and is an integer (case c: Int =&gt; c) then we attribute the result value to the currentCounterNum variable, if not, then we set it to 0.</p><p>Similarly, we will use a match to define the patient ID, we check if an entry with the “identifiant” parameter exist, remember if its 0 it’s a new entry, else its an update. <br>If an entry exist on the data storage with the key {ownerAddress}_patient_{identifiant}_identifiant” and it’s an Int then we return it to patientID and it’s an update else the patientID is currentCounterNum +1 which is then a new entry with a new auto incremented ID.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a76945df6fdb4f9fd18f8c0068989f25/href">https://medium.com/media/a76945df6fdb4f9fd18f8c0068989f25/href</a></iframe><p>After that we build a json with all the data to store it as well on the data storage, this will be usefull to access all data through a unique key request in our Web App. Remember each invoke call send several parameters for a unique case/patient.</p><p>We also want to keep an entry per parameter to use the data storage as an open API where you could get all entrie per location only, age only and so on.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c3005d71a2d018e46c6fe73c5df834ee/href">https://medium.com/media/c3005d71a2d018e46c6fe73c5df834ee/href</a></iframe><p>Next step, we needs to define how we will update the value of the {userAddress}_counterNum key, ether with the last know identifiant (if we are updating an entry) or the new identifiant (if create a new entry), for that we do:</p><pre>let updateCounter = if(identifiant == 0) then currentCounterNum + 1 else currentCounterNum</pre><p>If identifiant parameter was 0 then it was a new entry, meaning we increment the counter of entry for this address by +1, else, the counterNum stay the same.</p><p>I’ll use this last piece of code to point out that in RIDE, every if statement needs a then and a else branch, both are mandatory.</p><p>We are alsmot there :) Next, we have an if statement again, so? so there will be a then and else right? This one is to check the status parameter, we only allow 3 possible status, 1,2 or 3 (in our project, 1 = confirmed, 2 = recovered and 3 = deceased)</p><pre>if(status != 1 &amp;&amp; status != 2 &amp;&amp; status != 3 ) then <em>throw</em>(&quot;Wrong status&quot;)</pre><pre>else</pre><pre># code continue here</pre><pre>...</pre><p>By the way, comments in RIDE only work single line and start with #.</p><p>And here we are, now at the last part of our Smart Contract! and its very easy because we will do the same as for the updateInfos @Callable, remember the WriteSet?</p><p>So we want write all our data on the storage, and remember, we needs 1 DataEntry(key,value) per data, meaning:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c98be60efb4062e1498dcc400dcb652a/href">https://medium.com/media/c98be60efb4062e1498dcc400dcb652a/href</a></iframe><p>That’s it, our dApp Smart Contract is finished!</p><h3>K) DEPLOY YOUR SMART CONTRACT</h3><p>We still have a couple of things to do, first of all, we needs to deploy this Smart Contract on a Waves Account, <a href="https://ide.wavesplatform.com/">from the online ide</a>, go to the top right and create a new account:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/350/1*eAAgIaTwBiFWIziGKTf58w.png" /></figure><p>Select it and copy the Address, go to the <a href="https://wavesexplorer.com/testnet/faucet">wavesexplorer faucet</a> to get some free waves token for testnet:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*gOZQ5T_T1LZSfkHAlYFtmQ.png" /></figure><p>Enter your address, click that your are not a robot (unless you are one :p) and click “Request 10 WAVES”.</p><p>Once you see these waves on your IDE Account, click on “console” at the bottom left and write deploy()</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/506/1*N6sLxmkGWHel8FstgI1vUw.png" /></figure><p>Push enter and the Smart Contract will deploy on the newly created account, this account will then become the dApp and the address of this account is the address you will use in your settings.js for this.dappAddress.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/511/1*uAgfxWWk7jrZCWxbiKXalw.png" /></figure><p>If you see the link to the transaction in wavesexplorer then everything when well!</p><p>You can now go back to our Web Application, in the settings.js file and change the this.dappAddress value to this new dApp address, save it, make sure webpack is still compiling and nodemon restarting.<br>Then go to <a href="http://localhost:3000/admin">localhost:3000/admin</a>, connect with waves signer and you will see an empty form, start entering data again, the title and description then a couple of entries and after that, go back to <a href="http://localhost:3000/">localhost:3000</a> and you should see these newly added data.</p><h3>L) CONCLUSION</h3><p>It was a bit long i know but i wanted to show you a complete real potential Blockchain use case application built from scratch with the front end, back end, the smart contract and everything integrated together.</p><p>I didn’t go as deep as i wanted in some parts because it was already quite long but the idea was to help you realise that finally, its not much different than building a website or a regular web app, if you look back over the 4 parts, 1 out of 4 was focusing on the Smart Contract, everything else was regular html, css, javascript, routing, api calls etc. Everything a front end developer know already.</p><p>Of course we could improve a lot from here, for example, a way to add entries in mass or even import a cvs of entries, display the waves balance in the admin page etc.</p><p>Going back to the Smart Contract, how does RIDE feel? It’s quite easy to understand right? There is of course a lot more to see and do with it but at least now, you know that it is not that complicated after all!</p><p>Here a couple of interesting tools to use that i’ll list here even if i wasnt able to include them in the process:</p><ul><li><a href="http://waves-dapp.com/">Waves Dapp</a> this one will allow you to test your smart contract very conveniently through a very simple UI and Waves Keeper</li><li><a href="https://chrome.google.com/webstore/detail/waves-keeper/lpilbniiabackdjcionkobglmddfbcjo?hl=en">Waves Keeper</a> this is an alternative to Waves Signer the one we used in our project, the difference is Keeper is a browser extension.</li><li><a href="https://docs.wavesplatform.com/en/">Waves Documentation</a> of course the official documentation is your friend and very helpfull, you’ll find everything there! If not, <a href="https://t.me/waves_ride_dapps_dev">ask on telegram</a></li><li><a href="https://wavesexplorer.com/">Waves Explorer</a> we only used it for the faucet but this is a very convenient tools to explorer account, blocks, transaction, dapp storage etc</li><li><a href="https://oracles.wavesexplorer.com/">Waves Oracle</a> to create oracle for your project</li></ul><p>I hope this will help some of you and if you have any question don’t hesitate to ask in comments or on the <a href="https://t.me/waves_ride_dapps_dev">Waves Developers telegram channel</a> and if you build something on Waves, don’t hesitate to share it with us, we love to see what others are doing!</p><p>The STEP 4 code:<br><a href="https://github.com/christopheSeeka/covstats-tuto/tree/step4">https://github.com/christopheSeeka/covstats-tuto/tree/step4</a></p><p>The complete web app code:<br><a href="https://github.com/christopheSeeka/cov-stats">https://github.com/christopheSeeka/cov-stats</a></p><p>The webapp example on TESTNET:<br><a href="https://covtest.sign-web.app/">https://covtest.sign-web.app/</a></p><p>The webapp on MAINNET:<br><a href="https://cov-stats.sign-web.app/">https://cov-stats.sign-web.app/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b53059709dbc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to build a Web App using Blockchain — Part 3]]></title>
            <link>https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-3-af611a08c558?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/af611a08c558</guid>
            <category><![CDATA[wave-protocol]]></category>
            <category><![CDATA[dapps]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <category><![CDATA[wavesplatform]]></category>
            <category><![CDATA[blockchain]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Sun, 19 Apr 2020 07:48:54 GMT</pubDate>
            <atom:updated>2020-05-06T10:28:13.533Z</atom:updated>
            <content:encoded><![CDATA[<p><em>In the previous article, we built together the html of the index page, our settings and getData classes, our index javascript logics and were able to get an index page displaying data from a Waves Blockchain Data Storage.<br>If you didn’t read the previous parts, </em><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-1-e3dab7bbdeb"><em>please start there</em></a><em>.</em></p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-1-e3dab7bbdeb"><strong>PART 1</strong></a><strong><br></strong>a) Define the project<br>b) Why use Blockchain?<br>c) Initiate the project</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-2-9d64a8de8e0f"><strong>PART 2</strong></a><strong><br></strong>d) Create the HTML for your INDEX views<br>e) Create a GetData and Settings Classes<br>f) Create the Index javascript logics</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-3-af611a08c558"><strong>PART 3</strong></a><strong><br></strong>g) Create the HTML for your ADMIN views<br>h) Create the Admin javascript logic<br>i) Integrate Waves Signer</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-4-b53059709dbc"><strong>PART 4</strong></a><br>j) Create the Smart Contract<br>k) Deploy the Smart Contract<br>l) Conclustion</p><h3>G) CREATE THE ADMIN HTML</h3><p>To get the step 3 code <a href="https://github.com/christopheSeeka/covstats-tuto/tree/step3">click here</a>.<br>To get the complete web app code <a href="https://github.com/christopheSeeka/cov-stats">click here</a>.</p><p><em>Now let’s work on the admin page, this page is accessible with the </em><a href="http://localhost:3000/admin"><em>localhost:3000/admin</em></a><em> route and display a button “start” which will open Waves Signer popin to let you ether create a new Waves account if you don’t have any yet or choose an existing one.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*WtCulUZKUCsTURtCBD6Kmw.png" /></figure><p><strong>THE ADMIN VIEW</strong><br><a href="https://github.com/christopheSeeka/covstats-tuto/blob/step3/views/admin.ejs">https://github.com/christopheSeeka/covstats-tuto/blob/step3/views/admin.ejs</a></p><p>Go to the ./views/admin.ejs file and change the content <a href="https://github.com/christopheSeeka/covstats-tuto/blob/step3/views/admin.ejs">with the following one from this page</a>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a000484674e0506136ae7482017b72b0/href">https://medium.com/media/a000484674e0506136ae7482017b72b0/href</a></iframe><p>Similarly to the index page, we first include all our needed libraries and css in the &lt;head&gt;.<br>We have a sort of header (where i could have used a &lt;header&gt; :)) with the title, the description and links to homepage or to <a href="https://www.waves.exchange/">waves.exchange</a>. <a href="https://www.waves.exchange/">Waves.exchange</a> is where you needs to go get your seed (if you just created an account) or get Waves token to pay transaction fee.</p><p>We use here the bootstrap basic accordion element separated in two blocks:</p><ul><li>Block 1 is where you manage the title and description of the page</li><li>Block 2 is where you add or edit entries cases</li></ul><p>You would see a <strong>&lt;div id=”loader”&gt;</strong> in the code which will be used as overlay element when we are waiting for data <em>(when we select an existing entry in the “identifiant” &lt;select&gt; for example)</em></p><p>Something to keep in mind, when we add a new entry, the identifiant list wont be available untill the transaction get at least 1 confirmation (no worries, it’s super fast on Waves).</p><p>At the bottom we include our javascript logics bundle call, remember?:</p><pre>&lt;script src=&quot;javascripts/bundle-admin.js&quot;&gt;&lt;/script&gt;</pre><h3>H) THE ADMIN JAVASCRIPT LOGIC</h3><p><a href="https://github.com/christopheSeeka/covstats-tuto/blob/step3/src/admin.js">https://github.com/christopheSeeka/covstats-tuto/blob/step3/src/admin.js</a></p><p>First we needs to add two new libraries here, Waves Signer:</p><pre>npm install @waves/signer</pre><p>And the Provider Web:</p><pre>npm install @waves.exchange/provider-web</pre><p>These two libraries are required to login with your Waves account and sign every transactions, in the admin page we will use the invokeScript transaction to update infos and to add/update entries.</p><p>Now go to ./src/admin.js and replace the content <a href="https://github.com/christopheSeeka/covstats-tuto/blob/step3/src/admin.js">with the content from this page</a>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1636d5e7f9ac5d08d7881c09be0678b2/href">https://medium.com/media/1636d5e7f9ac5d08d7881c09be0678b2/href</a></iframe><p>We will go quickly over it but only focus on what is related to the dApp calls.</p><p>First we import our libraries and classes then to configure Waves Signer we do the following:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6cb474074e8e397ece323fe554d3c3ef/href">https://medium.com/media/6cb474074e8e397ece323fe554d3c3ef/href</a></iframe><p>Remember, getdata.nodeUrl is getting the nodeURL we entered in our settings.js, we are using a testnet url, for mainnet or stagenet it would be a different url.</p><p>Same with the providerUrl used for new Provider(), it also come from our configuration file.</p><p>After that we see a resetForm, pretty self explanator, same for displayAlert.</p><p><strong>Then we have 4 important listeners:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*04pLEbAi9rdkg7z9sL2-aw.png" /></figure><h4><strong>The “change” event</strong></h4><p>Listening over the <strong>&lt;select id=”identifiant”&gt;</strong> element and called every time we choose a differet option in this &lt;select&gt;, here its quite simple, ether we select an existing option and it mean we are updating an entry or we leave it as “New entry” which have the value = 0 and it means we create a new entry.</p><p>When we choose an existing entry, this listener will automatically retrieve all the info with our getdata.getDataByKey() method with the proper key as argument and display the data in the different fields.</p><p>We could just have retrieve the json entry (you will see that in the next part) but i wanted to show you a different way, getting each separated data from our Node API.</p><h4><strong>The “login” event</strong></h4><p>This one is linked to the <strong>&lt;button id=”login”&gt;</strong> element and is calling the Waves Signer method signer.login() which open the signer popin where you create/choose your account. Once you select an account, the callback will:</p><ul><li>Get the name/title of the page and display it</li><li>Get the introduction texte of the page and display it</li><li>Retrieve all the entry id associated to your address and populate the <strong>&lt;select id=”identifiant”&gt;</strong> element with it</li></ul><p>The Waves Signer login method work as follow:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d5809ea145f299d58892831e6129a0fb/href">https://medium.com/media/d5809ea145f299d58892831e6129a0fb/href</a></iframe><h4><strong>The “addEntry” event</strong></h4><p>This is called every time <strong>&lt;input id=”addEntry”&gt;</strong> is clicked, the callback will define if we add a new entry or update an existing one, based on the <strong>&lt;select id=”identifiant”&gt;</strong> selection. Then it will create the needed parameters for our invokeScript transaction, which is the transaction type we needs on Waves Blockchain to call our dApp Smart Contract function (that we will create in part 4 of this series).</p><p><strong>Here our data object:</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/265f2f1cd8ce95745415c7ebe4520c58/href">https://medium.com/media/265f2f1cd8ce95745415c7ebe4520c58/href</a></iframe><p><strong>dApp</strong> is the address of the dApp account with our smart contract attached to it, we pass here the dappAddress that we get from our settings.js file</p><p><strong>call.function </strong>this is the name of the function we want to call on the Smart Contract/dApp account, here it’s <strong>addUpdateCase</strong></p><p><strong>call.args</strong> is an array of object with all the different data from our form that needs to match the parameters of the dapp function (in exact order) we are calling, note that you needs to define the type (integer, string, boolean or bytearray) aside of the value.</p><p>Once our data are ready, we will sign these data and broadcast them to the Blockchain through the Node API.</p><p><strong>To sign data with signer you just have to use the following:</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/24871f4e51dd8b6a4cda69d3898e621a/href">https://medium.com/media/24871f4e51dd8b6a4cda69d3898e621a/href</a></iframe><p>Basically, you use the invoke method of Waves Signer (each transaction type have its own method), you call this invoke method with your data object as parameter and then you attach the broadcast() method right after it.</p><p>Signing data don’t send them to the blockchain, it only sign the data with your private key (you sign with your Waves account), once you signed, you needs to send these data to the Blockchain, which is what broadcast is doing.</p><p>Since its a promise, you simply can add your .then() and .catch() after broadcast() to do your stuff once its sent.</p><p>You will see a <strong>checkStateChange</strong> function too in my code, i wont go over it for now as i don’t want overcomplicate things, in short, its because since we added a new entry, we need to wait it to be confirmed and then update or <strong>&lt;select id=”identifiant’&gt;</strong> list.</p><h4>The “accountInfo” event</h4><p>This one is called when you click on the <strong>&lt;input id=”accountInfo”&gt;</strong> element, in the first form of our accordion element, to update the title and description, it work exactly like the previous event, meaning it create a data object with data and use the same dApp address.</p><p>The <strong>call.function</strong> here will change, we want call another one, which is <strong>“updateInfo”</strong> and then the <strong>call.args</strong> will simply get the title and description data from the form fields.</p><p>We sign the data with <strong>signer.invoke()</strong> method again, we broadcast it and we clear the form once its done.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9a40d14da85a90549efa2e9c74a6d220/href">https://medium.com/media/9a40d14da85a90549efa2e9c74a6d220/href</a></iframe><p>At the end of the ./src/admin.js file you’ll see a loadResize function, this is juste to adjust the layout on different screens.</p><p>You should now be able to go to <a href="http://localhost:3000/admin">localhost:3000/admin</a>, click on “start” and login with your account (or create a new one), if you don’t have any testnet waves token, <a href="https://wavesexplorer.com/testnet/faucet">go get some here</a>.</p><p>Try to enter a “Page name” and “Introduction” once connected, then click <strong>UPDATE INFOS,</strong> after that, click on <strong>“ADD OR UPDATE ENTRY”</strong> to switch tab and fill the form, click on <strong>ADD NEW CASE</strong>, once its done, you should see your data at localhost:3000/your_waves_address</p><p>If you want configure the Web App on your Waves Address, you can change this.userAddress in settings.js with your own address (the one you used to add an entry); then localhost:3000 will directly display your data.</p><p>And that’s it for our STEP 3!! Almost done! we have one more step to go!</p><p>In <a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-4-b53059709dbc">STEP 4</a> we will see the dApp Smart Contract, go over it together, see how to deploy it then we will configure our Web App to use this dApp instead of the current one.</p><p>The STEP 3 code:<br><a href="https://github.com/christopheSeeka/covstats-tuto/tree/step3">https://github.com/christopheSeeka/covstats-tuto/tree/step3</a></p><p>The complete web app code:<br><a href="https://github.com/christopheSeeka/cov-stats">https://github.com/christopheSeeka/cov-stats</a></p><p>The webapp example on TESTNET:<br><a href="https://covtest.sign-web.app/">https://covtest.sign-web.app/</a></p><p>The webapp on MAINNET:<br><a href="https://cov-stats.sign-web.app/">https://cov-stats.sign-web.app/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=af611a08c558" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to build a Web App using Blockchain — Part 2]]></title>
            <link>https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-2-9d64a8de8e0f?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/9d64a8de8e0f</guid>
            <category><![CDATA[smart-contracts]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[dapps]]></category>
            <category><![CDATA[wavesplatform]]></category>
            <category><![CDATA[wave-protocol]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Sun, 19 Apr 2020 07:47:59 GMT</pubDate>
            <atom:updated>2020-05-06T10:27:21.498Z</atom:updated>
            <content:encoded><![CDATA[<p><em>In the previous article, we saw together what we are going to build, why we want to use the Blockchain and how we plan to do it. Then we prepared all our development environment and routes as well as empty views. We are now ready to build our Web App content! If you didn’t read the part 1,</em><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-1-e3dab7bbdeb"><em> please start there</em></a><em>.</em></p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-1-e3dab7bbdeb"><strong>PART 1</strong></a><strong><br></strong>a) Define the project <br>b) Why use Blockchain? <br>c) Initiate the project</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-2-9d64a8de8e0f"><strong>PART 2</strong></a><strong><br></strong>d) Create the HTML for your INDEX views<br>e) Create a GetData and Settings Classes<br>f) Create the Index javascript logics</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-3-af611a08c558"><strong>PART 3 </strong></a><strong><br></strong>g) Create the HTML for your ADMIN views<br>h) Create the Admin javascript logic<br>i) Integrate Waves Signer</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-4-b53059709dbc"><strong>PART 4</strong></a><br>j) Create the Smart Contract <br>k) Deploy the Smart Contract<br>l) Conclustion</p><h3>D) CREATE THE INDEX VIEW</h3><p>To get the step 2 code <a href="https://github.com/christopheSeeka/covstats-tuto/tree/step2">click here</a>.<br>To get the complete web app code <a href="https://github.com/christopheSeeka/cov-stats">click here</a>.</p><p>Let’s start with the views, remember we already defined ours routes for index and admin, we now needs to builds these templates, lets start with index.ejs.</p><p><strong>What do we needs and how i structured it:</strong></p><p><strong>Edit button<br></strong>This button is a link to the admin page, anyone can go there and connect with his own Waves account, he then can start add data.</p><p><em>Remember, the web app is deployed with a settings.js file (that we will create later) so the root url of the Web App will only show data based on the account defined in this settings file but anyone can have his own page simply by adding his account address (the one he used to add data in the admin page) after the root url.</em></p><p><strong>Title<br></strong>The title for the displayed page, this is administrable in the admin page, it can be the name of an university, a city, an hospital or anything to identify the data source.</p><p><strong>Description<br></strong>Here you can describe the data, for example “Welcome to the COVID19 Tracking Data page of the XXXX City”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*HuoIwRK08e0zT4DczCgWAg.png" /><figcaption>Example of title and description area</figcaption></figure><p><strong>Graph<br></strong>A graph displaying the number of cases by day, this is to give a visual about the situation, to see quickly if it’s going up or down.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*Uw86LoNjJ8SKZyoHF4M0Bw.png" /><figcaption>Example of the graph</figcaption></figure><p><strong>Filters<br></strong>You can filter every columns of the table to group the data according to your own criterias</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*UKJRS8qybRjSikoDs5ENOQ.png" /><figcaption>The differents filters</figcaption></figure><p><strong>Widgets</strong><br>Four separated widgets will display the counts of Total, Confirmed, Recovered and Deceased Cases, each identified with a different color.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*xNICxdeINHqRZJVu5xC7Mg.png" /><figcaption>The 4 widgets</figcaption></figure><p><strong>Data in a sortable table<br></strong>Pretty self explanatory, this will display all the data and allow you to sort them on each columns.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*_7xQUCJk140BzlhCHm4Usw.png" /><figcaption>The table that contains all the entries</figcaption></figure><p><strong>Pagination options<br></strong>Basic pagination options.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*v9fVBcv9aUkkTOZwj0_heg.png" /><figcaption>The table pagination</figcaption></figure><p><strong>Links<br></strong>Here will be displayed the address of the dApp account, which is where the displayed data are stored as well as the owner account address, which is the address of the account that is managing these data.</p><h4>THE CSS</h4><p>To keep this tutorial “short”, i wont spend any time on the css part, just open the style.css file in ./public/stylesheets/ and <a href="https://github.com/christopheSeeka/covstats-tuto/blob/step2/public/stylesheets/style.css">add the content from this file</a>.</p><h4><strong>THE INDEX HTML</strong></h4><p><a href="https://github.com/christopheSeeka/covstats-tuto/blob/step2/views/index.ejs">https://github.com/christopheSeeka/covstats-tuto/blob/step2/views/index.ejs</a></p><p>We include in this page several libraries needed for the different displays such as <a href="https://datatables.net/">dataTable</a>, <a href="https://canvasjs.com/">CanvasJs</a>, <a href="https://jquery.com/">Jquery</a>, <a href="https://getbootstrap.com/">Bootstrap </a>and our <a href="https://fonts.google.com/specimen/Roboto">fonts from google.</a></p><p><strong>Check the &lt;head&gt; section of the index file to see these changes:</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9fb5c6eeaea35bba10d076b6d1d7e054/href">https://medium.com/media/9fb5c6eeaea35bba10d076b6d1d7e054/href</a></iframe><p><strong>Then we strucure the &lt;body&gt; part with 4 container:</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c79058b5408af64a457db2239d817e1/href">https://medium.com/media/2c79058b5408af64a457db2239d817e1/href</a></iframe><p><strong>You will find at lines:</strong></p><ul><li>21: the edit button, the title and and the description, these data will be retrieved from the blockchain API</li><li>30: the widgets, this include a <strong>&lt;div id=”chartContainer”&gt;</strong> element, this is empty and will receive the chart dynamically created later based on the dApp Storage data.</li><li>64: the table that will contain all the data, the tbody of the table is empty and will be populated later with dynamic data from the Blockchain Data Storage through Node API calls.</li><li>89: the footer that will contain our links, some link will be added dynamically later.</li></ul><p><a href="https://github.com/christopheSeeka/covstats-tuto/blob/step2/views/index.ejs">Get the code here</a> and use it as replacement for the ./views/index.ejs file</p><p>Also create a canvasjs.min.js into ./public/javascripts/ and add in it the content <a href="https://github.com/christopheSeeka/covstats-tuto/blob/step2/public/javascripts/canvasjs.min.js">from this file</a>.</p><p>Our index view is now ready to receive data, before moving to the associated javascript logics, we will create 2 simple classes to simplify our work.</p><h3>E) GETDATA &amp; SETTINGS CLASSES</h3><p>Here we will create two classes to simplify the Web App configuration and the get requests on the Node API.</p><p><strong>THE SETTINGS CLASS<br></strong><a href="https://github.com/christopheSeeka/covstats-tuto/blob/step2/settings.js">https://github.com/christopheSeeka/covstats-tuto/blob/step2/settings.js</a></p><p>To allow easy configuration of the Web App, i made a settings.js file at the root of the project, this file will be imported in our getData class and used in the different javascript logics later.</p><p>First create a new file named settings.js at the root folder and add the following:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/edf6997fce7a18f51f7d12ec0216788c/href">https://medium.com/media/edf6997fce7a18f51f7d12ec0216788c/href</a></iframe><p><strong>This class allow us to define the following:</strong></p><ul><li><strong>this.network</strong> is the network we want to use, ether “T” for Testnet, “W” for Mainnet or “S” for Stagenet.</li><li><strong>this.nodeURL</strong> is the Node API URL for our get request on the data storage.</li><li><strong>this.providerUrl</strong> is the url of the Waves Signer provider we want to use, here is <a href="https://www.waves.exchange/">waves.exchange</a>, which is where your account will be manageable.</li><li><strong>this.userAddress</strong> is the address of the account managing the main data (the one displayed on the root url). Leave it by default for now.</li><li><strong>this.dappAddress</strong> is the address of the dApp account where the data are validated and stored. Leave by default for now.</li></ul><p>Then we have a getter to easily get these data from anywhere.</p><p><strong>THE GETDATA CLASS<br></strong><a href="https://github.com/christopheSeeka/covstats-tuto/blob/step2/src/getData.js">https://github.com/christopheSeeka/covstats-tuto/blob/step2/src/getData.js</a></p><p>To easily get our data i created another small class that will do get requests to the Node API everytime we needs data.</p><p>Create a file named getData in ./src/getData.js and add the following content from this file:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5938bbd7b1a0dd48069f0fe8a74c0e36/href">https://medium.com/media/5938bbd7b1a0dd48069f0fe8a74c0e36/href</a></iframe><p>Here we import the settings file we just created earlier and initiate it in a “config” variable. Then we start writting the class, in the constructor, we match the fields based on the settings file using the getter (config.get())<br>There is also an “explorerSegment” field we didn’t mention yet, you will see that later.</p><p>Then we have a conditional block that will check if we have a Waves address as url segment (well, it check if there is something, we could add a isAddress verification method later as improvement), if we do, then we use this as userAddress to get the data, if not, we use the userAddress defined in our settings</p><p>Remember, if you access the root url of the webapp, it use the userAddress you defined in setting, if we access the url/address then it use this address from the url segment.</p><p>Finally we have the async method that will call the node API with a simple fetch get request using the node url we defined in our settings.js (<a href="https://nodes-testnet.wavesnodes.com/"><em>https://nodes-testnet.wavesnodes.com</em></a>). To this nodeUrl we attach the path of the end point we needs (<a href="https://nodes-testnet.wavesnodes.com/api-docs/index.html">see the node api end points list here</a>) and the dappAddress then we use the “ match” method with the key we are looking for, exemple:</p><p><a href="https://nodes-testnet.wavesnodes.com/addresses/data/3NBbHi3Vj5yt37Yv9XZtfwMy7KnZUWSY3uM?matches=3NBSNZiKU3h51dyTyMGX2sPdPfyjqBKf2F4_patient_(.*)">https://nodes-testnet.wavesnodes.com/addresses/data/3NBbHi3Vj5yt37Yv9XZtfwMy7KnZUWSY3uM?matches=3NBSNZiKU3h51dyTyMGX2sPdPfyjqBKf2F4_patient_(.*)</a></p><p><em>Note the (.*) at the end here, which mean anything after our string is allowed.</em></p><h3><strong>F) THE INDEX JAVASCRIPT LOGIC</strong></h3><p><a href="https://github.com/christopheSeeka/covstats-tuto/blob/step2/src/main.js">https://github.com/christopheSeeka/covstats-tuto/blob/step2/src/main.js</a></p><p>Now we needs to write our javascript logics that will basically retrieve our data from the dApp Data Storage and do all the data processing, for that we will use our getData class.<br>We will then inject all these data into our index html.</p><p>Remember to start your watchers if they are not active from last part, open a first terminal and run:</p><pre>npm run watch</pre><p>and a second one where you type:</p><pre>nodemon</pre><p>First of all, there is one more plugin we needs to add and its <a href="https://github.com/apostrophecms/sanitize-html">sanitize-html</a>, we want clean up all string from any possible javascript code to avoid <a href="https://en.wikipedia.org/wiki/Cross-site_scripting">XSS attacks</a>, at least for the front end display. If you use public data from Blockchain i would recommand to always sanitize it before displaying.</p><p>Open a 3rd terminal and run the following command:</p><pre>npm install sanitize-html</pre><p>Now, go to ./src/main.js and copy the code <a href="https://github.com/christopheSeeka/covstats-tuto/blob/step2/src/main.js">from this file</a> into your file, remember ./src/main.js is the file compiled into ./public/javascripts/bundle-main.js which is then included at the bottom of our index.ejs.</p><p><strong>The code is a bit long so i wont go in detail over everything but i commented the key points:</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6ea297e6e3c4975ca4086a184d7b6500/href">https://medium.com/media/6ea297e6e3c4975ca4086a184d7b6500/href</a></iframe><p><strong>What are we doing hre:</strong></p><p>So, first we import sanitize-html and our getData class so we can use the getDataByKey method.</p><p>We then declare some variable and start retrieving our data, example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e8a8150f4bcdbb9e0d78baf6a117bb96/href">https://medium.com/media/e8a8150f4bcdbb9e0d78baf6a117bb96/href</a></iframe><p>Here we pass the <strong><em>{userAddress}_name</em></strong> as parameter of getDataByKey, this is the key we are looking for in the data storage of the dApp, it will give us the name/title of the page, we then inject it into the html <strong>&lt;h1 id=”title”&gt;</strong>.</p><p>We do the same for description, with the key <strong><em>{userAddress}_description</em></strong> and inject the result into the <strong><em>&lt;p id=”introtop”&gt;</em></strong>.</p><p>After that we see two functions, <strong><em>initTable()</em></strong> and <strong><em>initChart()</em></strong>, i wont go into details as it would be very long but in short, they get the data from the view and will filter, sort and organize all of them as needed. <br>But before that, we needs to retrieve and process all the data from the data storage and add them to the view, which is what next code do with another getDataByKey call.</p><p>You see here that we use the key <strong><em>{userAddress}_counterNum</em></strong>, this is because each account using the dApp storage will have an auto incrementing “counter” that will serve as identifiant for new entry. So we do a call on this key, if there is no result for <strong><em>{userAddress}_counterNum</em></strong> that mean no data, else, there is data and we start processing them, generating each lines of our table and add it to the view. Then we populate our different counting widgets, our footer urls <em>(this is where we use the explorerSegment because depending of the network we use, it would change)</em> and finally we call our <strong>initTable().</strong></p><p><strong><em>InitTable()</em></strong> will initiate the <strong>dataTable </strong>plugin and if all go well, end by calling the <strong>initChart</strong> plugin, from there canvasJs will do his job to generate our chart and inject it into the <strong><em>&lt;div id=”chartContainer“&gt;</em></strong> element.</p><p>If you go to <a href="http://localhost:3000/">localhost:3000</a> you will see the same page as <a href="https://covtest.sign-web.app/">https://covtest.sign-web.app/</a>, for now it is using the default userAddress and dappAddress, later on you will use your own.</p><p>And that’s it for the index!!</p><p>Was a bit of a work! but remember, i said it will be “quite easy”, easy is not necessary short :) Here we are building a complete, working Blockchain Web App from scratch so it require a bit of work of course.</p><p>In the <a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-3-af611a08c558">STEP 3</a> we will work on the ADMIN page and implement Waves Signer! Stay tuned and if any question, comment or message me.</p><p>The STEP 2 code:<br><a href="https://github.com/christopheSeeka/covstats-tuto/tree/step2">https://github.com/christopheSeeka/covstats-tuto/tree/step2</a></p><p>The complete web app code:<br><a href="https://github.com/christopheSeeka/cov-stats">https://github.com/christopheSeeka/cov-stats</a></p><p>The webapp example on TESTNET:<br><a href="https://covtest.sign-web.app/">https://covtest.sign-web.app/</a></p><p>The webapp on MAINNET:<br><a href="https://cov-stats.sign-web.app/">https://cov-stats.sign-web.app/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9d64a8de8e0f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to build a Web App using Blockchain — Part 1]]></title>
            <link>https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-1-e3dab7bbdeb?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/e3dab7bbdeb</guid>
            <category><![CDATA[wave-protocol]]></category>
            <category><![CDATA[wavesplatform]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <category><![CDATA[dapps]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Sun, 19 Apr 2020 07:47:01 GMT</pubDate>
            <atom:updated>2020-05-06T10:26:53.212Z</atom:updated>
            <content:encoded><![CDATA[<p><em>When i started to develop a Web application using Waves Protocol, i was a bit lost, Blockchain was new to me and it was hard to find examples from a Front End Web Developer point of view. In this serie, we will develop a complete Web App from scratch. (see the end project running here: </em><a href="https://covtest.sign-web.app/">https://covtest.sign-web.app/</a>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*SKwVmu_bcDVM9pcAcOpQgg.png" /></figure><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-1-e3dab7bbdeb"><strong>PART 1</strong></a><strong><br></strong>a) Define the project <br>b) Why use Blockchain? <br>c) Initiate the project</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-2-9d64a8de8e0f"><strong>PART 2</strong></a><strong><br></strong>d) Create the HTML for your INDEX views<br>e) Create a GetData and Settings Classes<br>f) Create the Index javascript logics</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-3-af611a08c558"><strong>PART 3 </strong></a><strong><br></strong>g) Create the HTML for your ADMIN views<br>h) Create the Admin javascript logic<br>i) Integrate Waves Signer</p><p><a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-4-b53059709dbc"><strong>PART 4</strong></a><br>j) Create the Smart Contract <br>k) Deploy the Smart Contract<br>l) Conclustion</p><p>In this article series i want to show you that despite the possible complexity of the overall Blockchain technology, developping a web application using Blockchain is still quite accessible for a front end web developer. <br>Of course it helps to understand in details every aspects of Blockchain (blocks, transactions, asymetric keypair etc.) but it is not necessary needed to start building.</p><p>Simply imagine things like this:<br><strong>Webapp &gt; API &gt; Middleware &gt; Database</strong></p><p>Thats it, Webapp is your regular web interface, API will be offered and accessible via the public Node (you could have your own node later eventually), the Smart Contract will act as a middleware and the data storage of the blockchain will be your database.</p><p>If you know how to use an API and install libraries, then all you needs to learn is <a href="https://docs.wavesplatform.com/en/ride/">RIDE (Waves programming language)</a> and it’s really easy, especially in most projects, the Smart Contract often only represent a small piece of the work, everything else will be what you know already eg. the HTML / CSS, Routing, API calls etc.</p><h3><strong>A) DEFINE THE PROJECT</strong></h3><p><em>To get a concrete example, we will build a simple web application tracking COVID19 Data for any entity eg. University, Hospital, City etc. <br>Keeping track of the COVID cases will be a necessity for upcoming months untill it disappear completely so it will be a good example for this tutorial.</em></p><p>You can find the working Webapp here: <br><strong>TESTNET</strong>: <a href="https://covtest.sign-web.app/">https://covtest.sign-web.app/</a><br><strong>MAINNET</strong>: <a href="https://cov-stats.sign-web.app/">https://cov-stats.sign-web.app/</a></p><p>The main idea is to have a web app that display a front page with all the tracking data like chart, filters, table etc.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/671/1*Wd6BhQXzO9HZqg_nDoFOEQ.png" /></figure><p>And a backoffice to administrate these data</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*eOttyoRrJnjuacXLeJ-Ywg.png" /></figure><p>The webapp will use a<strong> dApp (Smart Contract) on Waves Blockchain</strong> to validate and store these data.</p><p>The webapp will also use <a href="https://github.com/wavesplatform/signer"><strong>Waves Signer library</strong></a><strong> </strong>to allow any Waves account to sign transactions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*qATE8QWEHYT366eLmOHIsA.png" /></figure><p>When you use a Blockchain, you needs what we call transactions, these transactions carry your data and are sent to the nodes through the node API and then are included in blocks, these blocks are linked together one after the other and it is what make the Blockchain, a chain of blocks. Smart Contract verify the validity of these transactions.</p><p>There is no fee in our project aside of the regular transaction fee going to the miners and that are needed to process any transaction on Blockchain.</p><p>The web app will offer two options for anyone to have their own tracking page:</p><ul><li><em>You can simply use the main entry point: <br></em><a href="https://covtest.sign-web.app/"><em>https://covtest.sign-web.app/</em></a><em> (for TESTNET)</em><br><em>and click “EDIT PAGE” button, here you will connect with your Waves account and start adding data. Your page will then be accessible with your data only at https://covtest.sign-web.app/{your_waves_address}</em></li><li><em>You clone the </em><a href="https://github.com/christopheSeeka/cov-stats"><em>repository from Github</em></a><em> and install your own version on your server, you will edit </em><strong><em>settings.js</em></strong><em> with your owner address (Waves account used to add data) and the dApp account. dApp account can be ether the public dApp address 3N5NLAqd9w7sNuUnjfWq7mzW3bherD6uZmn (for TESTNET) or your own dApp address (you will then deploy the smart contract on it).</em></li></ul><p>Any entity can then host its own web app or use the public one and display their official Waves address + link to this tracking page into their official website.</p><p>Having this link and address on official website of the entity you know then that the data are officials.</p><h3>B) WHY USE BLOCKCHAIN?</h3><p><em>Why would we choose to use blockchain for this? There is several reasons and you should always ask yourself “why blockchain” before starting, blockchain is NOT the answer to everything, it is slower than centralized database, data are public and immutable and it involve transaction fees.</em></p><ul><li>We want give opportunity to anyone to see the data in real time and track any possible changes in a totally transparent manner</li><li>We won’t have to develop a GET API or a secured Login/Account system, both will be available by default with Waves Signer / Waves Account and the Blockchain Node API</li><li>We want give opportunity to anyone with a Waves account to start its own tracking page easily</li><li>We want these data public, immutable and decentralized for future reference</li><li>With all the above, an entity using the dApp cannot modify any data to claim different results later or shut them down in weeks, months or years</li></ul><h3><strong>C) START A NEW PROJECT</strong></h3><p>To get the code of the step 1 <a href="https://github.com/christopheSeeka/covstats-tuto/tree/step1">click here</a>.<br>To get the code of the full web app <a href="https://github.com/christopheSeeka/cov-stats">click here</a>.</p><p>Keep in mind that this project is open source and available for anyone to use but the main goal when i built it was education.</p><p>I limitate the use of libraries/tools like Typescript, Sass, Waves Transactions, Surfboard as well as framework like React or Vue (i prefer work in Vanilla JS in general anyway). <br>I also limitate the code splitting in several files or anything that would over complexify the structure because the goal is to keep it accessible to any front end developer level as well as helping understand as much as possible what really happends.<br>I heavily commented the code on that purpose. <br>This project can most certainly be improved.</p><p>In this tutorial, i’m going to build the webapp using the following technology and libraries:</p><p><strong>For the webapp :</strong></p><ul><li>VSCODE as ide</li><li>NodeJS and ExpressJS for the routing &amp; architecture</li><li>Webpack &amp; Babel to allow us working with es6</li><li>Nodemon to simplify the process</li><li>HTML / CSS and Bootstrap for the views</li><li>Vanila javascript for the programming logics</li><li>Waves Signer for the signature of transactions</li><li>Jquery, DataTables and CanvasJs for data display and graph</li><li>Sanitize-html to sanitize the data we receive from data storage</li></ul><h4><strong>Lets start!</strong></h4><p><em>Let’s first install all the needed libraries, of course i assume that you already have nodejs and npm installed here, if not please </em><a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm"><em>follow these steps</em></a></p><p>Create a new empty folder and do a right click in it “open with Code”, this will open the VSCODE editor.</p><p>From there, in VSCODE, open a terminal and type the following to install Express JS:</p><pre>npm install express -g</pre><p>Now, we will initiate the new project with:</p><pre>express --view=ejs .</pre><p>We are simply telling express to create a new project using EJS as view engine, the . mean we create it at the root of the folder we are currently in.</p><p>You should now have the following files and folders structure as well as a ready to use app.js file:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/714/1*6MemPJZ7kB1WEAVwhGbKYg.png" /></figure><p>To install dependencies just use the following command:</p><pre>npm install</pre><p>We now needs to install Webpack and Babel that will allow us to work in <a href="https://www.w3schools.com/js/js_es6.asp">es6</a>:</p><pre>npm install webpack</pre><p>In your packages.json, modify the scripts section as follow:</p><pre>&quot;scripts&quot;: {<br>  &quot;start&quot;: &quot;node ./bin/www&quot;,<br>  &quot;build&quot;: &quot;webpack -p&quot;,<br>  &quot;watch&quot;: &quot;webpack --watch&quot;<br>}</pre><p>We have 3 scripts here, “<em>start”</em> is the regular npm start that lunch our webapp, “<em>build”</em> will use webpack to compile our es6 javascript into es5 bundle and “<em>watch”</em> will watch any change and compile without the needs to lunch a build command manually each time.</p><p>Now, we will install babel:</p><pre>npm install -D babel-loader @babel/core @babel/preset-env babel-polyfill</pre><p>Now, create a file named webpack.config.js at the root of your project and add the following:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fe77fdb69ce5ff26c2feca2cf6a6ba8a/href">https://medium.com/media/fe77fdb69ce5ff26c2feca2cf6a6ba8a/href</a></iframe><p>As you can see in the entry section of this file, we will needs to create a ./src folder with two files, main.js that will be the javascript code for our index page and admin.js that will be the javascript code for the admin page, the admin page is where anyone will be able to connect with a Waves account and manage data related to this account.</p><p>In the output section, the compiled code (from <a href="https://www.w3schools.com/js/js_es6.asp">EcmaScript 6</a> to EcmaScript 5) will be renamed as bundle-[name].js and save in the public/javascripts folder, all your front end assets will be in this ./public folder, meaning:</p><p><strong>./src/main.js</strong> will compile as <strong>./public/javascripts/bundle-main.js<br>./src/admin.js</strong> will compile as <strong>./public/javascripts/bundle-admin.js</strong></p><p>Please create a ./src folder then in this folder, create 2 files, main.js and admin.js, leave it empty for now. <br>“<strong>./”</strong> represent the root of your project, don’t include it in the folder name :)</p><p>You will also notice in this webpack.config.js file the use of babel loader, for this, we will also have to create another file at the root of our project and call it <strong>.babelrc</strong> don’t forget the . at the begining.</p><p>In this .babelrc files, simply add the following:</p><pre>{<br>&quot;presets&quot;: [&quot;@babel/preset-env&quot;]<br>}</pre><p>We also needs a couple more libraries to avoid runtime errors on async/await:</p><pre>npm install --save-dev <a href="http://twitter.com/babel/plugin-transform-runtime">@babel/plugin-transform-runtime</a><br>npm install --save <a href="http://twitter.com/babel/runtime">@babel/runtime</a></pre><p>Update your .babelrc as follow:</p><pre>{<br>  &quot;sourceType&quot;: &quot;unambiguous&quot;,<br>  &quot;presets&quot;: [&quot;@babel/preset-env&quot;],<br>  &quot;plugins&quot;: [&quot;@babel/plugin-transform-runtime&quot;]<br>}</pre><p>You can now simply write in the console:</p><pre>npm run watch</pre><p>On first run it will ask you the following:</p><p><em>Do you want to install ‘webpack-cli’ (yes/no)</em></p><p>Just type <strong>“yes”</strong></p><p>You should see the following, which mean everything is working as expected and the files are compiling:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*P0fLWBfqZl9HrfmhPyX8Fw.png" /></figure><p>Open a second terminal (you want keep the webpack watch terminal running) and we will install another important library to simplify our development, type:</p><pre>npm install -g nodemon</pre><p>Then just type the following in terminal to run nodemon:</p><pre>nodemon</pre><p>Nodemon is a very convenient tools that will restart your server after every changes in any file. We have now 2 terminals running, one with webpack watching your files and one with nodemon restarting the server everytime a file change.</p><p>Now your files structure and packages.json architecture should look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*o19McGyAisMwUgAjetAXfA.png" /></figure><p>Lets now create our routes, route will define what happens when we call a certain url. By default, we have 2 routes in ./routes, index and users.</p><p>The index is as follow:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/65987f3e1902c43d619357f86efde237/href">https://medium.com/media/65987f3e1902c43d619357f86efde237/href</a></iframe><p>We dont needs users route but an admin route, lets rename the ./routes/users.js file as ./routes/admin.js then change the content as follow:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9ab51a0f048e112ced00761ce2ea3f70/href">https://medium.com/media/9ab51a0f048e112ced00761ce2ea3f70/href</a></iframe><p>Im not going to explain everything when it come to nodejs / Express or even the regular javascript i’m going to write later, it is out of the scope and would take too long but remember you always can ask questions in comments section and there is plenty of tutorials already on these matter.</p><p>Now go back into your app.js and change your routes related code as follow:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/204c40d33f4413f68b4f924543afa380/href">https://medium.com/media/204c40d33f4413f68b4f924543afa380/href</a></iframe><p>We change line 7 as:</p><pre>var indexRouter = require(&quot;./routes/index&quot;);</pre><p>line 8 as:</p><pre>var adminRouter = require(&quot;./routes/admin&quot;);</pre><p>line 22 and 23 become</p><pre>app.use(&quot;/&quot;, indexRouter);<br>app.use(&quot;/admin&quot;, adminRouter);</pre><p>And added at line 24 the following:</p><pre>app.use(&quot;/*&quot;, indexRouter);</pre><p><strong>In short:</strong></p><ul><li>If we call <strong><em>webapp_url/</em></strong><em> or </em><strong><em>webapp_url/*</em></strong> it will use the index Router (./routes/index.js) which will render the index view (./views/index.ejs)</li><li>If we call <em>webapp_url/admin</em> it will use the admin Router (./routes/admin.js) which will render the admin view (./views/admin.ejs)</li></ul><p>webapp_url/* where * represent anything (anything else than admin since a route is defined for admin) and we will use it as * = waves address, a parameter we will needs to display data for any waves account.</p><p>So then we needs to also adjust our views.</p><p>Open the ./views/index.ejs and change the content with:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9a3483025fd3d6967406913dab083412/href">https://medium.com/media/9a3483025fd3d6967406913dab083412/href</a></iframe><p>Simply duplicate ./views/index.ejs for now and rename it as admin.ejs, in this new file replace “index” by “admin” in the texte.</p><p>Notice that we added the following right before the &lt;/html&gt; of the ./views/index.ejs file:</p><pre>&lt;script src=&quot;javascripts/bundle-main.js&quot;&gt;&lt;/script&gt;</pre><p>Change it into ./views/admin.ejs for the admin view file:</p><pre>&lt;script src=&quot;javascripts/bundle-admin.js&quot;&gt;&lt;/script&gt;</pre><p>If everything is working as expected, you can now access your webapp at localhost:3000</p><p><em>If you want adjust the config and change the port for example, go to the ./bin/www file</em></p><p>Test that everything is compiling as expected, for that, go to ./src/main.js and type:</p><pre>console.log(“Index Rock!”)</pre><p>Save the change and go back to your webapp, localhost:3000, click right then “inspect”, go to console tab and you should see there “Index Rocks:”.</p><p>Try the same with ./src/admin.js and type:</p><pre>console.log(“Admin Rock!”)</pre><p>Save it and go to localhost:3000/admin, check the console!</p><p>If both message are showing, then you Rock too! You completed the first step on how to create a Webapp using Waves Blockchain Protocol and have your architecture ready.</p><p>The STEP 1 code:<br><a href="https://github.com/christopheSeeka/covstats-tuto/tree/step1">https://github.com/christopheSeeka/covstats-tuto/tree/step1</a></p><p>The complete web app code:<br><a href="https://github.com/christopheSeeka/cov-stats">https://github.com/christopheSeeka/cov-stats</a></p><p>The webapp example on TESTNET:<br><a href="https://covtest.sign-web.app/">https://covtest.sign-web.app/</a></p><p>The webapp on MAINNET:<br><a href="https://cov-stats.sign-web.app/">https://cov-stats.sign-web.app/</a></p><p>In the upcoming <a href="https://medium.com/@crashartifacts/how-to-build-a-web-app-using-blockchain-part-2-9d64a8de8e0f">STEP 2</a>, we will work on the html and javascript logics of the index page, stay tuned!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e3dab7bbdeb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Signature Digitale des Blocks et Transactions sur la Blockchain]]></title>
            <link>https://medium.com/@crashartifacts/signature-digitale-des-blocks-et-transactions-sur-la-blockchain-7d8c372ac10d?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/7d8c372ac10d</guid>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[signature-digitale]]></category>
            <category><![CDATA[wavesplatform]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <category><![CDATA[transactions]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Sun, 09 Feb 2020 11:31:05 GMT</pubDate>
            <atom:updated>2020-02-09T11:31:05.365Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jGPw1Il_rNfhpKJ1OzQeCg.png" /></figure><h3><strong>Qu’est ce qu’une Signature ?</strong></h3><p>Pour pouvoir envoyer des transactions ou des blocks sur la Blockchain ils<br>doivent être obligatoirement signés.</p><p>Lorsque l’on crée une transaction, qui n’est qu’un ensemble de données sous forme d’objet (voir schéma 1 ci dessous), nous utilisons notre clé privée provenant de notre seed (phrase secréte de 15 mots) afin de signer de manière digitale cette transaction.</p><p>Signer une transaction va ajouter une propriété “Proof” dans l’objet de cette dite transaction, cette entrée est un simple tableau qui contiendra notre signature, preuve que nous avons bien signé ces données avec notre compte et qui pourrait contenir jusqu’à 7 autres signatures (à noter que ce tableau n’est pas limité qu’à des signatures, on pourrait passer d’autres infos) dans le cas d’une transaction multisig.</p><p>A noter que les exemples ici sont basés sur la <a href="https://www.wavesplatform.com/">Blockchain Waves</a> et bien sur les informations diffèrent d’une Blockchain à l’autre même si les fondamentaux restent généralement les même. <br>Sur la Blockchain Waves vous verrez parfois une propriété “signature” au lieu de “proof”, c’est en fait parce qu’en version 1, au début de la Blockchain Waves, on ne pouvait passer qu’une seule et unique signature. Les transactions en version 2 remplacent cette propriété par “proof” et permettent donc du multi-signature.</p><p>Dans l’exemple “schéma 1” nous passons uniquement les paramètres requis par la librairie utilisée, ici <a href="https://github.com/wavesplatform/waves-transactions">waves-transactions</a> pour NodeJs qui elle se charge d’ajouter les paramètres par défaut manquant.</p><p>Une fois la transaction signée, elle est “propagée” (broadcast) en étant transmise au réseau de node via l’une d’entre elle et via la methode “broadcast()” ici pour la librairie utilisée. La transaction passe par l’UTX Pool en attendant d’être traitée et incluse dans un block.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fOJajHXUp6Dj_MyEksADFA.png" /><figcaption>Schema 1 — créer une transaction et la signer</figcaption></figure><p>Le principes est relativement similaire pour les blocks, en effet, un compte qui mine des blocks est un simple compte Waves avec seed, paire de clés et adresse et il signe les blocks générés avec sa clé privée.</p><p>Pour rappel, une node peut miner des blocks des lors qu’elle a au moins 1000 waves sur sa node, soit directement sur son compte soit via le leasing (principe de location de waves). Dans un prochain tutorial nous verrons ensemble comment installer et configurer votre propre node. Cependant n’importe qui peut avoir sa propre node, sans les 1000 waves, ce qui donnera une node de validation de block mais qui ne mine pas.</p><p>Un block contient plusieurs informations avec entre autre, outre les transactions validées, une référence au block précédent, un block id qui est le hash de deux éléments combinés, à savoir le block id du block précédent + le hash de toutes les transactions du block en cours.</p><p>Ce block sera également propagé sur le réseaux de nodes ou celle ci vont valider la validité de la signature du block mais aussi que ce block avait bien le droit de miner un block sur la base du consensus de la Blockchain.</p><h4><strong>Points clés :</strong></h4><ul><li>Chaque transaction est signé via la clé privée de l’émetteur</li><li>Chaque block est signé par la clé privée du compte de la node</li><li>On peut également signer n’importe quel données avec la clé privée</li><li>Les transactions en version 1 utilisaient une signature unique</li><li>Les versions 2 utilisent un tableau “Proof” contenant 1 à 8 signatures</li><li>On vérifie la validité d’une signature via la clé publique du compte</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GnSsBbReGEU-vWOpaL6Yxg.png" /><figcaption>Schéma 2 — Détail du processus de signature des transactions et des blocks.</figcaption></figure><h3><strong>UTX POOL (Unconfirmed Transactions) :<br>Les transactions non confirmées</strong></h3><p>Il y a une étape importante entre le moment ou la transaction est envoyée et son traitement par une node.</p><p>Sur le schéma précédent (schéma 2) nous voyons à gauche le processus de signature d’une transaction par un compte qui ensuite propage cette transaction signée vers la node qui mine et celle ci vérifie les transactions.</p><p>A droite du même schéma, nous voyons alors le processus de validation d’un block, ce qui correspond en fait au détail de la dernière étape de la partie gauche “Node qui mine”.</p><p>Il y a en fait une étape intermédiaire qui est l’UTX Pool, une sorte de “salle d’attente” ou les transactions transitent en attendant d’être traitées par la node qui obtiendra le droit de miner un block.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AHBcu291OY-imojsPHuYEA.png" /></figure><p>Il est donc important d’en tenir compte, en effet, nous pourrions avoir l’idée de passer des choses “secrètes” dans nos transactions, des données à usage unique comme par exemple des mots de passe ou code pour obtenir xx free tokens et nous comparerions ces codes aux hash équivalent stockés sur l’espace de stockage du compte. Mais du fait de l’UTX Pool n’importe qui pourrait voir ces informations en “écoutant” les transactions non confirmées et ainsi les utiliser avant même que la transaction initiale soit traitée ou encore si elle était rejetée pour une raison quelconque.</p><h4>Points clés :</h4><ul><li>Chaque transaction passe par l’UTX Pool</li><li>Une transaction peut y rester plus ou moins longtemps</li><li>La transaction est donc visible avant son traitement</li><li>De ce fait on ne passe pas de mot de passe même à usage unique</li><li>Toutes les transactions de l’UTX Pool sont traitées</li></ul><p>N”hésitez pas si vous avez la moindre question ou un sujet en particulier que vous aimeriez voir traité sur notre chaîne Youtube.</p><p><strong>Pour voir notre vidéo en lien avec cet article c’est ici :</strong><br><a href="https://www.youtube.com/watch?v=KBy2P17hT1M">https://www.youtube.com/watch?v=KBy2P17hT1M</a></p><p><strong>PROCHAINES VIDEOS</strong></p><p><strong>12 février Waves explorer et IDE</strong>, nous verrons en détail chacun des éléments de l’explorateur Waves en ligne puis nous verrons l’ensemble des possibilités offertes par l’IDE en ligne qui simplifie grandement le développement de dApp et Smart Contract</p><p><strong>15 février Waves Keeper</strong>, cette extension navigateur, similaire à Matamask, permet aux utilisateur de votre application Blockchain de gérer l’ensemble de leurs comptes directement depuis le navigateur et de manière entièrement sécurisée.</p><p><strong>19 février Préparer son environnement</strong> de développement local est la suite logique après s’être familiarisé avec l’IDE en ligner. Nous verrons comment installer l’ensemble des éléments, à savoir l’extension Waves pour VS CODE, une node privée via Docker, le plugin Surfboard etc.</p><p><strong>22 février Utiliser son environnement</strong> précédemment installer et comprendre l’ensemble des fonctionnalités de Surfboard pour la création, la compilation et un déploiement rapide de vos smart contract</p><p><strong>25 février RIDE V4 et Waves node 2.0</strong> arrivant sous peu, nous passerons en revue l’ensemble des changements liés à ces nouvelles version, pour RIDE mais aussi pour le protocole Waves.</p><p><strong>Suivez nous et posez toutes vos questions sur :</strong></p><p>Youtube : <a href="https://bit.ly/37cWEAq">https://bit.ly/37cWEAq</a><br>Telegram : <a href="https://www.youtube.com/redirect?redir_token=phOsWKA_r-F3WGxKP2LKnNb1KoR8MTU4MTMwOTk2OUAxNTgxMjIzNTY5&amp;q=https%3A%2F%2Ft.me%2FwavesdappsFR&amp;v=KBy2P17hT1M&amp;event=video_description">https://t.me/wavesdappsFR</a> <br>Twitter : <a href="https://www.youtube.com/redirect?redir_token=phOsWKA_r-F3WGxKP2LKnNb1KoR8MTU4MTMwOTk2OUAxNTgxMjIzNTY5&amp;q=https%3A%2F%2Ftwitter.com%2FWavesDevFr&amp;v=KBy2P17hT1M&amp;event=video_description">https://twitter.com/WavesDevFr</a> <br><a href="https://www.youtube.com/redirect?redir_token=phOsWKA_r-F3WGxKP2LKnNb1KoR8MTU4MTMwOTk2OUAxNTgxMjIzNTY5&amp;q=https%3A%2F%2Fwww.wavesplatform.com&amp;v=KBy2P17hT1M&amp;event=video_description">https://www.wavesplatform.com</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7d8c372ac10d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[WAVES : Blockchain, Consensus, Cryptographie, Comptes et Transactions.]]></title>
            <link>https://medium.com/@crashartifacts/waves-blockchain-consensus-cryptographie-comptes-et-transactions-f1aa62d2185e?source=rss-e835c6bb39e1------2</link>
            <guid isPermaLink="false">https://medium.com/p/f1aa62d2185e</guid>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[ride4dapps]]></category>
            <category><![CDATA[developpeur]]></category>
            <category><![CDATA[smart-contracts]]></category>
            <category><![CDATA[wavesplatform]]></category>
            <dc:creator><![CDATA[Christophe Verdot]]></dc:creator>
            <pubDate>Mon, 27 Jan 2020 06:19:22 GMT</pubDate>
            <atom:updated>2020-01-28T02:56:12.978Z</atom:updated>
            <content:encoded><![CDATA[<h3>WAVES : Blockchain, Consensus, Cryptographie, Comptes et Transactions.</h3><p><em>Cet article est la retranstription du wébinaire du samedi 25 janvier 2020 disponible à l’adresse suivante :</em></p><p><a href="https://www.youtube.com/watch?v=Vvc0Xh8DuFE">https://www.youtube.com/watch?v=Vvc0Xh8DuFE</a></p><h3><strong>Qu’est-ce qu’une Blockchain ?</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4aMSR1UY1PKmAKr4j5SUuQ.png" /></figure><p>Une blockchain est simplement une base de données persistante, immuable et décentralisée.</p><p>Une Blockchain c’est un enchainement de blocks liés entre eux par l’utilisation de hash cryptographiques.</p><p>Une Blockchain à un « Height » et chaque block qui la compose à un « height » également.</p><p>Le « height » d’une blockchain est le numéro du dernier block dans la chaine de blocks, le height de chaque block et simplement son propre numéro de block dans la chaîne.</p><p>Les blocks contiennent des transactions.</p><p>Une Blockchain est donc composé d’une séquence de blocks mais aussi d’un réseau qu’on appelle Blockchain Network composé de « Nodes ».</p><p>Chaque Node représente une copie complète de la blockchain, de l’ensemble des blocks qui la compose et donc aux données identiques, sur un server ou un ordinateur différent.</p><p>Il existe ce qu’on appelle le « Chain ID », un paramètre de configuration de la blockchain pour définir le type de réseau de celle-ci, il en existe 3 sur la blockchain Waves :</p><ul><li><strong>StageNet </strong>(ChainID 83 / 0x53 / S) *</li><li><strong>TestNet</strong> (ChainID 84 / 0x54 / T)</li><li><strong>MainNet </strong>(ChainID 87 / 0x57 / W)</li></ul><p>*(decimal / hexa / ASCII)</p><h3>Les différents réseaux de la Blockchain Waves</h3><p><strong>MAINNET</strong><br>Est le réseau original et fonctionnel ou les transactions utilisent les cryptocurrencies ayant une vraie valeur économique, en bref, le Mainnet représente la blockchain Waves actuelle.</p><p><strong>TESTNET</strong><br>Est une version ayant toutes les fonctionnalités du Mainnet mais utilisant un token fictif, sans valeur économique et un réseau séparé du Mainnet, le Testnet, comme son nom l’indique est uniquement pour les test durant le développement, ce qui évite les pertes en cas d’erreurs de code.<br> <br><strong>STAGENET</strong><br>Est le réseau expérimental, il inclus les même fonctionnalités que le Mainnet et Testnet mais aussi les possible futures fonctions testées ici avant d’être déployées sur les autres réseaux.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fDjP8Ya-v6ENbkppXLovVg.png" /></figure><h3><strong>Qu’est-ce qu’un Block ?</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kI2cX4KLje4s6J9dAAA0Ug.png" /></figure><p>Un block représente un maillon de la Blockchain.</p><p>Un block contient entre autres des transactions et peut avoir une taille de block de 1Mo maximum.</p><p>Le délai entre chaque création de block est de 1 minute et 5 secondes entre les micro blocks (Waves NG).</p><p>L’identifiant d’un block est le résultat du hashage cryptographique de deux éléments combinés :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Nxr7qOMUhgLMNlJ1Wzds9Q.png" /></figure><p>Le block header contient une référence à l’identifiant du block précédent.</p><p>Le block header contient également le hash de l’ensemble des transactions que sont incluse dans celui ci</p><p>L‘identifiant d’un block est en fait le hashage de l’identifiant du block précédent + le hash de l’ensemble des transactions du block en cours.</p><p>C’est donc ce qui lie chaque block entre eux via le hash cryptographique du block précédent et rend la Blockchain immuable, si nous voulions modifié un block dans la chaîne il nous faudrait alors re miner l’ensemble des blocks suivants, ce qui est bien sur totalement impossible sans être détecté et demanderait beaucoup de temps et d’énergie.</p><h3>Qu’est ce que Waves NG et les Blocks Fluides ?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jlHLZweXhzk4k1mDKxzJbg.png" /></figure><p><strong>La Blockchain Waves utilise le Protocol Waves NG</strong> qui provient de Bitcoin NG et utilise le principe de block fluides ou chaque block est composé de :</p><ul><li><strong>Un Leader block</strong> aussi appelé Key Block ou header, cet header ne contient pas de transactions mais plusieurs informations, notamment : une référence unique au block précédent qui est un hash cryptographique provenant du header du précédent block. <br> Une fois le leader sélectionné, il peut miner pendant 1 minute (blocktime)</li><li><strong>Multiple micro-block</strong> qui contiennent les transactions, un micro-block est ajouté par le Miner toutes les 5 secondes pendant 1 minute et contient jusqu’à 200 transactions par microblock</li></ul><h3><strong>Consensus de la Blockchain Waves</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o7nVo6JxfT0Du5NQu1Q0WQ.png" /></figure><p>Le consensus représente les règles établies entre toutes les nodes du réseau pour choisir le prochain validateur de blocks.</p><p>Il existe différents types de consensus sur les différentes Blockchain, les plus populaires sont :</p><ul><li><em>Proof Of Work (POW)</em></li><li><em>Proof Of Stake (POS)</em></li></ul><p>On peut visualiser cela de manière simplifiée, et donc pour arriver au consensus, avec le Proof Of Work, toutes les Nodes du réseau doivent essayer en même temps de résoudre un problème mathématique donné, la première à le résoudre « gagne » et peut Miner le block suivant.</p><p>Pour le Proof Of Stake, au lieu de faire travailler toutes les Nodes en même temps, on va en sélectionner une et elle seule va être chargée de résoudre le problème. La sélection est basée sur différent paramètres, notamment le montant de tokens détenue par la Mining Node.</p><p>Waves utilise le Lease Proof Of Stake, qui reprend les principes du POS mais avec un principe supplémentaire de Leasing. En effet pour pouvoir participer au réseau en tant que Miner de block il faut d’abord avoir un nombre de tokens donné, pour la Blockchain Waves il s’agit de 1000 Waves. Le principe de Leasing permet aussi aux personnes n’ayant pas ces 1000 Waves de participer au Mining en les louant a une node ayant elle au moins 1000 Waves et ainsi d’obtenir une part des gains « reward ».</p><p>Il est possible d’avoir sa propre node sans avoir les 1000 Waves requis, cette node devient alors uniquement une Node de validation qui validera les blocks et transactions mais ne mine pas et ne reçoit donc pas de reward.</p><h3><strong>La cryptographie</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DAXuZOMwvNxi7gKpU4VvKA.png" /></figure><p>La cryptographie représente une part importante de la blockchain que ce soit pour la création des clés publiques et privés, de l’adresse, de la création de blocks ou de la signature de transactions.<br> <br><strong>Points clés de la cryptohaphie utilisée sur la blockchain waves :</strong></p><p><strong>Blake2b256</strong> et <strong>Keccak256</strong> pour la création de hash cryptographique exemple : <em>keccak256(blake2b256(account seed bytes)) = H4do9ZcPUASvtFJHvESapnxfmQ8tjBXMU7NtUARk9Jrf</em></p><p><strong>Curve25519</strong> pour la création/vérification de signature<br> <br><strong>Base58</strong> pour la conversion de tableau de données en string exemple : <em>“teststring” = [5, 83, 9, -20, 82, -65, 120, -11] = 7bWpTW</em></p><h3><strong>Les comptes</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2HRQe1jP32pJrSZI1Af_uA.png" /></figure><p>Un compte c’est simplement une seed dont découle une paire de clés public et privée ainsi qu’une adresse, le tout liés à la Blockchain via la cryptographie et utilisé pour signer les transactions et les ordres.<br> <br><strong>Chaque compte est composé d’une seed unique, une phrase secrète de 15 mots minimum générés aléatoirement, exemple </strong>:</p><p><em>manage manual recall harvest series desert melt police rose hollow moral pledge kitten position add</em><br> <br><strong>De cette seed sont générés la clé publique et la clé privée via différents hashages cryptographiques :</strong></p><p><strong>Clé privée :</strong> <em><br>3kMEhU5z3v8bmer1ERFUUhW58Dtuhyo9hE5vrhjqAWYT</em></p><p><strong>Clé publique :</strong> <em><br>HBqhfdFASRQ5eBBpu2y6c6KKi1az6bMx8v1JxX4iW1Q8</em><br> <br>Comme son nom l’indique, la clé privée ne doit jamais être partagée, au même titre que la seed / Phrase secrète. L’une ou l’autre sont nécessaires pour accéder à son compte et signer des transactions.</p><h3><strong>Comment obtenir un compte</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zli1RniPSLurPqEZaWpieA.png" /></figure><p>Il existe différents moyens de vous “créer” un ou des comptes Waves. Techniquement on ne “crée” pas de compte, on génère des informations associées à un compte.</p><p>Tous les comptes existent par défaut sur la blockchain à partir du moment ou ils correspondent à une adresse et paire de clés valides.</p><p><strong>Créer un compte pour les non développeur</strong><br>www.waves.exchange<br>Waves Desktop wallet<br>Waves Mobile wallet<br>Waves Keeper<br> <br><strong> Créer un compte pour les Développeur</strong><br>ide.wavesplatform.com<br>Waves Signer<br>Librairies :<br>ts-lib-crypto, waves-transactions etc</p><h3><strong>Adresse du compte</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sUOfQrUnb4JiE13w_5xgZw.png" /></figure><p>Chaque compte a également une adresse unique associée et peut également créer plusieurs alias (plus facile à mémoriser) :<br> <br><strong>Adresse Mainnet :</strong> <br><strong><em>3P</em></strong><em>PbMwqLtwBGcJrTA5whqJfY95GqnNnFMDX</em></p><p><strong>Adresse Testnet/Stagenet :</strong> <br><strong><em>3N</em></strong><em>BVqYXrapgJP9atQccdBPAgJPwHDKkh6A8<br></em><strong><em>3M</em></strong><em>vujUZTtoANRzrKYKzx99Vtb9TUh6VPCA8</em></p><p><strong>Alias :<br></strong><em>christophe-waves (de 4 à 30 charactère max)</em><br> <br>A noter qu’on différencie facilement une adresse Mainnet de Testnet car elle commence toujours par 3P pour 3N ou 3N en Testnet et Stagenet.<br> <br> <strong>Balance du compte</strong><br> Un compte peut stocker différents tokens, Waves ou custom tokens, tous associé à l’unique adresse du compte. Le montant de ces tokens représente la balance du compte ou Account Balance</p><h3><strong>Stockage de données</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RQtLp5wyyXyLZhPd5vLd9g.png" /></figure><p>Chaque compte à également un espace de stockage associé et illimité permettant de stocker des données au format clé/valeur. Chaque clé doit être unique<br> <br> <strong>Type de données stockables</strong><br> Il est possible d’y écrire 4 types de données :</p><ul><li><em>String</em></li><li><em>Boolean</em></li><li><em>Integer</em></li><li><em>Bytes Array</em></li></ul><p><strong>Ecrire des données</strong><br> Pour écrire des données sur l’espace de stockage d’un compte il faut utiliser soit une Transaction de type Data soit une transaction de type InvokeScript.<br> <br><strong>Ecrite via Data Tx</strong></p><ul><li><em>100 entrées max par transaction</em></li><li><em>32Ko max par entrée / valeur</em></li><li><em>150 Ko max pour l’ensemble des entrées</em></li></ul><p><strong>Ecrite via InvokeScript Tx</strong></p><ul><li><em>100 entrées max par Transaction</em></li><li><em>5Ko par entrée / valeur</em></li><li><em>5 Ko max pour l’ensemble des entrées</em></li></ul><h3><strong>Modification des données :</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K0uYYxzUekz-qbpQqHCq_A.png" /></figure><p>La valeur associée à chaque clé peut être réécrite en réutilisant l’une des deux transactions précédentes et en ciblant la même clé. La version actuelle de RIDE ne permet pas de supprimer d’entrées mais la version 4 à venir elle, le permettra.<br> <br> Il faut visualiser cet espace de stockage comme étant l’état actuel du compte, on parle d’ailleurs généralement d’état de compte (account state) et même si on y modifie des entrées, les précédents sont toujours et de manière immuable accessibles sur la blockchain via leur identifiant de transaction.</p><h3>Les types de comptes</h3><p><strong>Sur la blockchain Waves il existe 3 types de comptes.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zatkDjBf15sp8X4otxL6aA.png" /></figure><p><strong>Les comptes simple « Account » : </strong><br>Représente les comptes non scriptés ou par défaut les transactions doivent être signées par la clé privé du compte émetteur<br> <br><strong>Les compte « Smart Account » : </strong><br>Représente un compte auquel un script de validation (Smart Contract) a été attaché et dont les validations et signatures des différentes transactions dépendent de la logique du script associé. 1 seul script par compte. Le Script valide uniquement les transactions sortantes<br> <br><strong>Les comptes « dApp Account » : </strong><br>Représente un compte auquel un script de validation peut être associé comme pour le smart account mais aussi des fonctions dites « callables « pouvant être appelée de l’extérieur avec la transaction de type InvokeScript.</p><h3><strong>Tokens</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*opYMdiL7moJbOurwf02GUg.png" /></figure><p>Les Tokens aussi appelés Assets représentent un actif numérique sur la blockchain, ils peuvent avoir une corrélation avec un objet réel ou être uniquement virtuel.</p><p>Il sont créés via la transaction de type Issue</p><p>Un token peut avoir une valeur économique ou non et peut être divisible ou non.</p><p>Chaque token à un identifiant unique qui correspond à l’identifiant de la transaction ayant servi à la création du dit Token.</p><p>La blockchain Waves utilise le token natif Waves qui représente le Token primaire, aussi appelé « Layer 1 Token » et tous les tokens custom créés sur la blockchain Waves représentent les token secondaire ou « Layer 2 tokens ».<br>Un token peut être scripté et de manière similaire au Smart Account, un token scripté, aussi appelé Smart Asset, sera chargé de valider et autoriser ou non toutes les transactions sortantes liées à ce token pour n’importe quel compte l’utilisant.</p><p>Chaque transaction nécessite un paiement en Waves appelé Transaction Fee, pris du compte de l’émetteur et servant à payer les Miners.</p><h3><strong>Les transactions</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0dMNeDp7RklQJkxzm1a3mw.png" /></figure><p>Une transaction est une action sur la blockchain initiée et signée par un compte waves.</p><p><strong>La blockchain Waves peu valider en moyenne 100 transactions par second, les stress test de 2016 étaient allé jusqu’à 900tx/sec.</strong></p><p>Un type de transaction spécial, le MassTransfer, permet de multiplier ce nombre par 100 en effectuant jusqu’à 100 transferts en un.</p><p>Il existe 16 types de transactions (17 on stagenet)</p><p>Chaque transaction contient un identifiant unique et un timestamp (horodatage)</p><p>Une transaction doit être signée par la clé privée de l’utilisateur avant d’être envoyée sur la blockchain (broadcast).</p><p>Elle sera ensuite vérifiée, validée et incluse dans un block attaché à la blockchain</p><h3><strong>Les types de transactions</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J8APMGyElssbQRvtirdNSg.png" /></figure><p><strong>Type 1 </strong>: Genesis transaction<br>Transaction unique servant à initier la blockchain<br> <br><strong>Type 2 :</strong> Transfer [Obsolète]<br>Transfer version 1 pour token Waves uniquement, remplacé par type 4</p><p><strong>Type 3 :</strong> Issue transaction<br>Permet de créer un Token/Asset<br> <br><strong>Type 4 :</strong> Transfer transaction<br>Permet de transférer un Asset/token d’un compte à un autre<br> <br><strong>Type 5 :</strong> Reissue transaction<br>Permet de recréer des tokens si le paramètre reissue du token est à true</p><p><strong>Type 6 :</strong> Burn transaction<br>Permet de détruire des tokens de manière définitive<br> <br><strong>Type 7 :</strong> Exchange transaction<br>Permet d’échanger des tokens entre eux</p><p><strong>Type 8 :</strong> Lease transaction<br>Permet de Louer ses tokens Waves a une Node pour le Mining<br> <br><strong>Type 9 :</strong> Lease cancel transaction<br>Annule les tokens précédemment loués<br> <br><strong>Type 10 :</strong> Alias transaction<br>Permet de créer un Alias pour le compte émetteur, sont autorisé :<br>minuscule, nombre, point, underscore, hyphen et arobase. 4 à 30 charactères maximum</p><p><strong>Type 11 :</strong> Mass Transfer transaction<br>Permet d’effectuer un transfert à plusieurs destinataires (jusqu’à 100) en une seule transaction<br> <br><strong>Type 12 :</strong> Data transaction<br>Permet d’écrire des données sur l’espace de stockage du compte émetteur<br> <br><strong>Type 13 :</strong> Set Script transaction<br>Permet d’attacher un script (Smart Contract) à un compte<br> <br><strong>Type 14 :</strong> Sponsorship transaction<br>Permet d’activer le principe de Sponsored Fee pour un Asset/Token<br> <br><strong>Type 15 :</strong> Set Asset Script transaction<br>Permet d’attacher un script (Smart Contract) à un Asset<br> <br><strong>Type 16 :</strong> Invoke Script transaction<br>Permet d’appeler une fonction depuis l’extérieur sur un compte dApp<br> <br><strong> Type 17 :</strong> Update Asset Info transaction [STAGENET ONLY] <br>Permet de modifier les informations d’un Asset/Token</p><h3><strong>Une transaction en détail</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_Qc0cIiQuiZwnMGlxnXcSw.png" /></figure><p><strong>Prenons l’exemple d’une transaction de type Transfer qui une fois signée et propagée (broadcast) se présente ainsi :</strong><br><br><strong>SenderPublicKey :</strong> La clé public du compte ayant signé la transaction (avec sa clé privée qui elle, bien sûr reste privée)</p><p><strong>Amount :</strong> Le montant de Token transférés</p><p><strong>Fee :</strong> Le coût de la transaction, chaque transaction à un cout minimum fixe, il est possible de passer un montant supérieur pour accélérer la validation de la transaction.</p><p><strong>Type :</strong> Correspond au type de transaction, chaque transaction à un type (nom entier) associé</p><p><strong>Version :</strong> Les transactions évoluant régulièrement au même titre que la blockchain, il y a donc un système de version servant à identifier la version de la dite transaction et sa structure de données</p><p><strong>Attachment :</strong> Il est possible d’attacher un message ou des données au format Bytes d’un maximum de 140 Bytes qui équivaut à 140 charactères</p><p><strong>Sender :</strong> l’adresse Waves de l’émetteur</p><p><strong>FeeAssetId :</strong> Permet de définir si on souhaite payer la transaction Fee avec un token custom au lieu de Waves. Pour que cela soit possible il faut que le token custom ai activé la fonction « Sponsored Fee «</p><p><strong>Proof :</strong> Tableau contenant la preuve du compte ayant signé la transaction avec sa clé privée, il peut y avoir plusieurs signataires/preuves dans le cas d’un multisig par exemple</p><p><strong>AssetId :</strong> Identifiant du token/asset à envoyé, si null (non renseigné), alors il s’agit du token Waves par défaut</p><p><strong>Recipient :</strong> Adresse du destinataire qui recevra les tokens envoyé</p><p><strong>FeeAsset :</strong> Idem FeeAssetId ce champ est la pour des besoins de rétrocompatibilité</p><p><strong>Id :</strong> Identifiant unique de la transaction</p><p><strong>Timestamp :</strong> Horodatage de la transaction</p><p><strong>Height :</strong><em> </em>Numéro / Height du block dans lequel la transaction à été incluse</p><p><strong>Abonnez-vous à notre chaîne :</strong><br><a href="https://www.youtube.com/channel/UC2DS9ktTKWGW3NHHV2Ja3_A">https://www.youtube.com/channel/UC2DS9ktTKWGW3NHHV2Ja3_A</a></p><p><strong>Suivez nous et posez toutes vos questions sur : </strong><br>Telegram : <a href="https://www.youtube.com/redirect?q=https%3A%2F%2Ft.me%2FwavesdappsFR&amp;v=Vvc0Xh8DuFE&amp;event=video_description&amp;redir_token=CKThoYNzEVJcWtDjPEiCKnCptI18MTU4MDE5MjgzNkAxNTgwMTA2NDM2">https://t.me/wavesdappsFR</a> <br>Twitter : <a href="https://www.youtube.com/redirect?q=https%3A%2F%2Ftwitter.com%2FWavesDevFr&amp;v=Vvc0Xh8DuFE&amp;event=video_description&amp;redir_token=CKThoYNzEVJcWtDjPEiCKnCptI18MTU4MDE5MjgzNkAxNTgwMTA2NDM2">https://twitter.com/WavesDevFr</a> <br>Facebook : <a href="https://www.youtube.com/redirect?q=https%3A%2F%2Fwww.facebook.com%2Fwavesfr&amp;v=Vvc0Xh8DuFE&amp;event=video_description&amp;redir_token=CKThoYNzEVJcWtDjPEiCKnCptI18MTU4MDE5MjgzNkAxNTgwMTA2NDM2">https://www.facebook.com/wavesfr</a> <br>Meetup : <a href="https://www.meetup.com/Waves-Blockchain-Developpeurs/">https://www.meetup.com/Waves-Blockchain-Developpeurs/</a></p><p>Wavesplatform : <a href="https://www.youtube.com/redirect?q=https%3A%2F%2Fwww.wavesplatform.com&amp;v=Vvc0Xh8DuFE&amp;event=video_description&amp;redir_token=CKThoYNzEVJcWtDjPEiCKnCptI18MTU4MDE5MjgzNkAxNTgwMTA2NDM2">https://www.wavesplatform.com</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f1aa62d2185e" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>