<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Textile Blog &amp; Newsletter</title>
        <link>https://blog.textile.io</link>
        <description>Blogs &amp; newsletter about web3 storage infrastructure &amp; happenings by Textile</description>
        <lastBuildDate>Sun, 12 Apr 2026 06:32:29 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Textile Blog &amp; Newsletter</title>
            <url>https://storage.googleapis.com/papyrus_images/bdd880551126a66a13f730bd0372314b.jpg</url>
            <link>https://blog.textile.io</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[You’re Invited: Join our new Discord [valid for 24 hours]]]></title>
            <link>https://blog.textile.io/youre-invited-join-our-new-discord-[valid-for-24-hours]</link>
            <guid>YkayQ4Acr5pNTgAnv2Hw</guid>
            <pubDate>Wed, 12 Feb 2025 14:50:04 GMT</pubDate>
            <description><![CDATA[Claim your OG role in our new agent intelligence network]]></description>
            <content:encoded><![CDATA[<p>Hi,</p><p>You’re getting this email because you’re a member of the Tableland/Textile community.</p><p>If you missed it last week, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://x.com/textileio/status/1887171412525191538">Textile and 3Box Labs have merged</a> to build the first decentralized intelligence network empowering agents to autonomously store, share, and exchange knowledge onchain. We’re launching a new Discord community for this network.</p><p>To thank you for being an early supporter, we’re giving you early access to our new Discord. By joining the server in the next 24 hours, you’ll get:</p><ul><li><p>An <code>OG</code> role exclusive to current Tableland Discord members (Snapshot before Feb 4, 2025)</p></li><li><p>Skip the waiting room, getting instant access to the full list of channels</p></li><li><p>Be part of the founding community shaping this new ecosystem</p></li></ul><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.gg/d9Usf44N"><strong>Grab your OG role now (link expires in 24 hours)</strong></a></p><p>See you there!</p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Textile Team)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/7867843ac33db76bc1f2934b1f28755f.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Building the Intelligence Layer for AI: Textile and 3Box Labs Join Forces]]></title>
            <link>https://blog.textile.io/building-the-intelligence-layer-for-ai-textile-and-3box-labs-join-forces</link>
            <guid>j3raIdTJl3nqwU7dwRg0</guid>
            <pubDate>Wed, 05 Feb 2025 16:31:30 GMT</pubDate>
            <description><![CDATA[Today, Textile and 3Box Labs have officially merged to create something bigger than ourselves: the intelligence layer for AI. You can read full coverage in today’s CoinDesk article, or check out our Tweet thread.]]></description>
            <content:encoded><![CDATA[<p>Today, Textile and 3Box Labs have officially merged to create something bigger than ourselves: the intelligence layer for AI. You can read full coverage in today’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.coindesk.com/business/2025/02/05/textile-3box-labs-merge-in-decentralized-data-tie-up-for-ai-agents">CoinDesk article</a>, or check out our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://x.com/textileio/status/1887171412525191538">Tweet thread</a>.</p><div class="relative header-and-anchor"><h2 id="h-a-note-from-our-founder">A Note from our Founder</h2></div><p>As CEO of Textile, for years I've had the privilege of working with 11 incredible builders who've pushed the boundaries in decentralized data. Today, Danny and the brilliant 3Box Labs crew are joining the Textile family. We've been friendly competitors, occasional collaborators, but always united by three core beliefs: public networks, developer-first thinking, and the open flow of data.</p><p>Both of our teams have deep roots in decentralized data infrastructure. We’ve consistently delivered innovations trusted by major players in the space, from Gitcoin to MetaMask. Through years of both competition and collaboration, we’ve developed a shared vision that AI will be embedded within every application that creates or consumes data. As specialized AI agents become central to this future, we're focused on launching a network that serves their unique needs with AI-first data protocols. It’s perfect timing; the multi-agent future is here and it relies on much of what our two companies have built to date.</p><div class="relative header-and-anchor"><h2 id="h-merging-two-powerhouses">Merging Two Powerhouses</h2></div><p>This merger brings together an unparalleled combination of talent and technology:</p><ul><li><p>Basin Network</p></li><li><p>Ceramic Network</p></li><li><p>Tableland DB</p></li><li><p>ComposeDB</p></li><li><p>30+ world-class employees</p></li><li><p>A thriving global community of 50,000+ developers</p></li></ul><div class="relative header-and-anchor"><h2 id="h-building-whats-next">Building What's Next</h2></div><p>In the coming months, we'll be launching the first multi-agent intelligence network that enables AI agents to store, exchange, and monetize their specialized intelligence and developed skills with other agents around the world. With our network, agents can collaborate on tasks and up-level their capabilities at significantly less cost and overhead compared to training foundational models. We're already working with leading partners who share our vision, including: Gaia, Story Protocol, Index Network, AgentDB, Collab.Land, Ocean, Matrix.one, and a few others.</p><p>As for Textile and 3Box products, they will be fully-integrated into the new network, playing significant roles in building out a comprehensive data infrastructure that underpins the system.</p><p>In the midst of focusing our efforts on advancing AI, our core principles remain unchanged:</p><ul><li><p>AI serves humans, not the reverse</p></li><li><p>Knowledge must flow freely</p></li><li><p>Collaboration beats competition</p></li><li><p>The future stays open</p></li></ul><p>This isn't just another merger. It's a sprint toward our future. And we're ready.</p><p>Follow <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://x.com/textileio">@textileio</a> for updates, including details about our upcoming public testnet and what's next.</p><p>Read the full story </p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Textile Team)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/9b8534f11dba7276c4aa03b70b4650d2.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Data availability with XOR-based schemes]]></title>
            <link>https://blog.textile.io/weeknotes-xor-da-basin-server</link>
            <guid>rHLH8lC6UNnHGCp8c8B5</guid>
            <pubDate>Tue, 23 Jul 2024 15:33:16 GMT</pubDate>
            <description><![CDATA[We review XOR-based schemes for Data Availability, and also a quick demo on how to set up Basin behind an HTTP server]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-data-availability-with-validity-proofs">Data Availability with Validity Proofs</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/avichalp">Avichal Pandey</a></p><div class="relative header-and-anchor"><h3 id="h-intro">Intro</h3></div><p>Basin is still in its research phase, and we’re exploring various data availability approaches, including XOR-based (and related) schemes for erasure encoding. In this architecture, the validators create an auxiliary data structure with a dual purpose. It can be used to repair data in case of data loss or data withholding attacks and to ensure that the validators are not deleting the old data they are supposed to store.</p><p>One common consideration in DA systems is to make the “data storage” requirement optional. This would enable light nodes to validate that no data was lost without downloading all the data. This guarantee is typically provided using data availability sampling and fraud proofs. However, fraud proofs introduce a “challenge” window, which deters the system’s finality. Fraud proofs are also tricky to implement and test.</p><div class="relative header-and-anchor"><h3 id="h-validity-proofs-for-da">Validity Proofs for DA</h3></div><p>An alternative to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.paradigm.xyz/2022/08/das">DAS</a> and fraud proofs is to validate erasure encoding itself using SNARKs. This idea first surfaced in the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://forum.celestia.org/t/zk-proving-das-part-1-intro/1047/5">Celestia forum last year</a>.</p><blockquote><p>If you created a way to generate a zk proof of correct erasure coding, then light nodes would not have to wait for a fraud proof window after sampling each block to consider it final. Second, we wouldn’t need bad encoding fraud proofs (BEFPs) which require the light node to download an entire row or column of the block data. Third, this unlocks the possibility of having consensus nodes vote on blocks without downloading all the data.</p></blockquote><p>In this post, I want to build upon this idea to see how feasible it is to “verifiably” compute the XOR-based codes using the modern SNARK frameworks. For example, I want to answer the questions like:</p><ul><li><p>How much time does it take to build a proof of encoding 1GB blob?</p></li><li><p>How big is the proof size?</p></li><li><p>How suited is a particular SNARK framework for this task</p></li></ul><div class="relative header-and-anchor"><h3 id="h-background">Background</h3></div><p>XOR-based codes are essentially a sequence of XOR operations. In my first experiment, I am considering a 1GB object that gets broken into 1KB chunks. Bitwise operations such as XOR had been the Achilles heel of SNARKs for a long time. However, recently, this problem has been addressed using two different types of solutions:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zkresear.ch/t/lookup-singularity/65">Lookup arguments</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eprint.iacr.org/2023/1784.pdf">Binary fields and tower extension</a></p></li></ul><p>The following is the crux of why bitwise operations are complicated in SNARKs. The arithmetic circuits used in SNARKs are defined over finite fields. In the case of elliptic curve-based SNARKs, these fields could be as large as 256 bits to make the protocol secure. Arithmetic operations such as additions and multiplications can be performed natively in the field while performing a bitwise operation requires simulating the operands and operations, which creates some overhead. The following image shows how converting an arithmetic circuit to a boolean circuit makes it bigger and wastes space by storing 1 bit in a data type used to represent a field element.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/850a79804ae3f4439c1913997ec4a4b2.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAMCAIAAACMdijuAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEZElEQVR4nGXPb1DSBxjA8d/txe52M+2sRs4U0ihSz3Ei6ISDoYbrlrBKZ9gPSXKb7uRSTEmqTetKIV/szJu7KYLo5Z0TGQgIIUVq+jsYTBBdni78G/pTUCHU9LbbqTff7LnPi+fV870H2Nl5d+Dvf3YCgfWJiT9tNsv4+NjY+KharVxYmFv1eeGVRX/A5w/4NjYD/oDfH/Bvbm+u+ryeVQ/shRfhxTXf2vrbdXgF/s/iLtgN7J/e2trYX9761x32PwYHXozYrFarWa9T22y/L7jnZ+en9wN7/HulDX/At9v27l50jNqtNot33Quv7PaW4MUVz7LHswxsv9v6f+CZUT8MDY6Pj72aeNUmFTud9iX4zV+vJze3t/Ybqz7vxmZg/4MleGnNt9bZ+aT2wf25+bkF94J33bviWYHhpeXlZcDtnodh94HZadcLk1GtUlosEAQN//LzY5Opz+l02GzWsXGnfdRuG7E5Ru2uGdf8m1nXjMs1/XpicsI149Lp1L92dphMpuem591y+cBA/9TU5NTUJOCwjzidjgNWC6TuUXU8aVerlGqVsk0mVv6mMBqNGk1Pf7/JYDTon+r1T/WQGbJYLZAZGoaGIDOk0fZ0K+SOsTHIDJkt5vvV1bUPH5gt5qGhl0CfXt9n0Ol0Wp1OazD06nRao9FgMhmVKgX/Jq+jo33w5eAzk9Fg7NP2arW9Wp1eq+nVqNRKTa9GqVYqVIrOrs66ujq5Qt6t6O6Sd3Uruit4PP7NMoVCIZfLgVaJRCZrlbZKpK0SmUwqlUkaG39qeFxfXsYj4nGFBZyGhob6+h+bmptaJC0tkhapTCKVSZqam5olzU3NTW3tbQXXOcycr1ok4sbGRrFY/PV1zndFhdzi4mtstlgsBh6JHu0R1dWJamoeikS1bBZIJZEqKytuC/i3Bfyiom8pRGJuTo5IJBQIKktKbnxTUPD9D3dqhTX37lXxeKWpVPJlemZtTU11VZVQKMzJzj6fkXGRTr9IpwuFQqC8rIxXyquoqCgtuZFz+dIXGTRsLIaUTODzy8vLy3i80lu3+JjTp0jJSXfv3mFkXqAQUz4KPpTLvFIpEJz/PAOPSygp4WZnZxUWFnK53GIulwWCVAqFlprKZrOLuVwgDwTzQJCTn8/OY5GSCEkJOGZO9rk0albWJRYLBMGr9MwLqVRyehqVwcjkcK5x8tnsPFYu8woIgoTEhKjIEyAIfsnITE9Lzb2ay2Qy8Qm49LQ0Wnr6p4RkJpMJpO0NlULJoGWgUSh0dBSDkYnHJaAiwqnUz5KTkz5GIChkMjElBXH0CAFPoNFoVCqVRjsXjUKFIxAo5IkYDIZMJoeHhSXiEgl4wrHQUDKZTCKRjoSEEFOIADIo6AwShcVi4+PiEKGHDwd9SMAnRkZEvA8AMWcxJ5HI9wDgNBp9Bo0GAOAkEonH47FYLB6fGB52HHH0WHjY8ciIiE/i40NDgk9FRZ9Go0OCD8XFxcXGxgZ/EBSDOfsvAIyT6Ur7w2MAAAAASUVORK5CYII=" nextheight="748" nextwidth="2000" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Source: Justin Thaler’s lecture</figcaption></figure><p>Lookup tables addressed this issue by precomputing all the results of bitwise operations and indexing them in a table that the prover can access. Another way to address this problem is to work with proving systems based on binary fields instead of prime fields (almost all SNARKs use prime fields). <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://vitalik.eth.limo/general/2024/04/29/binius.html">Binius</a> is a pioneer in this area and is widely considered a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.lambdaclass.com/snarks-on-binary-fields-binius/">paradigm</a> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.lambdaclass.com/binius-part-2/">shift</a> in SNARKs.</p><p>This Binius project is at a very early stage in terms of implementation. As a reference, we have a few papers and talks. However, in terms of concrete implementation, we only have a non-production-ready <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gitlab.com/IrreducibleOSS/binius">POC</a>.</p><p>The Binius approach is well suited to our case for the following reasons:</p><ul><li><p>XOR-based erasure codes can be performed in binary fields without much overhead.</p></li><li><p>Unlike other elliptic curve-based SNARKs (Groth16, Plonk, etc.) and some commitment schemes like KZG, it doesn’t require a trusted setup.</p></li><li><p>Unlike other hash-based SNARKs (STARKs), bitwise operations don’t incur overhead.</p></li><li><p><em>Probably</em> the fastest-known proving times.</p></li><li><p>Support of proof composition.</p></li></ul><div class="relative header-and-anchor"><h3 id="h-the-experiment">The Experiment</h3></div><p>To test Binius, I have modified one of their examples to perform random XOR operations instead of AND operations. For this experiment, we are assuming that some <code>N</code> number of XOR operations is a substitute for actual encoding computation.</p><p>The following are observations from my local machine (a Mac M1 with ten cores and 32 GB memory).</p><table style="minWidth: 50px"><colgroup><col><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>Data</p></td><td colspan="1" rowspan="1"><p>1Gb = 1024 <em> 1024 </em> 1024</p></td></tr><tr><td colspan="1" rowspan="1"><p>chunk size</p></td><td colspan="1" rowspan="1"><p>1Kb = 1024</p></td></tr><tr><td colspan="1" rowspan="1"><p>chunks</p></td><td colspan="1" rowspan="1"><p>1024 * 1024</p></td></tr><tr><td colspan="1" rowspan="1"><p>field elements in 1 chunk</p></td><td colspan="1" rowspan="1"><p>1Kb/size(u128) = 64</p></td></tr><tr><td colspan="1" rowspan="1"><p>leaves (Field elements)</p></td><td colspan="1" rowspan="1"><p>1024 <em> 1024 </em> 64</p></td></tr><tr><td colspan="1" rowspan="1"><p>total operations (1Gb)</p></td><td colspan="1" rowspan="1"><p>1024 <em> 1024 </em> 64</p></td></tr><tr><td colspan="1" rowspan="1"><p>compute trace (field elements)</p></td><td colspan="1" rowspan="1"><p>1024 <em> 1024 </em> 64</p></td></tr><tr><td colspan="1" rowspan="1"><p>compute trace size (bits)</p></td><td colspan="1" rowspan="1"><p>1024 <em> 1024 </em> 64 * 7</p></td></tr><tr><td colspan="1" rowspan="1"><p>proof time</p></td><td colspan="1" rowspan="1"><p>~60ms</p></td></tr><tr><td colspan="1" rowspan="1"><p>proof size</p></td><td colspan="1" rowspan="1"><p>~320 bytes</p></td></tr></tbody></table><p>This experiment is just a first attempt at the problem. It only approximates the actual XOR-based encoding computation. The circuit might need to have more constraints to be secure. Let us assume a high enough error margin. For instance, let’s say generating a proof for actual encoding will take 10x more time. It will still finish in ~600ms!</p><p>These results are highly encouraging compared to my expectations. I thought generating a practical proof might take 10-15 minutes. <strong>My first naive implementation took 10 minutes for an object size of 125MB</strong> (1/4th the size of the object in the table). With proper batching of the computation trace, prover latency was dramatically reduced. Furthermore, this is just a first glance at the Binius repo. There might be more levers to pull to optimize proving time.</p><div class="relative header-and-anchor"><h3 id="h-concerns-with-binius">Concerns with Binius</h3></div><ul><li><p>it is extremely new. The Binius reference implementation is a POC not ready for production use. There is no documentation or dev chat to ask questions, and the only way to learn how to use it is by looking at existing examples.</p></li><li><p>it offers a low-level API for generating SNARK proofs. We must write the computation trace and specify the SNARK circuit by hand, constraint by constraint. We have to deal with polynomials. Writing SNARKs at this level of abstraction is slow and error-prone. It is analogous to using assembly language to write our programs.</p></li></ul><div class="relative header-and-anchor"><h3 id="h-conclusion">Conclusion</h3></div><p>The first issue should be resolved with time as the project matures. ZKVMs addresses the second issue.</p><p>Today, most RISC-V-based ZKVMs (RISC Zero, SP1, Jolt, Nexus, etc.) can take a high-level Rust program as input and produce a SNARK proof. Hiding all the complexity of generating computation trace, circuit constraints, and polynomial manipulation.</p><p>Unfortunately, as of today, most ZKVMs are based on STARKs not Binius. However, a16z’s Jolt has Binius support on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/a16z/jolt/issues/212">roadmap</a>, and work on it has already <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/a16z/jolt/issues?q=binius">started</a>.</p><p>This leads me to conclude that using Jolt with Binius could enable validity proofs. Working with ZKVM also allows us to swap out the VM later. For instance, we could start with <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dev.risczero.com/api">RISC Zero</a> since it has great documentation and examples but swap it out for Jolt when it supports Binius.</p><div class="relative header-and-anchor"><h2 id="h-basin-demo-hosted-http-server">Basin demo: Hosted HTTP server</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We created a demo for how to use Basin with a "hosted" server setup:</p><ul><li><p>A backend wallet sends object storage transactions on behalf of a requesting user.</p></li><li><p>You can <code>/set</code> a file—up to 100 MB in the demo (but the protocol itself has higher limits).</p></li><li><p>You can also <code>/list</code> all objects in the store.</p></li></ul><blockquote><p>Clone the repo and review the README instructions to get started!: <code>textileio/demo-basin-server</code></p></blockquote><p>From the client's perspective, <code>curl</code> requests are sent to either push files:</p><pre data-type="codeBlock"><code>curl <span class="hljs-operator">-</span>X POST <span class="hljs-operator">-</span>H <span class="hljs-string">'Content-Type: multipart/form-data'</span> \
<span class="hljs-operator">-</span><span class="hljs-operator">-</span>form <span class="hljs-string">'address=0x79447b8db3a9d23f7db75ae724ba450b7b8dd7b0'</span> \
<span class="hljs-operator">-</span><span class="hljs-operator">-</span>form <span class="hljs-string">'key=hello/test'</span> \
<span class="hljs-operator">-</span><span class="hljs-operator">-</span>form <span class="hljs-string">'file=@test.dat'</span> \
http:<span class="hljs-comment">//localhost:8081/set</span>

<span class="hljs-comment">// this will log the onchain transaction for storing the object</span>
{
  <span class="hljs-string">"data"</span>: <span class="hljs-string">"bafy2bzacedxeu3g3uazqpn2ln7yvyfhc6ilj3vi5bf3h6usvygsxaub7paws4"</span>,
  <span class="hljs-string">"gas_used"</span>: <span class="hljs-number">4311212</span>,
  <span class="hljs-string">"hash"</span>: <span class="hljs-string">"1DDBED9D0398C4A7C0B2E0DE99BCE77C34232CC1AD45E9304F990A416ACAF830"</span>,
  <span class="hljs-string">"height"</span>: <span class="hljs-string">"956895"</span>,
  <span class="hljs-string">"status"</span>: <span class="hljs-string">"committed"</span>
}</code></pre><p>And also list the data in the store:</p><pre data-type="codeBlock"><code>curl <span class="hljs-operator">-</span>X POST <span class="hljs-operator">-</span>H <span class="hljs-string">'Content-Type: application/json'</span> \
<span class="hljs-operator">-</span>d <span class="hljs-string">'{"prefix": "hello/", "limit": 10}'</span> \
http:<span class="hljs-comment">//localhost:8081/list</span>

<span class="hljs-comment">// this logs data under the common prefix</span>
{
  <span class="hljs-string">"common_prefixes"</span>: [],
  <span class="hljs-string">"objects"</span>: [
    {
      <span class="hljs-string">"key"</span>: <span class="hljs-string">"hello/world"</span>,
      <span class="hljs-string">"value"</span>: {
        <span class="hljs-string">"cid"</span>: <span class="hljs-string">"bafybeid3weurg3gvyoi7nisadzolomlvoxoppe2sesktnpvdve3256n5tq"</span>,
        <span class="hljs-string">"metadata"</span>: {},
        <span class="hljs-string">"resolved"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-string">"size"</span>: <span class="hljs-number">5</span>
      }
    }
  ]
}</code></pre><p>The backend is written in Rust and makes use of the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/textileio/basin/tree/main/sdk">Basin SDK</a>. Running the server will let you log information about incoming requests:</p><pre data-type="codeBlock"><code><span class="hljs-number">2024</span><span class="hljs-operator">-</span>07<span class="hljs-operator">-</span>20T17:<span class="hljs-number">49</span>:<span class="hljs-number">27.589</span><span class="hljs-operator">-</span>04:00 <span class="hljs-operator">-</span> INFO Starting server at <span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>:<span class="hljs-number">8081</span>
<span class="hljs-number">2024</span><span class="hljs-operator">-</span>07<span class="hljs-operator">-</span>20T17:<span class="hljs-number">50</span>:<span class="hljs-number">12.015</span><span class="hljs-operator">-</span>04:00 <span class="hljs-operator">-</span> INFO {<span class="hljs-string">"body"</span>:<span class="hljs-string">"{\"multipart/form-data; boundary=------------------------u3Cayud8pzT4bsvlrHH4Z5\"}"</span>,<span class="hljs-string">"route"</span>:<span class="hljs-string">"set"</span>}
<span class="hljs-number">2024</span><span class="hljs-operator">-</span>07<span class="hljs-operator">-</span>20T17:<span class="hljs-number">50</span>:<span class="hljs-number">14.691</span><span class="hljs-operator">-</span>04:00 <span class="hljs-operator">-</span> INFO {<span class="hljs-string">"client_addr"</span>:<span class="hljs-string">"127.0.0.1:50064"</span>,<span class="hljs-string">"duration_ms"</span>:<span class="hljs-number">2676</span>,<span class="hljs-string">"method"</span>:<span class="hljs-string">"POST"</span>,<span class="hljs-string">"path"</span>:<span class="hljs-string">"/set"</span>,<span class="hljs-string">"status"</span>:<span class="hljs-number">200</span>}
<span class="hljs-number">2024</span><span class="hljs-operator">-</span>07<span class="hljs-operator">-</span>20T17:<span class="hljs-number">50</span>:<span class="hljs-number">33.952</span><span class="hljs-operator">-</span>04:00 <span class="hljs-operator">-</span> INFO {<span class="hljs-string">"body"</span>:<span class="hljs-string">"{prefix: Some(\"hello/\"), delimiter: None, offset: None, limit: Some(10)}"</span>,<span class="hljs-string">"route"</span>:<span class="hljs-string">"list"</span>}
<span class="hljs-number">2024</span><span class="hljs-operator">-</span>07<span class="hljs-operator">-</span>20T17:<span class="hljs-number">50</span>:<span class="hljs-number">34.371</span><span class="hljs-operator">-</span>04:00 <span class="hljs-operator">-</span> INFO {<span class="hljs-string">"client_addr"</span>:<span class="hljs-string">"127.0.0.1:50068"</span>,<span class="hljs-string">"duration_ms"</span>:<span class="hljs-number">419</span>,<span class="hljs-string">"method"</span>:<span class="hljs-string">"POST"</span>,<span class="hljs-string">"path"</span>:<span class="hljs-string">"/list"</span>,<span class="hljs-string">"status"</span>:<span class="hljs-number">200</span>}</code></pre><p>You could imagine adding other endpoints like getting the actual file at the object or deleting data, but hopefully, the demo server is enough to get you started!</p><hr><div class="relative header-and-anchor"><h1 id="h-read-and-watch">Read &amp; watch</h1></div><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dev.risczero.com/proof-system/stark-by-hand">Stark by hand</a>: An in-depth tutorial on STARKs internals by tge RISC Zero team.</p></li></ul><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/e83f55fb78c8f8fd0006d1564d13e39e.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Base mainnet, EthCC, Studio Console, & upcoming Basin features]]></title>
            <link>https://blog.textile.io/weeknotes-base-ethcc-console-s3</link>
            <guid>fRWJJPL5a68JtNox4qyV</guid>
            <pubDate>Wed, 17 Jul 2024 21:47:18 GMT</pubDate>
            <description><![CDATA[Onchain summer with Base mainnet support, EthCC learnings, new Studio Console + layout, & upcoming Basin features.]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><p>It's been a few weeks since our last post, largely due to an all-company offsite (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://beyulretreat.com/">outside of Aspen, CO</a>), travels, and some holidays. But, we've still been building new capabilities for both Tableland and Basin, plus, we attended some events (aka EthCC).</p><div class="relative header-and-anchor"><h2 id="h-tableland-base-mainnet-support-is-live">Tableland Base mainnet support is live!</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>Base has been one of the most sought-after chain integrations from our developer community. Generally speaking, there's a <em>ton</em> of activity on Base, including Farcaster frames functionality (which we're huge fans of). </p><p>We wanted to make sure developers were able to use Base on both mainnet and the Sepolia testnet for onchain summer. Both of these chains are now officially supported!</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>Check out the docs that describe the official Tableland contracts on Base and useful other information: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.tableland.xyz/quickstarts/chains/base">here</a></p></div></div></div></div><div class="relative header-and-anchor"><h2 id="h-ethcc-brussels-recap">Ethcc Brussels Recap</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://github.com/marlanat27">Marla Natoli</a></p><p>EthCC was buzzing with builders, creators, and organizations dedicated to innovating around AI, data management, and so much more. Our team left the week feeling more optimistic than ever about all the possibilities that can be unlocked with decentralized database infrastructure, both near and long-term. A few highlights: </p><ul><li><p>We co-hosted our 2nd Proof of Data Summit with Ceramic, which was a half-day event filled with thought leadership talks and panels from teams including DIMO, WeatherXM, IoTex, Filecoin, Vana, and more. We'll be sharing recordings of sessions in the coming weeks</p></li><li><p>Our Partnerships lead, Marla Natoli, presented at the FIL Dev Summit where she talked about Basin and the opportunities and use cases it unlocks for DePIN &amp; AI organizations</p></li><li><p>Marla also presented alongside Ally from Lilypad at the Filecoin Foundation Network Base event, where they spoke about synthetic data and ways that Basin aims to unlock more innovation for AI and ML organizations. A joint POC is in the works and will be showcased soon.</p></li><li><p>We connected with existing friends and partners, and opened up conversations around new partnerships that we're sure will lead to some pretty epic POCs</p></li></ul><p>We'll be sharing recordings and highlights from the event, so be sure to follow us on socials and subscribe to weeknotes for updates!</p><div class="relative header-and-anchor"><h2 id="h-studio-redesign-and-new-console-feature">Studio redesign and new Console feature</h2></div><p>The Studio has made numerous incremental updates to the overall UX flow. </p><div class="relative header-and-anchor"><h3 id="h-sidebar-and-project-navigation">Sidebar &amp; project navigation</h3></div><p>ICYMI—a sidebar now organizes the layout more intuitively at both the "user" and "project" levels. Projects are outlined a bit more clearly in a stacked view, too. </p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fce579c07c13ff9de3afb20119517916.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAPCAIAAAAK4lpAAAAACXBIWXMAABYlAAAWJQFJUiTwAAACQ0lEQVR4nGMIDqjNyZhfnLvS3i7RyTUiLb2+sLDb0yNBS8dZ39ADjnT0XbV0nJGRmoa9o1NUZFSht09yc/MMd4+EyMgCY1PPrOymosL2uKS6tbM7jp5czODqmOrlnu/hkmdjE2lnF+buGmdi5C4mqsHHqcDHqwRHYqKacrJGaEhL08bYyE1L087G2l9f19HYyE1VxdLU2F1Hx1ZW2iQszLdpUiXD+lUX///4/+7F/y2rH+7f9q6meH6wT8LsaWs3rT50aOfFVUt2Xjj5YN+2C8E+CQwMQiI88vysUnAkyCbNwyQJR/ysUgKcUmpK1ts33nv56P+FE78zE9oZEiLKJnevriiY4OuWGuSd6Wgdpq9lGx2aHRWS6e4YGuyTlJtSHRuaY2bgIi+hqSyjB0fyEpqSwqoK0ggRBUkdSQElbVXrhMjK3LTW4uzusMBMBjf70NzUuhDfVDVFM11Va1UFU0sTj+KstqLM5k1rjsWFFUiJalmbekUEZhpoOpgbukOQgaZDbFheT+ucEJ9kiLiBpoO/R3xz3ZTCzIbCzDo3uxApEQ1HG3+GyKDstoZZVUW9EEXaqjZqCsZ2lr52lr5u9qGWJh5aKpb6GraGmnZaKpbIyNTA2czARV/DFi6ir2FrZuBiZuBiZeppou+soWJhZ+nDYKDpYG3qbW3qbaDpAELaDmJ8inwsoADlY5EU5pEV4ZGHBD2EgYz4WaXgCkR45IV5ZOHRA5HV07QCWYCCtB3EhZQxzRIhHY1aIDIaRDxDJBUBABtFBe7vmEyaAAAAAElFTkSuQmCC" nextheight="1012" nextwidth="2156" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Once you click on a project, it'll display a sidebar with the Console (new!), table definitions, settings, and general metadata for the projects and their environment. The breadcrumbs also reflect the hierarchy in a more readable way.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e5b69b18e245808e19a68626b88c970c.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAXCAIAAADlZ9q2AAAACXBIWXMAABYlAAAWJQFJUiTwAAAGIklEQVR4nI1UXWzb5BoOsFXQjW40Y0mbJVnsxHFSO2ntOInt2Pnr4sRefuomJmuaJk2bkpYUmrJ1LdCNTlsH4yiHjU6tGKBBgYoe2h1goE1oqMAkEBcIIcHNuEDAuT03RwcuixJX0bR1AumR9dn+vvf5nvd93lch9ZwujyxPltdod5b1iaXS3PGpaig0gHZ2p/sqx6eqw8OzFsTP84XqP96ZmblAUT1WxGdF/EaTh2GS+cIUzw/OzS1F+Hx24OlOLDxePlWpnOnPzX7w5vw3P76pCIcK2cxMb7zCc6UoP+pnMmqVZZ/SpFZZQMChUSMatXWf0myBiVisx8ceam1VNTW1NDW1tLeZ1CqrWmVRqywa9dai8br/UdiKOEKxHsX7y99u/rH5y63Na1d+vfqv36afupR77InrH329vrKx+tb15vtUrc0HHlSoiC73wvkq7XKaQcAMAgzlBjRQy4721uYDrc0HWna0792paTzl7/cr9hk1nQocDca43OjgDAJ5EMhj1DlYUmBJQbUXaGsFVXsB1V5AuVuPduACz7MMyzIsQRDNzQ+pWrXK3Xo5qLztDih36TrMpMJLJWJcLsRKCMQgEAODJKCx+6mEyBek+AjpiCCQx2ZmHHY/Q4W9dIShwqQzqGrVdkBOLxmLBI4cYlNGneN2QAYnAnlgwO1xC4rh/snpp89GuaxJT9jNXtIRAbXY7LFzF15afv3iv2NczqQntCrUpCesRhoGSQtIW0DaZmZcXaFzp169svL5pYX1BD8Y5bJRLivyBZEvhFgJR4MwSLJkVJFPV+ZPLs1OVY+OnZYVQAYnDJKgDjdoukx6IsRK19a/mT+5ZNITsso6PDgaeHVhdeXy1aNPnfbTYn9ydItDGIpyWRfGbRHEuJwoDLkwDkeDDYJGIBgkvVRi/uRSPl2BQfJ2gjoYGHDHuNx4cdbVFRJC2cfzx0VhSL5+Q8FEsf9o43a1H0CNoAsJWECadSVmj50T+cJ48dlMb/k2Dg+G+HA0aAHpy5eu/Hzrv2fnFj9Y++I/P///w7Uvw4E+OZlbCp47Vn3uWBWF2EaRIT0OaOyGdsSo68IQXwMIRMuA9LjpIAZo7IDGrlZCe3ZqETNt1GE6lRXQ2OtXpCGDgyI4BQIxLoxzYVxDgVGHRUP9+XRl8Mhk8nBRFivDClJWkKrvpB2ofzQ/LcVL+fREVnpStk0tb3AtbwhcU1lTcFta64AZQGN/ZvKF9ZWNj9e+Wlu5Odw/OZAqZ6WJgVR5IFUu9E9GAhkYcNNE5LXFteXXrta3baTFUVEYEoWhZKyYFmsFRyGWJYU7CeQUjeanz5xY4LySE3Y4cKEDDrhhmnDHCZwn8YiP6oUBN4b4zpy4WH3xjXx6wqQn5IbwkrFDbErkC0Lo3gSQwYlCbIeZNIH4K8ubt95b+9/NG1/8vvnD2Us3F1dvfPaddj9ar4dHNt7o0Mz5c5f7esemK/ML1bcez025MM6kJ7ZcdDeBUYfRhOB2hChX5PlXfv1u/fpPNzbe/37zxqnFD6uXP/7kK8LW3XARAjEvnlpae/fTuZnzC9W3N659e/Gf78hzAYVYHxXfnkCKj4wXZ8eLsyNSISoMd/v7RX8yzBfERCl1eGg0P41AHl0bYmiv4ZEm7cMPaJS79Xt2apsUqj07NO37IV0b0r4fctj929VA2yn7D9B2dpg9GOLFEK+9w2uDaJtsU9gDA85Hd+uUu2rYdswpd+ladrR3QM5tCEAtln/sSSleinJZHA3UzUfLFoQBNwy4cTTwd3BPm+ra0MUL725c/351+bNMcjwSyES5rBQfCbGSEMpGApk7j9yFRt/cs8h+KhFkkofYVF/vmBQfEflCPj0h8oW+3jGRL/wlQaNztyeADE4rSJn0BHTQJQ9Ug6arsZD9Vx9Zbrmx5Q63mRmbmbGCFOdNLb383tL51UR4cGtU3KXA4aUShSMTSWE4n56Ih2vjNhkrisKQFC9J8VLycDHG5fp6xsK+dIzLZXrLkUAGR4MyCFs3iYVpgids3fdKkcPjPFyv88iRREkO0dczJiPTW86nK1K8NJAaF4IZIZgpF07EwznC1i2jwYSjQZaM/gnR20Zfr0nfkgAAAABJRU5ErkJggg==" nextheight="1580" nextwidth="2156" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><div class="relative header-and-anchor"><h3 id="h-the-console">The Console</h3></div><p>Now, you can read and write table data directly in the UI! Every project has a <em>Console</em> in the sidebar. This opens up a query interface where you can execute SQL queries on your existing table definitions. The examples below show the results from a mutating query (logs the transaction information):</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4794fdd7f5152546c5b92f48bf6c4138.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAUCAIAAABj86gYAAAACXBIWXMAABYlAAAWJQFJUiTwAAADmUlEQVR4nGOIjq6vKFtcWDDbxS0+KiovObUqLa3GysYvIDg9N78lObXK1jHYNzBlwuQVRaVdto7BFta+cGRs5hEZWxAZW5CT15SV2xgZW+DqHhWfVFZY3BobXzmzv+v0qfUMUaG1SbE9kWFN9rZRocG50RFFfj4p2loOjg5hIUGZUeEF+vqutjaBebltIUGZRoauykoWcCQna+TkGOrkGOrnk+Tnk+TsGGZs6ObsGBYRluPiFNfeXHPi2haGzMTyxoqe2LAcHVVLFVljMUHV4uyKxJjUAO8QTRVTFgZRATZpXhZJBgY+XhZJATZpMX5FSVEVOBLlkxfjVxRgkxZgkxblk4eIQNisDJIqcmYMC2cf/PPl/58v/7esvrVr0yNf99RA9/CavJaMmMK8xPJZU5bPm7lm7tRV61btSwjNKkuvyk+tcrIO1FWzMdZ2hCMLYw9kLgQZaNn7eEQyTOxcd/3ir4O7nsydsm/9iss+7skGmlZhvknG2g56ataOtv4udkFgMkBf3cpUx9FA00ZD0URZRo8gkhFTt7HwYijLbeqon2pv5ScrrmWk7aCpYuHhHJaTViMpqsLLIsnLIsnFBCJB4cMlI8AlI8gtCwkQgoiXRVJf24ahLKd90cwtU3qW52U0Wpp46arZyElqaqqYaqqYSoqqyktp4UIyYurIXFlxdTQkLqBkbe7OEBmUlRRTHOid5O0Wa2nkpapgGuqfvG3d0fUr9rvYBfEwSwiwSfOzSUEchcmAI3EBJTTEzyTlaOPH0Nkwc960tW4OYcY6zg7WgSqyxpmJ5Xevvzuy71paQhkkHCHI3NjN3NgNzHCFITcrE3eIiKSoqhi/IjISYJMGxUFqXMWUnuUt1VMsTTwhFiTHFD669fnM0btb1h65cPpRQ0X/pN6FPS2zm6smQRhtdVM6GqaXF7b1t82d1LtwxuTlPS2zVRUMIYkY3QJjHWcNJUtddVsLI6gF0aGZR/Zd27X51J4tp309YsT4FeEBLSWmLsavxMwgzMIgCkcQLprzERZAzLUw8oRbkJZQ+ubpv4/P/z++9WXt8r1njt5du3xvWkJpeWFbTlpNkHeSILushIiKGL+ShIiKhIiKpKgqmIvbAjiyNPLSUrUy0LTxcgn38Yi2t/Tx94z194zVUDSBZGMBNmkhDhnMBIMViQsoYbXAGi158LNJgYsHVQjCdCkuJMAmbWLogMUC4o0QG7WAfzSITAwdAC9clg07fGQaAAAAAElFTkSuQmCC" nextheight="1440" nextwidth="2314" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>And a read query (logs the table data):</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3d6716e72146e04ae453b4636bed6302.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAPCAIAAAAK4lpAAAAACXBIWXMAABYlAAAWJQFJUiTwAAAB4ElEQVR4nGPITKpqrZlWkNGgr2GnqWypJGNQlFcbERLn6xmiqWrJxSTJyiDGxSTJwiDKzSwlwqdAPBLkkTMzdmaYP33n/et/zxx52dW4YmLHBjf7yLSYnAnNU0oyytKicvNTqmZMWdFWN3nO1JUVhW2aypb6GnZEIk1lS2+3SIaFMw98e/P/79f/pw99uXXxf2x4maGGZXRgmrWJh7WJh79nbEJUfnxkbm5adZh/io6aDZFIT91GTcnM1SGYobl68uypq/w84tXkTdwcw/TUbQozi/Zu22mka83HKi3AJsXLIsnLAgooATYpMX4FIhFEl6WJC0Nr7fTdm8/Onri2ILPJ2sRbX8NOmFNWSkxNTECRPCTALqOpZDKtd7GvR4ydlRdDQWZTcW5rXFh+sHeqtYm3jrqtuqKxvJSWnIQG2UhNTt/GzENd0djVIZChvWF6XWmPpoqVqZ6bs22oprKlu2OIuqKxgrQ22UhOQgMSBu6OIQxleR1rlx2Y0b/SysTL2tRXR91WU8mEEtMVwBYoSGtLCCo52vgxeDpHQ5C1iTfIAjUbskNfDIYcrP3srX2N9exAydTdMdxUz81Uz42KFiiA/SEmoGhv7cvgbBsKMhqCqGSBGCw5gZLpqAUCAx1EAPeS/ehVIHQ8AAAAAElFTkSuQmCC" nextheight="1094" nextwidth="2316" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><div class="relative header-and-anchor"><h2 id="h-basin-feature-updates">Basin feature updates</h2></div><p>A lot is happening with <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://basin.textile.io/">Basin</a> that isn't <em>quite</em> live yet. There are a few things to keep an eye out for in the coming future:</p><ul><li><p><strong>AWS S3 compatibility</strong>: A fully compatible S3 client with the Basin Rust SDK. We even tested it out on <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://clickhouse.com/">ClickHouse</a> to ensure it can be used with other 3rd party solutions. It's in the final review stage and should be ready in the coming weeks. </p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>In fact, we have a quick demo of the Basin S3 adapter with a MinIO client: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://drive.google.com/file/d/1Kou_jeFg3HgAAMBI8vvvAHLXl0yge-zV/view?usp=sharing">here</a>.</p></div></div></div></div></li><li><p><strong>Faucet service</strong>: This won't be live until a month or two from now (pending some WIP infrastructure changes), but the work is complete. We've stocked up on a <em>ton</em> of tFIL (s/o <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://chainsafe.io/">ChainSafe</a>) and will deploy a Basin subnet faucet service to let you quickly get started with development. This will allow you to "register" new accounts (e.g., bridging accounts from EVM → FVM) on the Basin subnet within seconds, subsequently letting you create and write to the object store with little friction.</p></li><li><p><strong>JavaScript SDK</strong>: You may have read our previous posts about wasm support for Rust. Our goal was to compile our Rust SDK to wasm, but due to some transitive dependencies that don't support the <code>wasm32</code> architecture, it isn't possible at this time without significant workarounds. Instead, we'll be developing a TypeScript-based SDK that closely follows the Rust implementation. The work is <em>just </em>getting started and still weeks away, but JS/TS support opens up a ton of use cases on the web development side of things!</p></li></ul><p>There are more things we'll be sharing soon, but those are some of the more near-term items we've been working on. If you've had a change to work with the Basin CLI or Rust SDK, definitely let us know in Discord and keep use posted on anything you'd like to see there!</p><hr><div class="relative header-and-anchor"><h1 id="h-read-and-watch">Read &amp; watch</h1></div><ul><li><p>Discussion on ZKVMs and ZKTLS: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/mattmurrs/status/1807531236606587053?s=61&amp;t=5WEh19uwPnk3W-8n_OCVnQ">here</a></p></li></ul><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/035b9f0785da27998bc1a720ce39879f.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Base Sepolia goes live & EthCC Proof of Data event]]></title>
            <link>https://blog.textile.io/weeknotes-ethcc-proof-of-data</link>
            <guid>85fqVlYwSHPxiTKBWVcx</guid>
            <pubDate>Mon, 17 Jun 2024 15:32:43 GMT</pubDate>
            <description><![CDATA[Learn how to build on Base Sepolia with Tableland, and read up on our upcoming EthCC Proof of Data event]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-base-sepolia-support-is-live">Base Sepolia support is live</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We've officially published a new version of our CLI and SDK, which includes Base Sepolia as a supported chain. You can read about the Base chain information on our docs site: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.tableland.xyz/quickstarts/chains/base">here</a>. All you <em>really</em> need to do is provide a chain RPC URL pointing to Base Sepolia—and also have testnet ETH in your wallet—and you're be good to go!</p><p>If you want to get started quickly, you can do this in the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/">Studio</a>. When you're ready to deploy a table, <em>Base Sepolia</em> is an option under the testnets section.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cd2e64256bf4f06a6d6c3581458d662b.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAZCAIAAADfbbvGAAAACXBIWXMAABYlAAAWJQFJUiTwAAAGFUlEQVR4nJ2Ua1CSWRiALRM2yyhnL2W2rUReUGwJXXEtUUkIRVTkgwQEAhwlxMunq6ggVxXxUhZOuVpWjpmRksUGBiSMlBttlk3bTs220zjNbr92ph/9aXa2nfhac8zLTO88P86cb+Z9znnf870BcFjwPIFrYYFrYXBYMCwIDgFfsIYIXLtuNd5lmCdgQfZ1O8IjolDx27bu3BGO2h6G3BGOCtsWEbYtInz7rvDtu8K2RSB3RmPQiUsSG4OLjcHtiUvaunX7Qsd7wWewDQEBa9BRuA79wLTn6bXR254bjyau+mZ9L2Z9LyzDbvOFm/du/2HUnSamFlCIbAhyGkDJYJHTgGxiYV4WH6CKKiTqKFR8UND64PWbID4I1qwJRCHjfjxhfvP67fMnr54/efXi2euXc2+eP3k165t7PPPXy7k3v878KeKDJaI6LiAt5ldL/IuykkYuS7YvKYuYWpCXxV9WEBCwJmr3tzrFCYvZZR6yDfReMg/ZBgeuHDeeGeg1Dw9aB/pGzUM2j/Oey37HPGSzjXunXPc9zplJx8xA/1h9tUEiqqMQ2asImlU9LrvPavEOnrZYRhzm4YnpqUce54zD9vOEddo27p2w3nLZfbZxr8M6bR11T00+sI66bePe+3d/B8s05DRgdcHU5IMJ67TF7HLZfR7nzDWLGyzX1lToq6RqWYkSlKrBcm1tZTNYpoF2yo80gWWaSqmKksGikjgrCTDoRDZdAtCEQJ64UqoqK2ksK2kEaML0FFomoYCQkkNMzSek5ECkpeQSU/MhoE+ZhIIcMm+VG+iVPdaxW6b2QSG76rRptKfjwuCZ6xJxA5suYWQL5t+P/7CFVBKHksGCDg4tVhGgo3AVparOlv66ylYBR1YP6hurW5S1BlaeIJvEJKXnZ5OYEFRSIZRxETlkXiQKExQED14fArG4RFxAlplKZ+aWFhWKREIxnycQCcXlssojEllJcen3eLyfJCqZAd3jY8GKPYhO4DFlDJpYyAU5TIFGrevq6G7RtxkNnQqFuqamDovFJrwL3KcLhFwwL4svESvEAqlarTUaOhvqlWBVNRodg8HE+bMnYLF7KAfo2cTCTxQwaGKAKioqLG5vP6pW67QafbmsCovdi8fj/dn3Egj7C5nC5Xqwaokq6FTBIbqECfAUCmVrq1EikQIAE4vdA9UnNi5WxD+slRvT9+evINgUsgWBCA3ZuHkJAZXEEbJBQVGpyh94f6SnpRP8gUajhXyBsqZ5X1I2mcAgphZkEj4ACQLXwkO3fP7lF18hEKGLn6mQDRYLamXFSkFRqVajNxqOajWtPaY+vb6tr+9sj6k3OiZGwON36kwMmpgDSA5zK1n5xVxAygWkh+ilKw07aJr2Hrv4cu7Ns0d/Xxwc++nKmMN+3eu+6XY673injncaeRw2j8NsVqpuXPXcnX4KDSXLiGPSMeOy+xzWaVmJErkzGg4LXvZPbqrrumZxeycfmo6etFy+ZL1yxWm3Wy5ftlutpu7uWhAUCwV1laDPM+uwTt/xPnbZfbfcDz3OGY/znm3cy6ZLUMjYZQXoKFyVVF1fbWjTneJzixWKJoVCLZcrjIZOubxBq9GfOtnPAFgsBjB8ZrSmQt+sOtFU16Gsa6uvNrwf1xmslV5RPBqfQ+Zl7M9LS8mlUhhtBmNXR3eTUtVj6lOrdXJ5w7mzw3J5QxGHK6/UUojs44bz3YbTPFbNxMg/Lx6//e3225ojJ1HIKDhsw9ICLCaZmVuaTWLnkHm5OcwmpUouV4BVPzQp1VqNHqyq5rA5B7OyBDy+Vt4OUEXHDecN6lMiTu1I39wvk2/dV/8tL+6MRMUtIYC/EwSikOgDabn7kkkp35EoJFprq7Gr44RWo9fpWs6dHe7q6EajYyIjI0X8wzVljQlYQhIuIwmXsS+ZnIBNwWKSsZjk1OSD33yNgn087BYSshEBhwXHxcb39fafOtmvUeuOHTPJ5fV4fBIej8dgMGUSKYMGBAQEIhBbQjYi/Gz+H8T82Rfd4APB60MQiFDc3kQWk52Xy6Bm59Go+TQafU/83sjdMahdkYm4JGTE7oWdXIH/AGifwlxjSEwqAAAAAElFTkSuQmCC" nextheight="1134" nextwidth="1426" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><div class="relative header-and-anchor"><h2 id="h-ethcc-is-comingand-so-is-proof-of-data">EthCC is coming...and so is Proof of Data</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We'll be at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethcc.io/">EthCC</a> in early July and present some talks about Basin and Tableland (see below). <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://streameth.org/ceramic_x_tableland">Earlier this year at ETHDenver</a>, we cohosted the Proof of Data event, which was all about decentralized data. The second iteration of this event will be held on July 9th, and we'll have talks given by IoTeX, DIMO, WeatherXM, and Filecoin!</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>Sign up for the Proof of Data event in Brussels: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://lu.ma/0vifocie">https://lu.ma/0vifocie</a></p></div></div></div></div><p>It's always great to meet up IRL, and we're also down to attend/cosponsor something else, too. We hope to have some new Basin-related POCs to share by then, and if <em>that's</em> something you're interested in working on, definitely reach out!</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>Fill out this quick form if you're interested in working with us! <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/partnerwithus">https://basin.textile.io/partnerwithus</a></p></div></div></div></div><div class="relative header-and-anchor"><h2 id="h-ipfs-camp-upcoming-talk">IPFS Camp upcoming talk</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jkosem">Jim Kosem</a></p><p>When you give a talk in front of a bunch of people you should probably have your facts straight. This is especially the case when you’re a designer giving a talk at a tech event, such as <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://2024.ipfs.camp/">IPFS Camp in Brussels</a> where I’ll be talking about <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/">Studio</a>, which I’ve been working on for the majority of the past year.</p><p>The funny thing is as part of a design track, I just might be speaking to other designers who are also working on developer tools and the developer experience such as myself. This led me to reexamine what I’ve been designing for and what the developer experience is for, meaning data and databases. So I had to go back and review just what those things mean and what they mean for interfaces and interactions. When you get lost in the weeds as it were with an application you’ve been working on for a while, you often lose track of the basics of what you’re doing, why data, why tables, why ownership, so talking about a forcing function to reexamine the first principles of your work is usually not a bad thing.</p><hr><div class="relative header-and-anchor"><h1 id="h-read-and-watch">Read &amp; watch</h1></div><ul><li><p>Introduction to STARKs by Eli Ben-Sasson: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=jg9KSNOO2XY">https://www.youtube.com/watch?v=jg9KSNOO2XY</a></p></li><li><p>NVIDIA’s new open synthetic data pipeline: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blogs.nvidia.com/blog/nemotron-4-synthetic-data-generation-llm-training">https://blogs.nvidia.com/blog/nemotron-4-synthetic-data-generation-llm-training</a></p></li><li><p>Introduction to State Space models: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://freedium.cfd/https://medium.com/thedeephub/gentle-introduction-to-state-space-models-e8cd7501e0cf">https://freedium.cfd/https://medium.com/thedeephub/gentle-introduction-to-state-space-models-e8cd7501e0cf</a></p></li><li><p>S3 is showing its age: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://materializedview.io/p/s3-is-showing-its-age">https://materializedview.io/p/s3-is-showing-its-age</a></p></li></ul><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/6bce7f8f468c6b77818d9e83d4223eb3.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Decentralized data landscape, Basin intro, Rust server 101 with warp, & GenAI design patterns]]></title>
            <link>https://blog.textile.io/weeknotes-data-landscape-basin</link>
            <guid>MC6kvO527oQuCOkzqfMg</guid>
            <pubDate>Mon, 10 Jun 2024 19:44:48 GMT</pubDate>
            <description><![CDATA[Read up on our latest blog posts about the decentralized data landscape plus Basin's initial architecture, learn how to build a simple Rust server with warp + tokio, and GenAI for design patterns.]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h2 id="h-decentralized-data-solutions-insights-and-opportunities">Decentralized Data Solutions: Insights and Opportunities</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/andrewxhill">Andrew Hill</a></p><p>Our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.textile.io/unlocking-the-future-of-data-high-value-solutions-for-onchain-builders">recent blog post</a> is essential reading for web3 builders, offering a thorough overview of the decentralized data landscape, complete with insights from a comprehensive survey of 32 developers and leaders. This piece highlights the opportunities and challenges in adopting decentralized infrastructure. It also calls out some key opportunities for all of us to improve data protocols in web3.</p><div class="relative header-and-anchor"><h2 id="h-basin-architecture-introduction">Basin architecture introduction</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.textile.io/basin-launch-overview">published a blog</a> about how <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/">Basin</a> (new &amp; improved) works and what makes its design unique. There's still a lot that we haven't fully dug into or implemented yet and are still researching, but this post should provide additional insights into the network.</p><p>The gist of it is that it's built on Filecoin's IPC subnet architecture for fast and verifiable data—specifically, object storage. If you want to learn more, the post talks about the general consensus mechanism, parent-child subnets/state, ABCI &amp; FVM, and more!</p><div class="relative header-and-anchor"><h2 id="h-simple-rust-api-server-with-warp-and-tokio">Simple Rust API server with warp &amp; tokio</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We're adding a feature to the Basin CLI that will let nodes run a daemon / API server to auto-fund new accounts. The problem this helps address is around DX. If you're a new user coming from the EVM world to the FVM and the Basin (IPC) subnet, your EVM account <em>is</em> compatible with the FVM, but there's a bit of "registration" required onchain.</p><p>Filecoin has an Ethereum Account Manager (EAM) that lets EVM <code>0x</code> addresses delegate to a <code>f410</code> address, which lets the hex-prefixed address work natively on Filecoin. But, for the <code>0x</code> address to work, it needs to be registered onchain with the EAM. This requires a transaction to be made.</p><p>In the coming weeks, we'll be adding a feature to the CLI that abstracts this process away. The core logic required here is a hosted/funded backend wallet that will send a small amount of FIL to a new account. Since Basin is only live of Filecoin Calibration, it doesn't actually "cost" anything for the backend wallet to fund new accounts. If you haven't had a chance to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/textileio/basin/tree/main/cli">use the Basin CLI yet</a>, get started while we implement it! Right now, you'll have to get your own tFIL testnet currency and <code>deposit</code> it into the Basin FVM subnet, and then you're good to go.</p><div class="relative header-and-anchor"><h3 id="h-setup">Setup</h3></div><p>Below is a skeleton of the API server. It uses warp as the server framework, and tokio for async operations. There's a single <code>/fund</code> endpoint that takes an address as a parameter, so a requires like <code>/fund/0x1234…</code> will trigger an FVM and Basin subnet transaction to execute sending some tFIL to the specified address.</p><pre data-type="codeBlock" language="rust"><code><span class="hljs-keyword">use</span> std::convert::Infallible;

<span class="hljs-keyword">use</span> dotenv::dotenv;
<span class="hljs-keyword">use</span> serde::Serialize;
<span class="hljs-keyword">use</span> serde_json::json;
<span class="hljs-keyword">use</span> std::sync::Arc;
<span class="hljs-keyword">use</span> tokio::sync::Mutex;
<span class="hljs-keyword">use</span> warp::{http::StatusCode, Filter, Rejection, Reply};

<span class="hljs-meta">#[tokio::main]</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">main</span>() {
    <span class="hljs-title function_ invoke__">dotenv</span>().<span class="hljs-title function_ invoke__">ok</span>();

    <span class="hljs-keyword">let</span> <span class="hljs-variable">state</span> = Arc::<span class="hljs-title function_ invoke__">new</span>(Mutex::<span class="hljs-title function_ invoke__">new</span>(State::<span class="hljs-title function_ invoke__">new</span>()));

    <span class="hljs-keyword">let</span> <span class="hljs-variable">fund</span> = warp::<span class="hljs-title function_ invoke__">post</span>()
        .<span class="hljs-title function_ invoke__">and</span>(warp::path!(<span class="hljs-string">"fund"</span> / <span class="hljs-type">String</span>))
        .<span class="hljs-title function_ invoke__">and</span>(<span class="hljs-title function_ invoke__">with_state</span>(state.<span class="hljs-title function_ invoke__">clone</span>()))
        .<span class="hljs-title function_ invoke__">and_then</span>(handle_fund);

    <span class="hljs-keyword">let</span> <span class="hljs-variable">router</span> = fund
        .<span class="hljs-title function_ invoke__">with</span>(
            warp::<span class="hljs-title function_ invoke__">cors</span>()
                .<span class="hljs-title function_ invoke__">allow_any_origin</span>()
                .<span class="hljs-title function_ invoke__">allow_headers</span>(<span class="hljs-built_in">vec!</span>[<span class="hljs-string">"Content-Type"</span>])
                .<span class="hljs-title function_ invoke__">allow_methods</span>(<span class="hljs-built_in">vec!</span>[<span class="hljs-string">"POST"</span>]),
        )
        .<span class="hljs-title function_ invoke__">recover</span>(handle_rejection);

    warp::<span class="hljs-title function_ invoke__">serve</span>(router).<span class="hljs-title function_ invoke__">run</span>(([<span class="hljs-number">127</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>], <span class="hljs-number">8081</span>)).<span class="hljs-keyword">await</span>;
}</code></pre><p>The <code>handle_fund</code> and <code>handle_rejection</code> are handlers that execute logic once the endpoint is hit. Aside from those, you can also pass some local state to the API—for example, perhaps you want to implement a simple rate-limiting feature. Passing/calling <code>with_state</code> lets you perform some operations to track some state every time the API is hit.</p><pre data-type="codeBlock" language="rust"><code><span class="hljs-comment">/// State for the API</span>
<span class="hljs-keyword">struct</span> <span class="hljs-title class_">State</span> {
    <span class="hljs-comment">// Rate limit data?</span>
}

<span class="hljs-keyword">impl</span> <span class="hljs-title class_">State</span> {
    <span class="hljs-comment">/// Create new state.</span>
    <span class="hljs-keyword">pub</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">new</span>() <span class="hljs-punctuation">-&gt;</span> <span class="hljs-keyword">Self</span> {
        State {}
    }
}

<span class="hljs-comment">/// Filter to pass the state to the request handlers.</span>
<span class="hljs-keyword">fn</span> <span class="hljs-title function_">with_state</span>(
    state: Arc&lt;Mutex&lt;State&gt;&gt;,
) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-keyword">impl</span> <span class="hljs-title class_">Filter</span>&lt;Extract = (Arc&lt;Mutex&lt;State&gt;&gt;,), Error = Infallible&gt; + <span class="hljs-built_in">Clone</span> {
    warp::<span class="hljs-title function_ invoke__">any</span>().<span class="hljs-title function_ invoke__">map</span>(<span class="hljs-keyword">move</span> || state.<span class="hljs-title function_ invoke__">clone</span>())
}</code></pre><p>The rejection handler is nice because it lets you control responses upon 404s, internal server errors, etc.:</p><pre data-type="codeBlock" language="rust"><code><span class="hljs-comment">/// Generic request error.</span>
<span class="hljs-meta">#[derive(Clone, Debug)]</span>
<span class="hljs-keyword">struct</span> <span class="hljs-title class_">BadRequest</span> {
    message: <span class="hljs-type">String</span>,
}

<span class="hljs-keyword">impl</span> <span class="hljs-title class_">warp</span>::reject::Reject <span class="hljs-keyword">for</span> <span class="hljs-title class_">BadRequest</span> {}

<span class="hljs-comment">/// Custom error message with status code.</span>
<span class="hljs-meta">#[derive(Clone, Debug, Serialize)]</span>
<span class="hljs-keyword">struct</span> <span class="hljs-title class_">ErrorMessage</span> {
    code: <span class="hljs-type">u16</span>,
    message: <span class="hljs-type">String</span>,
}

<span class="hljs-comment">/// Rejection handler for the API.</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">handle_rejection</span>(err: Rejection) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-type">Result</span>&lt;<span class="hljs-keyword">impl</span> <span class="hljs-title class_">Reply</span>, Infallible&gt; {
    <span class="hljs-keyword">let</span> (code, message) = <span class="hljs-keyword">if</span> err.<span class="hljs-title function_ invoke__">is_not_found</span>() {
        (StatusCode::NOT_FOUND, <span class="hljs-string">"Not Found"</span>.<span class="hljs-title function_ invoke__">to_string</span>())
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-variable">Some</span>(e) = err.find::&lt;BadRequest&gt;() {
        <span class="hljs-keyword">let</span> <span class="hljs-variable">err</span> = e.<span class="hljs-title function_ invoke__">to_owned</span>();
        (StatusCode::BAD_REQUEST, err.message)
    } <span class="hljs-keyword">else</span> {
        (StatusCode::INTERNAL_SERVER_ERROR, <span class="hljs-built_in">format!</span>(<span class="hljs-string">"{:?}"</span>, err))
    };

    <span class="hljs-keyword">let</span> <span class="hljs-variable">reply</span> = warp::reply::<span class="hljs-title function_ invoke__">json</span>(&amp;ErrorMessage {
        code: code.<span class="hljs-title function_ invoke__">as_u16</span>(),
        message,
    });

    <span class="hljs-title function_ invoke__">Ok</span>(warp::reply::<span class="hljs-title function_ invoke__">with_status</span>(reply, code))
}</code></pre><p>Lastly, this is a stubbed-out example of the actual handler for the endpoint. It's where you'd do some processing or make other function calls that handle the bulk of the logic, such as the onchain calls to the FVM for the "registration" process:</p><pre data-type="codeBlock" language="rust"><code><span class="hljs-comment">/// Handles the `/fund/&lt;address&gt;` request.</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">handle_fund</span>(
    address: <span class="hljs-type">String</span>,
    state: Arc&lt;Mutex&lt;State&gt;&gt;,
) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-type">Result</span>&lt;<span class="hljs-keyword">impl</span> <span class="hljs-title class_">warp</span>::Reply, warp::Rejection&gt; {
    <span class="hljs-comment">// Do stuff</span>

    <span class="hljs-keyword">let</span> <span class="hljs-variable">json</span> = json!({<span class="hljs-string">"tx"</span>: <span class="hljs-string">"stuff"</span>});
    <span class="hljs-title function_ invoke__">Ok</span>(warp::reply::<span class="hljs-title function_ invoke__">json</span>(&amp;json))
}</code></pre><div class="relative header-and-anchor"><h3 id="h-thinking-about-generative-ai-ux-design-patterns">Thinking about <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://uxplanet.org/generative-ai-ux-design-patterns-192bb169ab99">Generative AI UX Design Patterns</a></h3></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jkosem">Jim Kosem</a></p><p>There are lots of questions about how AI will impact “knowledge” work moving forward as we all huddle in front of our machines for terminal velocity to be achieved to see if things calm down. One thing is for sure though in the meanwhile, we should think about how to use this stuff. There are no shortage of screeds of enthusiasm and self flagellating doomsaying, but one thing you don’t see often are patterns.</p><p>Design patterns are quite simply codified recommendations of use. You should design or build software this way or that. The interesting thing here is establishing how AI fits in terms of scope. The current approach we’ve seen thus far is that you type something into a box and AI does everything. This article examines it from a different and more nuanced standpoint, one that the staid and solid enterprise types like Microsoft have already known, which is you need to be clever where you slot it in and how much. You need to think which nail the hammer is going to pound down, rather than demolish a bed of nails with a ton of concrete. The author also takes this slightly further in exploring the notions of this fit being alongside or separate, layered or integrated. Perhaps most interesting as paragraph upon paragraph is written or perhaps even generated about provenance of produced words, images and sounds is the notion of awareness and action.</p><p>All in all, it’s a good, middle of the road piece of thinking about AI in the tools that people like us at Textile are building.</p><hr><div class="relative header-and-anchor"><h1 id="h-read-and-watch">Read &amp; watch</h1></div><ul><li><p>Talk on how to deisgn protocols by Eddy Lazzarin (a16z crypto CTO) <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=WGfS6pPJ5jo">https://www.youtube.com/watch?v=WGfS6pPJ5jo</a></p></li><li><p>Native vs Foreign DA: Interesting discussion on trust assumptions on different types of DA <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://paragraph.xyz/@vinny/native-vs-non-native-da">https://paragraph.xyz/@vinny/native-vs-non-native-da</a></p></li><li><p>Backstory of Lasso and Jolt: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=Uy0Qap3fePI">https://www.youtube.com/watch?v=Uy0Qap3fePI</a></p></li><li><p>A promising EIP (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-7683">7683</a>) that would standardize an API for cross chain trade execution. Vatalik seems to think this is promising, which is a good sign for community support. Plus, it's being driven by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://uniswap.org/">Uniswap</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://across.to/">Across</a>—some more info <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linkedin.com/posts/uniswaporg_say-hello-to-erc-7683-in-collaboration-activity-7198329386746437632-6BlR">here</a>.</p></li></ul><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <category>decentralize</category>
            <category>data</category>
            <category>basin</category>
            <category>web3</category>
            <category>onchain</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/c73aa977e906a2bee54f3a8932f04078.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Unlocking the future of data: high-value solutions for onchain builders]]></title>
            <link>https://blog.textile.io/unlocking-the-future-of-data-high-value-solutions-for-onchain-builders</link>
            <guid>bY3mEQJ2IaLMvvRiZ5Pq</guid>
            <pubDate>Thu, 06 Jun 2024 17:29:59 GMT</pubDate>
            <description><![CDATA[Survey insights: Key findings from 32 developers and leaders in crypto projects on decentralized data solutions.Security & compliance: 36% priori...]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h3 id="h-tldr">TLDR</h3></div><ul><li><p><strong>Survey insights:</strong> Key findings from 32 developers and leaders in crypto projects on decentralized data solutions.</p></li><li><p><strong>Security &amp; compliance:</strong> 36% prioritize enhanced security; 27% highlight regulatory compliance as crucial.</p></li><li><p><strong>Adoption barriers:</strong> Transition costs (36%) and tool fragmentation (21%) hinder widespread adoption.</p></li><li><p><strong>Blockchain data protocols:</strong> Opportunities and challenges in AI, cloud infrastructure, and the data economy.</p></li><li><p><strong>A solution for object storage:</strong> Introducing Basin, a decentralized data storage solution on Filecoin, addressing high throughput, security, and cost efficiency.</p></li></ul><div class="relative header-and-anchor"><h3 id="h-introduction">Introduction</h3></div><p>There’s a powerful shift underway in the web3 space, one that's long overdue. Projects are now actively seeking decentralized solutions for data storage, processing, and delivery in ways we only dreamed of two years ago. With the rapid advancement of scalable blockchain protocols and the growth of sectors like compute, crypto-AI, and DePIN, understanding the decentralized data landscape has become crucial for developers and businesses alike.</p><p>To get a better handle on this shift—why it's happening and what could accelerate it—we conducted a comprehensive survey of 32 developers and leaders from crypto-based projects.</p><ul><li><p>80% of respondents were company leaders.</p></li><li><p>Half of the projects we surveyed raised over $1,000,000 in funding.</p></li><li><p>Most companies estimated the value of their data to be in the tens of thousands of dollars or more.</p></li></ul><div class="relative header-and-anchor"><h3 id="h-survey-insights-the-push-towards-decentralization"><strong>Survey Insights: The Push Towards Decentralization</strong></h3></div><p>We asked our research group questions about a wide range of topics related to their infrastructure decisions, technology aspirations, and the trade-offs they weigh when executing their own visions. Our findings revealed a clear inclination towards decentralized data architectures with lagging adoption. Here’s what we found:</p><ul><li><p><strong>Security and Compliance:</strong> 36% of respondents highlighted enhanced security as a primary driver for decentralized infrastructure. This move promises enhanced resilience and tamper-proof systems, which are critical in a landscape fraught with cybersecurity threats. Additionally, 27% cited regulatory compliance as a crucial factor, reflecting a growing emphasis on data sovereignty and user privacy.</p></li><li><p><strong>Barriers to Adoption:</strong> Despite the apparent benefits, two major barriers hinder widespread adoption:</p><ul><li><p><strong>Cost Concerns:</strong> Transition costs, from initial technology investments to ongoing development efforts, were cited by 36% of the projects as a deterrent. Practically speaking, it’s not simple to leave the centralized cloud and adopt a decentralized infrastructure.</p></li><li><p><strong>Tool Fragmentation:</strong> 21% of respondents pointed to the fragmentation of available tools, complicating decentralized solutions integration and operational efficiency.</p></li></ul></li></ul><p>These insights suggest a critical need for more integrated and cost-effective solutions to facilitate the transition from traditional cloud-based models to decentralized data architectures.</p><div class="relative header-and-anchor"><h3 id="h-blockchain-data-protocols-a-moment-of-opportunity"><strong>Blockchain Data Protocols: A Moment of Opportunity</strong></h3></div><p>Blockchain data protocols are at a pivotal juncture, with the potential to fundamentally reshape AI, cloud infrastructure, and the data economy. The growth of data availability networks and the development of decentralized physical infrastructure networks (DePINs) drive optimism about a more decentralized future. However, the transition is not without its challenges. The fragmented landscape of existing tools and the high costs associated with adopting the latest technologies are significant hurdles that need addressing.</p><p>Once a project has one foot in AWS, it's hard to justify not using the cloud for everything. The biggest competition for web3 data protocols are centralized cloud providers. And to beat the cloud, we still need to simplify the path to adoption. We also need to provide more comprehensive solutions to complex problems in systems that require data services.</p><p>In response to our survey, participants pinpointed the components of their data architecture they hope to transition to web3 alternatives:</p><ul><li><p>55% - Caching and retrieval (e.g., <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">CDN</a>)</p></li><li><p>52% - High throughput data storage (e.g., <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://aws.amazon.com/s3/">S3</a>)</p></li><li><p>30% - Streaming (e.g., <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://kafka.apache.org/">Kafka</a>)</p></li></ul><div class="relative header-and-anchor"><h3 id="h-basin-a-decentralized-data-storage-solution"><strong>Basin: A Decentralized Data Storage Solution</strong></h3></div><p>In response to these needs, we’re building <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/">Basin</a>, a decentralized data store designed to meet modern data systems' high-throughput and security demands. Built on the robust <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://filecoin.io/">Filecoin</a> network, Basin offers a scalable solution for developers needing reliable and accessible data storage options. Key features include:</p><ul><li><p><strong>Verifiable Data for Trust:</strong> Ensure data integrity with cryptographic security, making data tamper-proof and trustworthy.</p></li><li><p><strong>High Throughput and Availability:</strong> Basin's architecture is designed for high performance, ensuring data is accessible whenever needed, supported by cryptographic proofs.</p></li><li><p><strong>Cost Efficiency:</strong> With a competitive pricing model, Basin allows projects to scale their storage needs without incurring prohibitive costs.</p></li></ul><div class="relative header-and-anchor"><h3 id="h-join-the-movement-toward-decentralized-data-management"><strong>Join the Movement Toward Decentralized Data Management</strong></h3></div><p>The future of data in the web3 space is poised for transformative growth, driven by innovations like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/">Basin</a>. As we continue to tackle tool fragmentation and high adoption costs, your involvement and feedback are invaluable. Together, we can build a robust data infrastructure that meets today's needs but also anticipates tomorrow's challenges.</p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Andrew Hill)</author>
            <category>market research</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/b1193689fb7f9d84fbf838b517658c5f.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[An introduction to Basin: The first data L2 on Filecoin]]></title>
            <link>https://blog.textile.io/basin-launch-overview</link>
            <guid>F4J540iMcUPsvM8jp5Fu</guid>
            <pubDate>Wed, 05 Jun 2024 14:00:45 GMT</pubDate>
            <description><![CDATA[Discover the basics about how Basin works with Filecoin's IPC subnet scaling framework for fast and scalable decentralized object storage]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h2 id="h-background">Background</h2></div><p>Basin is a decentralized data layer, enabled by subnets that are purpose-built for onchain data storage. It is built on top of the Filecoin Virtual Machine (FVM) and provides a horizontally scalable, verifiable, and cost-effective data availability layer for onchain applications, networks (e.g., DePINs), and services. The first <em>data Layer 2 (L2)</em>. A handful of specialized "machines" for object storage and data anchoring power the Basin's featured data services.</p><blockquote><p>Basin is currently an alpha testnet, and the network is subject to fortnightly changes with rolling updates. Please be aware that the network may be reset at any time, and data may be deleted every two weeks. A more stable testnet will be released in the future that won't have this limitation.</p></blockquote><div class="relative header-and-anchor"><h3 id="h-architecture">Architecture</h3></div><p>Basin is developed using the Filecoin <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.ipc.space/">InterPlanetary Consensus (IPC) framework</a>. IPC is a blockchain scaling solution and architectural design that is an alternative to existing L2 scaling solutions and is based on the design principles of on-demand horizontal scaling.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5542ef9465a332f41062c01178db3a85.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAIAAAC1qksFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE6klEQVR4nH2Ve0xTZxjGmyxLlmwu2x8zZjp2UTcTzHSim0N00QlFFBW5OGUKdQVLtlasR8AJYguV0tIbxbZQDgep0HIUwdOCLRUVzTZTtokgbEo7lNZTyqVrC360k+YseBICxfjl+ed85/LL95z3fV4KAFM225Dd4bTZhgCYIhYsr8cHwFTA7x92uuxPnr5aXo8v5HVKX9+jzKO5S8NWZx7Ntdy9txCwceVayosV/sHafd/siY/aFfMlddu66PT470tOnpkrDiuvVl49HQzOAwAwheMum20Ix12jrtGAPxAC2Ls5dvm7H76/aHncprjk7fv2U5PjImPjImOz9tPPQQWkKopLpYXFHFYuLFaGAtxuD3rJUFlV14y12x4Nhnw94A+oROd3RCfvjEm5ZTRfQTG16uKD+/093X3KUhmHlcth5aE1mq827T54iNmggpUlslCAzTb0Q0bO2++E0ejQb3csBDHvdsAfqOBLstIyknbsO8WEKpUXyuU1brdnwDoo5ApnATQ6xIaKtJXISwBzL8ZHxia8PmFZWU/P/dkd0ZlzaXvSPlv6RcK25F9v39WiehjW2R3O4tO8fAY7n8HGGlDy4VcDZnbHR0YdDgeGtXV1/QEAmPD6xkfGlKWyAztTd2zaRf067rrp1uQzwCmSimXV4mJRYkxKUsx3mqoL08Hgf8+fzwUAMEXW5LwT+KcAqmt+7fWP2VARAJMTXt+E1yc/J8mmHdsaEZOZkmEymHse/H35st5o6izlCNatilrzaZRariYIYjoYJAEEQbjdHhx34bjL7fbMAxBE8K/+marF9Oab5puL3lzK/PGUpJAvLCjiQgWVApm2qhaRqUjJzvIVvLIZixqbJp+ByWfgMqJRlkgIgsBxF3kCu8P5EgCUU9xuvnOt1UShLIbYXNFpXg4ti3fiZ+YB2mLKG3uitnNYeTlHfordsGXZW+8lf7tbUXb+8wjq5q1J8hLp+jXRUE4xX6CkUJYZDB047poH8Hk8V5vbwj7ZmF8g/Nc9/tj6j/3JU+nZ0uNpjJN01qnM7MPxyXkMprSQx2PnZR+iZyQcOJaacQnRqpHGOk3TRSXMSs+2dN0fsA6KZdUGQ0eoReMjo/19/bdv/2K12sifPOH1wRXqw2nHd+6mYXpz9599MKyDYR2mN7forpxmQBmJRzqwVqOp02jqxOobQywKPcGkdxJtRKlUqkQiJQiCBGgRDTefy8xklhTymq8Y+QJlubymGWsXcMUrwtavWh6plqvbTDeumW7NrSIy36aDwZlGo9GhFSsjaHSou6un3WRasmQJgtSSXea0P62WKpjpx8I/2pAan2a5e69O00T2gYArymewC7JO1KuQet1Vo6kTkale0gezUYHpzaOusd+7usLDwxUKBQCANA2uULOzchKiUw4lHFEpNZwiaX6BEK5FFWXnSQDWgDZj7eglw4sqWgAgnXo8aMdx1/jIGABAq9UqFAqLxUKaVlNRzUxnRq7ewjiY1dZ6HW0y6NAWo6mzUlZJRkUH1qpF9VjbDay+Uc4RhgLIuN66LZGM64DfLxaLEQQZGBhwOBxO3KkSlCtLZSKOQCUov6iESSEVVZJCPpnSVUJ5a1NLa1OL7CxfLVqQpuTAIRUycEiXRl1jtkeDw47hYcew9aF1VrNDxvrQ2tvd29vda31oXThw/gfzedXhMHUgxQAAAABJRU5ErkJggg==" nextheight="1080" nextwidth="1920" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><div class="relative header-and-anchor"><h3 id="h-ipc-and-subnets">IPC &amp; subnets</h3></div><p>IPC allows for permissionless creation of new blockchain subsystems called <em>subnets</em>. Subnets are organized hierarchically, enabling seamless internal communication and eliminating the need for cross-chain bridges. Each subnet can employ its specific consensus algorithm and inherit security from parent subnets, and this structure facilitates hosting or sharding applications based on performance or cost needs.</p><p>Subnet operators must run a full validator node for both the parent and the child subnet. The parent subnet is responsible for the security of the child subnet, and the child subnet is responsible for its own consensus and state transitions.</p><blockquote><p>Basin is currently a single child subnet rooted in its parent Filecoin Calibration testnet. Future versions of the Basin will align more closely with IPC's permissionless subnet spawning and configurable consensus mechanisms.</p></blockquote><div class="relative header-and-anchor"><h3 id="h-cometbft-and-state-replication">CometBFT &amp; state replication</h3></div><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.cometbft.com/v0.38/">CometBFT</a> (formerly known as <em>Tendermint</em>) helps the Basin achieve state machine replication across all nodes in the network. Its consensus algorithm is based on a variant of Practical Byzantine Fault Tolerance (PBFT) and relies on a round-robin proposer selection mechanism while incorporating elements that improve PBFT's performance and communication overhead. It is a fast, battle-tested, and well-designed consensus engine.</p><p>CometBFT is a standalone process that issues commands to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/consensus-shipyard/ipc/tree/main/fendermint">Fendermint</a> and exposes a public JSON RPC API, much like the Ethereum JSON RPC API.</p><div class="relative header-and-anchor"><h3 id="h-abci-and-fendermint">ABCI &amp; Fendermint</h3></div><p>Basin's blockchain functionality is exposed as a unified ABCI++ application controlled by CometBFT.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.cometbft.com/v0.38/spec/abci/">Application Blockchain Interfaces (ABCI)</a> programs interface between CometBFT and the actual state machine being replicated. ABCIs implement deterministic state machines to be securely replicated by the CometBFT consensus engine. The "++" in ABCI++ refers to additional functionality that CometBFT enables compared to the original ABCI, which helps improve the overall scalability and feature surface area.</p><p>Fendermint is a specialized ABCI++ interface to the Filecoin Virtual Machines (FVM) and Ethereum-compatible FEVM. It exposes FEVM/FVM-specific functionality within subnets, allowing the Basin subnets to behave like Filecoin but with custom parameters to greatly improve throughput and features. Fendermint is also a standalone process that includes:</p><ul><li><p><strong>Interpreters:</strong> Responsible for handling commands from CometBFT.</p></li><li><p><strong>Snapshots:</strong> CAR files that can be offered to peers for quick chain sync.</p></li><li><p><strong>IPLD resolver:</strong> A libp2p-based service that is used to resolve CIDs from IPFS as well as the network of validator peers. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ipld.io/">IPLD</a> powers the network's ability to store and retrieve data in a content-addressable way.</p></li></ul><div class="relative header-and-anchor"><h3 id="h-consensus">Consensus</h3></div><p>Checkpoints that reference subnet state are pushed to the parent subnet in a bottom-up fashion, which is essential for the parent to validate the state transitions of the child. Basin passes checkpointed headers to its parent and uses the CometBFT ledger to gather relevant signatures and data. Additionally, the Basin can contact the IPLD resolver &amp; store to read and write data to its internal state so that it is IPLD addressable. There is also a <em>top-down</em> sync action; subnets must have a view of their parent's finality, which includes the latest block hash, power table information, and (in the future) cross-subnet message passing.</p><p>In general, data is represented as CIDs onchain (within a Basin machine's state), and the actual data is stored offchain in a node's local (networked) block store. Basin uses the concept of a <em>detached payload</em> asynchronous sync mechanism, which is a transaction that includes a CID reference to an object but does not include the object data itself. When a detached payload is added to the chain, validators are required to download the object data from the network and verify that it matches the CID reference. This ensures that all validators have a copy of the object data and can verify the integrity of the object store state.</p><p>The core IPC process for top-down parent finality is a vote-based mechanism. Once a validator has the data locally (via synchronization with its peers), the validator issues a <em>vote</em> to the other validators to confirm data availability (this is similar to Ethereum's concept of a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethereum.org/en/developers/docs/data-availability/#data-availability-committees">data availability committee</a>). During this time, normal block production continues. The leader of a given consensus round checks the vote tally for quorum based on the power table (stake) within the subnet. If a quorum is reached, the leader injects a synthetic transaction into the proposal, which is validated by the other validators based on their view of the vote tally, and then finally during the execution of this transaction, the object is marked as <code>resolved</code>.</p><div class="relative header-and-anchor"><h3 id="h-machines-smart-contracts">Machines (smart contracts)</h3></div><p>Basin's core functionality is enabled with a series of data machines, which are synonymous with smart contracts or "actors" that run on the FVM and are used to manage, query, and update the state of the subnet. The FVM is responsible for executing the logic of the Basin protocol, including processing transactions, updating account balances, and managing the state of the network. There are three primary machines in the Basin:</p><ul><li><p>Machine manager</p></li><li><p>Object store machines</p></li><li><p>Accumulator machines</p></li></ul><p>The FVM executes messages in WASM over machine state and uses the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/bytecodealliance/wasmtime">Wasmtime</a> runtime, and this includes a WASM implementation of the EVM bytecode interpreter. Under the hood, any "built-in" and "custom" (unique / subnet-specific) smart contracts are compiled to CAR files and provided to the subnet during genesis.</p><div class="relative header-and-anchor"><h3 id="h-machine-manager">Machine manager</h3></div><p>Users can deploy new machines on-demand using the machine manager. This interface is responsible for creating new object stores or accumulators and also managing the state of the network. Each machine is associated with a unique address, which is used to identify the machine on the network.</p><div class="relative header-and-anchor"><h3 id="h-object-store-machine">Object store machine</h3></div><p>These are key-value stores that allow you to push and retrieve data in a familiar S3-like fashion. Object stores support byte-range requests and advanced queries based on a key's prefix, delimiter, offset, and limit. The object store machine provides a set of methods for interacting with the store, including <code>put</code>, <code>get</code>, and <code>delete</code>, which allows users to store and retrieve data from the store.</p><p>Internally, the state of an object store is represented as an IPLD-based HAMT (hash array mapped trie). The IPLD data model provides a flexible and extensible way to represent complex data structures.</p><div class="relative header-and-anchor"><h3 id="h-accumulator-machine">Accumulator machine</h3></div><p>An accumulator is a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.grin.mw/wiki/chain-state/merkle-mountain-range/">Merkle Mountain Range (MMR)</a>-based verifiable anchoring system for state updates. You can push values up to 500KiB and retrieve them by index. Accumulators support querying for state root, MMR peaks, and total leaf count. As you push new data to the accumulator, you can retrieve the underlying data at a <code>leaf</code> or other relevant data structure components like <code>peaks</code> and total <code>count</code>. Similar to the object store machine, the accumulator stores a CID summary in its on-chain state.</p><div class="relative header-and-anchor"><h3 id="h-accounts">Accounts</h3></div><p>Accounts (ECDSA, secp256k1) are used to send data-carrying transactions as you would on any blockchain system. Since the Basin is built on top of Filecoin's FVM, the addresses follow a <em>slightly</em> different convention than a purely EVM-based account system. Here's a quick primer:</p><ul><li><p>Addresses are prefixed with a network identifier: <code>t</code> for Filecoin testnet, or <code>f</code> for Filecoin mainnet, and there are five different address types denoted by the second character in the address string: <code>t0</code>/<code>f0</code> to <code>t4</code>/<code>f4</code>.</p></li><li><p>If you're coming from the EVM world, you'll mostly see two types in the Basin:</p><ul><li><p><code>t2</code>/<code>f2</code>: Any FVM-native contract that gets deployed, such as the object store and accumulator machines.</p></li><li><p><code>t4</code>/<code>f4</code>: A namespaced contract address, and <code>t410</code>/<code>f410</code> is a specialized namespace for Ethereum-compatible addresses (wallets <em>and</em> smart contracts) on the FVM.</p></li></ul></li><li><p>Namely, each <code>t410...</code>/<code>f410...</code> address is equivalent to a <code>0x</code> address; the hex address is <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.filecoin.io/smart-contracts/filecoin-evm-runtime/address-types#converting-to-a-0x-style-address">encoded in the FVM address string</a>.</p></li></ul><p>Once your EVM-style account is registered on a subnet, the <code>0x</code> and its corresponding <code>t410...</code>/<code>f410...</code> addresses can be used interchangeably on Filecoin and all Basin subnets.</p><div class="relative header-and-anchor"><h3 id="h-access-control">Access control</h3></div><p>Currently, there are two types of write-access controls: only-owner or public access. For example, you can create an object store that you, and <em>only</em> you can write to—gated by signatures from your private key. Or, you can have "allow all" access where anyone can write data.</p><p>This is being further refined, and there will be more robust access control mechanisms soon.</p><div class="relative header-and-anchor"><h3 id="h-broadcast-modes">Broadcast modes</h3></div><p>For context, there are three ways in which transactions can be sent/broadcasted to the network: <code>commit</code>, <code>sync</code>, and <code>async</code>. Here's a quick overview of each:</p><ul><li><p><code>commit</code>: Wait until the transaction is delivered and final (default behavior).</p></li><li><p><code>sync</code>: Wait only for the result of a local transaction pre-check, but don’t wait for it to be delivered to all validators (i.e., added risk the transaction may fail during delivery).</p></li><li><p><code>async</code>: Does not wait at all. You will not see errors in your terminal (i.e., added risk the transaction may fail during delivery).</p></li></ul><div class="relative header-and-anchor"><h3 id="h-limits">Limits</h3></div><p>There are a few limitations and behaviors of which to be aware when using the Basin network:</p><ul><li><p>The maximum size for a single object is 1 GiB.</p></li><li><p>Objects less than or equal to 1024 bytes are "on-chain" objects stored fully onchain.</p></li><li><p>Objects greater than 1024 bytes are "detached" objects that get stored offchain and resolved as a CID.</p></li><li><p>The current throughput of the Basin is hundreds of transactions per second (TPS) (note: this is a rough estimate and may vary based on network conditions. The node design is still under heavy development, and optimizations are being made).</p></li></ul><div class="relative header-and-anchor"><h2 id="h-start-building-today">Start building today!</h2></div><p>Basin comes with both a CLI and Rust SDK that exposes the core network interfaces. You can find detailed instructions for each of these in their respective subdirectories:</p><ul><li><p>CLI: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/textileio/basin/tree/main/cli">here</a></p></li><li><p>SDK: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/textileio/basin/tree/main/sdk">here</a></p></li></ul><p>Since the Basin is built on top of Filecoin, you must have FIL in your account to interact with the network. Basin is currently only live on the Filecoin Calibration network, so you can get tFIL via the faucet <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://faucet.calibnet.chainsafe-fil.io/funds.html">here</a>. For reference, Filecoin chain information can be found <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://chainlist.org/?search=filecoin&amp;testnets=true">here</a>.</p><p>For example, you can use the CLI with your Ethereum-style account (and note the <code>adm</code> usage below is simply an internal codename for Basin):</p><pre data-type="codeBlock" language="shell"><code><span class="hljs-meta prompt_">&gt; </span><span class="bash"><span class="hljs-built_in">export</span> PRIVATE_KEY=abcd1234... <span class="hljs-comment"># your wallet private key</span></span>
<span class="hljs-meta prompt_">&gt; </span><span class="bash">adm account deposit 0.1</span>
<span class="hljs-meta prompt_">&gt; </span><span class="bash">adm objectstore create <span class="hljs-comment"># create an object store</span></span>
<span class="hljs-meta prompt_">&gt; </span><span class="bash"><span class="hljs-built_in">export</span> CONTRACT_ADDRESS=t2abc123... <span class="hljs-comment"># object store contract address via above</span></span>
<span class="hljs-meta prompt_">&gt; </span><span class="bash">adm objectstore add \
--address <span class="hljs-variable">$CONTRACT_ADDRESS</span> \
--key <span class="hljs-string">"my/object"</span> \
./hello.json</span>
<span class="hljs-meta prompt_"># </span><span class="bash">{</span>
<span class="hljs-meta prompt_"># </span><span class="bash">  <span class="hljs-string">"status"</span>: <span class="hljs-string">"committed"</span>,</span>
<span class="hljs-meta prompt_"># </span><span class="bash">  <span class="hljs-string">"hash"</span>: <span class="hljs-string">"48BD1767DC5739C1EABB25FBC8E6718E3E8DE95FB7EE74D13895F2E9D9F5E00A"</span>,</span>
<span class="hljs-meta prompt_"># </span><span class="bash">  <span class="hljs-string">"height"</span>: <span class="hljs-string">"358569"</span>,</span>
<span class="hljs-meta prompt_"># </span><span class="bash">  <span class="hljs-string">"gas_used"</span>: 4784697,</span>
<span class="hljs-meta prompt_"># </span><span class="bash">  <span class="hljs-string">"data"</span>: <span class="hljs-string">"bafy2bzacebnjpu5e3ushfu2weqvmtvk7vnndg4fkqsbr4zub52cyekcix7l4o"</span></span>
<span class="hljs-meta prompt_"># </span><span class="bash">}</span>
<span class="hljs-meta prompt_">
&gt; </span><span class="bash">adm objectstore get \
--address <span class="hljs-variable">$CONTRACT_ADDRESS</span> \
<span class="hljs-string">"my/object"</span> \
<span class="hljs-comment"># {"hello":"world"}</span></span></code></pre><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <category>filecoin</category>
            <category>object storage</category>
            <category>s3</category>
            <category>ipc</category>
            <category>subnet</category>
            <category>data availability</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/9111188cbefc544731c27b5933c96e1c.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Base Sepolia support, new query placeholders, Rust-isms, & AI learnings]]></title>
            <link>https://blog.textile.io/weeknotes-base-sepolia</link>
            <guid>chbbcxmkbmBRNcbg0u5o</guid>
            <pubDate>Mon, 03 Jun 2024 18:50:01 GMT</pubDate>
            <description><![CDATA[New Tableland query placeholders features & Base chain support, Rust Options with references plus wasm, and AI Lilypad spotlight/learnings]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-tableland-support-for-placeholders-and-query-params-for-query-endpoint">Tableland support for placeholders and query params for <code>/query</code> endpoint</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/brunocalza">Bruno Calza</a></p><p>A <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/go-tableland/releases/tag/v1.11.0">new version</a> of Tableland was released with support for placeholders and query params for <code>/query</code> endpoint (both <code>GET</code> and <code>POST</code>).</p><p>Here are some examples:</p><ul><li><p><code>GET /query</code></p></li></ul><pre data-type="codeBlock"><code>https:<span class="hljs-regexp">//</span>tableland.network/api/v1/query?statement=<span class="hljs-keyword">select</span> * from _137_266 where ksuid = ? <span class="hljs-keyword">and</span> year = ?&amp;params=<span class="hljs-string">'26G4V9VLoG9wVTeBE1M4UhJzOPi'</span>&amp;params=<span class="hljs-number">2011</span>
<span class="hljs-comment"># url-encoded version</span>
https:<span class="hljs-regexp">//</span>tableland.network/api/v1/query?statement=<span class="hljs-keyword">select</span>%20*%20from%20_137_266%20where%20ksuid%20=%20?%20and%20year%20=%20?&amp;params=%2726G4V9VLoG9wVTeBE1M4UhJzOPi%27&amp;params=<span class="hljs-number">2011</span></code></pre><ul><li><p><code>POST /query</code>:</p></li></ul><pre data-type="codeBlock"><code>curl -s -X POST <span class="hljs-string">"https://tableland.network/api/v1/query"</span> \
--data <span class="hljs-comment">'{</span>
  <span class="hljs-string">"statement"</span>: <span class="hljs-string">"select * from _137_266 where ksuid = ? and year = ?"</span>,
  <span class="hljs-string">"params"</span>: [<span class="hljs-string">"26G4V9VLoG9wVTeBE1M4UhJzOPi"</span>,<span class="hljs-number">2011</span>]
}<span class="hljs-comment">'</span></code></pre><p>With that change, it becomes a lot easier to programmatically build your query requests and send it to the Tableland Gateway. You don't need to worry about query building!</p><div class="relative header-and-anchor"><h2 id="h-tableland-base-sepolia-chain-support">Tableland Base Sepolia chain support</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>Tableland is adding Base Sepolia chain support! We've already updated the validator and the <code>@tableland/evm</code> repo, so you can build on Base today with smart contacts. The downstream clients (JS SDK and Studio) will be incorporating Base support later this week.</p><p>Note this is only for the Base <em>testnet</em>, so mainnet is not something available, yet. Mainnet will be added based on developer demand…so let us know if it's something you're looking for on Tableland!</p><div class="relative header-and-anchor"><h2 id="h-optionlessandtgreater-vs-andoptionlesstgreater-in-rust">Option&lt;&amp;T&gt; vs. &amp;Option&lt;T&gt; in Rust</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://github.com/avichalp">Avichal Pandey</a></p><p>How do you decide whether to use <code>Option&lt;&amp;T&gt;</code> or <code>&amp;Option&lt;T&gt;</code> as function arguments or returns types in Rust? For instance, should you choose the first or second version in the code shown below for public functions?</p><pre data-type="codeBlock" language="rust"><code><span class="hljs-keyword">pub</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">data_a</span>(&amp;<span class="hljs-keyword">self</span>) <span class="hljs-punctuation">-&gt;</span> &amp;<span class="hljs-type">Option</span>&lt;Data&gt; {
	&amp;<span class="hljs-keyword">self</span>.<span class="hljs-number">0</span>
}

<span class="hljs-keyword">pub</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">data_b</span>(&amp;<span class="hljs-keyword">self</span>) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-type">Option</span>&lt;&amp;Data&gt; {
	<span class="hljs-keyword">self</span>.<span class="hljs-number">0</span>.<span class="hljs-title function_ invoke__">as_ref</span>()
}</code></pre><p>The choice of one over the others will impact the code base's overall performance, flexibility, and maintainability.</p><p>Here is a great explanation <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://youtu.be/6c7pZYP_iIE">https://youtu.be/6c7pZYP_iIE</a></p><div class="relative header-and-anchor"><h2 id="h-experimenting-with-rust-and-wasm-compilation">Experimenting with Rust &amp; wasm compilation</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We're working on getting the Basin SDK to compile to wasm, which makes it easier to build downstream JavaScript or Python clients that are constantly in sync with the base Rust crate. The most common approach is <code>wasm-bindgen</code> plus <code>wasm-pack</code>. With <code>wasm-bindgen</code>, you add macros to the parts of your library that you want to be able to compile to wasm:</p><pre data-type="codeBlock" language="rust"><code><span class="hljs-keyword">use</span> wasm_bindgen::prelude::*; 

<span class="hljs-meta">#[wasm_bindgen]</span>
<span class="hljs-keyword">pub</span> <span class="hljs-keyword">struct</span> <span class="hljs-title class_">Data</span> {
	inner: <span class="hljs-type">u8</span>,
}</code></pre><p>And then you build it by specifying your crate and the target architecture:</p><pre data-type="codeBlock"><code>wasm<span class="hljs-operator">-</span>pack build <span class="hljs-operator">-</span><span class="hljs-operator">-</span>target web my_crate</code></pre><p>You also might have directives that use different features for architecture-specific dependencies:</p><pre data-type="codeBlock"><code><span class="hljs-section">[target.'cfg(target_arch = "wasm32")'.dependencies]</span>
<span class="hljs-attr">my_dependency</span> = <span class="hljs-string">"0.0.1"</span></code></pre><p>The Rust cookbook has a ton of information on how to set this all up, too: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rustwasm.github.io/docs/book/reference/add-wasm-support-to-crate.html">here</a>. For example, if a library is doing any I/O, you'll have to set up additional wasm support with <code>js-sys</code> or <code>web-sys</code>, which let you implement features that NodeJS or a web browser supports for file access. If there are any async operations, the <code>wasm-bindgen-futures</code> crate is also required for converting JS <code>Promise</code>s to Rust <code>Future</code>s.</p><div class="relative header-and-anchor"><h2 id="h-ai-spotlight-lilypad">AI Spotlight: Lilypad</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/marlanat27">Marla Natoli</a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://lilypad.tech/">Lilypad</a> is creating a distributed compute network that focuses on enabling AI use cases such as AI and ML. They enable the contribution of idle compute power from your own hardware via their established and verifiable processes powered by smart contracts. Their focus is on high-throughput data processing to power models that require high-performance computing. Lilypad’s decentralized compute network can significantly reduce the cost and time associated with generating large datasets.</p><p>With the proliferation of AI services and infrastructure, there are a few key recurring themes we’re hearing about from teams working in AI - the need for compute power, the importance of internet-scale processing, and the value of verifiable data pipelines. At Basin, we’re looking to support a decentralized, high-throughput compute workflow with our decentralized object storage solution running on horizontally scaleable subnets (powered by IPC). This makes key data available quickly, enabling compute over that data from various stakeholders and facilitating collaboration over datasets, which is becoming more and more important to facilitate AI training.</p><p>If you’re working in AI and interested in decentralizing database infrastructure to bring collaboration and verifiability to your data, we’d love to hear from you. R<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/">ead more about Basin here</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/partnerwithus">apply for our private beta here.</a></p><div class="relative header-and-anchor"><h2 id="h-what-we-still-have-up-on-the-machines">What we still have up on the machines</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jkosem">Jim Kosem</a></p><p>In <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.strangeloopcanon.com/p/what-can-llms-never-do"><em>What can LLMs never do?</em></a>, Rohit Krishnan exposes some fascinating gaps in the AI takeover of everything.</p><p>There is no shortage of polar-swinging discussions around LLMs and “AI” in general. It is either going to save humanity and single-handedly make a better cocktail than any human ever could, say the cheerleaders, who often have a monetary stake in this “force” (because what else is it really at this point, nebulous...). On the other side of the debate globe are the fearful and huddled masses seeing nothing but doom and gloom.</p><p>This is a large camp that is quite easy to join because humans are easy to frighten, and when there is lots of money to be made, it’s easy to get screwed. There is hope for the masses that there are things the LLMs just can’t figure out which most three to four-year-old humans can, such as statements of equality (this is that and that is this) and interestingly, things involving words and grids. Who would have knew. The LLMs sure didn’t.</p><hr><div class="relative header-and-anchor"><h1 id="h-other-updates-this-week">Other updates t<strong>his week</strong></h1></div><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ethcc.io/">ETHcc</a> is about a month away! We’ll have a couple of folks in attendance, so keep an eye out for further announcements and when/where we’ll be. And if there are any events you’d like to collaborate on, let us know on Discord!</p></li></ul><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/68dfeb37bda649131e0800e836578e5d.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Basin launch, IoTeX + Risc0 + WeatherXM POC, & upcoming hackathons]]></title>
            <link>https://blog.textile.io/weeknotes-basin-launch-poc</link>
            <guid>bzj716P9UdMnH4XPVpuB</guid>
            <pubDate>Wed, 29 May 2024 17:03:01 GMT</pubDate>
            <description><![CDATA[Basin launch as a Filecoin L2, a review of a Basin POC for verifiable rewards, and updates on new hackathons coming up.]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-basin-launch">Basin launch</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>ICYMI—we officially announced the newest iteration of Basin. Our initial MVP was centered around pushing arbitrary data to "vaults" with writer access controls, a hot layer for immediate access, and archival to Filecoin. The new Basin takes learnings from this and simplifies it to <em>a Filecoin data L2 with object storage</em>. There's a lot more to it, and we've written a detailed blog about it and have a new landing page with more information.</p><p>If onchain object storage (think: S3, but decentralized) is something you're interested in, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/partnerwithus">fill out the form on the site</a> or hop into our Discord!</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>Check out the blog <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.textile.io/introducing-basin">here</a> and our new website: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/">https://basin.textile.io</a></p></div></div></div></div><div class="relative header-and-anchor"><h2 id="h-basin-poc-with-iotex-weatherxm-risc0-and-filecoin">Basin POC with IoTeX, WeatherXM, Risc0, &amp; Filecoin</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We wrapped up a proof of concept with IoTeX, WeatherXM, Risc0, &amp; Filecoin to show how a decentralized system can enable transparent contributor token reward calculations. The main premise is that it's a permissionless workflow where no central entity is managing the rewards distribution, rather, it could be automated with networks performing each step.</p><p>As WeatherXM pushes data to Basin, IoTeX's W3bstream runs Quality of Data (QoD) calculations over it and leverages Risc0 zk proofs for data validity. Lastly, as new QoD scores are calculated they are <em>also</em> written to Basin and later archived to Filecoin for long-term data availability and dispute resolution.</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>You can read the detailed blog post: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.textile.io/wxm-w3bstream-risc0-poc">here</a></p></div></div></div></div><div class="relative header-and-anchor"><h2 id="h-backdrop-hackathon-v5">Backdrop hackathon v5</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We've been supporting the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://backdrop.so/">Backdrop</a> program for their v3 and v4 cohorts, and we'll also support the next few cohorts, too. Backdrop is a mini-accelerator / hackathon that supports hackers in a 4-week buildout and helps connect them with potential grants and funding across web3, AI, OSS, and more.</p><p>The v5 cohort kicks off in July. Now, that the Basin alpha is live, we'll support Backdrop through additional bounties that focus on Basin usage in addition to Tableland. There will <em>probably</em> be a couple of new Basin features by then that'll make it even easier to switch over to Basin from "traditional" object storage providers, so keep an eye out for that.</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>If you're interested in applying, head over to the Backdrop website: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://backdropbuild.com">https://backdropbuild.com</a></p></div></div></div></div><hr><div class="relative header-and-anchor"><h1 id="h-further-reading">Further reading</h1></div><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.ben-evans.com/benedictevans/2024/4/19/looking-for-ai-use-cases">In <em>Looking for AI use-cases</em></a>, Ben Evans questions the wide base use cases for LLMs. He sweeps wide, wondering what is there for everyone, when will this supposed generalized application happen, and how.</p></li><li><p>For the encryption folks, there are a few interesting resources on different approaches in a web3 native setting. We might also write a deep dive blog post on these and related themes in the coming weeks.</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.threshold.network/applications/threshold-access-control">Threshold proxy re-encryption</a> is a novel encryption mechanism that distributes re-encryption keys across a network, and once a threshold is met, it can give decryption access to a criteria-fulfilling party.</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.jeremykun.com/2024/05/04/fhe-overview/">Fully homomorphic encryption</a> lets an entity compute over encrypted data without <em>ever</em> decrypting it. It lets you make arbitrary computations and extends the feature set of previous iterations—but a simple example would be to “add 1 to this encrypted data,” and after performing the calculation, only the original encryptor can see the result.</p></li></ul></li></ul><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <category>basin</category>
            <category>object storage</category>
            <category>s3</category>
            <category>iotex</category>
            <category>weatherxm</category>
            <category>risc0</category>
            <category>filecoin</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/d29d50260e5b3ad78ef5a7a832d88097.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Bringing transparency to DePIN token incentives]]></title>
            <link>https://blog.textile.io/wxm-w3bstream-risc0-poc</link>
            <guid>M2NeZeX2C4poD6RfnlVc</guid>
            <pubDate>Tue, 28 May 2024 17:56:01 GMT</pubDate>
            <description><![CDATA[A Proof of Concept with IoTeX's W3bstream and WeatherXM for enabling transparent contributor token reward calculations]]></description>
            <content:encoded><![CDATA[<p>WeatherXM, Textile, and IoTeX have teamed up to create a joint proof of concept (PoC) that showcases a workflow for enabling transparent contributor token reward calculations built on decentralized infrastructure. At the heart of decentralization is the promise of mechanisms that ensure value creators are fairly rewarded for their contributions.</p><p>In the Decentralized Physical Infrastructure Networks (”<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://iotex.io/blog/what-are-decentralized-physical-infrastructure-networks-depin/">DePIN</a>”) space, early contributors often invest in hardware and take the time to capture and contribute data to an ecosystem in exchange for token rewards. However, most DePINs are still calculating and distributing token incentive payouts in a centralized, opaque manner, making it difficult for contributors or investors to know if they’re receiving the correct amount of tokens for their contribution. With this PoC, we’ve demonstrated what a more transparent, decentralized, and trustless future could look like for DePINs and their token incentive payouts to their contributors.</p><div class="relative header-and-anchor"><h2 id="h-background">Background</h2></div><p>WeatherXM has been designing its protocol and ecosystem to lead from a place of transparency, sharing the many intricacies that makeup quality of data (QoD) scores for reward payouts and continually experimenting with decentralized back-end infrastructure to open up access to and collaboration over their data. Their input and feedback have been invaluable to us as we design <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/">Basin</a>, a Data Availability (”DA”) and Long-Term Storage (”LTS”) layer, to unlock new data use cases for DePINs. Namely, data is immediately available with the Basin hot cache layer while being replicated to Filecoin for long-term persistence. We’ve also been working closely with the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://iotex.io/">IoTeX</a> team on their new compute protocol W3bstream, which, in turn, supports <a target="_blank" rel="noopener noreferrer" class="dont-break-out discussion-level-1 discussion-id-1a006d2e-46f7-4fe5-a856-2b403345bb47 notion-link-token notion-focusable-token notion-enable-hover" href="https://www.risczero.com/">Risc0</a>’s newly released <a target="_blank" rel="noopener noreferrer" class="dont-break-out discussion-level-1 discussion-id-1a006d2e-46f7-4fe5-a856-2b403345bb47 notion-link-token notion-focusable-token notion-enable-hover" href="https://www.risczero.com/zkvm">zkVM</a>. Ultimately, a DA/LTS layer should be modular and part of a DePIN’s middleware stack, so we all collaborated on a proof-of-concept that leveraged all three protocols.</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>If you want to dive straight into the POC, check out the source code here: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/machinefi/WeatherXM-IoTeX-Textile-POC">https://github.com/machinefi/WeatherXM-IoTeX-Textile-POC</a></p></div></div></div></div><p>To provide a bit more context, here’s a quick overview of what each protocol does:</p><ul><li><p><strong>W3bstream</strong>: compute protocol built for DePINs that allows for off-chain, verifiable computing on data (with zero knowledge proofs) and can trigger smart contracts on any blockchain, facilitating the creation of circular token economies.</p></li><li><p><strong>Risc0</strong>: a zero-knowledge verifiable general computing platform based on&nbsp;<a target="_blank" rel="noopener noreferrer" class="dont-break-out discussion-level-1 discussion-id-87f19282-3719-4c21-a7bc-94bc037b4d3e notion-link-token notion-focusable-token notion-enable-hover" href="https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof">zk-STARKs</a>&nbsp;and the&nbsp;<a target="_blank" rel="noopener noreferrer" class="dont-break-out discussion-level-1 discussion-id-87f19282-3719-4c21-a7bc-94bc037b4d3e notion-link-token notion-focusable-token notion-enable-hover" href="https://en.wikipedia.org/wiki/RISC-V">RISC-V</a>&nbsp;microarchitecture.</p></li><li><p><strong>WeatherXM</strong>: DePIN network that's powered by community-owned weather stations (devices), purpose-built by WeatherXM for weather data collection and incentivized to share data.</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/"><strong>Basin</strong></a>: a DA/LTS storage layer that provides hot/cold decentralized storage for large datasets with hot cache + Filecoin…sorta like a “data L2.”</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/df55a458ca3fd775bc0380d852dd625f.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAPCAIAAAAK4lpAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEoUlEQVR4nD1UW4gbVRg+IPjgqy/iBaqFFhX0pSKo+FSVLfVNis8F+1IEi7SFenlTrCi0uopPioiKxe2uzZLFTUm33exummSzyexMMpvMpZnMTObMZC6dk7n0zGR+maT4Pfych5/znfN93/8jVVU5juv1erIsJ0kCAJZl1et1VVVhBt/3RVGc9/A8L0mS7/sAIAhCobCqqkNRFCRJCoKAEOK6bhzH8wOlFAAQz/Orq6u1Wm19fT0MQ0rp1tZWuVxmWTYMwyRJwjBkGIZl2cFgwDDM7u4uxhgAGIZZXPyuVmuWy5VSqeQ4juu61WqVZdlKpdJut8MwzAls2xZFUVEUWZbTNIUs63BcvdkShH4cRZ7nzV8tSZIgCIPBgGXZg4MDy7IAgNLUGu8o6ornWWk6pfQBz/ONRoPjuE6nQwjJCQAgy7I0TbMsA4Cx7aCX3kOPvvrm+xcBgJCJZVmO4xiGoeu6M4NhGJTSLJsCgDb6uSeez7IAABzHxhi7ruv7vmmajuPkBEmS9Ltdfn/fsW0A2G11ETqGnllATx23TFOWZZ9MHC/0PI8QMhdN13VN0w4ORJYtbVW//e2Pb27cuD43LEkSZTgMw0jV9fszq1AQBK16ndnbE/p933NLt7bQY68h9Ao6+q4oCLJyT90brH3yp2mNRVHUdV2WZc/zut3ueOxhs17e+OHKlZ+KxeLcecdxC8V1UZJ32Tbb6aRJgtI0VRWFa7dNwyDEL2/uIPQCQk+i5060Wnt9oTeSPX1vN6ETQibuDL7vG4aRZRmliW07pmlSSj3Ps207iiLf9+f5EQQBY4wope1Go9VoRGEUBqSwdgsdOn7qzCV09GQcU3s8Nu2x6fqapmPDmCtrmibGuFRa1zSdYbharZYkSRRFnU4HYzzChoFxtd5UNX2WovG4vrPTrNVMwwiDyfXCOnr+5NeLv6AjJx5QGkURTadpOh1h7PlEECWaTjMAz/MwNjWN73YrGxu3Nzc3m82mZVm+77M9fqipW9XaPUXJCdI07R8ciDxPCLHHVmHtJkIvo0eOoUPvJJSGUTQzL1OlfhBM3LE5NzMIJgAwMu4sLX949uxHi4uLmqYFQWCaJgmCedznnSiO4/29vc7+fhzHYTBZKtxEh9/69fe/0JGFOKZBGP7bu3+tNbp2V1xh8DJnL3XJjkKiMJjm4U40dchxnOu6hBBFUdptZqVQ1PVRX5aGupYTOONxbXu7Va+bhjEh/j/Fm+jx1984dQ4dXgBItgWMLvTRpwL6TECXBHSxj8710OeiMsqHGQBkWa5UKrmSlGqahjFWVY3SxDCxOcv9wzm4Jwj+fX+aJhtbNYReROhpdGgBYFpsK+gLCX2voK9k9KOCrg7y+qW0LxszoQJZEiVJsixrMBiYZi6gOtIppY7jRjN580lOZsiFAxBkbRbTJ9CzbwNkTcnIH36hj8730ce9vM4+JA5HAKAbd/9ePnP69AeXL19WFCVN0yRJqu2mqmlrpXKb4R4SzDFfFVmWbTfYpbVKk+0DwIT4t/nRCufc4OwVzl5mrRXOvsNrNI5nu8g3jHz9CYLw/z0AMM0yfTSa76L/APpwonEC/YrkAAAAAElFTkSuQmCC" nextheight="710" nextwidth="1482" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><div class="relative header-and-anchor"><h2 id="h-how-does-it-work"><strong>How does it work?</strong></h2></div><p>WeatherXM pushes station/device data to Basin on a daily basis. Separately, the network runs a <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://github.com/weatherxm-network/qod">Quality of Data (”QoD”)</a> algorithm that gets incorporated into the <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://docs.weatherxm.com/reward-mechanism">token rewarding mechanism</a>. The IoTeX team built on top of the WeatherXM dataset stored on Basin, while also demonstrating how the QoD pipeline could work within a decentralized compute network. Namely, W3sbtream could run the QoD algorithm daily over the WeatherXM data and then also store those results in Basin, along with zk proofs.</p><p>You can think of this process in three steps:</p><ul><li><p><strong>Ingest</strong>: WeatherXM pushes data to a Textile Basin on a daily basis as a Parquet file.</p></li><li><p><strong>Compute</strong>: The daily QoD score per station is calculated for the entire network, with a zk proof by W3bstream.</p></li><li><p><strong>Visualizations:</strong>&nbsp;Access to the data &amp; reward proofs is provided through a simple dashboard (<a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://index.weatherxm.network/">here</a>).</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/eb0461c5e5dfd71bd52cb553c7285d03.png" class="image-node embed"><figcaption htmlattributes="[object Object]" class="">Data flows from WeatherXM to Basin to W3bstream …and back to Basin for storing W3bstream data, too.</figcaption></figure><div class="relative header-and-anchor"><h2 id="h-how-is-it-built">How is it built?</h2></div><p>In the POC, the first step in the process is already accounted for without additional effort because WeatherXM is already sending station data to Basin. The second step requires W3bstream to pull data from Basin and run QoD calculations. Luckily, the QoD algorithm is open source and comes ready to go with a Docker setup: <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://github.com/weatherxm-network/qod">here</a>. You can generate the QoD scores with that repo using the following commands, which include the station/device ID and time ranges to generate the QoD scores:</p><pre data-type="codeBlock" language="shell"><code><span class="hljs-meta prompt_">&gt; </span><span class="bash">docker build -t wxm-qod:<span class="hljs-built_in">local</span> .</span>
<span class="hljs-meta prompt_">&gt; </span><span class="bash">docker run \
  -v /datasets:/datasets \
  wxm-qod:<span class="hljs-built_in">local</span> obc_sqc.iface.file_model_inference \
  --device_id &lt;device_id&gt; \ <span class="hljs-comment"># unique WeatherXM device ID</span></span>
  --date &lt;date&gt; \ # the QoD score for that day
  --day1 &lt;yesterday&gt; \ # the data at the start time
  --day2 &lt;today&gt; \ # the data at the end time
  --output_file_path results.json</code></pre><p>For example, W3bstream nodes could run this QoD algorithm daily to generate the dataset on-machine. The next step is the verifiability component; you must prepare the prover code&nbsp;to compute the average QoD scores with the W3bstream zk engine. A reference example is located in <code>methods.rs</code> (<a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://github.com/machinefi/WeatherXM-IoTeX-Textile-POC/blob/main/dataset/methods.rs">here</a>) that defines how to generate a risc0 proof. The actual implementation looks like this, which <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://crates.io/crates/risc0-zkvm">risc0-zkvm</a> and those <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://github.com/machinefi/WeatherXM-IoTeX-Textile-POC/blob/main/dataset/methods.rs">custom methods</a> that define a <code>ZK_ELF</code>, <code>ZK_ID</code>, and <code>ZK_PATH</code>:</p><pre data-type="codeBlock" language="rust"><code><span class="hljs-keyword">use</span> zk_methods::ZK_ELF;
<span class="hljs-keyword">use</span> risc0_zkvm::{
    default_prover,
    serde::{from_slice, to_vec},
    ExecutorEnv, Receipt,
};

<span class="hljs-comment">// Compare them inside the ZKP</span>
<span class="hljs-keyword">pub</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">avg</span>(a: <span class="hljs-type">String</span>) <span class="hljs-punctuation">-&gt;</span> (Receipt, <span class="hljs-type">String</span>) {
    <span class="hljs-keyword">let</span> <span class="hljs-variable">env</span> = ExecutorEnv::<span class="hljs-title function_ invoke__">builder</span>()
        .<span class="hljs-title function_ invoke__">write_slice</span>(&amp;<span class="hljs-title function_ invoke__">to_vec</span>(&amp;a).<span class="hljs-title function_ invoke__">unwrap</span>())
        .<span class="hljs-title function_ invoke__">build</span>()
        .<span class="hljs-title function_ invoke__">unwrap</span>();

    <span class="hljs-comment">// Obtain the default prover.</span>
    <span class="hljs-keyword">let</span> <span class="hljs-variable">prover</span> = <span class="hljs-title function_ invoke__">default_prover</span>();

    <span class="hljs-comment">// Produce a receipt by proving the specified ELF binary.</span>
    <span class="hljs-keyword">let</span> <span class="hljs-variable">receipt</span> = prover.<span class="hljs-title function_ invoke__">prove</span>(env, ZK_ELF).<span class="hljs-title function_ invoke__">unwrap</span>();
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"{:?}"</span>, receipt);

    <span class="hljs-comment">// Extract journal of receipt (i.e. output c, where c = a + b)</span>
    <span class="hljs-keyword">let</span> <span class="hljs-variable">c</span>: <span class="hljs-type">String</span> = <span class="hljs-title function_ invoke__">from_slice</span>(&amp;receipt.journal.bytes).<span class="hljs-title function_ invoke__">expect</span>(
        <span class="hljs-string">"Journal output should deserialize into the same types (&amp; order)"</span>,
    );
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"{}"</span>, c);

    (receipt, c)
}</code></pre><p>Then, generating the actual proof uses the <code>avg</code> function above (for averaging QoD scores):</p><pre data-type="codeBlock" language="rust"><code><span class="hljs-keyword">use</span> zk::avg;
<span class="hljs-keyword">use</span> zk_methods::ZK_ID;

<span class="hljs-keyword">fn</span> <span class="hljs-title function_">main</span>() {
	<span class="hljs-comment">// An example of a single WeatherXm device ID, its QoD, </span>
    <span class="hljs-comment">// and the proof type as a stored variable / string</span>
    <span class="hljs-keyword">let</span> <span class="hljs-variable">json_str</span> = <span class="hljs-string">"[
        \"{\\\"data\\\":\\\"[{\\\\\\\"device_id\\\\\\\":\\\\\\\"e1f8a900-1dfb-11ed-9972-4f669f2d96bd\\\\\\\",\\\\\\\"qod_score\\\\\\\":0.9644833333333332},\\\"receipt_type\\\":\\\"Stark\\\"}\"
        ]"</span>;

    <span class="hljs-keyword">let</span> (receipt, _) = <span class="hljs-title function_ invoke__">avg</span>(json_str.<span class="hljs-title function_ invoke__">to_owned</span>());
    <span class="hljs-comment">// Verify receipt (and error if there's an issue)</span>
    receipt.<span class="hljs-title function_ invoke__">verify</span>(ZK_ID).<span class="hljs-title function_ invoke__">expect</span>(
        <span class="hljs-string">"code you have proven should successfully verify"</span>,
    );
}</code></pre><div class="relative header-and-anchor"><h2 id="h-how-to-use-it">How to use it?</h2></div><p>Once the prover code (<code>methods.rs</code>) is defined, you can then use the W3bstream network to run proofs over the data by using the <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://sandbox.w3bstream.com/">W3bstream Sandbox</a>. Start by providing the prover code and <em>where</em> the QoD/proof data is to be written (i.e., to Basin) before submitting the request to the network:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fdfdf668014800b1c7f5f627e143cc30.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAVCAIAAACor3u9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEV0lEQVR4nI2VX2zbRBzH/cALD8DbHtgjQqrEBKVoTBvdw6RJk3jgiWfE3nhjA22TJqS0bN0fNA3oGFPJQv/Qv06T0rRzmiVpvdSuE8exc8nZucSx4+aSNGnaUZiQ0JYV5HhtvbSsO310+t2d7773+93vzkTBKKUgSkgwIclJoCSBIit5VcOt5IvP9xQ1HYsAiSAjAgSgmskau1E1TCzjFc9M+JdB8rcJ36j73vCEjwoyIsjxCYUXM7yYESQkSFlBylpNsz+hpFFB1fD4JNXnGutzjQ2OeAHMQ0W3AxQNqctEvoBTQM1BLS9r3JIUE2UA87wALThBttsmfIrjoaxoqoaZeIZL5vmUziayLUTiSiSuKKpBPFr/89Nr14nOY8TRI5/duJkC6gIjAJhXsoYdqOj2ZiZraHrJNx/v6e3v6e2/6Rzv/XXyzojv1oD3eyfpIgOBGPKzUEEF4lF944TDQRxqI95p+6TnSlKQZ+8vChJq8Rc+jyVA0cJXjuuO7+6QFOsOcORcs6ZYco71BGNUJGkK6AYWEpkoB+KxFBtNslGA1JK5TVRQsoac0S3D7orpDSpYHnztuPHNtd6+EZ9zjHKOzbpIv4sM3G3Ws7RkhqiIK9PUgrN/YtxLkd45z3SgeaomvJgRQc48XgHaDhyJaTNnVA1TtPjlxStXfxoYoxZpMR/i0X1OsfCzMGCFqGCUeAFG2ESETTCcREf4cIQP09EmXJiOBueXGE4y9ZpHLUgIwLwlEI7KF6/2Xv7R2e8JTswxozMPZiPAz0KLZwK6gVeqa48fP7Fo7JTNbetfW2k0NjefPl2priF12b+YdE0GBqdCQ1MhKzJ7C+i4Wq09rNYe1up/lCtrL4Oml1QNB9lUiEcM0GlRDfOIFtUAB7cJclsh8lH03SG3a8jTP+xl+TSAughyJmnVxLJtCCBn3YOpmRDp9ZOeeyLImbPSKlA0O+ZF0w3MCzDKp2JCmuNBTEgLksILMCbKlq2gAlKLu1hWNUx6qYFhNxV8sJ1dLTwTqK6uSwAglGs0Gk92sWcpV1aRasSE9DwdFSQFqUUzm3dhvkW6ga0d5TSsGRXNqOi4ahnb5HeB1KKBy+VKtVKtlSvVIi7/H+Y98M6EXENkMyBoT0QzxHk7sqJZ8wtG6QWrmwIFo8QJChOXmRjcIs3EYbMnzcRgJJaKg1xSKdiByHjxujsCBi6zvOyeCk9TDDkV9vgWcsZaVq9n9XrOWNu2M9qqHUUtF/E+e9/xwL8UHw3QZDBiMUkvjYeZbdxNPDS3wzwbTcr4JT2orawSHe8RLeXAq8TBN4g3XyMOvm7WB15pGf/wwoV//vpbLewfKKJcqhGnPzef68MfEIfbm7xPdB4ljh8zfxLHPzLrziNbQ+3mZ4favrj988b6hm7g/QWKuHL6h1tvnT3Tcf5ce5OO8+dOdnd9fPnbU5cunezuOtXdfaLL8a5t9O2zZ27/Pluv1fdNoSIu/wcaGhQo9yrDLwAAAABJRU5ErkJggg==" nextheight="1918" nextwidth="2877" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Alternatively, this can be performed programmatically with the IoTeX CLI (<code>ioctl</code>). It’ll run through similar steps and log the results:</p><pre data-type="codeBlock"><code><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">"messageID"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"c4a2be1c-def3-463f-813a-12efc7e46856"</span><span class="hljs-punctuation">,</span>
  <span class="hljs-attr">"states"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"state"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"received"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"time"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2024-03-22T19:05:36.661Z"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"comment"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">""</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"state"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"packed"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"time"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2024-03-22T19:05:40.2937Z"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"comment"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">""</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"state"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"dispatched"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"time"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2024-03-22T19:19:08.268849Z"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"comment"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">""</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"state"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"proved"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"time"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2024-03-22T19:24:53.339793Z"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"comment"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">""</span>
    <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">"state"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"outputted"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"time"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2024-03-22T19:24:57.587218Z"</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">"comment"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">""</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span></code></pre><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>All of the data is made available on Basin, so you can inspect the CID to see what the proof looks like—here’s an example: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://bafybeigcwwx67s27str46u45grpk7xn3brqe2fqezgogaiycscjs53xhqm.ipfs.w3s.link/">bafybeigcwwx67s27str46u45grpk7xn3brqe2fqezgogaiycscjs53xhqm</a></p></div></div></div></div><div class="relative header-and-anchor"><h2 id="h-build-open-data-pipelines">Build open data pipelines</h2></div><p>Reach out to <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://tableland.xyz/discord">Tableland</a>, <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://iotex.io/discord">IoTeX</a>, or <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://weatherxm.com/discord">WeatherXM</a> if you found this PoC useful! There are so many ways you can build on what this demonstration showed, such as using:</p><ul><li><p>WeatherXM’s weather station data in a compute or visualization workflow. Explore data on <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://index.weatherxm.network/">index.weatherxm.network</a> or use their <a target="_blank" rel="noopener noreferrer nofollow" class="dont-break-out" href="https://api.weatherxm.com/api/v1/docs/">client API</a>.</p></li><li><p>W3bstream to run verifiable computation over arbitrary data (e.g., DePIN device data) with zk proofs (including to automate your token incentive streams and build contributor trust in your reward calculations).</p></li><li><p>Basin for data availability and storage (e.g, DePIN device data or compute results/proofs).</p></li><li><p>Risc0 to significantly speed up your development, and build a Rust program, whose execution can be proven by zero-knowledge technology.</p></li></ul><p><em>This post was co-authored by: Textile (Dan Buchholz, </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/dtbuchholz"><em>@dtbuchholz</em></a><em>) &amp; IoTeX (Giuseppe De Luca, </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/iotex_dev"><em>@iotex_dev</em></a><em>)</em></p><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Textile)</author>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <category>iotex</category>
            <category>weatherxm</category>
            <category>textile</category>
            <category>data availability</category>
            <category>zk</category>
            <category>zero knowledge</category>
            <category>weather</category>
            <category>web3</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/97044a0628f90b9d369131e24f154221.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Decentralizing object storage and data availability through scalable Filecoin subnets]]></title>
            <link>https://blog.textile.io/introducing-basin</link>
            <guid>l2b5LjhEDMK6VZffuj7v</guid>
            <pubDate>Thu, 23 May 2024 15:50:26 GMT</pubDate>
            <description><![CDATA[We're thrilled to introduce Basin, our groundbreaking solution for high-throughput, decentralized data storage. Today, we're launching a private beta...]]></description>
            <content:encoded><![CDATA[<p>We're thrilled to introduce <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/">Basin</a>, our groundbreaking solution for high-throughput, decentralized data storage. Today, we're launching a private beta for large-scale data-producing protocols and applications. This is your chance to experience cutting-edge decentralized application development using Basin’s simple object storage (S3 compatible) protocol, powered by the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://filecoin.io/">Filecoin network</a>.</p><div class="relative header-and-anchor"><h3 id="h-what-is-basin"><strong>What is Basin?</strong></h3></div><p>Basin is designed to overcome the limitations of traditional cloud storage, providing a scalable, secure, and verifiable data management solution. Leveraging <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.filecoin.io/basics/interplanetary-consensus">Interplanetary Consensus</a>, Basin can help protocols manage their data at internet speed. It offers an S3-compatible object store backed by a scalable consensus protocol. Basin ensures data availability and scalability through its subnet architecture, offering high-throughput storage atop Filecoin’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dashboard.starboard.ventures/dashboard">exabytes of storage</a> capacity.</p><div class="relative header-and-anchor"><h3 id="h-why-filecoin"><strong>Why Filecoin?</strong></h3></div><p>We chose Filecoin as the backbone for Basin because of its unmatched decentralized storage capacity. This massive capacity allows Basin to offer persistent data availability and verifiable integrity across a decentralized network. Moreover, Basin benefits Filecoin by providing a high-throughput data lifecycle management tool that streamlines the onboarding and utilization of large-scale data, enhancing the overall network.</p><div class="relative header-and-anchor"><h3 id="h-why-basin"><strong>Why Basin?</strong></h3></div><p>Much like a basin that collects and channels water, our platform aggregates, secures, and optimizes data flow. Basin was created to meet the critical needs of transparency, security, and efficiency, supporting applications such as <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/aiml">AI/ML</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/compute">decentralized compute</a>, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/depins">DePINs</a>. With Basin, your data remains tamper-proof and authentic, fostering trust and transparency.</p><div class="relative header-and-anchor"><h3 id="h-core-features"><strong>Core Features</strong></h3></div><ul><li><p><strong>Data Availability at Internet Speed:</strong> Our high-throughput, S3-compatible architecture ensures your data is always accessible with cryptographic proofs.</p></li><li><p><strong>Verifiable Data for Trust:</strong> Basin provides cryptographic security guarantees, ensuring your data remains tamper-proof and authentic.</p></li></ul><div class="relative header-and-anchor"><h3 id="h-real-world-use-cases"><strong>Real-World Use Cases</strong></h3></div><p>Basin is designed for protocols and autonomous agents that require reliable storage capacity on demand for varying time frames. Built on crypto primitives, it can be programmed and paid for seamlessly without lock-in, long-term plans, or centralized accounts. As part of our private testnet, we’re working with a select set of partners and customers including <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://weatherxm.com/">WeatherXM</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://iotex.io/">IoTex</a> to build POCs that showcase how Basin unlocks real-world value.</p><p>WeatherXM is currently using Basin to move toward fully decentralized infrastructure, prioritizing transparency and open data availability for the data coming from their network of weather stations. Basin facilitates data collaboration by combining high throughput, temporary data availability with long-term archiving to Filecoin, allowing contributors to build on top of device data, unlocking value and monetization opportunities for their network. Basin could also be used to enable verifiability, signing data at the source, and ensuring all data is cryptographically provable. This decentralized framework ensures transparency in rewards calculations, offering confidence to network participants.</p><p>To add automation to transparent rewards flows, we’ve been working closely with IoTex via their W3bstream solution. W3bstream is a compute protocol built for DePINs that allows for off-chain, verifiable computing on data (with zero knowledge proofs) and smart contract triggers to facilitate circular token economies. Basin acts as a high throughput data availability option for W3bstream, allowing protocols to send data to Basin’s hot cache layer for compute via W3bstream before generating a proof. This unlocks a transparent and programmatic rewards structure that can be used by any protocol. To get updates on our upcoming POC, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.textile.io/">subscribe to our blog here</a>.</p><div class="relative header-and-anchor"><h3 id="h-easy-to-use-data-infrastructure">Easy-to-use data infrastructure</h3></div><p>While our full suite of features will roll out throughout 2024, you can sign-up to start using Basin today. Here’s what it looks like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/amazingdatamachine/adm/tree/main/cli#object-store">to store data on the network</a> : </p><pre data-type="codeBlock"><code># Create an object store (i.e., a smart <span class="hljs-class"><span class="hljs-keyword">contract</span>-<span class="hljs-title">based</span> <span class="hljs-title">data</span> <span class="hljs-title">container</span>)
&gt; <span class="hljs-title">basin</span> <span class="hljs-title">objectstore</span> <span class="hljs-title">create</span>

</span>{
  <span class="hljs-string">"address"</span>: <span class="hljs-string">"t2weumc7otsi3kniwjgy2xnemws5jpi3vmbnxg4fa"</span>,
  <span class="hljs-string">"tx"</span>: {
    <span class="hljs-string">"gas_used"</span>: <span class="hljs-number">15004808</span>,
    <span class="hljs-string">"hash"</span>: <span class="hljs-string">"3999595D0F74F912323F0F545204BE9D0605CE741275120E553FA395E64DA48D"</span>,
    <span class="hljs-string">"height"</span>: <span class="hljs-string">"358550"</span>
  }
}

# Add an object to the store (sends an onchain <span class="hljs-built_in">tx</span>)
<span class="hljs-operator">&gt;</span> echo <span class="hljs-string">'{"hello":"world"}'</span> <span class="hljs-operator">|</span> basin objectstore add \
<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-keyword">address</span> t2weumc7otsi3kniwjgy2xnemws5jpi3vmbnxg4fa \
<span class="hljs-operator">-</span><span class="hljs-operator">-</span>key <span class="hljs-string">"my/object"</span>

{
  <span class="hljs-string">"status"</span>: <span class="hljs-string">"committed"</span>,
  <span class="hljs-string">"hash"</span>: <span class="hljs-string">"48BD1767DC5739C1EABB25FBC8E6718E3E8DE95FB7EE74D13895F2E9D9F5E00A"</span>,
  <span class="hljs-string">"height"</span>: <span class="hljs-string">"358569"</span>,
  <span class="hljs-string">"gas_used"</span>: <span class="hljs-number">4784697</span>,
  <span class="hljs-string">"data"</span>: <span class="hljs-string">"bafy2bzacebnjpu5e3ushfu2weqvmtvk7vnndg4fkqsbr4zub52cyekcix7l4o"</span>
}

# Get an object <span class="hljs-keyword">from</span> the network (resolved after <span class="hljs-built_in">tx</span> <span class="hljs-keyword">is</span> committed onchain)
<span class="hljs-operator">&gt;</span> basin objectstore get \
<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-keyword">address</span> t2weumc7otsi3kniwjgy2xnemws5jpi3vmbnxg4fa \
<span class="hljs-string">"my/object"</span>

{<span class="hljs-string">"hello"</span>:<span class="hljs-string">"world"</span>}</code></pre><p>Here is a brief overview of the technical arcitecture:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c6435623ce7aa0293724ddacd1058b1b.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAgCAIAAABo/kRRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAIIElEQVR4nG1VfVATZx7embu5Tmduzrv7o3eOdz2nHlc/EE+DCkJEMmK04Ee0ASt4JdJGQkIhAZIg34F8kIQEyJIPIqyYYMgiZInJ8pHAZFdMtkjSjmLby804wdb80ZswU4M3XTtzuUniOJ7TZ94/3v3t8z77/H77vr8XIEnS43Sik5Po5KTTZlt0uYh79zwIsoJhDwhiBcNWA4HlxUV0cnLZ41nBMA+C+DEsyZyZWfZ4XDZbiCASKQAbGxuB+flGDudtAGjkcB4QhPP2bYNKtXfHjuNHjrTU1a3euzdlsbTU1Z0rKjqRlxeYn7eYzV8Fg+Vnz15hMr8KBn3z8//58cekFkmSTrt9amxsSKm0mEweBPF5POlHZUeHQaUicNzjdFr0+hGdbkipXJyZQWDYZbNZ9Hqb2eyy2Qgcf+krkUg839z86cWLWCyGoujzzc1EIvFkfT0UCqVfkSQZi8XmZmdJkvzpxYsn6+ter3djY+P55uaT9XWSJNOmXmq9QiyF9CQcDqeD8Xg8Go2mFSORSCwWI0kyzbFarfEUwuEwSZJJLfI1hMPheDweiUTi8Xh6QXp9NBpNR16BJMm1tTU2m02hUHJyct70lUgkwuHwks+HorPRaPSbf4ZNpmEURWOxGEEQcrlcIpGwWCwURdN2vF4vjuNUKlUkEhEEkdRCEITBYLBYrPb29nnP4vv7cyuusB130NMXWXxx27NnP+A4Tk+BwWBs376dwWCUlJSEw2GTyUSn03NycgAAQBAkqbW2tmYymdAUlnz4yQvln/IEk9PODz683ClXxeNxPp9Po9EoFAqDwcjKysrIyEh7wXHc6/VaU/i/HCORiFwubxAIzp9nTjscicR/v3v6NBKJpKv+BshUZREEeb0+QHorEAThDwRoKZSWliIIshoMhkIhHMdhGEbRWYL4HH8NBEGEQiF/IOAPBNLMSCQCLHg8QArnmWV33HNjlnE3Ov9xZZVU1msegYYMJvMIpFRrhKJm8wg0PjE5PjGZjvQPgkMGY/8gmJqYBnUgsBoMVlayjhUWajTa9EdSFu6GQl/4A4QPw80jo9dHb3Z09XBquIWFNCaTCYLg2tqj1WDwwcOHa2uP/IGAD8MNRlNSq4bLpdNPikRiCIIkEokPw7xeb5Ow6etvvn78+HFaa/j6qMFoFAgEPB5Po9Gq1GoYngyFQk3CJp/P9/2/v9dotMDi4qJE0s1msy+WXeTxeBAEWa3W1mvtl5gV/X3gFOxoEAq7pQpBk1gmV7DZbBaLxWazTSYTDMMKhaq87HKLuN01M8vj1QL+QKC5pbW6tqG0opInEPaBw6AZuiZqra8WnKSdknbKubzPxC0dHV09nV0SnkB45sJFNo+vBc1W2MGvE1wTtB6n0ttFnTweDyAIokEoLKus3rL13fwTJRl7D37EqhaLGj/jXKmuugz29xYcK3z717/N2LlbKGr+B7t2y9Z3cwvpOw/kFjMrGgT8xrqrn3x8USXrrOFyk1psNie/qLissrqSU3/8zIe5R4tuQNDNG5CuXztxa1wuV35QfLa6pra1reMw9fj5iqryT7jFzIq/5xzVaLSTsE2rUado8qRWo1DMrm/KpOTsO5iXScmpF7XSabTcvVnniorO0emtbR3dUkVHV09La5uorSuTkpN95NiufdlNbZJi+qnDmZllxafpR4/y+XyAID6XymRK7UBze2dHj6xXrbVPOSrKyv76p210KpWWd2RQB4J6I6g3agcGNAO65vaupLaqb8rpqq3hZGVk0KlUyq6dzWIxcD9436A3Q2abBYKvibtqquvfz8hsErR8ef9RV7tMo9YNGYzawSGlWjs8fN0CwRYIVvRoqtl1+/ZmV7E4/ruhAa1JD47I5IpkjjKpesLi9Mwta5T6v2Vk/e43f+RyGixj03t2Z19gXDKPjA7o9ApVn0yqvHXT4ZlbHoPgg9n5vwK2lDErLTemCgtOnSkplUi6kzmCesNVTk3W/gOniksKCmmp86Frbm2XynqVao1mQDeg04N6o1Kt4dXVHzycU1BIy8un1vEbhgymHplcqdYMGUzqvr7kvh8ymDq6evYdyM7Lp1IohxqF4m6pIi0hlfW+0tIM6BSqvnxqwe7MrJ179nK4tUq1RqnWmkcgUG9U92mBUOiLiorLdDodQZBexeDBbGpJMRMet1EPHdq/a/eY2axUa0C9sR/U13B5NBoNgiBodLyw4NSe3RRk+g7zzJm/bN1qGhhQKHoBHL/rcruj0e++ffLtO7//MwAAf3jnvZtmKHPHewAAzIzfUqo10E2LUq2ddiDR6NNnz37Iz6WlOstbQ/36q5c+AgBgWKMBQRDwYdigDvRh+ILH29Agqqmpr6riSHvkLUJheWlZS/O1dDkGdHqD0eR0uaYdiKRbzq8XsT/licWtHS0t50pON9Tzkz0nFoutBkMTdrtUJjMYjTVcrsViWfB4XG50bmHB6XKh6KzL7UZRFEGcE3b7hN2uUqulMllnV1eTULjg8fgw3Ifhq8Hgyx7t9XorKsrb2tr6+vqi0egbl9MbV5lIJGKxWHK5HIbhdORljw6H/zXtQHwY5g8Qq8HQyCg0Ne1wuVGXG7XDsPn6dTsMD+pAi8V6e3raarO53Gia6XKjI6PQgsebJvswLLkn5hY8y/5kb1zyYSurwWV/YMmHffngYYNQCABA1v4D27Yl/8kvfvnW8RMnVlaDSz5syYct+wOBwMqyP5AeLjcKhMNhOwxPO5CfHRaL1WKxOl3uIYMx6c5662dpU9OOxcXF/wEPqKxFfYhaxQAAAABJRU5ErkJggg==" nextheight="2752" nextwidth="2152" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><div class="relative header-and-anchor"><h3 id="h-join-the-basin-beta"><strong>Join the Basin Beta</strong></h3></div><p>We invite you to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/partnerwithus">partner with us</a> in building the future of data. If you’re interested in using Basin, fill out <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.textile.io/partnerwithus">this form</a> to get access to our private testnet or to talk to a member of our team about collaboration opportunities.</p><p>Stay updated as Basin powers the next wave of decentralized innovation. Join us, grow with us, and reshape the data landscape.</p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Andrew Hill)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/fe0437b2b8b2c9cfcd572fec3e554260.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: DIMO launch, New Data Paradigm discussion, & DePIN corner with Nodle]]></title>
            <link>https://blog.textile.io/weeknotes-dimo-launch</link>
            <guid>nkm42AxYNQART1JEPTQ7</guid>
            <pubDate>Mon, 20 May 2024 23:54:31 GMT</pubDate>
            <description><![CDATA[DIMO mainnet launch on Polygon + Tableland (ICYMI), bulk table Studio imports, reviewing our "New Data Paradigm" Twitter space, and a look into Nodle's smartphones as the edge.]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-dimo-launch-and-importing-studio-tables-in-bulk">DIMO launch &amp; importing Studio tables in bulk</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>ICYMI—DIMO officially launched on Polygon mainnet with Tableland! </p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>Read more about the DIMO launch <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.textile.io/tableland-dimo-polygon-launch">here</a>, and you can see hundreds of tables they've created on behalf of their manufacturers <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/partners/dimo">here</a>. It's truly open &amp; collaborative data!</p></div></div></div></div><p>From this launch, we have a <em>WIP</em> feature that will be released in the future that lets you upload existing tables to the Studio in bulk quantity. One of the reasons we’re adding it is because DIMO has <em>tons</em> of tables. We’ve started to consider more UX improvements, particularly, related to DIMO’s use case where a project might have significantly more tables than the average use case (i.e., more than a handful).</p><p>One component we’re working on is enhancing the CLI to make this type of setup easier for anyone with a table factory-like design. The syntax will look something like this:</p><pre data-type="codeBlock" language="shell"><code><span class="hljs-meta prompt_"># </span><span class="bash">Import from CSV file with headers: <span class="hljs-string">'tableName'</span>, <span class="hljs-string">'description'</span>, <span class="hljs-string">'definitionName'</span></span>
<span class="hljs-meta prompt_">&gt; </span><span class="bash">studio import bulk path/to/csv/file</span> </code></pre><p>Once executed, this will log the progress as each table from the CSV gets imported into your Studio project. Much easier than trying to do that one by one! But…if you did need to import one-off tables, the CLI has an existing command to perform this, and the UI has a few places where you can easily execute an import as well.</p><p>Since we're <em>just</em> wrapping up some of the initial revamps and kicking off that new work, be sure to let us know if there’s anything you’d like to add or change with how things work today.</p><div class="relative header-and-anchor"><h2 id="h-the-new-data-paradigm-envisioning-the-future-of-decentralized-data"><strong>The New Data Paradigm: Envisioning the Future of Decentralized Data</strong></h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/BrianHoffstein">Brian Hoffstein</a></p><p>Last Thursday, we hosted a discussion on "The New Data Paradigm." The session offered a comprehensive exploration of the evolving landscape of decentralized data technologies, featuring insights from pioneers in the field. Panelists shared their perspectives on interoperability, security innovations, and the transformative potential of decentralized storage solutions.</p><p><strong>Jonathan Victor, Co-founder of Ansa</strong> Moderating the discussion, Jonathan Victor articulated the core values driving the shift towards decentralized technologies: "When I think about why this space is important, it's less so about purely just saying decentralization for the sake of it. It's really thinking about how we build applications that are more resilient than any individual cloud provider, any individual protocol, and more hopefully composable and interoperable.” His perspective highlighted the goals of this paradigm: to create robust, adaptable systems capable of withstanding the evolving technological landscapes.</p><p><strong>Joshua Noble, Co-founder of Filebase</strong> Joshua Noble added on with the integration capacities for decentralized storage to enhance artificial intelligence, stressing the transformative implications for data management within this emerging arena of our collective landscape: "The future looks pretty bright on our side, and I think really for the future of IPFS as a whole, we've been having a lot of discussions with a number of AI communities and we're starting to see a lot of this data come online." He expanded on this dynamic intersection of AI and decentralized networks, alluding to the important path ahead for innovative solutions in data handling and accessibility.</p><p><strong>David Whittington, Infrastructure Architect at PDS</strong> David Whittington shared his perspective on the potential for decentralized data to create more dynamic and interconnected data ecosystems: "Building up datasets by composing different data over time is very interesting because... over time, datasets can just refer to each other and you can have composite data sets." David continued on this thread, illustrating a future where data is not only more accessible but also more collaboratively utilized across various platforms and users.</p><p><strong>Kanishk Khurana, Dev Rel Lead at Fleek</strong> Kanishk Khurana discussed challenges and solutions encountered by Fleek in managing web3 infrastructure, particularly in enhancing security: "We have about 100,000 websites already deployed and we've had our fair share of phishing and malicious users. We've sorted that out to be a very big problem. So we've implemented new security hashing compute solutions that we were able to build out to mitigate a lot of those problems." Kanishk’s example highlighted Fleek's commitment to providing robust, secure environments for developers in the evolving digital landscape.</p><p><strong>Nandit Mehra, Founder of Lighthouse</strong></p><p>Nandit Mehra described the upcoming transformations within Lighthouse aimed at enhancing decentralization: "From our side at Lighthouse, we are focusing on making the protocol permissionless in the coming quarters. This will involve transitioning all endowment pool contracts to the Filecoin Virtual Machine, which will be controlled by a DAO. Additionally, the roles of data bundling, aggregation, and access control will transition from our internal team to external community and ecosystem teams." His vision for Lighthouse highlights a shift towards a governance model that is open and driven by the community, fundamentally changing how data management and storage are handled within the platform.</p><div class="relative header-and-anchor"><h3 id="h-charting-the-course-for-decentralized-data-solutions"><strong>Charting the Course for Decentralized Data Solutions</strong></h3></div><p>The panelists not only shared updates from their projects but also discussed the broader implications and aspirations for the impact of these technologies on the digital world. They delved into practical aspects of decentralized data systems, emphasizing the enhancement of data sovereignty, and improving accessibility and integration across various platforms.</p><p>Their insights underscore the critical need for scalable, secure, and interoperable data solutions that can support the next generation of digital applications. From boosting AI capabilities to fostering more resilient and inclusive data infrastructures, the potential for decentralized technologies to drive significant innovation is vast.</p><p>We extend our gratitude to Jonathan Victor for his expert moderation and to all the panelists for their enlightening contributions. You can listen to the whole conversation <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=9ASuZiBBtjw">here</a>.</p><p>For those eager to engage further in these topics, stay tuned for upcoming sessions and join our ongoing discussions on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://x.com/tableland">Twitter</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.com/invite/dc8EBEhGbg">Discord</a>.</p><div class="relative header-and-anchor"><h2 id="h-depin-corner-nodle">DePIN Corner: Nodle</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/marlanat27">Marla Natoli</a></p><p>Nodle is a DePIN focussed on authenticating media content and location via their decentralized physical infrastructure network that requires only a smartphone to participate. The idea is to take advantage of the mass amounts of smartphones in the world and put them to work in new ways, turning them into Edge Nodes and rewarding users for performing work. These edge notes are able to read devices and sensors using Bluetooth, and Nodle connects this information to the blockchain. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.nodle.com/">Read more about how Nodle works here.</a></p><p>Nodle is particularly interesting in their ability to connect the concept of DePIN to real-world use cases, having launched a number of products including their Click Camera App which has a goal to fight misinformation and make the creation of media verifiable. Seeing these use cases come to fruition is exciting, as this is exactly the type of use case we aim to help solve using Basin, our decentralized object storage solution. Nodle has recently taken steps to decentralize its data infrastructure by integrating Filecoin for decentralized storage, indicating a need for a decentralized infrastructure stack to power the next generation of verifiable information. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/nodle.eth/8IXVebrWIBRfUSEFb4oBtKY2Bx2rYxhX8hea_uzg7AE">Read more about how they’re using Filecoin here</a> and get in touch if you’re looking for solutions related to verifiable and decentralized data.</p><hr><div class="relative header-and-anchor"><h1 id="h-further-reading">Further reading</h1></div><p>Below are some recent topics and articles that we found interesting and wanted to share with our readers!</p><ul><li><p>For the encryption fans—drand has a cool approach to timelocking data: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://drand.love/docs/timelock-encryption">https://drand.love/docs/timelock-encryption</a></p></li><li><p>Catch up on Jack Dorsey’s interview with Mike Solana, which is all about open protocols—including tidbits about adding value to for-profit entities: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.piratewires.com/p/interview-with-jack-dorsey-mike-solana">https://www.piratewires.com/p/interview-with-jack-dorsey-mike-solana</a></p></li><li><p>For the Reth fans out there, there’s a new feature for Reth execution extensions (”ExEx”), which is a framework for building offchain infrastructure as post-execution hooks: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.paradigm.xyz/2024/05/reth-exex">https://www.paradigm.xyz/2024/05/reth-exex</a></p></li><li><p>And if you found that interesting, check out the podcast for a Reth overview and how Paradigm thinks about its prospective future: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.youtube.com/watch?v=jEUD-G8cF78">https://www.youtube.com/watch?v=jEUD-G8cF78</a></p></li></ul><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <category>dimo</category>
            <category>tableland</category>
            <category>polygon</category>
            <category>depin</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/3b200f92e1cfed1f077cffcd354739b2.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[DIMO Launches Vehicle Definitions Database on Tableland + Polygon]]></title>
            <link>https://blog.textile.io/tableland-dimo-polygon-launch</link>
            <guid>bSybwuJCoEubdEa6E4Y6</guid>
            <pubDate>Wed, 15 May 2024 17:41:39 GMT</pubDate>
            <description><![CDATA[A walkthrough about how DIMO deployed a public, verifiable, & collaborative dataset on Tableland + Polygon]]></description>
            <content:encoded><![CDATA[<p>DIMO continues to drive forward its mission to create the world’s first decentralized, open, connected vehicle network. If you follow the DIMO ecosystem, you’ve likely heard Yev, DIMO’s co-founder and CTO, talk about the vast amounts of data created by your vehicles, yet owned and controlled by vehicle brands, leaving owners out of the value exchange. DIMO is working to flip that script, allowing drivers to collect and access data about their vehicle, choose what data they’d like to share and with whom, and receive rewards for participation in the network. But DIMO’s open vehicle network unlocks another important value — to enable a developer ecosystem to build on top of this data, accelerating innovation and creating new use cases not possible in a closed economy.</p><div class="relative header-and-anchor"><h2 id="h-public-and-verifiable-data">Public &amp; verifiable data</h2></div><p>Gating data within the silos of car manufacturers stifles innovation and limits which players can contribute to the future of connected vehicles. This could lead to further privacy challenges if the same large tech companies that own most of our data, are the ones dictating how our vehicle data is being used and monetized. DIMO is combatting this with their open network, putting users in control of how data is used, and enabling developers to create value and get rewarded accordingly. A critical component to this success is ensuring they are using and creating reusable infrastructure that supports collaboration—this is where Tableland comes in.</p><p>Tableland provides a database solution that meets all the criteria DIMO was looking for: enable collaboration and composability over the data, allow for some level of ACL (to minimize spam entries), and ensure others can replicate the model (to encourage further creation of open information). Further, with the recent launch of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/">Tableland Studio</a>, it’s easier than ever for developers to find DIMO’s tables, build on top of the data, or recreate a similar structure for a different set of data.</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>Check out DIMO’s data in the Studio: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/partners/dimo/">https://studio.tableland.xyz/partners/dimo</a></p></div></div></div></div><p>This public good dataset is now deployed on mainnet and available for anyone to use. It is an important step toward making it easier for new projects and developers to build within the DIMO ecosystem. Read on to dive deeper into this collaboration and how it works.</p><div class="relative header-and-anchor"><h3 id="h-the-public-dataset">The Public Dataset</h3></div><p>DIMO and Tableland collaborated to create a decentralized, public dataset containing DIMO vehicle definitions. One of the primary benefits of open data is that it enables anyone to build on top of and use that information. The <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.dimo.zone/docs/identity-protocol/overview">onchain-related components</a> consist of:</p><ul><li><p>A primary registry contract is the main entry point for adding or removing related module contracts.</p></li><li><p>A series of “node” contracts that include:</p><ul><li><p><strong>Manufacturer</strong>: Stores information about a vehicle’s or aftermarket device’s manufacturer.</p></li><li><p><strong>Vehicle</strong>: Mints an NFT representation of the owner’s vehicle, including the manufacturer, owner, make, model, and year.</p></li><li><p><strong>AftermarketDevice</strong>: Mints an NFT representation of an aftermarket IoT device, including the EVM associated address for the device, serial number, and hardware/IMEI information.</p></li><li><p><strong>SyntheticDevice</strong>: Mints an NFT representation of a “synthetic device,” which is then mapped to a vehicle ID.</p></li><li><p><strong>Integration</strong>: Mints an NFT representation that uniquely identifies an integration node.</p></li></ul></li><li><p>A <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.dimo.zone/docs/identity-protocol/pairing">DIMO user pairs</a> their EVM wallet with devices and vehicles, and then devices and vehicles are also mapped to one another. Specifically, the <code>AftermarketDeviceId</code> and <code>VehicleId</code> are stored in the “device definitions” table in Tableland.</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p>Check out the implementation by the DIMO team here: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/DIMO-Network/dimo-identity">https://github.com/DIMO-Network/dimo-identity</a><br><br>And the initial reference demo code by the Tableland team is below, which also has a unique setup with a dynamic merkle tree that represents the offchain table state fully onchain: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/dimo-vehicle-defs">https://github.com/tablelandnetwork/dimo-vehicle-defs</a></p></div></div></div></div></li></ul><div class="relative header-and-anchor"><h2 id="h-why-did-we-do-it">Why did we do it?</h2></div><p>Tableland and DIMO set out to manage the device registry identities to help maintain and update the global list of valid vehicles fully transparently. While much of this data is public, DIMO spent considerable time and resources to source and format the data in a usable way and wants to simplify this for future use cases. For example, the onchain-driven and open dataset lets anyone query the vehicle registry and help compose data as part of the vehicle NFT metadata:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/281daff7a4ec5edffd3bc67acbcf5e16.png" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>This also allows DIMO to seamlessly create new entries in the vehicle registry through onchain actions—without any additional database infrastructure setup—and it lets their end users see exactly what data about their vehicle is made available on the network. For an introduction to how we’re helping DePINs like DIMO, read our initial partnership blog post: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.textile.io/building-a-secure,-verifiable-future-for-depin-data-introducing-our-partnership-with-dimo-and-weatherxm">here</a>.</p><div class="relative header-and-anchor"><h2 id="h-how-does-it-work">How does it work?</h2></div><p>Let’s review the DIMO implementation noted above. There are two main contracts:</p><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/DIMO-Network/dimo-identity/blob/device-definitions/contracts/implementations/tableland/DeviceDefinitionTable.sol"><strong>DeviceDefinitionTable</strong></a>: Manages table creation and mutations for vehicle definitions so that DIMO can add new manufacturer vehicle definitions to the network</p><ul><li><p>Note: This manages vehicle information and should not be confused with the Device nor Vehicle contracts mentioned above.</p></li></ul></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/DIMO-Network/dimo-identity/blob/device-definitions/contracts/implementations/tableland/DeviceDefinitionController.sol"><strong>DeviceDefinitionController</strong></a>: Additional access controller that ensures only the core smart contract can forward SQL write statements to the manufacturer/user-owned table.</p><ul><li><p>Namely, table writes are gated by NFT ownership, but they still must pass through the smart contract so that valid and "authorized" SQL is written.</p></li></ul></li></ul><p>Plus, the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/DIMO-Network/dimo-identity/blob/device-definitions/contracts/libraries/tableland/DeviceDefinitionTableStorage.sol"><strong>DeviceDefinitionTableStorage</strong></a> contract provides a storage interface for a mapping that holds <code>manufacturerId</code> and its <code>tableId</code>.</p><div class="relative header-and-anchor"><h3 id="h-table-creation">Table creation</h3></div><p>Every manufacturer minted by the <code>Manufacturer</code> contract gets its own table. The following method is where a table is created, and information about the table’s creator/owner, manufacturer, and table ID is emitted in an event—called by an authorized manufacturer:</p><pre data-type="codeBlock" language="solidity"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createDeviceDefinitionTable</span>(<span class="hljs-params">
	<span class="hljs-keyword">address</span> tableOwner,
	<span class="hljs-keyword">uint256</span> manufacturerId
</span>) </span>{ 
	<span class="hljs-comment">// Assertions &amp; SQL... </span>

	<span class="hljs-keyword">emit</span> DeviceDefinitionTableCreated(tableOwner, manufacturerId, tableId); 
};</code></pre><p>The device definitions table has the following schema. The table is “nameless” but is created with a unique format like <code>_{chainId}_{tableId}</code>.</p><pre data-type="codeBlock"><code><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> _ (
  id TEXT <span class="hljs-keyword">PRIMARY</span> KEY,
  model TEXT <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
  <span class="hljs-keyword">year</span> <span class="hljs-type">INTEGER</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
  metadata TEXT,
  ksuid TEXT,
  devicetype TEXT,
  imageuri TEXT,
  <span class="hljs-keyword">UNIQUE</span>(model, <span class="hljs-keyword">year</span>)
)</code></pre><p>When an authorized party calls <code>createDeviceDefinitionTable</code>, they must make sure a <code>Manufacturer</code> NFT is minted first and then pass the manufacturer ID to the method. A mapping in the contract tracks which manufacturer owns which table. The Solidity implementation of the table described above is the following, and you can see that <code>address(this)</code> is used to mint the table to the actual contract:</p><pre data-type="codeBlock" language="solidity"><code><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> statement <span class="hljs-operator">=</span> <span class="hljs-keyword">string</span>(
	<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(
		<span class="hljs-string">"CREATE TABLE _"</span>, 
		Strings.toString(<span class="hljs-built_in">block</span>.<span class="hljs-built_in">chainid</span>),
		<span class="hljs-string">"(id TEXT PRIMARY KEY, model TEXT NOT NULL, year INTEGER NOT NULL, metadata TEXT, ksuid TEXT, devicetype TEXT, imageuri TEXT, UNIQUE(model,year))"</span> 
	)
); 
<span class="hljs-keyword">uint256</span> tableId <span class="hljs-operator">=</span> tablelandTables.create(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), statement);</code></pre><p>Right after minting the table, the contract transfers ownership to the manufacturer/address that called the method. Before doing so, it sets the table’s controller to a Tableland controller contract (described below). This ensures that while the new owner does have full control of the table, the data they write to is <strong>must</strong> be written <em>by</em> the DIMO smart contract. In other words, all table writes are gated by the smart contract’s logic and available methods.</p><pre data-type="codeBlock" language="solidity"><code>tablelandTables.setController(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), tableId, <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>));
INFT(<span class="hljs-keyword">address</span>(tablelandTables)).safeTransferFrom(
	<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
	tableOwner,
	tableId
);</code></pre><p>From an access control perspective, the contract methods handle the assertions before an SQL is executed. The snippet below shows how this works for the table creation process by checking:</p><ul><li><p>The passed <code>manufacturerId</code> (the <code>Manufacturer</code> contract’s NFT) is valid.</p></li><li><p>The method’s caller has an admin role and is the owner of the token at <code>manufacturerId</code>.</p></li><li><p>There isn’t an existing table created for the <code>manufacturerId</code>.</p></li></ul><pre data-type="codeBlock"><code><span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>manufacturerIdProxy.exists(manufacturerId)) {
    <span class="hljs-keyword">revert</span> InvalidManufacturerId(manufacturerId);
}
<span class="hljs-keyword">if</span> (
	<span class="hljs-operator">!</span>_hasRole(ADMIN_ROLE, <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>) <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span>
	<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> manufacturerIdProxy.ownerOf(manufacturerId)
) <span class="hljs-keyword">revert</span> Unauthorized(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);

DeviceDefinitionTableStorage.Storage
	<span class="hljs-keyword">storage</span> dds <span class="hljs-operator">=</span> DeviceDefinitionTableStorage.getStorage();
TablelandTables tablelandTables <span class="hljs-operator">=</span> TablelandDeployments.get();

<span class="hljs-keyword">if</span> (dds.tables[manufacturerId] <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
	<span class="hljs-keyword">revert</span> TableAlreadyExists(manufacturerId);
}</code></pre><p>And there is also a table “controller” definition that ensures this smart contract is the only one that can write to the table:</p><pre data-type="codeBlock" language="solidity"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getPolicy</span>(<span class="hljs-params">
    <span class="hljs-keyword">address</span> caller,
    <span class="hljs-keyword">uint256</span>
</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params">TablelandPolicy <span class="hljs-keyword">memory</span> policy</span>) </span>{
    <span class="hljs-keyword">if</span> (caller <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>)) {
        policy <span class="hljs-operator">=</span> TablelandPolicy({
            allowInsert: <span class="hljs-literal">true</span>,
            allowUpdate: <span class="hljs-literal">true</span>,
            allowDelete: <span class="hljs-literal">true</span>,
            whereClause: <span class="hljs-string">""</span>,
            withCheck: <span class="hljs-string">""</span>,
            updatableColumns: <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span>[](<span class="hljs-number">0</span>)
        });
    }
}</code></pre><p>To reiterate—the manufacturer is the only one that can call the smart contract’s table mutation methods, and the smart contract is, technically, the one forwarding the SQL statements and doing the actual onchain calls to the Tableland registry.</p><div class="relative header-and-anchor"><h3 id="h-insert-vehicle-definitions">Insert vehicle definitions</h3></div><p>Once a table exists, the manufacturer can insert new definitions into the table. The <code>insertDeviceDefinition</code> follows similar assertions as described above before inserting data, also using the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/DIMO-Network/dimo-identity/blob/tableland/contracts/interfaces/INFTMultiPrivilege.sol">INFTMultiPrivilege</a> contract to manage permissions:</p><pre data-type="codeBlock" language="solidity"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">insertDeviceDefinition</span>(<span class="hljs-params">
    <span class="hljs-keyword">uint256</span> manufacturerId,
    DeviceDefinitionInput <span class="hljs-keyword">calldata</span> data
</span>) </span>{
	<span class="hljs-comment">// Assertions &amp; SQL...</span>

	<span class="hljs-keyword">emit</span> DeviceDefinitionInserted(tableId, data.id, data.model, data.year);
}</code></pre><p>The Solidity implementation is the following, where <code>data</code> includes:</p><ul><li><p><code>id</code>: The alphanumeric ID of the Device Definition.</p></li><li><p><code>model</code>: The model of the Device Definition.</p></li><li><p><code>year</code>: The year of the Device Definition.</p></li><li><p><code>metadata</code>: The metadata stringfied object of the Device Definition.</p></li></ul><pre data-type="codeBlock" language="solidity"><code>tablelandTables.mutate(
    <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
    tableId,
    SQLHelpers.toInsert(
        <span class="hljs-string">""</span>,
        tableId,
        <span class="hljs-string">"id,model,year,metadata,ksuid,devicetype,imageuri"</span>,
        <span class="hljs-built_in">string</span>.<span class="hljs-built_in">concat</span>(
            <span class="hljs-keyword">string</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-string">"'"</span>, data.id, <span class="hljs-string">"'"</span>)),
            <span class="hljs-string">","</span>,
            <span class="hljs-keyword">string</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-string">"'"</span>, data.model, <span class="hljs-string">"'"</span>)),
            <span class="hljs-string">","</span>,
            Strings.toString(data.year),
            <span class="hljs-string">","</span>,
            <span class="hljs-keyword">string</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-string">"'"</span>, data.metadata, <span class="hljs-string">"'"</span>)),
            <span class="hljs-string">","</span>,
            <span class="hljs-keyword">string</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-string">"'"</span>, data.ksuid, <span class="hljs-string">"'"</span>)),
            <span class="hljs-string">","</span>,
            <span class="hljs-keyword">string</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-string">"'"</span>, data.devicetype, <span class="hljs-string">"'"</span>)),
            <span class="hljs-string">","</span>,
            <span class="hljs-keyword">string</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(<span class="hljs-string">"'"</span>, data.imageuri, <span class="hljs-string">"'"</span>))
        )
    )
);</code></pre><p>Which, when seen by a Tableland validator node, gets emitted and materialized as the following SQL statement:</p><pre data-type="codeBlock"><code><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span>
  "_{chainId}_{tableId}" (id, model, <span class="hljs-keyword">year</span>, metadata, ksuid, devicetype, imageuri)
<span class="hljs-keyword">VALUES</span>
  (
    <span class="hljs-string">'{data.id}'</span>,
    <span class="hljs-string">'{data.model}'</span>,
    {data.year},
    <span class="hljs-string">'{data.metadata}'</span>
    <span class="hljs-string">'{data.ksuid}'</span>,
    <span class="hljs-string">'{data.devicetype}'</span>,
    <span class="hljs-string">'{data.imageuri}'</span>
  )</code></pre><p>Note that the <code>{...}</code> values in the example statement above would be actual string-encoded values that were passed as part of the <code>data</code> method parameter.</p><p>There are a few other available methods for retrieving a table’s name or ID as well as a batch insert variation.</p><div class="relative header-and-anchor"><h2 id="h-how-can-someone-use-it">How can someone use it?</h2></div><p>All of this makes it possible to openly query the vehicle definitions by using Tableland clients like the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.tableland.xyz/sdk">SDK</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.tableland.xyz/validator/api/">REST API</a>. Thus, a developer could build on top of the dataset or query information related to their DIMO vehicle.</p><p>The DIMO team made it easy for anyone to test out this setup, too, by providing scripts and instructions for deploying the contracts on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.tableland.xyz/local-tableland/">Local Tableland</a>. You can start by cloning their repo and checking out the <code>device-defintions</code> branch:</p><pre data-type="codeBlock" language="shell"><code>git clone https://github.com/DIMO-Network/dimo-identity
cd dimo-identity
git checkout device-definitions</code></pre><p>Then, check out the <code>/scripts/tableland/instructions.md</code> file (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/DIMO-Network/dimo-identity/blob/device-definitions/scripts/tableland/Instructions.md">here</a>) to see the full guide. After installing npm packages, you can run the following script and tasks against a Local Tableland network:</p><pre data-type="codeBlock" language="shell"><code>npx hardhat run scripts/tableland/deployLocalTableland.ts --network localhost
npx hardhat --network localhost mint-manufacturer manufacturerNameExample
npx hardhat --network localhost create-dd-table &lt;your_manufacturer_id&gt;</code></pre><p>This will log the manufacturer token and table information:</p><pre data-type="codeBlock"><code>Minting manufacturer manufacturerNameExample <span class="hljs-keyword">for</span> <span class="hljs-number">0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266</span>...
Manufacturer manufacturerNameExample minted <span class="hljs-keyword">with</span> ID: <span class="hljs-number">142</span>
Creating Device Definition <span class="hljs-keyword">table</span> <span class="hljs-keyword">for</span> manufacturer ID <span class="hljs-number">142.</span>..
Device Definition <span class="hljs-keyword">table</span> created
<span class="hljs-keyword">Table</span> ID: <span class="hljs-number">2</span>
<span class="hljs-keyword">Table</span> Name: _31337_2
<span class="hljs-keyword">Table</span> Owner: <span class="hljs-number">0xffffffffffffffffffffffffffffffffffffffff</span></code></pre><p>Lastly, you can call the <code>insertDeviceDefinition</code> or even use something like the Tableland SDK to insert data and expand the dataset. Recall that the access controls limit table mutations such that only the smart contract has the right to mutate data, and only the table’s owner (i.e., the manufacturer) has the right to call the method.</p><div class="relative header-and-anchor"><h2 id="h-learn-more">Learn more</h2></div><div class="relative header-and-anchor"><h3 id="h-textile"><strong>Textile</strong></h3></div><p>We’ll continue to put out additional walkthroughs of our partner and general use case implementations in long-form posts. But, if you’d like to stay up to date with what we’re building on a week-by-week basis, follow us here on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://paragraph.xyz/@textileio">Paragraph.xyz</a> (it's what our blog site uses), or, hop into our Discord for the latest updates: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">here</a>.</p><div class="relative header-and-anchor"><h3 id="h-dimo"><strong>DIMO</strong></h3></div><p>Visit the DIMO <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dimo.zone/">Website</a> to learn more about how to get involved as a user or developer in their network, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://x.com/DIMO_Network">follow them on X</a> for the latest updates.</p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <category>web3</category>
            <category>sql</category>
            <category>database</category>
            <category>dataset</category>
            <category>dimo</category>
            <category>vehicle</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/dbbd1f82fd47c29e51cfd7307ff0b7ad.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Studio copy feature, Brave wallet + SIWE, updated docs, & the Curb Cut Effect]]></title>
            <link>https://blog.textile.io/weeknotes-studio-copy-feature,-brave-wallet-siwe,-updated-docs,-and-the-curb-cut-effect</link>
            <guid>HowfE2uf2FWsvHqMEaX7</guid>
            <pubDate>Mon, 13 May 2024 17:18:15 GMT</pubDate>
            <description><![CDATA[Studio copy feature, Brave wallet + SIWE, updated docs, & the Curb Cut Effect]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-studio-table-import-and-schema-copying-feature">Studio table import &amp; schema copying feature</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>Within the Studio, a feature lets you view any table across the Tableland network. But, there's also another level to this: you can take <em>any</em> <em>table</em> and import it directly into your Studio project.</p><p>For example, let's say you or someone else created this table with the Tableland SDK or smart contracts:</p><div data-type="callout" type="info"><div class="callout-base callout-info" data-node-view-wrapper="" style="white-space:normal"><img src="https://paragraph.xyz/editor/callout/information-icon.png" class="callout-button"><div class="callout-content"><div><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/table/_137_275">https://studio.tableland.xyz/table/_137_275</a></p></div></div></div></div><p>When you're on the table inspection page, there's a <code>…</code> icon in the top-right corner:</p><figure float="none" width="663px" data-type="figure" class="img-center" style="max-width: 663px;"><img src="https://storage.googleapis.com/papyrus_images/443045cecb6b2283d4e62f463eb9cc34.png" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Clicking that will prompt you with two options:</p><ul><li><p>Import the table into your project.</p><ul><li><p>For example, you might discover some random table on the network and could then use the CLI to run queries against the data—where the imported table can be contained in / referenced by your personal project.</p></li><li><p><em>Note: importing a table is an existing feature, but this saves you a couple of steps vs. manually typing in the data via a form input!</em></p></li></ul></li><li><p>Copy the table schema.</p><ul><li><p>That is, it doesn't copy the actual data stored in the table, but the table's definition is created in your project and can act as a nice starting point / help with ideation.</p></li></ul></li></ul><p>The goal of these two features is to make it even easier to interact with existing tables that weren't deployed on the Studio but are still accessible within it. As always, if you have feature requests, let us know on Discord or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/studio/issues">open an issue on GitHub</a>.</p><div class="relative header-and-anchor"><h2 id="h-studio-sign-in-with-ethereum-localhost-and-brave">Studio Sign In With Ethereum, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost">localhost</a>, and Brave</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/joewagner">Joe Wagner</a></p><p>This week we found an issue affecting our Studio dev team when working with the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://brave.com/">Brave browser</a>, and the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.npmjs.com/package/siwe">SpruceID SIWE npm package</a>. We were able to fix the issue in studio and contribute <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/spruceid/siwe-quickstart/pull/41">an update</a> to the SpruceID quickstart code base.</p><div class="relative header-and-anchor"><h3 id="h-tldr"><strong>TL;DR;</strong></h3></div><p>If you're unable to use Sign In With Ethereum in a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost">localhost</a> sandbox with Brave Wallet, the fix is to start explicitly including the optional <code>scheme</code> field in the SIWE message. An example of the needed change can be found here <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/spruceid/siwe-quickstart/pull/41">https://github.com/spruceid/siwe-quickstart/pull/41</a>.</p><div class="relative header-and-anchor"><h3 id="h-the-problem">The Problem</h3></div><p>While manually QA testing the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/">Studio web app</a> with Brave one of our dev team noticed the sign-in was no longer working. When attempting to sign in Brave, it shows the following error dialog:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2b3f06d5a360fea305b841fe6a1d2676.png" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>A discerning eye will notice that the URL in the red text is <code>http</code>, and the URL in parentheses is <code>https</code>. Sign-in was working in all the other browsers being tested, so we figured that there was some nuance to Brave that was setting <code>https</code> as a default for an optional value.</p><p>Further debugging led to the discovery that the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eips.ethereum.org/EIPS/eip-4361">spec</a> shows the first field is the optional <code>scheme</code>. It turns out that if the <code>scheme</code> isn't provided, most browsers are either leaving it out or parsing it out of the <code>uri</code> field. However, Brave's implementation of the spec is to set a default value of <code>https</code> if <code>scheme</code> isn't provided.</p><div class="relative header-and-anchor"><h3 id="h-the-fix">The Fix</h3></div><p>The fix ended up being fairly simple. We updated our version of the <code>siwe</code> package to one that supports <code>scheme</code> and started parsing the scheme out of the page uri.</p><p>Here's the PR for our update: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/studio/pull/270">https://github.com/tablelandnetwork/studio/pull/270</a></p><p>We hope this helps anyone who runs into a similar issue. If that's the case, or you just want to say hi definitely give us a shout on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/tableland">Twitter</a>.</p><div class="relative header-and-anchor"><h2 id="h-new-sdk-v7-docs-and-templates-are-now-live">New SDK v7 docs &amp; templates are now live</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>The new Tableland SDK has been published officially as <code>@tableland/sdk@7.0.0</code>—along with all other clients that depend on it (Local Tableland, CLI, Hardhat plugin, etc.). We've walked through the changes in our most recent Weeknotes, but the only major changes are:</p><ul><li><p>Polygon Mumbai has been swapped for Polygon Amoy</p></li><li><p>ethers v5 has been swapped for ethers v6</p></li></ul><p>Our docs site is now updated (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.tableland.xyz">https://docs.tableland.xyz</a>) with all of these changes. Namely, the SDK usage hasn't changed, but many of the snippets had to be refactored to take into account the points noted above. Also, all of our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.tableland.xyz/quickstarts/templates">template repos</a> have been updated as well, so you can get started quickly with the newest SDK!</p><div class="relative header-and-anchor"><h2 id="h-the-curb-cut-effect">The Curb Cut Effect</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jkosem">Jim Kosem</a></p><p>Accessibility seems to be trending. This is new in a way that is almost disturbing for several reasons, the first of which is why it has taken so long, and the second being what caused this. I think it might have to do with just wanting things to work.</p><p>We as as species have lived with the breakneck speed of technological advancement for two to three decades now. At no other point in our collective history has anything resembling this, and it’s all largely happened in how we learn to use and adapt to software patterns. Yet a lot of the basics have been somehow skipped. Whilst there are endless patterns and documentation for <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://developer.apple.com/videos/play/wwdc2023/10072/">spatial design</a>, which happened yesterday for all intents and purposes, there is little on how to navigate with a keyboard with something as notionally simple as a <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://designnotes.blog.gov.uk/2017/04/20/were-building-an-autocomplete/">web page form autocomplete</a>.</p><p>There is this idea of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Curb_cut_effect">The Curb Cut Effect</a>: if you make things better for people with access needs, you make it better for all users. For instance, most people use the curb cut whether in a wheelchair or not, because it’s just easier. The same goes for websites and tools. If they are simple in navigation and content structure, easy to read, and things like the tab focus work, it won’t be better just for some people, but for everyone.</p><hr><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Dan Buchholz)</author>
            <category>textile</category>
            <category>web3</category>
            <category>tableland</category>
            <category>sql</category>
            <category>brave wallet</category>
            <enclosure url="https://storage.googleapis.com/papyrus_images/c3e1d8da580aede447116300e4fb853a.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: New SDK, DePIN Twitter space, & designing for devs]]></title>
            <link>https://blog.textile.io/weeknotes-new-sdk,-depin-twitter-space,-and-designing-for-devs</link>
            <guid>V1rtAkG1M5azJUE0fTph</guid>
            <pubDate>Mon, 29 Apr 2024 21:21:51 GMT</pubDate>
            <description><![CDATA[Begin transmission…Ethers v6 migration, Amoy, & breaking changesThe new Tableland SDK has been unofficially released at v7.0.0-pre.0. This will intro...]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-ethers-v6-migration-amoy-and-breaking-changes">Ethers v6 migration, Amoy, &amp; breaking changes</h2></div><p>The new Tableland SDK has been <em>unofficially</em> released at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.npmjs.com/package/@tableland/sdk">v7.0.0-pre.0</a>. This will introduce breaking changes because of two things:</p><ul><li><p>Polygon Mumbai is being deprecated as a whole, and providers no longer support it. Instead, you should migrate over to Polygon Amoy (chain ID: <code>80002</code>). Tableland validators have already made the change, so it’s possible to use it today!</p></li><li><p>Ethers v6 has been out for quite some time. We’ve finally migrated to ethers v6, so some slight functionality changes in terms of setting up a sgner need to be accounted for if you’re coming from ethers v5. We’ll be updating our docs shortly to demonstrate how to use ethers v6 as well. But, the <code>Database</code> class and all of its methods should be exactly the same…they just work a bit differently under the hood.</p></li></ul><p>The official release of the <code>@tableland/sdk@7.0.0</code> should be out relatively soon, and the Studio will also incorporate these changes. If you have any questions about Mumbai → Amoy or using ethers v6, hop in our Discord and let us know!</p><div class="relative header-and-anchor"><h2 id="h-exploring-the-dynamics-of-depins-advancing-the-frontier-of-decentralized-infrastructure"><strong>Exploring the Dynamics of DePINs: Advancing the Frontier of Decentralized Infrastructure</strong></h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/BrianHoffstein">Brian Hoffstein</a></p><p>Last Thursday, we hosted a Twitter Spaces discussion focused on the blossoming field of Decentralized Physical Infrastructure Networks, or DePINs. Moderated by Xinxin Fang of IoTeX, this session convened ecosystem leaders to delve deeply into the potential of DePINs for real-world applications, examining both inherent challenges and emerging opportunities. The insights shared cast light on innovative pathways for integrating these technologies into our interconnected digital and physical realms.</p><p><strong>Jonathan Victor, co-founder of Ansa</strong>, provided deep insights into the foundations of building a thriving DePIN ecosystem. He emphasized the critical balance between supply and demand sides for achieving sustainable growth:</p><p>&quot;I think for successful projects, one important aspect is how you build momentum. This isn&apos;t just on the supply side; it’s also on the demand side, ensuring you&apos;re balancing your economy overall, not just focusing on one half.&quot;</p><p><strong>Rob Solomon, co-founder of DIMO</strong>, addressed the challenges and necessities of aligning DePIN projects with market needs, especially in his work within the automotive sector. He highlighted the importance of demonstrating real-world demand for such technologies:</p><p>&quot;The big question is, do people actually want these physical networks? Are we going to find product-market fit? We&apos;re actively demonstrating that developers want to build on top of the DIMO protocol, showing that the data we generate for vehicles is valuable and leads to the creation of great apps and user experiences.&quot;</p><p><strong>Manos Nikiforakis, co-founder of WeatherXM</strong>, offered a thoughtful perspective on defining the success of DePIN projects. He advocated for a more community-centric approach over conventional metrics:</p><p>&quot;Many people define success by looking at the token&apos;s price performance. It shouldn&apos;t be that way. Success should be measured by the benefits the project delivers to specific groups, whether they&apos;re part of our community or the end-users of our products.&quot;</p><div class="relative header-and-anchor"><h3 id="h-innovating-for-tomorrow-depins-at-the-crossroads-of-technology-and-society"><strong>Innovating for Tomorrow: DePINs at the Crossroads of Technology and Society</strong></h3></div><p>The panelists explored various facets of DePIN technology, emphasizing interoperability, user-centric design, and the need for thoughtful regulatory considerations. Each speaker brought unique insights into navigating the complexities of decentralized technologies and integrating them into scalable, user-focused solutions. Themes highlighted included the necessity of balancing innovation with practical market needs, the importance of composability for future expansion, and redefining success in meaningful ways.</p><p>This discussion provided a comprehensive overview of the challenges and opportunities within the DePIN sector, offering invaluable insights for anyone interested in the future of decentralized technologies. Our speakers not only outlined the complexities of developing such networks but also discussed their potential to revolutionize industries by enhancing efficiency, transparency, and community engagement.</p><p>We extend our gratitude to Xinxin Fang for his expert moderation and to Jonathan, Rob, and Manos for their invaluable contributions to this enlightening discussion. For those seeking to explore the topics discussed further, the full conversation is available <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://youtu.be/sufPjLrP0ng">here</a>.</p><p>Stay tuned for more insightful discussions by following us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/tableland">Twitter</a> and joining our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.com/invite/dc8EBEhGbg">Discord</a> server, as we continue to explore the cutting edge of the decentralized future.</p><div class="relative header-and-anchor"><h2 id="h-speaking-developer">Speaking Developer</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jkosem">Jim Kosem</a></p><p>I might be doing some more speaking at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ipfsevents.io/ipfs-camp/2024">another developer conference</a> or two quite soon. This is a good, but slightly uncomfortable spot to be in when you’re a designer. You’re typically talking a different language to what is hopefully a crowd of interested people. That means you need to assume very little. I’ve done my fair share of speaking to non-designer crowds, everything from teacher trainers in central Africa to the European Union Parliament, but developers are something different.</p><p>When you’re talking to people whose job is to build things that have to work, there isn’t a lot of wiggle room or even necessarily interested in learning about things that don’t relate to that. Thinking through what I could talk about, and how we’ve been building and learning and building and learning how <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/">Tableland Studio</a> should work, I think we might have something that might not require so much translation and explanation. That is because in this case, developers are the users. This is in itself slightly different from most design content as well, because there isn’t necessarily a regular consumer using an app or service, but a developer using an app or service to build another app or service.</p><p>The differences are quite huge, but a lot of themes are the same. How do you understand what people want to do? What are the right questions to ask and to whom? How can we learn what is really going on in many different ways? All of these and more are “design thinking” but with a very specific and higher-order user set. It’s all about thinking about the user as a builder for another user. Slightly abstract, but user designers like me need to have empathy regardless.</p><hr><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Textile)</author>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Generating distributed random variables using cryptographic hashes, solving Ethers v6 + Hardhat nonce issues, & thinking about responsive design]]></title>
            <link>https://blog.textile.io/weeknotes-generating-distributed-random-variables-using-cryptographic-hashes,-solving-ethers-v6-hardhat-nonce-issues,-and-thinking-about-responsive-design</link>
            <guid>08WNIRqHkfPFzI5PCTZN</guid>
            <pubDate>Mon, 22 Apr 2024 19:27:27 GMT</pubDate>
            <description><![CDATA[Begin transmission…Flipping bits (and coins) with hashesby Carson FarmerSimulating Geometric Distributions with 32-byte HashesIn the realm of probabi...]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-flipping-bits-and-coins-with-hashes">Flipping bits (and coins) with hashes</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/carsonfarmer">Carson Farmer</a></p><div class="relative header-and-anchor"><h3 id="h-simulating-geometric-distributions-with-32-byte-hashes">Simulating Geometric Distributions with 32-byte Hashes</h3></div><p>In the realm of probabilistic data structures like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Skip_list">skip lists</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Treap">treaps</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://inria.hal.science/hal-02303490/document">merkle search trees</a>, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://interjectedfuture.com/lab-notes/lab-note-033-cascading-boundary-changes-in-prolly-trees/">others</a>, efficiently generating random numbers that follow specific distributions is crucial. One particularly interesting problem is simulating a geometric distribution—a model used to describe the number of trials needed to achieve the first success in a sequence of independent and identically distributed Bernoulli trials. At the same time, in <em>distributed</em> (and/or peer-to-peer) systems, we also end up <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.investopedia.com/hash-rate-6746261">doing a lot of hashing</a>. And a good hash function should be <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.cryptographyengineering.com/2012/07/17/indifferentiability/">pretty much indistinguishable from a random string of bits</a>. So in this post, we’ll try to combine these two ideas, and explore an interesting method to generate geometrically distributed random variables using cryptographic hashes, by treated the hashes as a source of random independent coin flips! The outcome will be probabilistic data structures with pseudo random values that are (ideally) <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://0fps.net/2020/12/19/peer-to-peer-ordered-search-indexes/">identical across peers in the peer-to-peer system</a> — deterministic randomness!</p><div class="relative header-and-anchor"><h3 id="h-the-basic-idea">The Basic Idea</h3></div><p>A geometric distribution typically requires a success probability <strong><em>p</em></strong> to determine the distribution of trials until the first success. If you want to simulate a geometric distribution with a probability that isn’t <strong><em>1/2</em></strong>, say something like <strong><em>p = 1 - (1/m)</em></strong>, you can manipulate a sequence of fair Bernoulli trials (each with <strong><em>p = 1/2</em></strong>) to achieve this. The solution involves transforming a 32-byte hash, which is essentially a 256-bit binary string, into the desired geometric distribution. But how?</p><div class="relative header-and-anchor"><h3 id="h-understanding-the-transformation">Understanding the Transformation</h3></div><p>Each bit in the hash can be thought of as a result from a fair coin flip—either 0 or 1, each with a probability of <strong><em>1/2</em></strong>. However, to simulate our target distribution, we need groups of bits where the group collectively has a success probability of <strong><em>1/m</em></strong>. To find the number of bits (<strong><em>k</em></strong>) per group, we calculate the smallest <strong><em>k</em></strong> for which <strong><em>2^k</em></strong> is greater than or equal to <strong><em>m</em></strong>. Mathematically, this is determined by:</p><div class="relative header-and-anchor"><h3 id="h-implementing-the-simulation">Implementing the Simulation</h3></div><p>Once <strong><em>k</em></strong> is determined, the hash is divided into groups of <strong><em>k</em></strong> bits. Each group is treated as a single trial with the desired success probability:</p><ol><li><p><strong>Extract Groups:</strong> We iterate over the 256 bits in batches of <strong><em>k</em></strong> bits.</p></li><li><p><strong>Determine Success or Failure:</strong> A group is considered a &quot;success&quot; if all <strong><em>k</em></strong> bits are 0.</p><ol><li><p>This happens with a probability of:</p></li></ol></li><li><p><strong>Count Trials:</strong> The count of groups until the first &quot;success&quot; is the result of our geometric distribution simulation.</p></li></ol><p>Here&apos;s a practical function to achieve this using Rust:</p><p><code>#[cfg(test)] mod tests { use rand::Rng; fn simulate_geometric_random(bytes: [u8; 32], m: u32) -&gt; u32 { // Compute ⌈log_2(m)⌉ let k = (m + 1).ilog2(); // Number of batches of k bits let batch_count = 256 / k; // Mask to extract k bits let mask = (1u8 &lt;&lt; k) - 1; for i in 0..batch_count { let byte_index = (k * i) / 8; let bit_index = (k * i) % 8; let batch = (bytes[byte_index as usize] &gt;&gt; bit_index) &amp; mask; // batch != 0 means we are looking for failure p = 1 / m // batch == 0 means we are looking for success p = 1 / m if batch == 0 { // +1 because geometric distribution starts at 1 return i + 1; } } batch_count + 1 // if no success found within the limit } #[test] fn test_calculate_rank() { let mut rng = rand::thread_rng(); let m = 4; let p = 1.0 - 1.0 / m as f64; let mut sum = 0; for _ in 0..1000 { let index = simulate_geometric_random(rng.gen(), m); sum += index; } println!(&quot;mean: {} expected: {}&quot;, sum as f64 / 1000.0, 1.0 / p); } } // running 1 test // mean: 1.333 expected: 1.3333333333333333 // test rank::tests::test_calculate_rank ... ok // test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.01s</code></p><div class="relative header-and-anchor"><h3 id="h-the-takeaway">The Takeaway</h3></div><p>This method is efficient and interesting, converting a simple hash value into a sequence of geometrically distributed random trials. It underscores how foundational concepts in probability can be applied to solve practical problems in computer science, particularly in the design of data structures where randomness and probability management are important. Another bonus, treating our hashes (something we have to do anyway) as a random oracle makes this approach computationally elegant and requires minimal additional resources, making it ideal for environments where performance and memory efficiency are critical.</p><div class="relative header-and-anchor"><h2 id="h-troubleshooting-ethers-v6-and-hardhat">Troubleshooting Ethers v6 and Hardhat</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We&apos;re close to launching a new Tableland SDK that includes Polygon Amoy support and also upgrades from ethers v5 to ethers v6. Most of the ethers changes shouldn&apos;t really break any of the behavior with the SDK, but it <em>will</em> result in a major dependency bump because it will no longer work with ethers v5.</p><p>The upgrade process led to a couple of challenges (and solutions!) with using ethers v6—particularly, when developing against a local Hardhat node:</p><ol><li><p>A perpetual <code>failed to detect network</code> error gets logged every second, even though the network exists (see <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ethers-io/ethers.js/issues/4377#issuecomment-2023855491">here</a> for more details). For the most part, this is more annoying than actually preventing the SDK from working.</p></li><li><p>A <code>nonce too low</code> or expired error, indicating that a transaction has been sent/accepted with the same nonce as one that&apos;s already been used. <em>This</em> is a huge issue because it became impossible to run our tests against a Local Tableland network, which runs a Hardhat node. Tests flakily fail due to a nonce issue.</p></li></ol><p>For problem (1), it turned out to be an easy fix. The <code>failed to detect network</code> error would get logged every time the <code>getSigner()</code> method was called on a provider. Before making that call, all that&apos;s needed is to <code>_detectNetwork</code>:</p><p><code>// Instantiate a `provider`—e.g., via `globalThis.ethereum` or an instance of `Eip1193Provider` import { BrowserProvider } from &quot;ethers&quot;; const browserProvider = new BrowserProvider(provider); await browserProvider._detectNetwork(); // this stops the annoying logging const signer = await browserProvider.getSigner();</code></p><p>For problem (2), this took <em>forever</em> to figure out. I tried:</p><ul><li><p>Always pass an ethers signer wrapped in an ethers <code>NonceManager</code> to the Tableland <code>Database</code> class.</p></li><li><p>Make sure all calls in a test are awaited before proceeding to the next test (to ensure that txs weren&apos;t being submitted too fast to the Hardhat node).</p></li><li><p>In the SDK&apos;s <code>Database</code>, <code>Registry</code>, and <code>exec()</code>, take the passed signer and force convert it to a <code>NonceManager</code>.</p></li><li><p>Try getting the nonce (via <code>signer.getNonce()</code>) before a call is made and manually pass it in tx calls.</p></li><li><p>Setting custom <code>JsonRpcProvider</code> options (note: this was the ~right solution).</p></li><li><p>In the before/after mocha test hooks, make calls to the Hardhat node and hardcode/reset the nonce with <code>hardhat_setNonce</code> (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hardhat.org/hardhat-network/docs/reference#hardhat-setnonce">here</a>)...but, for obvious reasons, this didn&apos;t work.</p></li></ul><p>It was a much simpler fix, as first described <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ethers-io/ethers.js/issues/4549">here</a>. An ethers <code>JsonRpcProvider</code> can take several options, and setting the <code>batchStallTime</code> and <code>cacheTimeout</code> are required to avoid the nonce issues. Also, since in this case, we&apos;re always connecting to the same network (a Hardhat node), the <code>staticNetwork</code> can reduce some calls, too, when coupled with the <code>network</code> param.</p><p><code>import { Network, Wallet } from &quot;ethers&quot;; const account = &quot;your_private_key&quot; const wallet = new Wallet(account); const chainName = &quot;local-tableland&quot;; // i.e., a hardhat node const chainId = 31337; const network = new Network(chainName, chainId); // Optional const signer = wallet.connect( new JsonRpcProvider(`http://127.0.0.1:8545`, network, { staticNetwork: true, // Reduce `eth_chainId` calls batchStallTime: 0, // Don&apos;t batch requests, send them immediately cacheTimeout: -1, // Don&apos;t cache }) );</code></p><div class="relative header-and-anchor"><h3 id="h-responsive-enough">Responsive enough</h3></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jkosem">Jim Kosem</a></p><p>We’re in the midst of designing and prototyping a number of sites, showing what we’re working on at Textile, which I’ve <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.substack.com/p/weeknotes-ethers-polygon-amoy-tableland">been writing about or around in the past couple of weeks or so</a>. At first, we talked about just putting a website up in Framer which should be good enough for now. Then I realized that you don’t quite get responsive behavior out of the box.</p><p>The long-standing issue with designing visuals, and well most things with screens, is that you sort of only half know what it will look like for the person that might stumble upon it. Color issues notwithstanding, there is no way to know what sort of device or screen size someone will use. So, just thinking about <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.hubspot.com/marketing/web-design-stats-for-2020">65.49% of global website traffic being on mobile devices</a> makes us think this is something we need to get underway. It just needs to work at this point, but fortunately, at this point, responsive design is quite established. Framer itself has some tools to help with this, but the interesting thing from a design standpoint is how to let the design degrade and how to decide what to cut. What is important to see or read when you’re on a phone? Just how much stuff should we be putting on a page at this point then? The issues are innumerable but part of the process of being loose in the right places with how to design for what is a constantly shifting target.</p><hr><div class="relative header-and-anchor"><h1 id="h-other-updates-this-week">Other updates t<strong>his week</strong></h1></div><div class="relative header-and-anchor"><h2 id="h-data-economy-hack-winners">Data Economy hack winners!</h2></div><p>Congrats to all of the team that participated in the Filecoin Data Economy hackathon. Here were the top 3 projects:</p><ol><li><p>DBNS by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/LionisNick">@LionisNick</a>—a unified namespace to host and collaborate datasets and AI models: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dorahacks.io/buidl/10525">here</a></p></li><li><p>DeRAG by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/debuggingfuture">@debuggingfuture</a>—a DataDAO-owned LLM AI with trustless, decentralized augmentation: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dorahacks.io/buidl/11199">here</a></p></li><li><p>ChainQuery by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/0x_Clint">@0x_Clint</a>—web3 Q&amp;A platform with token-based rewards and AI augmented answers: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dorahacks.io/buidl/11186">here</a></p></li></ol><div class="relative header-and-anchor"><h2 id="h-decentralized-intelligence-hack-winners">Decentralized Intelligence hack winners!</h2></div><p>The DI hack had 7 total winners—3 top projects, and 4 honorable mentions:</p><ul><li><p>Arbitrarian—simplifying smart contract learning and ERC20 token creation: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://learnweb3.io/hackathons/decentralized-intelligence-season-2/projects/7d2b1d9a-89cc-4622-9337-0de583a31b07/">here</a></p></li><li><p>Memester—merging meme creation with blockchain for rewards: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://learnweb3.io/hackathons/decentralized-intelligence-season-2/projects/230703f4-bad5-49f2-9b21-0141f48dd6ca/">here</a></p></li><li><p>Spooky—storytelling with AI and blockchain, minting narratives as NFTs: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://learnweb3.io/hackathons/decentralized-intelligence-season-2/projects/122580aa-1603-471f-9a53-70a21371f1f5/">here</a></p></li><li><p>DeFi Pets—interactive DeFi learning through AI-powered NFT pets: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://learnweb3.io/hackathons/decentralized-intelligence-season-2/projects/92cc07ad-3c27-4f33-ab1c-c856ea1a36ef/">here</a></p></li><li><p>dChat—secure, decentralized communication via blockchain: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://learnweb3.io/hackathons/decentralized-intelligence-season-2/projects/bb56c0aa-bfcd-47e0-993f-68835c9a9ce6/">here</a></p></li><li><p>TokenMart—revolutionizing e-commerce with tokenized rewards: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://learnweb3.io/hackathons/decentralized-intelligence-season-2/projects/f7bae58f-4d77-4730-b56c-514234e827dd/">here</a></p></li><li><p>Crypto Subscriptions—managing crypto subscriptions with ease: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://learnweb3.io/hackathons/decentralized-intelligence-season-2/projects/a251e4f2-ec26-4c8f-9c6a-cac55bacf8cb/">here</a></p></li></ul><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Textile)</author>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Ethers + Polygon Amoy, Tableland Studio highlights, DePIN corner with Wingbits, design through prototyping, & decentralized AI Twitter space retro]]></title>
            <link>https://blog.textile.io/weeknotes-ethers-polygon-amoy,-tableland-studio-highlights,-depin-corner-with-wingbits,-design-through-prototyping,-and-decentralized-ai-twitter-space-retro</link>
            <guid>XQ1wSZmk0Z4ixI6lBoZ9</guid>
            <pubDate>Mon, 15 Apr 2024 22:19:49 GMT</pubDate>
            <description><![CDATA[Begin transmission…Ethers + Polygon Amoy—and Mumbai deprecationby Dan BuchholzIf you haven&apos;t been in the loop, Polygon deprecated the Mumbai tes...]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-ethers-polygon-amoyand-mumbai-deprecation">Ethers + Polygon Amoy—and Mumbai deprecation</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>If you haven&apos;t been in the loop, Polygon deprecated the Mumbai testnet. Providers like Alchemy have also <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.alchemy.com/blog/polygon-amoy-is-live">deprecated Mumbai RPCs</a>—so…it&apos;s time to transition to Amoy! We&apos;ll be releasing a new <code>@tableland/evm</code> and downstream clients later this week, which will swap the chains from a support perspective.</p><div class="relative header-and-anchor"><h3 id="h-custom-amoy-logic">Custom Amoy logic</h3></div><p>Support for Amoy isn&apos;t <em>quite</em> ready out-of-the-box if you&apos;re working with ethers v6. This is due both to fluctuations in gas <em>and</em> the fact the default ethers <code>maxFeePerGas</code> and <code>maxPriorityFeePerGas</code> values are wildly incorrect. For example, if you use the built-in method, you&apos;ll get values like this:</p><p><code>import { ethers } from &quot;hardhat&quot;; // using ethers within hardhat context const { maxFeePerGas, maxPriorityFeePerGas } = await ethers.provider.getFeeData(); // maxFeePerGas: 1000000030n (note: `n` signifies `bigint`; it&apos;s wei) // maxPriorityFeePerGas: 1000000000n</code></p><p>But, if you look on the Amoy Gas Station (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gasstation-testnet.polygon.technology/amoy">here</a>), these values will <strong>be up to 30x larger</strong> (e.g., <code>35185714305 wei</code>). If you pass the default values, your transaction will never get accepted because the fees are far too low. Instead, you must create a custom method—or use the ethers <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ethers-io/ethers.js/blob/29beb93ea76d560a129e4bc3fde6ee9c8cc887c4/src.ts/providers/plugins-network.ts#L200">plugin</a>—to fetch the live fees.</p><p>You can do this with a Node <code>fetch</code> call and also make it generalized so that it either returns the Amoy fee data <em>or</em> the built-in method&apos;s fee data (for other chains):</p><p><code>import { network } from &quot;hardhat&quot;; import type { FeeData } from &quot;ethers&quot;; async function getFeeData(chainName: string): Promise&lt;FeeData&gt; { if (chainName === &quot;polygon-amoy&quot;) { try { const url = &quot;&lt;https://gasstation-testnet.polygon.technology/amoy&gt;&quot;; const response = await fetch(url); const data = (await response.json()) as AmoyFeeData; // a custom interface that aligns to the API above const feeData = new FeeData( null, // No gas price value needed BigInt(ethers.parseUnits(String(data.fast.maxFee), &quot;gwei&quot;)), BigInt(ethers.parseUnits(String(data.fast.maxPriorityFee), &quot;gwei&quot;)) ); return feeData; } catch { const feeData = new FeeData(); return feeData; } } else { return await ethers.provider.getFeeData(); } } const chainName = network.name; // &quot;polygon-amoy&quot; or whatever chain const { maxFeePerGas, maxPriorityFeePerGas } = await getFeeData(chainName);</code></p><p>Since Amoy is pretty new, the costs to deploy a contract also seem to vary quite a bit and are more expensive than when deploying on Mumbai. For example, an upgradable contract deployed on a low gas day (Sunday) cost around 0.18 MATIC, but on a higher gas day (Monday), it was closer to 0.8 MATIC.</p><p>If you need Amoy test MATIC, the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.alchemy.com/faucets/polygon-amoy">Alchemy</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://faucet.polygon.technology/">Polygon</a> faucets each drip 0.5 MATIC per day…which isn&apos;t great when fees are so high, but what can you do?!</p><div class="relative header-and-anchor"><h2 id="h-tableland-studio-updates">Tableland Studio updates</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>We officially launched the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://studio.tableland.xyz/">Studio</a> a few weeks ago and are continuing to build new features. Most of the more recent additions were changes to optimize the developer/user experience within the app. Let&apos;s review a few of them.</p><div class="relative header-and-anchor"><h3 id="h-dark-mode">Dark mode</h3></div><p>Let&apos;s be honest…everyone prefers dark mode! We changed the design to make this the default color when you visit the Studio app.</p><div class="relative header-and-anchor"><h3 id="h-slide-inout-panels">Slide in/out panels</h3></div><p>When creating projects or tables, you used to be redirected to a form to fill out the information, which led to more clicks. Now, a nice panel pops out from the right-hand side, which lets you fill out the info without the redirection.</p><img src="https://storage.googleapis.com/papyrus_images/37a379c61bb542a50ff2518b0fc6f601.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAWCAIAAAAuOwkTAAAACXBIWXMAABYlAAAWJQFJUiTwAAAESklEQVR4nI1VbU8iVxSmvsB26Ix35nLnDcl+2MqiLq7adpMmpqRVK9vgGqBAFVDLbnXBKoiAkAUEGcFaXZeitVo3JmuaRj/YpG2aNE1/Qb/1L/QHtP9gm5mrrIovmzy5OffczH3mPOfcc1Qsq+e4mwyDEOIAgCQJLgHd2KhpM72TmlvJJteDD1NDVr/TFrga08GsimX1SKenge5aArWaaDN1v9j59e+//tkuH9oGvNcSBAMJFccJHCdAyAqC4XUi+Lrw3GOfsPa6PfYJ16B8i2tQRu3ttgGvzxWSCRDiSBIwDGIYdG0E3679sPfdUTws2e+P4dudtoDHPuFzhc4h+DAVD0sqCFkW8XjVEpRGTVyIG5q3VKr6llt3VhZ39nd/Wi/tSZnKcn5LylSK2c1IaME1GBh2TJ7G5FhCJmARLwoizwmiICLE0QCeBQ0ADRkdhKyWoMzt70Ue56aD2elgNh6WYjOFSGghNlN4NBqtlWiw3zs+MitHgL+HkKUB1BJULSiyiaJAY6PaZOzcLh/uP//F5wrZBrz2+6NOWwCXk8c+cQ5OW+CL0bhCoAAhrmpjsIhjEX+y8gwDu8z3itnN/d2fv984TM6Vhqz+C9N7popOJOJ5ThAEURT0CkRBECFkGQYyDMQhUmRTl/leIrKUnCtJmcqT2ArWByM6lU9ElrARncpHQrlIaCESyskRiIK+WW/AHCerTMYinjv28IKcIdR19/3DF78d/fiHlKlgLC9u41RLmcpacXcptyFvsxtSppJPlwP+WRVCHM8JLOKrWT1tUBTAW4aBJEm1t747O5UfH5m1DXhtA15rr7vP4uizOKy97qqNj/CpnGQaKBlWRMBay1XL6M7nmQL1dQ0mY8fWs8Onxb2qxMm5UnKuFJspzEeLWD2fK4RPh6x+THD8m5DRyYrTOmzjH4eMjqEVQ8lBe2v35yPRYcckrpN4WJIylcXMN8v5rXy6nE+XpdzGuPvLMwS4Oi97X5ozD+0Nk7EjHi4+K+0d7P0eeZzrszj6LZ9iiarKVJvgKwIIWYIga8ufIMhT/iZFos7M/GruyWpmfjWbXMNrPl3OzK/iwj+NYwIAaE6uGf255kNRQK83iIIeNyiKom+8qTUZO6X0ztrywUKqEpspxMNSau6reFiajxYvJaABxA0VIQ6j2vKwn1U6FccJJEkZWzr+PPrv5b8vC6mD3g+GBq3+qjK1r6xKQJMkIAiKagI0vKBdU00A0AxJyhG0mbof+RJjnthnjuC1w+BVBPgiUd/cbJBHG9YHOwGAzYabot4AgA7PA4994sEnPqdt/HUJgBIBABApPefczAEAsohXBgYeON1+93St3FcRaAmqoV5TV6duqNc01GvUagIDb0/5tSpV3du37iijargq/RWw9rrliWY03u7psXz04cdmc1drq7mK9raOnh5Lf7/1xH+3peW284G3mN3Mp9fxs7oWiejS/yei9wccFftdAAAAAElFTkSuQmCC" nextheight="1516" nextwidth="2242" class="image-node embed"><div class="relative header-and-anchor"><h3 id="h-exposing-environment-ids-and-improved-project-layout">Exposing environment IDs &amp; improved project layout</h3></div><p>In the Studio CLI, the concept of an <em>environment ID</em> was part of certain commands, but it wasn&apos;t obvious how or where these came from. The UI shows these on the project&apos;s page, along with improvements in how the project’s description is rendered. When working in the CLI, you use the project ID to then, for example, set a context that lets the CLI know you intend to work within this project.</p><img src="https://substack-post-media.s3.amazonaws.com/public/images/8aa5141a-a16f-4f2b-8260-fbc44e22f73d_2212x800.png" alt="" class="image-node embed"><div class="relative header-and-anchor"><h3 id="h-tweaks-and-more-to-come">Tweaks &amp; more to come</h3></div><p>Lastly, we made some small tweaks to the logic (e.g., route name guards against reserved keywords) and created a new package to help modularize forms.</p><p>Those initial changes were part of a design and user experience improvement process. Next, we&apos;re starting to dive into letting users edit certain information in the Studio—and if you&apos;re looking for something that isn&apos;t a feature or something that isn&apos;t working as expected, be sure to let us know!</p><div class="relative header-and-anchor"><h2 id="h-depin-corner-wingbits">DePIN Corner: Wingbits</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/marlanat27">Marla Natoli</a></p><p>Wingbits** is organizing a community around employing Automatic Dependent Surveillance-Broadcast (ADS-B) technology to capture, aggregate and monetize aviation data, to enhance aviation safety and efficiency. They have a variety of hardware options to choose from, and participants can claim a hexagon of coverage on a first-come, first-served basis. The goal is to get enough coverage in certain areas to reach critical mass whereby they can begin monetizing the data. Participants are rewarded based on volume and quality of coverage data via a token, with the hope of creating a flywheel effect as more data is monetized.</p><p>ADS-B is a type of aircraft tracking data that is transmitted by aircraft in real-time including the aircraft’s position, velocity, altitude, etc. The main output includes flight tracking data feeds for both live and historic flights which enables developers to access real-time data for various use cases including flight tracking websites, insights to improve operations for airlines and charters, air traffic control organizations, emergency services, and more.</p><p>Wingbits is still early in their DePIN journey, and we’re excited to see how the incentive mechanisms they have in place can catapult their community toward creating enough data to kickstart monetization. This would be yet another industry that could begin creating valuable data outside of walled gardens and siloes, giving data consumers more options for how they collect and use data.</p><p>If you’re interested in starting to open up your data, or in exploring how decentralized data infrastructure could support collaboration, monetization, and verification, we’d love to hear from you. Feel free to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/marlatextile/30min">set up some time</a> with us here or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">join our Discord and get in touch</a>.</p><p>**Information was taken from <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.wingbits.com/">https://docs.wingbits.com/</a></p><div class="relative header-and-anchor"><h3 id="h-designing-for-the-web-through-prototyping">Designing for the web through prototyping</h3></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jkosem">Jim Kosem</a></p><p>This past week has been a lot of making web prototypes, namely in <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.framer.com/">Framer</a>, a tool that allows designers to design and publish websites without coding. I learned how to make websites a long time ago, longer than most could imagine or want to imagine. It’s what led me to interaction design and user research. When you design software that nine times out of ten, or even more actually, comes to the world in a browser, if you’re not building an actual website, you’re building an application that shares many of the functions of one.</p><p>So, understanding the web as material means you need to not only know what can happen in a browser, but you have to sketch out how it looks and feels. You must play around with how it scales and changes and adapt your design to that. This means you need to prototype before you build. We’ll make websites properly, digging deeply into the frontend, but right now, design means seeing quickly how it works first.</p><div class="relative header-and-anchor"><h2 id="h-insights-from-the-intersection-of-ai-and-crypto-pioneering-the-future-of-decentralized-technologies"><strong>Insights from the Intersection of AI and Crypto: Pioneering the Future of Decentralized Technologies</strong></h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/BrianHoffstein">Brian Hoffstein</a></p><p>Last Thursday, we hosted a Twitter Spaces event featuring innovators from the forefront of &quot;Decentralized AI.&quot; Moderated by Jonathan Victor of Ansa Research, this session delved into how blockchain and decentralized networks can revolutionize artificial intelligence. Leaders from this emerging frontier discussed the vast potential and the synergistic effects of these technologies, revealing numerous ways they could alter our economic systems, redefine privacy and security, and enhance communal governance.</p><p><strong>Joel Thorstensson, co-founder of 3Box Labs and creator of Ceramic</strong>, emphasized the societal implications of decentralized technologies. He pointed out, &quot;The consequence of AI models can be used for a lot of good stuff, a lot of bad stuff. And a lot of the bad stuff is like impersonation and things like that. This is actually something that the crypto space, since the early cypherpunks, foresaw… with things like public key cryptography, we can actually change the structure of society.&quot; He underscored the need for ethical frameworks to govern the deployment of these technologies, reflecting Ceramic Network’s commitment to building a secure, open web where data integrity and verifiability are paramount.</p><p><strong>Ben Fielding, co-founder of Gensyn</strong>, discussed the practical benefits of decentralization for AI, particularly in terms of resource allocation. He noted, &quot;Decentralization essentially allows us to unlock a lot of those resources by drastically lowering the barrier to being a supplier of the resources.&quot; Ben&apos;s insights stress how decentralization enhances the efficiency and scalability of AI applications, an approach that Gensyn is applying to create a global supercluster of computational resources. He also emphasized the vital role of open-source models in keeping the development of AI technologies accessible and inclusive.</p><p><strong>Doug Petkanics, founder of Livepeer</strong>, focused on the market dynamics of decentralized networks, emphasizing the necessity of aligning supply with real-world demand. Doug explained, &quot;To actually bring on real demand, and to make sure that fees are flowing to the supply side as well, you have to productize and you have to meet the market where it is, you have to make a product that fits in with the way that people want to consume these resources.&quot; He also highlighted the importance of regulatory environments that support rather than stifle innovation, ensuring that new technologies can reach their full potential without unnecessary barriers.</p><p><strong>David Minarsch, co-founder of Valory</strong>, highlighted another dimension of decentralization by discussing the role of autonomous agents. He articulated, &quot;Another way to think about decentralization in this context is at the other end of the spectrum, where the autonomous agent is something we share, which essentially works as a collective whole.&quot; David’s work at Valory is reshaping how communities and organizations interact with AI through their design of autonomous, co-owned systems that empower individual and collective decision-making, further underscoring the need for data verifiability to ensure trust and functionality in these systems.</p><p>The conversation explored the impact of regulatory environments on innovation, the importance of data verifiability to maintain trust in decentralized systems, and the necessity of open-source models to democratize access to technology. These interconnected themes illustrated the challenges and opportunities at the intersection of AI and blockchain technologies. As we look toward a future where these technologies are increasingly intertwined, the insights from these leaders will help provide a roadmap for navigating the challenges and seizing the opportunities that lie ahead.</p><p>We’d like to thank Jonathan for his excellent stewardship of the conversation, as well as Joel, Ben, Doug, and David, for their participation and contributions to the field broadly. Thanks to pioneers like them, the trajectory of technological development and its societal impact are in capable hands. You can listen to the full conversation <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://x.com/tableland/status/1778483302715863241">here</a>.</p><p>Stay tuned for upcoming discussions on the cutting-edge of our decentralized future by following us on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/tableland">Twitter</a> and joining our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://discord.com/invite/dc8EBEhGbg">Discord</a> server.</p><hr><div class="relative header-and-anchor"><h1 id="h-other-updates-this-week">Other updates t<strong>his week</strong></h1></div><div class="relative header-and-anchor"><h3 id="h-hackathon-roundup">Hackathon roundup</h3></div><p>The Filecoin Data Economy hack is over, and winners will be announced this upcoming Wednesday—three prizes for 1st/2nd/3rd will be awarded. Plus, the LearnWeb3 Decentralized Intelligence hack is also over, so keep an eye out for the top 3 hacks and top 4 runner-ups!</p><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Textile)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/37a379c61bb542a50ff2518b0fc6f601.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Weeknotes: Axelar for Filecoin and Ethereum bridging, building on Tableland with Python, and a brief history of dark mode in applications]]></title>
            <link>https://blog.textile.io/weeknotes-axelar-for-filecoin-and-ethereum-bridging,-building-on-tableland-with-python,-and-a-brief-history-of-dark-mode-in-applications</link>
            <guid>yTae338NARHATAdcYHAv</guid>
            <pubDate>Mon, 08 Apr 2024 19:49:57 GMT</pubDate>
            <description><![CDATA[Begin transmission…Bridging Between Filecoin and Ethereum using Axelarby Avichal PandeyAxelar OverviewAxelar is a proof-of-stake blockchain built usi...]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h1 id="h-begin-transmission">Begin transmission…</h1></div><div class="relative header-and-anchor"><h2 id="h-bridging-between-filecoin-and-ethereum-using-axelar">Bridging Between Filecoin and Ethereum using Axelar</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/avichalp">Avichal Pandey</a></p><div class="relative header-and-anchor"><h3 id="h-axelar-overview">Axelar Overview</h3></div><p>Axelar is a proof-of-stake blockchain built using Cosmos SDK. It delivers <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.axelar.dev/dev/general-message-passing/overview">cross-chain communication</a> between <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.axelar.dev/dev/reference/mainnet-chain-names">various</a> blockchain networks.</p><p>In this post, we will see a minimal example of cross-chain message passing between an EVM contract deployed on the Filecoin blockchain and the one deployed on Ethereum. Let&apos;s first look at how Axelar&apos;s bridging network works.</p><img src="https://storage.googleapis.com/papyrus_images/c57191fcb0f1ec2ef02efbb76b996bff.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAATCAIAAAB+9pigAAAACXBIWXMAAAsTAAALEwEAmpwYAAADLklEQVR4nKVVzY6jRhA2NHRDB2xAQNv8CfAYA2YMGX5mgBlrJqvMNRNFyib7JHvYU/YS7UOstJGiPUbKKnmEHPaFckoUYbzI8TgzG22r1Croqvq6vq6uHiGOuy8QIZoBAELEcYBhWIT2lwZBHMdjzELY60dldP8Xx3FhFK7T9SIIFotFdV5Ztt1HlBWlrMqiKFanqzzPoziK4qgsy5kxY7e7eRwAIjSRpKZtLi8v27at64umaU6zdNgjIaRu6qIoLq/aq81V3dSmZfEYP5QBRKjjYZspCyGPse04M2OmaiohZLodAzziONOyVE3TdM12HMM0sSD0vr37EQBBFAkhsqKIkiQriiCKgGFlRdN0omo6wphmmH0fGoCJLKu63hmPxyyEgiiK4/Fk634IABHyfL9umjRNz/K8aRvbsQVRLMqLp98/u755omo6RF1a+27BMvz26Xd3X3/j+XMWwiRJ8iLvJM8PLP9FEWBYwLAQIR5jLAjT6UwcT+7zy2MMIQyjME4ShtlhDyTvm+0AAMPQgNnOYLAYUVScJEdp5TEeURQhRFHVEUV1ESBktwIYZhAaABbCDsB2bH/um5blz31FVXtOvfn8q7u7NMtkRTkoc4iQYVpplq3W6cwwIEIz05hOp4ZpGsZOmU6njuuoqtoBuK4bBIHv+9EqIoQAhhFE8TT7vG7a87omhBwkwUI4P1k8+fL2i9vb+ckCIlSU3c2IVlEcx2EUrdN1GMdVVXmet6OIoul+HmLRABBCxPEYfCih/mB4/FlPbl82/dIeLcco4jEe5ODGBUEgyVJ/eqN+UFSnU1SWZa7nUTT9wZcfIuwHPNIq9qnAghCGoSAIE0l69erHFy+ev3z5A0TIcV3bcR5oQQ/1onsY+Py8Mi3z3a+//P3Xnz+9eU0IcVx3oO6TAHiMwTYPXdd//+3d+/d/vH37c1+mHxP9ozKQZNnzPddzN5urszy/vr42TXN+ciLL8n910P8BABHnet7Nzc1ms4miqCyLqqratm3axrTMTwVgIVRUpa4vqqrKi3y5XGZZtlwu4yRJ09Oz/MzzvUcxHslgKP/tDdgpw+cDz8AA8A9PXoGTi1kCwgAAAABJRU5ErkJggg==" nextheight="493" nextwidth="844" class="image-node embed"><p><em>Source: Axelar </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.axelar.dev/dev/general-message-passing/overview"><em>docs</em></a></p><div class="relative header-and-anchor"><h3 id="h-bridge-components">Bridge components</h3></div><div class="relative header-and-anchor"><h3 id="h-gateways">Gateways</h3></div><p>The gateway contracts are deployed on each chain connected to the Axelar network. When a user initiates a cross-chain message, they first interact with a Gateway.</p><div class="relative header-and-anchor"><h3 id="h-incoming-relayers">Incoming Relayers</h3></div><p>Once a Gateway contract receives a message, it emits an event. Incoming relayers pick up the event and submit it to the Axelar network for processing.</p><div class="relative header-and-anchor"><h3 id="h-validator-nodes">Validator nodes</h3></div><p>When Axelar validators receive the event sent by an external chain, they verify that it exists on the source chain and then vote to reach a consensus about its validity. The Gateway only allows actions on the external chain if the Axelar validators reach a consensus threshold.</p><div class="relative header-and-anchor"><h3 id="h-outgoing-relayers">Outgoing relayers</h3></div><p>Like the incoming relayers, outgoing relayers monitor outgoing transaction queues containing cross-chain messages already approved and signed by the validators and periodically submit these transactions to external chains.</p><div class="relative header-and-anchor"><h3 id="h-gas-payment">Gas Payment</h3></div><p>Although a cross-chain transaction touches at least three different chains, thanks to the Gas Receiver contract, the gas can be paid with the native tokens of the source chain.</p><p>To provide a developer-friendly experience, Axelar deploys a Gas Receiver contract to all connected EVM chains. Under the hood, the Gas Receiver estimates the total gas cost required across the source chain, Axelar network, and destination chain. It converts source-chain tokens into AXL, destination-chain tokens, and other required currencies.</p><p>Hence, in our example, we can pay for the entire transaction with tFIL.</p><hr><div class="relative header-and-anchor"><h3 id="h-filecoin-lessgreater-ethereum-example">Filecoin &lt;&gt; Ethereum Example</h3></div><p>Start by importing the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/axelarnetwork/axelar-gmp-sdk-solidity">Axelar Solidity SDK</a> in the source file. We will use three dependencies from the SDK: <code>AxelarExecutable</code>, <code>IAxelarGateway</code>, and <code>IAxelarGasService</code>. We will extend the <code>AxelarExecutable</code> contract and use it to send and receive cross-chain messages on respective chains.</p><img src="https://substack-post-media.s3.amazonaws.com/public/images/e0fa0605-37de-426e-8d5f-c1fc0d4c576c_2434x1118.png" alt="" class="image-node embed"><p>We must provide the address of the Gateway and the Gas Service in the constructor. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.axelar.dev/resources/contract-addresses/mainnet">Here</a> is a list of available gateways and gas services contracts deployed on various supported networks.</p><p>Next, we will add two more functions to our contract to implement a minimal cross-chain message flow. The function <code>sendMessage</code> will trigger a new cross-chain message. Along with the actual message, we will provide <code>destinationChain</code> and <code>destinationAddress</code>. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.axelar.dev/resources/contract-addresses/mainnet">Here</a> is a list of supported destination chain names.</p><img src="https://substack-post-media.s3.amazonaws.com/public/images/4d5b8d6e-f2a1-4b50-b658-17c807b13e3a_1938x984.png" alt="" class="image-node embed"><p>Lastly, we will add one more function: <code>_execute</code>. It will be used on the other side to receive the message. In addition to the message we sent, we will receive the <code>sourceChain</code> and <code>sourceAddress</code>.</p><img src="https://substack-post-media.s3.amazonaws.com/public/images/228abb3f-3dee-4b6e-ad61-bdea7c09a086_1932x590.png" alt="" class="image-node embed"><p>We will deploy this contract on the Filecoin calibration testnet and Ethereum Sepolia to test our minimal cross-chain flow. Here is how to do it using <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/foundry-rs/foundry">Forge</a>. Recall that the constructor arguments are Gateway and Gas Service contract <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.axelar.dev/resources/contract-addresses/testnet">addresses</a> on the respective chains.</p><p><code>forge create --rpc-url &quot;YOUR_RPC_URL&quot; --private-key &quot;YOUR_PRIVATE_KEY&quot; --contracts src/SenderReceiver.sol SenderReceiver --constructor-args 0x999117D44220F33e0441fbAb2A5aDB8FF485c54D0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6</code></p><p>We can trigger the cross-chain message by calling the <code>sendMessage</code> function on the source chain. Finally, remember to <code>abi.encode</code> the actual message as a <code>string</code>.</p><p><code>cast send --private-key YOUR_PRIVATE_KEY --rpc-url YOUR_RPC_URL 0x6e80e2411E8afc76186A2f4955FBf037B95b25FE &quot;sendMessage(string,string,string)&quot; &quot;ethereum-sepolia&quot; &quot;0x6e80e2411E8afc76186A2f4955FBf037B95b25FE&quot; &quot;0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001548656c6c6f2066726f6d20636f6e747261637420410000000000000000000000&quot;</code></p><p>After you have successfully triggered a cross-chain message, you can monitor its status on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://testnet.axelarscan.io/gmp/0xd0a341e3b641a5c57e080aee2351c36bc24790a5d5c0bb50e78acf18ab2c24bb:1">axelarscan</a>.</p><div class="relative header-and-anchor"><h2 id="h-building-with-python-tableland">Building with Python + Tableland</h2></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz">Dan Buchholz</a></p><p>The Tableland SDK is designed for JavaScript/TypeScript applications. For Python developers, there isn&apos;t a great way to get started. We&apos;ll be releasing some official docs to make it easier to set up a Tableland connection shortly, but we wanted to give devs a quick previous as to what they can do.</p><div class="relative header-and-anchor"><h3 id="h-calling-the-registry-with-web3py">Calling the registry with <code>web3.py</code></h3></div><p>The most popular framework for working with blockchains is <code>web3.py</code>, so start by installing this package in your Python project: <code>pip install web3</code>.</p><p>You need the Tableland registry&apos;s ABI (<code>TablelandTables.sol</code>) to interact with the contract. The <code>evm-tableland</code> repo makes this easy with the following steps:</p><p><code>git clone &lt;https://github.com/tablelandnetwork/evm-tableland&gt; cd evm-tableland npm install npm run build cat artifacts/contracts/TablelandTables.sol/TablelandTables.json | jq &apos;.abi&apos; &gt; abi.json</code></p><p>Now that we have the ABI, we can connect to the registry. There are two things we&apos;ll need:</p><ul><li><p>A private key to sign transactions.</p></li><li><p>The provider of the chain&apos;s RPC provider.</p></li></ul><p>The example below shows how you&apos;d do this if you&apos;re connecting to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost:3000/local-tableland/">Local Tableland</a> with a Hardhat account:</p><p><code># Define provider and private key provider_uri = &quot;&lt;http://localhost:8545&gt;&quot; private_key = &quot;59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d&quot; # Set up web3 instance and signer w3 = Web3(Web3.HTTPProvider(provider_uri)) signer = Account.from_key(private_key)</code></p><p>We have the provider and signer. Thus, we can load the ABI and connect to the Tableland registry. If we&apos;re using Local Tableland, the registry address is <code>0xe7f1725e7734ce288f8367e1bb143e90bb3f0512</code>:</p><p><code>from web3 import Web3 from eth_account import Account from eth_utils import to_checksum_address # Existing code... abi_file = &quot;abi.json&quot; # Path to the ABI file abi = read_file_to_json(abi_file) registry_addr = &quot;0xe7f1725e7734ce288f8367e1bb143e90bb3f0512&quot; registry = w3.eth.contract( address=to_checksum_address(registry_addr), abi=abi )</code></p><p>This is all we need to make onchain calls! We can execute both a <code>CREATE TABLE</code> and <code>INSERT</code> statement like so, and for each, we can parse the <code>CreateTable</code> or <code>RunSQL</code> event, respectively:</p><p><code># Create a table table_prefix = &quot;my_table&quot; chain_id =. 31337 # E.g., for Local Tableland + Hardhat node tx_hash_create = registry.functions.create( signer.address, f&quot;CREATE TABLE {table_prefix}_{chain_id} (id integer, val text)&quot; ).transact() create_rec = w3.eth.wait_for_transaction_receipt(tx_hash_create) create_log = registry.events.CreateTable().process_receipt(create_rec) data = create_log[0] table_id = data[&quot;args&quot;][&quot;tableId&quot;] # Write to it table_name = f&quot;{table_prefix}_{chain_id}_{table_id}&quot; tx_hash_mutate = self.registry.functions.mutate( signer.address, table_id, f&quot;INSERT INTO {table_name} VALUES (1, &apos;hello&apos;)&quot; ).transact({&quot;from&quot;: signer.address}) mutate_rec = w3.eth.wait_for_transaction_receipt(tx_hash_mutate) mutate_log = registry.events.RunSQL().process_receipt(mutate_rec) data = mutate_log[0] transaction_hash = data[&quot;transactionHash&quot;].hex()</code></p><div class="relative header-and-anchor"><h3 id="h-experimental-python-sdk">Experimental Python SDK</h3></div><p>There&apos;s an <em>experimental</em> Python SDK that can be used to interact with the Tableland registry. It&apos;s <em>not officially supported</em> (i.e., not an official Tableland package), but it&apos;s a good starting point for Python developers. One of the challenges with the approach above is that you also need to interact with the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost:3000/validator/api/">validator APIs</a> to make sure onchain SQL is successfully materialized.</p><p>The <code>[tableland](&lt;https://github.com/dtbuchholz/tableland-py&gt;)</code> Python library handles this and makes it easier to get started. You can install by running the following command:</p><p><code>pip install tableland</code></p><p>You can import the library and set up the connection in a way that&apos;s similar to the official Tableland JavaScript SDK:</p><p><code>from tableland import Database private_key = &quot;59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d&quot; # Replace with your private key db = Database( private_key=private_key, provider_uri=&quot;&lt;http://localhost:8545&gt;&quot;, # Replace with your RPC provider URL )</code></p><p>Creating a table includes the registry contract call as shown in the walkthrough above, but it also handles waiting for the validator to materialize the SQL and includes error messages in case of syntax issues:</p><p><code># Create a new table statement = &quot;create table my_table (id int, val text)&quot; create_event = db.create(statement) table_name = create_event[&quot;table_name&quot;] table_id = create_event[&quot;table_id&quot;] # Check if there are any errors if create_event[&quot;error&quot;] is not None: print(f&quot;Error: {create_event[&apos;error&apos;]}&quot;)</code></p><p>Once a table is created, writing to it is straightforward and follows a similar pattern.</p><p><code># Insert a row into the table statement = f&quot;insert into {table_name} (id, val) values (1, &apos;hello&apos;)&quot; write_event = db.write(statement) # Check if there are any errors if write_event[&quot;error&quot;] is not None: print(f&quot;Error: {write_event[&apos;error&apos;]}&quot;)</code></p><p>Lastly, the <code>read</code> method lets you write arbitrary SQL statements to query the table:</p><p><code># Query the table statement = f&quot;select * from {table_name}&quot; data = db.read(statement) print(data) # [{&apos;id&apos;: 1, &apos;val&apos;: &apos;hello&apos;}]</code></p><p>If you&apos;re interested in contributing to the library, you can find the source code on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/dtbuchholz/tableland-py">GitHub</a>.</p><div class="relative header-and-anchor"><h3 id="h-going-dark">Going dark</h3></div><p>by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jkosem">Jim Kosem</a></p><p>Colour can count for a lot. Recently with Tableland Studio we’ve been piloting a dark mode colour scheme. This is a bigger deal than you probably think and the history of dark mode is an interesting one. We’ve been working with the idea coming from the angle of Studio being a developer tool, and especially as such, it works first in CLI, and then we bring it to the GUI. This actually matches up with <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://eyeondesign.aiga.org/a-brief-history-of-dark-mode-from-the-matrix-like-displays-of-the-early-80s-to-today/">the origin story of dark mode</a>, which was in early UI designs for text-based terminals.</p><p>Way back when, actually turning on a pixel had computing and energy costs that were comparatively significant. So, it was cheaper to just turn on the ones you needed, which at the time, were for text. Then, as early Windows-based interfaces came to the scene, the thinking was that it should remind all these people new to using computers of paper. So, it all went white. That&apos;s simple, really. There are, of course, other issues in terms of glare and spending long amounts of time reading screens, where dark mode may help, but we’re thinking about the aesthetics and our origin in terminals and paying a bit of homage to that.</p><hr><div class="relative header-and-anchor"><h1 id="h-other-updates-this-week">Other updates t<strong>his week</strong></h1></div><div class="relative header-and-anchor"><h2 id="h-current-hackathons-coming-to-an-end">Current hackathons coming to an end</h2></div><p>We’ve been sponsoring the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://dorahacks.io/hackathon/filecoin-data-economy/detail">Filecoin Data Economy</a> and the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://learnweb3.io/hackathons/decentralized-intelligence-season-2/">LearnWeb3 Decentralized Intelligence</a> hackathons. Projects have made their final submissions, and we’ll be judging and deciding on winners by the end of the week. Check out next week’s post for more details on those projects!</p><div class="relative header-and-anchor"><h1 id="h-end-transmission">End transmission…</h1></div><p>Want to dive deeper, ask questions, or just nerd out with us? Jump into our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://t.me/tablelandxyz">Telegram</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tableland.xyz/discord">Discord</a>—including weekly <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/carsonfarmer/research-office-hours">research office hours</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://calendly.com/dan-buchholz/dev-office-hours">developer office hours</a>. And if you’d like to discuss any of these topics in more detail, comment on the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/weeknotes/issues">issue over in GitHub</a>!</p><blockquote><p>Are you enjoying Weeknotes? We’d love your feedback—if you fill out a quick survey, we’ll be sure to reach out directly with community initiatives in the future!: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hhueol4i6vp.typeform.com/to/pbUwIuWm">Fill out the form here</a></p></blockquote>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Textile)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/c57191fcb0f1ec2ef02efbb76b996bff.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[WeatherXM + Textile: DePIN Data Storage, Retrieval, & Rewards Computation]]></title>
            <link>https://blog.textile.io/weatherxm-textile-depin-data-storage</link>
            <guid>rftAYefL5w0kJ4es5a2o</guid>
            <pubDate>Mon, 08 Apr 2024 18:43:02 GMT</pubDate>
            <description><![CDATA[Open and verifiable DePIN data for transparent rewards and data access]]></description>
            <content:encoded><![CDATA[<div class="relative header-and-anchor"><h2 id="h-tldr">TL;DR</h2></div><p>WeatherXM used Textile to do the following:</p><ul><li><p>Bring open data availability of station/device data and rewards calculations to help progress toward fully decentralized infrastructure and bring transparency to the dataset.</p></li><li><p>Enable verifiable data such that the data is signed at the source, ensuring all data is cryptographically provable with access controls on data mutations.</p></li><li><p>A decentralized framework for computation, such as <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/weatherxm-network/qod">QoD</a>, providing the WeatherXM ecosystem a way to build on top of the data.</p></li></ul><blockquote><p>You can view available “events” (data pushes) <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://basin.tableland.xyz/vaults/wxm.weather_data_dev/events?limit=5">here</a> and extract the device data at the <code>https://basin.tableland.xyz/events/&lt;event_cid&gt;</code> endpoint for further analysis, as described below.</p></blockquote><div class="relative header-and-anchor"><h2 id="h-what-is-it">What is it?</h2></div><p>Textile and WeatherXM are working together to design a solution for DePIN data availability (“DA”), storage, and retrieval. If you’re unfamiliar with WeatherXM, it is a network that's powered by community-owned devices, purpose-built by WeatherXM for weather data collection. As part of the network, stations/devices throughout the globe are incentivized to share data.</p><p>WeatherXM’s goal is to make network data more accessible so developers can build on top of it. The station/device data are replicated to Basin for decentralized storage, allowing for computation over that data. The data flows through Basin, which can support cache with TTL, and is replicated to Filecoin for long-term storage guarantees.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e577fedf44d376fdacd5786cb9649bd6.png" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEj0lEQVR4nG1Uz2/cRBR+PVTiD6iACiqhSohfKgIE7SmiQggQRe0RcSQoUi5wCYQDLRS1QoIDJPzMsfwI7QE1LSogZRt12babZBe7ybrr3bUd27LX3tjetSce73iz9s4grys4tJ9G7zRv3pvve9+DTqejKIppmq7rDodDxthgMKjX67quszGSJLEsyzAMVdMMw9B13fd9SiljLE1ThBDGGCGU594NEAThypUra2trhULB8zzGmCAIly7/XqlUoyhijFFKZVnmOE6W5Xq9Xi6XVVVN05QxRgjheX55eblQKNi2Hcexqqq2bWtjmKYZBAE4jsNxnCRJHMfFccwYUyRRV2VdlT3PHQwGjUZDUbY0TVPGEEVRkqRms5mOsbq6WiwW89w4jmu1miiKtZogSZIgCKZpwl1/om/PzsGzbx6b/DhAO4wxx3E6dsc0zJxJx3EMw/B9/z8Cc+Sk3YOiNE1t02w1GigIGGOe14P7jsCeIwBPXC9zKPA729sk2UU7AQ4xxjhJEoSQYRhhGKqqWiwWl8cwDCNXJbsURZTSNE0ppRBhzK+t1TiuVRejCG9s1uDg63DgNdh7+M+Vkiy1oojcXLhmyV7XdxFCjuOEYajrerPZtCxrZmZmenr61KlT5XI5TUeMsdKNm+++976marl+2Q9USarxvCYrYRhubG7CvgmABwAO/VH4W5JE1w5vfHvZ3lKNdrvX60mS5Hmeruu5zmEY5qQNh0Pbthhjolg/e3r20tLScJhkFFFKW/X6BseFYRhFuMrx8NBL8PBR2PvC1VLVdTqu4+4muySOCIkJIcPhEGNsWZZpmqIouq5brVY1Leu31+thjBljwzQhcXYzK+D3euViscbz25YdRXi9egseP1YqXt3z9Ilr5dq4R4yCjHTHcRRFsSwLYxzHsSzLPM/7vi8IgqqqruuqqprbiPTJiLLRWHUghDRu397keaezjRBar1Rh/1E48ArAc2u8yGiSJBkV7XY7DEPLshFCjDEcRbmGMzMzU1NTs7Oz586dc13X87yacPsfwXKDJJck00BuNNRWixASYbxe4WD/ixMnpuHBieuVGmM0SRPGdr32FkEeITuDOHMfISRJMopXVlbOnz+/tLRkmmY+u90eqtwSDcPMfQooCFZLpRrPd12X9PvrVR4eefmnXy7AoeOFG7cYS5781YTPtuAbHeY0+EqDLzX4Qv3+psEYHY3nZGNjo9ls5oLnj2bzMz5ZAYzxJs9v8nzHtqMoqlR5uH8C4CmAZzhBGcUhnN3KzmkFzijw6Th+0Jr4Wck+RzOjKYqSm8D1XBSgER2pXrutXO1H3p0p8ly367r5nnDcLsDzAPsADlZrTbqLs/ZPK/CRnJU5o8DnKnwoHf5RZmw0YuzixYsLCwuLi4vlcrlerzPGol1yobBY+WuekG5W4P8VMfY6paM33vkEHjv+6KtT7Y5HE/LWbzJ8rcN3ehbntDz+cH0r52B+fn5ycvLkyZOlUil3BqU0DMMdFIwyCvMCNAO71zJJ01HSx0nfH/SDAe4Nwu4A95K+nw4H+fVx6h3ccxf9C5Z99NOIGUY+AAAAAElFTkSuQmCC" nextheight="723" nextwidth="1442" class="image-node embed"></figure><p>Basin is designed to be flexible and work with raw file uploads (e.g., parquet) or even database streaming (e.g., Postgres). Data is replicated to the network in a “vault” and then can be retrieved by the vault’s CIDs for further processing.</p><p>There are two possible data availability options for a vault—hot or cold storage:</p><ul><li><p><strong>Hot layer</strong>: Cache with time-to-live (TTL) where the data is made available for the defined timeline and immediately retrievable (i.e., no need to wait for long propagation or finality times).</p></li><li><p><strong>Cold layer</strong>: Persistence on Filecoin where all data is flushed for long-term retrieval.</p></li></ul><p>This makes it possible to run computation over the open data where both the inputs—and, potentially, outputs—are highly available in the short term and also retrievable after cold storage flushing (e.g., dispute resolution).</p><div class="relative header-and-anchor"><h2 id="h-how-does-weatherxm-use-the-basin-data">How does WeatherXM use the Basin data?</h2></div><p>WeatherXM device data is made available for data consumers through hot + cold storage replication, and this data is used today in a dashboard available at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://index.weatherxm.network/">https://index.weatherxm.network</a>. You’ll notice two tabs on that page:</p><ul><li><p><strong>Weather Data</strong>: Device data located in the Textile vault <code>wxm.weather_data_dev</code></p></li><li><p><strong>Rewards</strong>: Calculations over the device data, located in the Textile vault <code>wxm.rewards_merkle_trees_dev</code></p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d379b1d0b9377a3b619075785ff5c473.png" alt="WeatherXM's dashboard displays the CIDs created when data is pushed to Textile Basin and provides a link to the Basin HTTP API." title="null" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAOCAIAAADBvonlAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB4klEQVR4nJVT227bMAzN///YXocBe+m6Nm1aB1saL7Us3kUOlNs1yW7NASFQluSjwyOuVqtVROx2u9vb25ubm2EYxhH+hohAxO12u7oIEfE0juu7+81m8+HTZngCa0ZsLEosZxERzLac+jdOCPaHsttPD8P39cO35wkqUAWaAUXNmps1a67WWDQiwF4I3qvAPQCZWCogEREzUk6RCJCQcgpIrNra2+0uUODuolkNVTve0dwrYAdBJvzw+Lgdhs9f7j9+3bs7i4maqLKcB4m+qXR3NeOIQw3Ki6q/Io5AxOvNsN4M13fD9qlEhFlY83a6bTnl7ucEHmEtIb3QvzgWhLuq7cfDj8NUZpwrLOM01ywsS38R+S4Wn1iOfHJ3Sy8diVpr81z7+VorzBUq5AiAuVSBiM9qjUi5oY9EDICdQE4IFveYxT0QX0wGTJOJFPOKailOKG1vhX7TeIRzgqurK2vGLMzcWuuWcneXMl9MRmIWERURazFD1uGPUM0lOS5RRIzj+N83p11mr0BjogrwEr2AtWYizJC9GHZRr0Tf1zqBSL4xNaNUk8Gqqf7VXuwE7u2E4D1do/1HU5nVDBCfpzJNpZRaSs28lOepiHDhAL5QwfElpmnqYyYdS/L6pS8dd/JPb0giWsMp6BIAAAAASUVORK5CYII=" nextheight="793" nextwidth="1811" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>We also built a demonstration of how developers can use the DePIN network’s data in the downstream compute and visualization pipeline. One of WeatherXM’s goals is to progressively decentralize their stack, and Basin is a key component to making that possible. We wanted to provide a way for developers to see exactly how they can build on top of the public dataset and add value to the WeatherXM ecosystem.</p><blockquote><p><em>We built a demonstration about how you can leverage WeatherXM and run queries over the data, which we’ll walk through below. You can review the</em> <code>Data.md</code> for the final visualizations that plot WeatherXM network data over historical trends and across the globe.<strong><em>Check it out here</em></strong>*: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/textileio/demo-basin-wxm-query">https://github.com/textileio/demo-basin-wxm-query</a>*</p></blockquote><div class="relative header-and-anchor"><h2 id="h-how-does-basin-work">How does Basin work?</h2></div><div class="relative header-and-anchor"><h3 id="h-background">Background</h3></div><p>The setup process for WeatherXM involved:</p><ul><li><p>Creating a vault with the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tablelandnetwork/basin-cli">Basin CLI</a>, which is an onchain interaction signed by a private key.</p></li><li><p>Aggregating device data that is processed by internal systems for <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.weatherxm.com/weatherxm-qod-quality-of-data-simplified-b5a42aee7367">Quality of Data</a> purposes.</p></li><li><p>Replicating internal data to the Basin DA layer on a consistent schedule—i.e., parquet files containing device data are written to the vault and signed by a private key.</p></li></ul><p>Once that data is available, anyone with knowledge of the unique vault identifier or vault owner’s address can extract and process the data. It’s openly accessible on the Basin network and through the cold layer. In our demo described below, we built a program that consists of:</p><ul><li><p>A Python script to fetch remote parquet files written to the vault, filtered over a time range, and identified at an IPFS CID.</p></li><li><p>A DuckDB in-memory SQL database for loading parquet files and executing queries.</p></li><li><p>Writing the query results to a CSV and markdown files and producing data visualization with geopandas (e.g., precipitation rate per geography).</p></li><li><p>Running the steps above weekly with GitHub Actions.</p></li></ul><p>You could imagine more complex flows with Docker images or compute networks like <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.bacalhau.org/">Bacalhau</a>, but the idea was to keep things lightweight to showcase how to interact with open, verifiable data.</p><div class="relative header-and-anchor"><h3 id="h-viewing-and-retrieving-weatherxm-data">Viewing &amp; retrieving WeatherXM data</h3></div><p>If you want to understand the basics behind Basin, you can start by installing the CLI on your machine. Make sure the path to Go binaries is in your shell’s <code>PATH</code> variable (e.g., include <code>$(go env GOPATH)/bin</code>).</p><pre data-type="codeBlock"><code>go install github.com/tablelandnetwork<span class="hljs-operator">/</span>basin<span class="hljs-operator">-</span>cli<span class="hljs-operator">/</span>cmd<span class="hljs-operator">/</span>vaults@latest</code></pre><p>Then, you can take a peek at what the structure and data within a vault look like. For example, list all vaults created by a specific account/address:</p><pre data-type="codeBlock"><code>vaults list <span class="hljs-operator">-</span><span class="hljs-operator">-</span>account <span class="hljs-number">0x75c9eCb5309d068f72f545F3fbc7cCD246016fE0</span></code></pre><p>Or, list out the events associated with a vault:</p><pre data-type="codeBlock"><code>vaults events <span class="hljs-operator">-</span><span class="hljs-operator">-</span>vault wxm.weather_data_dev</code></pre><p>Which provides the “events” (i.e., vault mutations &amp; CIDs) for the vault. Note the <code>cache_expiry</code> field shows when the highly available data will expire from the cache.</p><pre data-type="codeBlock"><code><span class="hljs-punctuation">[</span>
  <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"cid"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"bafybeicizws2qymmcn657b3qa7rm2w2lz4bdumxc6b66jw4ac4fsrhmsxm"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"timestamp"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1709078400</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"is_archived"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"cache_expiry"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2024-05-16T20:56:47.379695"</span>
  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
  <span class="hljs-punctuation">{</span>
    <span class="hljs-attr">"cid"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"bafybeigppam7v3uwarke5iulytgptdj6hzjta5kye7nljbvemzje6r3xma"</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"timestamp"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1709596800</span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"is_archived"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span>
    <span class="hljs-attr">"cache_expiry"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2024-05-16T19:49:50.277204"</span>
  <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">]</span></code></pre><p>This period is defined upon vault creation such that all files written to the vault follow the same expiry logic. Note the data is flushed to cold storage and still available after the cache expiration. The CIDs can then be retrieved and processed locally:</p><pre data-type="codeBlock"><code>vaults retrieve <span class="hljs-operator">-</span><span class="hljs-operator">-</span>output <span class="hljs-operator">&lt;</span>filename<span class="hljs-operator">&gt;</span> <span class="hljs-operator">&lt;</span>event_cid<span class="hljs-operator">&gt;</span></code></pre><div class="relative header-and-anchor"><h2 id="h-demo-how-to-use-weatherxm-data">Demo: How to use WeatherXM data</h2></div><p>Now that we understand how Basin works, we can review some of the demo’s features since it builds on top of the WeatherXM vault data. The first step is to get all of the vaults for a specific address and then retrieve all of the events and CIDs for the vaults. This can be done programmatically with the Basin HTTP API (where <code>{variable}</code> would be replaced by actual string values—e.g., <code>account=0x75c9eCb5309d068f72f545F3fbc7cCD246016fE0</code>):</p><ul><li><p>Get vaults for address: <code>curl https://basin.tableland.xyz/vaults?account={address}</code></p></li><li><p>Get events for vault: <code>curl https://basin.tableland.xyz/vaults/{vault}/events</code></p></li><li><p>Download the raw data at an event: <code>curl https://basin.tableland.xyz/events/{event_cid} -o data.parquet</code></p></li></ul><p>Let’s presume the files have been downloaded at each event for WeatherXM’s vault into some <code>data_dir</code> directory. We then load these parquet files into a DuckDB in-memory instance.</p><pre data-type="codeBlock"><code><span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path

<span class="hljs-keyword">from</span> duckdb <span class="hljs-keyword">import</span> connect

<span class="hljs-keyword">def</span> <span class="hljs-title function_">create_database</span>(<span class="hljs-params">data_dir</span>):
    db = connect()
    files = Path(data_dir) / <span class="hljs-string">"*.parquet"</span>  <span class="hljs-comment"># Read all parquet files in data directory</span>
    db.execute(<span class="hljs-string">f"CREATE VIEW xm_data AS SELECT * FROM read_parquet('<span class="hljs-subst">{files}</span>');"</span>)

    <span class="hljs-keyword">return</span> db</code></pre><p>We can now run queries over the WeatherXM device data! This will calculate average or aggregate metrics for temperature, precipitation, wind, etc., and create a DataFrame for subsequent processing.</p><pre data-type="codeBlock"><code><span class="hljs-keyword">def</span> <span class="hljs-title function_">execute_queries</span>(<span class="hljs-params">db, start, end</span>):
    <span class="hljs-comment"># Set up columns for average calculations</span>
    columns = [
        <span class="hljs-string">"temperature"</span>,
        <span class="hljs-string">"humidity"</span>,
        <span class="hljs-string">"precipitation_accumulated"</span>,
        <span class="hljs-string">"wind_speed"</span>,
        <span class="hljs-string">"wind_gust"</span>,
        <span class="hljs-string">"wind_direction"</span>,
        <span class="hljs-string">"illuminance"</span>,
        <span class="hljs-string">"solar_irradiance"</span>,
        <span class="hljs-string">"fo_uv"</span>,
        <span class="hljs-string">"uv_index"</span>,
        <span class="hljs-string">"precipitation_rate"</span>,
        <span class="hljs-string">"pressure"</span>,
    ]

    <span class="hljs-comment"># Set up all query parts</span>
    avg_selection = [<span class="hljs-string">f"avg(<span class="hljs-subst">{col}</span>) AS <span class="hljs-subst">{col}</span>"</span> <span class="hljs-keyword">for</span> col <span class="hljs-keyword">in</span> columns]
    avg_calculations = <span class="hljs-string">","</span>.join(avg_selection)
    query_parts = [
        <span class="hljs-string">"SELECT min(timestamp) AS range_start, max(timestamp) AS range_end,"</span>,
        <span class="hljs-string">"COUNT(DISTINCT device_id) AS number_of_devices,"</span>,
        <span class="hljs-string">"mode(cell_id) AS cell_id_mode,"</span>,
        <span class="hljs-string">"sum(precipitation_accumulated) AS total_precipitation,"</span>,
        avg_calculations,
    ]

    <span class="hljs-comment"># Add WHERE clause for time filtering, if applicable</span>
    where_clause = <span class="hljs-string">""</span>
    <span class="hljs-keyword">if</span> start <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">and</span> end <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        where_clause = <span class="hljs-string">f"WHERE timestamp &gt;= <span class="hljs-subst">{start}</span> AND timestamp &lt;= <span class="hljs-subst">{end}</span>"</span>
    <span class="hljs-keyword">elif</span> start <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        where_clause = <span class="hljs-string">f"WHERE timestamp &gt;= <span class="hljs-subst">{start}</span>"</span>
    <span class="hljs-keyword">elif</span> end <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        where_clause = <span class="hljs-string">f"WHERE timestamp &lt;= <span class="hljs-subst">{end}</span>"</span>

    <span class="hljs-comment"># Combine all parts into one query and execute</span>
    query = <span class="hljs-string">" "</span>.join(query_parts) + <span class="hljs-string">" FROM xm_data"</span> + <span class="hljs-string">f" <span class="hljs-subst">{where_clause}</span>"</span>
    <span class="hljs-keyword">try</span>:
        result = db.execute(query).pl()  <span class="hljs-comment"># Create a polars DataFrame</span>
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Error executing DuckDB aggregate queries: <span class="hljs-subst">{e}</span>"</span>)
				<span class="hljs-keyword">raise</span></code></pre><p>Lastly, we can use geopandas to create visualizations from the returned DataFrame. In the example, there are a few rough bounding boxes (“bbox”) for each major continent with lat/long bounds:</p><pre data-type="codeBlock"><code>bboxes = {
    <span class="hljs-string">"north_america"</span>: (14, 72, -172, -52),
    <span class="hljs-string">"south_america"</span>: (-55, 12, -85, -34),
    <span class="hljs-string">"europe"</span>: (35, 72, -13, 60),
    <span class="hljs-string">"africa"</span>: (-35, 38, -18, 55),
    <span class="hljs-string">"asia"</span>: (-11, 81, 25, 179),
    <span class="hljs-string">"australia"</span>: (-48, -6, 108, 178),
}</code></pre><p>For example, this calculates the total precipitation accumulated by <code>cell_id</code> within a bounding box:</p><pre data-type="codeBlock"><code><span class="hljs-keyword">def</span> <span class="hljs-title function_">query_bbox</span>(<span class="hljs-params">db, bbox, start, end</span>):
    <span class="hljs-comment"># DuckDB query to select and aggregate data within the bounding box</span>
    query = <span class="hljs-string">f"""
    SELECT cell_id, SUM(precipitation_accumulated) as total_precipitation, AVG(lat) as lat, AVG(lon) as lon
    FROM xm_data
    WHERE lat BETWEEN <span class="hljs-subst">{bbox[<span class="hljs-number">0</span>]}</span> AND <span class="hljs-subst">{bbox[<span class="hljs-number">1</span>]}</span> AND lon BETWEEN <span class="hljs-subst">{bbox[<span class="hljs-number">2</span>]}</span> AND <span class="hljs-subst">{bbox[<span class="hljs-number">3</span>]}</span>
    """</span>

    <span class="hljs-comment"># Add WHERE clause for time filtering, if applicable</span>
    where_clause = <span class="hljs-string">""</span>
    <span class="hljs-keyword">if</span> start <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">and</span> end <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        where_clause = <span class="hljs-string">f"AND timestamp &gt;= <span class="hljs-subst">{start}</span> AND timestamp &lt;= <span class="hljs-subst">{end}</span>"</span>
    <span class="hljs-keyword">elif</span> start <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        where_clause = <span class="hljs-string">f"AND timestamp &gt;= <span class="hljs-subst">{start}</span>"</span>
    <span class="hljs-keyword">elif</span> end <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        where_clause = <span class="hljs-string">f"AND timestamp &lt;= <span class="hljs-subst">{end}</span>"</span>

    <span class="hljs-comment"># Combine all parts into one query and execute</span>
    query = query + <span class="hljs-string">f" <span class="hljs-subst">{where_clause}</span>"</span> + <span class="hljs-string">" GROUP BY cell_id"</span>
    <span class="hljs-keyword">try</span>:
        result = db.execute(query).df()  <span class="hljs-comment"># Create a pandas Dataframe</span>
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
				<span class="hljs-built_in">print</span>(<span class="hljs-string">f"Error executing DuckDB bbox query: <span class="hljs-subst">{e}</span>"</span>)
				<span class="hljs-keyword">raise</span></code></pre><p>By taking the pandas DataFrame and passing it to geopanda’s <code>GeoDataFrame</code> method, you can create maps that plot data at lat/long coordinates, such as the one described above for the North American bbox. The history CSV file also plots information week-over-week—below is what the device trends look like (hint: the number of devices is increasing!):</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8d7e46bdc57da6ff7243354261d4a0ee.png" alt="A simple demo of computing the number of devices and precipitation plot over the WeatherXM vault." title="null" blurdataurl="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAIAAAD4YuoOAAAACXBIWXMAAAsTAAALEwEAmpwYAAACpklEQVR4nJVUTXPaMBD1P8+p004PPfQP5NYfkOm5mem0PWSaBGgIGAMBbGNjjPVlydJKsjq2AyEc2vBG45F2xvt235PW894Mdw7Kpyfn3BmpPc+jjGFCkm2+yXeEkHyb5fm2W1mWLaI43eZCcM7LApfb3SeEwjNK8zwv2mSLNPsTzPvBfJWm1mpjAECqdhFGp6uYC26MRIT29fscL89Qx/O8RRwP54v7kX8/mvT8abJJGSVClJUUrKRaK1FxpZo9xuQz+7rMo+ffKaXGmP82sUN4vS2WySZM0skyGowDgpGSApQQJYvX6yRNMCqSbLNYrT9kv5d5+koirfUrl8qSEMJacM6dc0ZrpZSopHN1QehwOmOUcM4EL8uShovlQ//h5ub2djh6itbvRr1fg8ELgVIKY2yM0XvII4BSAECFxLwivAIAxNjt0B8ORwQjwUu0y3nJ0iQZ+NP7cTAP4493o4G/98A5BwAdwQG2RW2tMbZUGguQSjfxtgpMWW8cDCbTvNhpKRZhGCzDh3HQbwlmq+jy5yxK82cCIQRjjFKqtT7hUKAxV1zqjs9aCwBG6wKTu0e/508HkxmmJErTP8Gs70+G09ndoz9dra6u/Cjae0AIQQidEFhrhQLEm7KbNvbQWgMoIVW4LeK8WG7ypEBcSm3MltCkQGGWZ5h8//KYRvsOAIBzTghp8zapjTFEAK2gPR531dx855y1tqoaM7Is45xzKcGAMUZCA2PMt8sf8Sx+ZTJCyBijQDPZKg66biR55jtIdLjQhxf+pkkgpcSEICoKwmnJuRBVVYn9t9t0EEI45+q6/vcIuL6+fqHvQnVda60PJbd2WAA4cf4g0RkdKKWad3SkQ1238ljLGDsEu/jxdDpjXl5cXDjnLlqcNNsFD+gib0/9F/8bWV6go5GrAAAAAElFTkSuQmCC" nextheight="930" nextwidth="1836" class="image-node embed"><figcaption htmlattributes="[object Object]" class="hide-figcaption"></figcaption></figure><div class="relative header-and-anchor"><h2 id="h-how-can-someone-use-it">How can someone use it?</h2></div><p>If you’d like to develop with or alter the demo code, start by cloning the repo and going through the setup steps described in the README.</p><pre data-type="codeBlock"><code>git <span class="hljs-built_in">clone</span> https://github.com/textileio/demo-basin-wxm-query</code></pre><p>Then, you can use the <code>make run</code> command to fetch events and compute queries over the data for the WeatherXM vault. You can also choose to pass <code>start</code> and <code>end</code> parameters to the <code>make run</code> command, which specifies timestamp ranges for data extraction.</p><p>If you want to use the WeatherXM data, the Basin HTTP APIs described in the sections above should provide all that you need. Namely, you can fetch the events and download the parquet files locally—or event load remote data into DuckDB from an IPFS gateway!</p><div class="relative header-and-anchor"><h2 id="h-next-steps">Next steps</h2></div><p>This is just the first post in a series of Basin data demonstrations. We’ll continue to put out additional walkthroughs in long-form posts, but if you’d like to stay up to date with what we’re building on a week-by-week basis, check out the Weeknotes newsletter on Substack!</p><p></p>]]></content:encoded>
            <author>textileio@newsletter.paragraph.com (Textile)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/e577fedf44d376fdacd5786cb9649bd6.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>