<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[3Box Labs - Medium]]></title>
        <description><![CDATA[We creates software for a more open, safe and collaborative web. We’re building Ceramic and ComposeDB. - Medium]]></description>
        <link>https://medium.com/3box?source=rss----32f96b75b1ef---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>3Box Labs - Medium</title>
            <link>https://medium.com/3box?source=rss----32f96b75b1ef---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 02 Mar 2026 16:05:20 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/3box" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Thinking of getting into blockchain? 6 things to consider]]></title>
            <link>https://medium.com/3box/thinking-of-getting-into-blockchain-6-things-to-consider-fd851090dd15?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/fd851090dd15</guid>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[decentralized-technology]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[crypto]]></category>
            <category><![CDATA[identity]]></category>
            <dc:creator><![CDATA[Danny Zuckerman]]></dc:creator>
            <pubDate>Mon, 10 May 2021 13:57:35 GMT</pubDate>
            <atom:updated>2021-05-13T12:49:55.594Z</atom:updated>
            <content:encoded><![CDATA[<h3>Thinking of getting into blockchain? 6 things to consider.</h3><p>In 2017, during crypto’s last bull run and after years of pointedly ignoring blockchain hype, I <a href="https://dazuck.medium.com/joining-consensys-decentra-mania-bd37858eb2b2">jumped down the rabbit hole</a>. I began to see crypto networks as the best coordination tool we’ve ever had. I met the most passionate, curious, interesting people I’ve ever worked with. And I loved that the challenges to overcome were organizational, economic, and political as much as technical.</p><p>In the past four years, I’ve collaborated with dozens of teams, helped found <a href="http://3boxlabs.com">3Box Labs</a> (a company) and launch <a href="http://ceramic.network">Ceramic Network</a>, and worked with several DAOs. The potential, challenges, and excitement in the space are still similar to 2017. But the range of experiments, opportunities, and team types is now incredibly broad.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V7yJ-hXVSSy0ghcuqKYRtg.png" /></figure><h3>What to consider as you jump down the rabbit hole</h3><h4><strong>1. Join a community, not just a team.</strong></h4><p>One of Plaid’s hiring criteria was “Did they read the docs?” In the crypto space, it’s “Did they join the community?”</p><p>Hop into the discord or slack, get a sense of the developers and users and how they are engaged. Picking a team without understanding the community would be like getting engaged before meeting your partner’s friends or family.</p><h4><strong>2. Be honest about what you’re in it for, and choose accordingly.</strong></h4><p>The pace of activity in the space is completely overwhelming. Make sure you land in a spot where that will drive your motivation not drain it.</p><p>If you enjoy constant, multi-disciplinary, frenetic learning and excitement, happy hours that veer back to interesting ‘work’ topics, and the feeling of a quasi-cult-like movement — you’ve found your tribe. Look for teams that were building through the last few years’ bear market. Protocol teams, DAOs, and the early DeFi builders. Join one working on something <em>you really care about</em> because you’ll need deep motivation to keep focus and energy.</p><p>If you want more balance or stability, the bull run has given rise to more traditional companies — exchanges (the new banks), infrastructure providers (picks and shovels), and creative studios — that build on this movement but in a more familiar setting. It’s a bit more sustainable and ‘normal.’</p><p>If you are in it for the money, there are plenty of DeFi projects with millions of dollars to spend. Or consider keeping your stable income and investing it in crypto.</p><h4><strong><em>3. How </em>do you like to work?</strong></h4><p>While the world has been adjusting to remote work, many crypto teams are native to it and push organizational experiments far beyond that.</p><ul><li>Do you want an office with teammates? Select for this, as most are remote</li><li>Real-time or asynchronous? Plenty of teams work purely off PRs and tickets, gaining massive flexibility but losing face time.</li><li>Radically flat, traditional org structure, or experimental? Do you want the empowerment promised by new org designs or the clarity of clear structures?</li></ul><p><strong>Could you work for a protocol?</strong></p><p>Many projects aim to (or already have) pass most power to a DAO or community. See how Yearn Finance <a href="https://gov.yearn.finance/t/how-we-think-about-yearn/7137">describes itself</a>. Does the idea of working with complete freedom and a loose association with other community members excite you and feel like the next era of organizations? Or does it seem like the death of coherence, agility, and coordination at scale? Understand a team’s long-term plan for the company and DAO, and if/when that is in the future.</p><h4><strong>4. How do you gauge progress?</strong></h4><p>Teams have different DNAs for how much to focus on technical advances, growth and sales, the long-term vision, or product adoption. This gap is wider than normal in the blockchain space because we’re so early — there’s so much green space, less obvious metrics, more delayed feedback, and some self-delusion about what’s working and what’s not.</p><p>Understand if teams are <a href="https://www.notion.so/Hiring-post-1dd60bc54c5d4302913951e8d126f02a">engineering, vision, or product-led</a> and what the upsides and downsides to this are, and think about whether those will match your own instincts. If you are instinctively drawn towards growth but the team holds ideology more dear, you could be very frustrated with the roadmap and strategy.</p><h4><strong>5. Understand crypto compensation.</strong></h4><p>Startup employees are used to salary, bonus, and equity. In crypto, there are also <em>tokens.</em> They are more liquid, more volatile, often higher upside, and sometimes far less tax-efficient than stock options. Know your situation and what combination of income you care about, and make sure the team you join is keeping the incentives of the founders, team, and investors aligned for the long term. <a href="https://ricburton.substack.com/p/the-liquidity-liability">This article</a> offers a good primer.</p><h4><strong>6. Principles and values matter more than ever.</strong></h4><p>Culture is what defines behavior in the absence of clear rules, and in projects with smaller teams and bigger communities, the early norms and values carry more burden than ever. Understand both what the team stands for <em>and</em> how they instantiate their values in their operations and their community.</p><p><a href="https://twitter.com/VitalikButerin/status/1343366729427079169">As Vitalik said</a>, “Even a billion dollars can’t compete with a project having a soul.” Make sure you believe fully in the culture being created and can see yourself as one of its core carriers.</p><h3>3Box Labs is hiring</h3><p>At <a href="http://3boxlabs.com">3Box Labs</a>, we are on a mission to transform the web’s relationship with data. If you are impact-driven, curious and bold, and care deeply about improving the web, we’d love to <a href="http://jobs.lever.co/3box">hear from you</a> — we’re hiring across our Engineering, Product, and Growth teams.</p><p>Our team is built around <a href="https://www.notion.so/threebox/About-3Box-Labs-7100eadf86624b1ba00793da29a08711">1 purpose, 5 core beliefs, and 8 guiding principles</a> as we work to build a community that can have as much impact as our tech. This means:</p><ul><li>Tangible impact on the future of the web from the center of the decentralized tech movement</li><li>Ownership over novel challenges as we scale and tokenize Ceramic Network</li><li>Collaboration with a world-class technical team (and partners) to create protocols and products</li><li>Constant feedback and usage from a rapidly growing open source community</li><li>Remote and flexible work, with frequent regional meetups and team retreats in amazing places</li><li>Huge upside through equity and the network, globally competitive comp, great benefits</li></ul><p><strong>Find all our </strong><a href="http://jobs.lever.co/3box"><strong>open jobs here</strong></a>, or reach out to <a href="mailto:jobs@3box.io">jobs@3box.io</a> and tell us what you’d like to do and why you’d be a great addition.</p><p><a href="http://3boxlabs.com">3Box Labs</a> | <a href="http://ceramic.network">Ceramic website</a> | <a href="http://twitter.com/ceramicnetwork">Twitter</a> | <a href="http://chat.ceramic.network">Discord</a> | <a href="http://github.com/ceramicnetwork/ceramic">GitHub</a> | <a href="http://developers.ceramic.network">Documentation</a> | <a href="http://blog.ceramic.network">Blog</a> | <a href="http://idx.xyz">IDX Identity</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fd851090dd15" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/thinking-of-getting-into-blockchain-6-things-to-consider-fd851090dd15">Thinking of getting into blockchain? 6 things to consider</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Entering the age of data privacy]]></title>
            <link>https://medium.com/3box/entering-the-age-of-data-privacy-7c3451ed3a57?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/7c3451ed3a57</guid>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[gdpr]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[identity]]></category>
            <category><![CDATA[privacy]]></category>
            <dc:creator><![CDATA[Danny Zuckerman]]></dc:creator>
            <pubDate>Thu, 12 Nov 2020 00:02:15 GMT</pubDate>
            <atom:updated>2020-11-12T00:02:17.034Z</atom:updated>
            <content:encoded><![CDATA[<h3>When regulation, new tech, and public opinion converge</h3><p>On May 25, enforcement begins under the European Union’s General Data Privacy Regulation (GDPR). This long-awaited regulation attempts to put the genie of digital personal data back in the proverbial bottle. Web companies were the first to realize the potential goldmine that is user data and began building businesses around it, attracting users and profits through a model of free services that generate data to sell or consumers to target. ~20 years into this model, public opinion and law-makers have realized the huge costs we’re suffering by letting people be turned into the product. Data breaches and abuses are perhaps the most visible, but huge inefficiencies and massive power in the hands of a few internet monopolies may be just as impactful.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*S-meZ13TBo1bEjJURZhRgg.png" /><figcaption>From Larry Diar <a href="https://diar.co/volume-2-issue-17/">https://diar.co/volume-2-issue-17/</a></figcaption></figure><p>Many businesses are scrambling to meet the new compliance standards. It’s a sweeping regulation that impacts any business operating in the EU, collecting data from EU citizens, or doing any business in the EU, so the impact is global. Interested observers are waiting to see how some of the more vague language will be interpreted and how aggressively regulators will pursue potentially massive fines (up to 4% of a company’s <em>global revenue). </em>Meanwhile, <strong>a few are pondering a very different set of questions: how do regulations built for Web2 complement the new models we are building for Web3?</strong></p><p>New cryptographic and decentralized technologies — most notably blockchains — have the potential to build data privacy into the core of digital systems. Developed while the GDPR and similar regimes were being drafted, the spirit of the technology and regulations are kindred: more control in users’ hands, more responsibility required of 2nd and 3rd parties. But it’s unclear in ways how the ‘letter of the law’ will apply to this new technology.</p><p>Thinking about how these simultaneous legal and technological changes, and shifts in social expectations, interact is key to planning for a more privacy-preserving future. While there are a few apparent incompatibilities — for example, the right to be forgotten on an immutable ledger — good design principles that help all parties make informed decisions can let these operate well together. <strong>Regulations and new technology that aim for ‘privacy by design,’ along with mounting public pressure for good data controls, can combine to usher in a new age of data privacy and user-control.</strong></p><h4>Private protections via public ledgers</h4><p>Blockchains like Ethereum are public ledgers: they store pieces of data on a shared system that anyone can access, and nobody can delete. One of the things this enables is a new <a href="https://www.nytimes.com/2018/01/16/magazine/beyond-the-bitcoin-bubble.html">‘identity layer’ for the Internet</a>, giving users control of their personal data.</p><p>This would change the dynamics of digital interactions, likely altering the currently popular model of collecting and monetizing vast amounts of consumer data — the practice that led to regulations like GDPR. This new dynamic is now possible because decentralized technologies can let us build a decentralized consensus around who somebody is, rather than relying on centrally built and managed silos like Facebook or governments.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9vrZMNTqYGAJyOFds5V9iA.png" /></figure><p>There’s an irony to using a public ledger to enable and protect private data. If personal data were put on Ethereum, that data would be permanently public for all to see and use. That is, of course, not what we’re doing at 3Box. As detailed in our <a href="https://medium.com/uport/privacy-preserving-identity-system-for-ethereum-dapps-a3352d1a93e8">approach to privacy-preserving identity</a>, this new system relies on a public ledger but minimizes what data is actually put there.</p><p><strong>All that needs to be stored on-chain is decentralized identifier (DID), which is just a random string of characters. </strong>It’s currently not explicit whether these addresses will be classified as personal information under GDPR. Some precedent and the treatment of IP addresses suggests it may, at least in some cases. However, the DID itself tells nothing about the user: it is simply a random public address that a user claims control of through a private key in order to interact with others via a decentralized identity.</p><p><strong>The personal data associated with a DID is controlled privately by the user</strong>. This data can be stored on private servers and encrypted so nobody but the user has access, can be pseudonymous so even when the user shares it doesn’t tie to their identity, and can be deleted anytime the user chooses. The only thing public is coded ‘pointers’ between the users DID and servers where the information is stored.</p><p><strong>Multiple keys are used so that even pseudonymous identities can’t be correlated. </strong>In 3Box’s system, a user can have many keys linked to a given identity and many identities, giving many ways to manage sharing or pseudonymity.</p><p><strong>This combination does require </strong><a href="https://medium.com/@lyricalpolymath/web3-design-principles-f21db2f240c1"><strong>thoughtful design </strong></a><strong>to help users, who act as their own data controller. </strong>Personal data does not need to be stored publicly — but it certainly can be. Many products, proposals, and open source projects would enable users write personal data to a blockchain if they chose to, and once this is done it cannot be undone. While we cannot control what’s possible in a world of open-source software, we can help developers and users <a href="https://medium.com/uport/different-approaches-to-ethereum-identity-standards-a09488347c87">make good decisions</a>. GDPR does not really anticipate situations in which the user is their own controller, and their own legal obligations to themselves.</p><p>Done right, users never have to disclose their personal data publicly <em>and </em>get all the benefits of an immutable, user-controlled transaction history. As one example of the flaws of today’s system: <a href="https://www.creditcards.com/credit-card-news/ftc-credit-report-mistakes-1270.php">21% of credit reports have erroneous data in them. </a>Immutable transaction records would enable proof of origination to prevent this (and the billions of dollars spent each year on identity resolution, with companies trading user data back and forth), while not requiring that users ever disclose their personal data.</p><p>This system isn’t just more secure, it can be more private and far more powerful. Not just for users, but for businesses too: it will make it possible for companies to deliver the same or richer user experience without the risk &amp; cost of holding customer data.</p><h4>Adoption through value, not just compliance &amp; tech</h4><p>It’s great that the EU is taking serious steps to curb data abuses, and GDPR may have a significant impact on corporate responsibility. It’s doubtful it will lead to wholesale shift in how data is treated today, with it primarily in the control of organizations. And while public opinion seems to be shifting to demand more security and privacy, convenience and complacency still reign in many cases.</p><p>To shift Web3 to a user-centric model, with data truly in the hands of users, will require something more: value. The new model and technologies we are creating ultimately need to show their worth not through ethics and laws but through products and services that give people and organizations obvious value. And while we have work to do, our model will provide enormous reasons for identities of all types to adopt:</p><ul><li>Save users from identity theft and data breaches (Equifax alone cost an estimated $4bn) and protect organizations against cybercrime, estimated to be $<a href="https://www.forbes.com/sites/louiscolumbus/2017/12/10/2017-roundup-of-internet-of-things-forecasts/#771dd60c1480">6tn </a>by 2021</li><li>Give consumers a route to some of the $100bn+ that Facebook &amp; Google collect in ad revenue, and businesses a more effective way to discover and serve their highest value customers</li><li>Make large data sets &amp; rich customer histories available to startups, reducing barriers to competition</li><li>Give users infinitely granular <a href="http://ec.europa.eu/justice/data-protection/files/factsheets/factsheet_data_protection_eurobarometer_240615_en.pdf">control </a>over their devices, accounts, relationships, and digital services</li><li>Reduce the 83% of adults who worry about identity theft, and the 40% who lose a password every week</li></ul><p>The GDPR in Europe may lead to some huge steps in curbing data breaches and giving users more control. It remains to be seen how regulators will treat public ledgers, a relatively new and unconsidered technology, but we’re confident they are complementary. The identity models being built on blockchain tech can not only enable the privacy and security the law aims for, but can drive widespread adoption of data rights and protections well beyond what the regulation calls for.</p><h4><strong><em>Join the conversation in the </em></strong><a href="http://chat.3box.io"><strong><em>3Box discord community</em></strong></a><strong><em>.</em></strong></h4><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7c3451ed3a57" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/entering-the-age-of-data-privacy-7c3451ed3a57">Entering the age of data privacy</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The 3 parts of identity in a dynamic world]]></title>
            <link>https://medium.com/3box/the-3-parts-of-identity-in-a-dynamic-world-f94724c2bae9?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/f94724c2bae9</guid>
            <category><![CDATA[identity]]></category>
            <category><![CDATA[data]]></category>
            <category><![CDATA[personal-data]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[blockchain]]></category>
            <dc:creator><![CDATA[Danny Zuckerman]]></dc:creator>
            <pubDate>Wed, 11 Nov 2020 23:58:50 GMT</pubDate>
            <atom:updated>2020-11-11T23:58:52.324Z</atom:updated>
            <content:encoded><![CDATA[<p>At 3Box we live and breathe identity, and while GDPR and data abuses like Facebook’s may be concerning, they have also brought some welcome attention to the issues of digital privacy and data control. As we push ahead to a self-sovereign future, I wanted to share how I think of the 3 parts of identity in our increasingly digital, interwoven society.</p><h4><strong>1. Reducible identifier</strong></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/728/0*s_cxhY0ja0gW8nmH" /></figure><p>Identity as a concept is difficult — even scholars in the field can’t agree on a definition. They do agree, though, that identity for each of us is not singular and static but rather plural and dynamic. Who we are changes over time and contexts. However, <strong>we as people and societies and institutions need something concrete to pick me out from the crowd of others</strong>, even others who may share my same name. In <a href="https://www.amazon.com/Seeing-like-State-Certain-Condition/dp/0300078153">Seeing Like a State </a>James Scott calls this ‘legibility.’ When we get past local communities and the Dunbar number, we need to make society understandable. We reduce things to lists and bits of information, and one of the must fundamental bits of information is who we are.</p><p><strong>We need a legible, concrete, reducible identity. </strong>This leads to passports, social security numbers, and other root identifiers from the physical world. Much of the work in the identity industry is around verifying and authenticating who somebody is in this regard, whether through knowledge questions, facial or bio metric scan, or proof that they know a password or hold a private key.</p><h4>2. Contextual identification</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*V5dxtvJ47m6ZyzVZ.jpg" /></figure><p>While reducible identification is critical to anyone trying to keep track of a group, it doesn’t actually tell us much about the person who has been identified. <strong>Context about that reducible identity gives orientation to who the person (or otherwise) actually is.</strong> Traditionally this may include where somebody lives (driver’s license), who their parents are, what tribe (including nationalities, teams, gangs, political affiliations, religion, etc) they are a part of, or who their employer is — anything you might fill out on a test or census form. More recently, this would include a person’s social graph (Facebook friends, LI contacts) and location data.</p><p><strong>This may be static or dynamic information, but it’s not ephemeral — it roots them in time and space. </strong>As we move to a more digital-first world, and hopefully soon <a href="https://medium.com/uport/entering-the-age-of-data-privacy-7c3451ed3a57">a self-sovereign world</a>, we talk often of capturing this contextual information as ‘attestations’ or ‘<a href="https://www.w3.org/TR/verifiable-claims-use-cases/">verifiable claims</a>’ to our root (reducible) identity, giving us a way to bring all the context about us together in a powerful, private, verifiable (trusted) way.</p><h4>3. Dynamic identity</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/420/0*bGiKqcZeTcZPYM_r.jpg" /></figure><p>A reducible identifier and contextual identification provide a way to differentiate each other, to verify who somebody is and know some categorical details about them. But <strong>they do not tell you <em>who somebody is</em>. The richness of our identity is captured in the multitude of behaviors, preferences, relationships, interactions, histories and even thoughts. </strong>Only here can true identity — the plural, dynamic identity — be seen. One persons preferences and behaviors may contradict each other over time, and often do, so this cannot be captured in a reducible and ‘verifiable’ context. It is only captured when our goal is to understand who somebody is deeply, rather than pick them out from a crowd of others.</p><p>In today’s world, data reflecting who we are is being generated and captured constantly. With much of our lives online and in our phones, and sensors cheap enough to put on everything, nearly all our interactions with the external world can be turned into digital data. In fact, our internal ‘data’ — health, mood, biological patterns is now logged as well. This is infamously captured and monetized by Facebook and others, but it is also incredibly powerful. If <a href="http://uport.me">put in control of users and creators of data</a>, we can <strong>build a world that lets us use this rich data to truly understand the people around us far better than ever before, and as far more than bits of reducible and contextual information.</strong></p><p>In fact, with rich, full identity data, we could understand our dynamic selves far better than previous identity construct have allowed us. In <a href="https://www.amazon.com/Homo-Deus-Brief-History-Tomorrow/dp/0062464310">Homo Deus</a> Yuval Harari envisions a breakdown of the singular ‘self’ into a multitude of biological signals and patterns and interactions, changing the very notion of identity — perhaps an indication of why this concept proves so hard to nail down.</p><figure><img alt="Image result for multiple selves" src="https://cdn-images-1.medium.com/proxy/1*F7jGskm9K0a9SNCctW6g7g.jpeg" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f94724c2bae9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/the-3-parts-of-identity-in-a-dynamic-world-f94724c2bae9">The 3 parts of identity in a dynamic world</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[IDX: A Devkit for Open Identity]]></title>
            <link>https://medium.com/3box/idx-a-devkit-for-open-identity-48edc88e8e85?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/48edc88e8e85</guid>
            <category><![CDATA[idx]]></category>
            <category><![CDATA[decentralized-identity]]></category>
            <category><![CDATA[ceramics]]></category>
            <category><![CDATA[did]]></category>
            <category><![CDATA[web3]]></category>
            <dc:creator><![CDATA[Michael Sena]]></dc:creator>
            <pubDate>Fri, 23 Oct 2020 13:29:56 GMT</pubDate>
            <atom:updated>2020-10-28T00:27:17.548Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*na2QrrjwKCpeMMUTYA81mg.png" /></figure><h4>The future of Web3 identity has arrived</h4><p><a href="https://idx.xyz"><strong>IDX</strong></a> is a brand new SDK for building with decentralized identity and user-centric data from the 3Box Labs team. <em>IDX is in alpha but if you’d like to start experimenting,</em><strong><em> </em></strong><a href="https://chat.idx.xyz"><strong><em>join our discord</em></strong></a><em> and jump into the </em><a href="https://idx.xyz/docs"><strong><em>docs</em></strong></a><em>.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wkxWqeHkbA2LAVamrH-ubA.png" /></figure><h3>A new era for Web3 development</h3><p>The Web3 vision for an internet that is open and interoperable, where users control their information requires a decentralized, cross-platform identity system. To this end, IDX is an open source JavaScript/TypeScript library that exposes high-level developer APIs to various meta-protocols and standards for decentralized identity. Not only is IDX powerful and flexible enough to meet all of your user and data management needs, but it wraps everything in an easy-to-use package that makes decentralized identity accessible to all Web3 developers.</p><p>Designed to be cross-platform and highly configurable, IDX is compatible with all blockchains, wallets, and a wide variety of user and application data storage options including <a href="https://ceramic.network">Ceramic</a>, <a href="https://textile.io">Textile</a>, <a href="https://orbitdb.org">OrbitDB</a>, <a href="https://filecoin.io">Filecoin</a>, <a href="https://ipfs.io">IPFS</a>, <a href="https://sia.tech">Sia</a>, and <a href="https://identity.foundation/secure-data-store/">Secure Data Stores</a> — so you can seamlessly integrate decentralized identity with the rest of your Web3 tech stack. With IDX, developers can now build much more sophisticated and powerful Web3 applications that rival and even exceed what’s currently possible on Web2.</p><h3>Why decentralized identity?</h3><p>If you’ve ever asked yourself any of these questions, then you should definitely consider adding a decentralized identity system to your development stack.</p><ul><li>How can I create a <strong>universal identifier</strong> to associate data resources from a variety of platforms to a single user?</li><li>How can I improve my user experience with <strong>decentralized social profiles</strong>?</li><li>How can users create a <strong>unified Web3 identity that links many different accounts</strong> within and across various blockchain platforms?</li><li>How can users <strong>establish trust and reputation</strong> by connecting their Web3 identity to existing Web2 social accounts (i.e. Twitter), various anti-sybil systems (i.e. <a href="https://brightid.org">BrightID</a>), domain names (i.e. DNS, <a href="https://ens.domains">ENS</a>, <a href="https://handshake.org/">Handshake</a>), and identity verification services (i.e. KYC)?</li><li>How can users create a universal and portable <strong>social graph</strong> of followers, friends, and contacts?</li><li>How can I <strong>store user and application data in various centralized and decentralized data storage technologies</strong> in a way that isn’t siloed to my application, gives users ultimate control and portability over their data, and works with all of their existing wallets/accounts?</li><li>How do I <strong>discover and import data</strong> that a user has created on another application, platform, or network so that I can use it inside my app?</li></ul><h3>IDX: An open identity framework for Web3</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*erbL1qHL2mPTMF31f0K33A.png" /></figure><p>Decentralized identity and user-centric data management are complex, broad-ranging capabilities that touch almost every other aspect of your app architecture. IDX removes the all of the guesswork from implementing these in a scalable and future-proof way.</p><h4>Build with unified digital identities</h4><p>Using IDX, all applications can access a shared, globally-available identity layer that contains unified users identities. Built 100% on permissionless protocols, IDX enables users and their most important information to seamlessly flow and interoperate across platforms, while giving users the ownership and control they demand. In a way, the identity capabilities offered by IDX sort of function as a decentralized Keybase but with much greater flexibility and decentralization.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IAhm-w54MKOPVCj55HV0uA.png" /><figcaption>A unified digital footprint!</figcaption></figure><p>The core of each identity consists of a <a href="https://www.w3.org/TR/did-core/">decentralized identifier (DID)</a> which acts as a globally-unique ID and an <a href="https://github.com/ceramicnetwork/CIP/blob/cip/idx/CIPs/CIP-11/CIP-11.md">identity index</a> which keeps track of an identity’s information. IDX allows developers to deploy identities as well as create, read, update, and delete a variety of metadata and information related to the identity, including but not limited to:</p><ul><li>Multiple user profiles for different contexts or applications</li><li>Portable social graphs, from followers to contacts and family</li><li>Links to multiple blockchain accounts from different protocols (Ethereum, Bitcoin, Polkadot, NEAR, Flow, etc)</li><li>Links to existing social accounts (Twitter, Github, Discord, Matrix, etc)</li><li>Links to domain names (DNS, ENS, Unstoppable, Handshake, etc)</li></ul><p>All DIDs, identity indexes, and metadata are securely stored on Ceramic’s permissionless document management network. Because all information is publicly available (but optionally encrypted) and linked via the identity index, any bit of information can be cross-resolved by querying based on any other information. For example you could lookup a user’s profile based on their DID, their Ethereum account, or their Twitter handle; or you could lookup a user’s Filecoin account based on their Polkadot account. We are working with <a href="https://thegraph.com">The Graph</a> on indexing these identity structures which will open up many new opportunities in this realm.</p><h4>Integrate with data storage solutions</h4><p>Unified identities are the gateway to a world of additional functionality for your application. If you also need a way of storing and managing user data, you have three main options.</p><ul><li>Use the IDX library to <em>directly</em> store documents on the Ceramic Network and add references to those documents in the user’s index. For this option, no additional software is needed; it works out of the box with IDX.</li><li>Store data in alternative data storage systems such as Filecoin, IPFS, Sia, Arweave, Textile, OrbitDB, Secure Data Stores, or Ethereum contracts and use IDX to add references to this data in your user’s index. For this option, you would need to separately install these technologies in your app alongside IDX.</li><li>Use a combination of the different data storage solutions above for your application, each with their own strengths and weaknesses, while mapping everything in your user’s IDX.</li></ul><p>Whichever data storage configuration you choose, IDX allows all data to be controlled by the user, discoverable by others, and portable across platforms. This is true regardless of where the data resides (servers or decentralized networks) or which application first created the data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*X5IFFJ3sG-BARmU9-7dZhA.png" /><figcaption>The identity index contains mappings to various data sources</figcaption></figure><h4>Share data across applications and silos</h4><p>As described above, the key aspect of IDX that de-silos information, promotes interoperability, and enables user control is the identity index. It provides a standard interface which allows any application or developer to set and query all available data that belongs to a user so that they might make use of it within their application. The identity index serves as the information root for each user and makes everything discoverable.</p><p>To further promote interoperability, the identity index allows developers to:</p><ul><li>Publish schemas, names, and descriptions for data points they are adding to the index, so others can more easily consume this information</li><li>Publish endpoints for where this information can be found, whether a DocID on Ceramic, a CID on IPFS/Filecoin, a contract on Ethereum, or an endpoint for a hosted service</li><li>Request permission to access encrypted data points in the index</li></ul><h3>Developing with IDX</h3><p>The following section outlines how to get started building with IDX. For more supporting materials, <a href="https://idx.xyz/docs"><strong>read the docs</strong></a>.</p><h4>Installation</h4><p>First, we’ll need to install the main IDX library and associated dependencies:</p><pre>npm install @ceramicnetwork/ceramic-http-client @ceramicstudio/idx @ceramicstudio/idx-constants</pre><h4>Query an identity</h4><p>Then we can use these libraries to connect IDX to a Ceramic network and interact with the documents associated to a given DID. This example shows how to simply query the basic profile for a given user.</p><pre>import Ceramic from &#39;@ceramicnetwork/ceramic-http-client&#39;<br>import { IDX } from &#39;@ceramicstudio/idx&#39;<br>import { definitions } from &#39;@ceramicstudio/idx-constants&#39;</pre><pre>// Use Ceramic devnet<br>const ceramic = new Ceramic(&#39;&lt;https://ceramic.3boxlabs.com&gt;&#39;)</pre><pre>// Use IDX-provided definitions aliases<br>const idx = new IDX({ ceramic, definitions })</pre><pre>// Get the basic profile of a known DID supporting IDX<br>async function getProfile(did) {<br>  return await idx.get(&#39;basicProfile&#39;, did)<br>}</pre><h4>Save data</h4><p>More advanced examples involving authentication and setting content can be found in the <a href="https://idx.xyz/docs/guide-authentication"><strong>IDX documentation</strong></a>.</p><p><em>Remember, IDX is still in alpha. If you have any questions, comments, or feedback on what we’ve built or how to use it, please </em><a href="https://chat.idx.xyz"><strong><em>reach out on Discord</em></strong></a><em>.</em></p><h3>About</h3><p>IDX is an open source library that is built and maintained with 💜 by the 3Box Labs team, creators of <a href="https://github.com/3box/3box-js">3Box.js</a>, a leading decentralized identity and data storage solution for Ethereum that has been used by 30,000+ users and 1,000+ projects. IDX is a smarter, mature evolution of 3Box.js. All DIDs and profiles created using 3Box.js will be automatically migrated to IDX once the library goes into production. We are working on various solutions to migrate user data that has been saved in spaces and threads to other IDX compatible data storage systems including Ceramic, Textile, and OrbitDB. If you have questions about this migration process or timeline, please reach out.</p><h3>Resources</h3><p><a href="https://idx.xyz"><strong>Website</strong></a><strong><br></strong><a href="https://idx.xyz/docs"><strong>Docs</strong></a><strong><br></strong><a href="https://chat.idx.xyz"><strong>Discord</strong></a><strong><br></strong><a href="https://github.com/ceramicstudio/js-idx"><strong>Github</strong></a><strong><br></strong><a href="https://twitter.com/identityindex"><strong>Twitter</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=48edc88e8e85" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/idx-a-devkit-for-open-identity-48edc88e8e85">IDX: A Devkit for Open Identity</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an encrypted todo list with 3Box (part 2/2)]]></title>
            <link>https://medium.com/3box/building-an-encrypted-todo-list-with-3box-part-2-2-da15aa2e2640?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/da15aa2e2640</guid>
            <category><![CDATA[ipfs]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[privacy]]></category>
            <category><![CDATA[decentralized-identity]]></category>
            <dc:creator><![CDATA[Rachel Black]]></dc:creator>
            <pubDate>Wed, 05 Aug 2020 11:37:26 GMT</pubDate>
            <atom:updated>2020-08-05T11:37:26.715Z</atom:updated>
            <content:encoded><![CDATA[<h4>Make privacy preserving, collaborative and censorship resistant applications with frontend code.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vQvIIEchSPKCX7OI2Zi8SQ.png" /></figure><h3>Part 2: Team lists</h3><h4>Intro</h4><p>Welcome to the second part of our todo app tutorial, built with 3Box confidential threads. If you haven’t visited part one, check that out first. Here we build out the scope of our todo app to accommodate team todos. This is where the power of confidential threads really shows. Outside of todo lists, there are many applications for <a href="https://medium.com/3box/confidential-threads-api-17df60b34431">confidential members threads</a>; private messages, censorship resistant social media, team chat, and more. Lets start by building our collaborative, confidential task list.</p><p>👉 <a href="https://silly-carson-76f98d.netlify.app/">Check out the demo here</a></p><p>🛠 <a href="https://github.com/RachBLondon/3box-todo-app">Completed tutorial codebase</a></p><h3>What you will learn in this tutorial</h3><h4>Members Confidential Threads</h4><ol><li>User flow for joining confidential members threads</li><li>Creating a confidential members thread</li><li>Recording team members opening the applications space</li><li>Adding team members to the thread</li><li>Retrieving team posts</li><li>Adding posts</li><li>Updating the UI</li><li>Testing the UI</li><li>Adding the profile hover component</li></ol><h4>Setup and Tech Stack</h4><p>This tutorial is a continuation of Part 1 , so complete that before starting. We will be using the same tech stack.</p><ul><li><a href="https://reactjs.org/"><strong>React</strong></a> — frontend framework</li><li><a href="https://ipfs.io/"><strong>IPFS</strong></a> + <a href="https://orbitdb.org/"><strong>OrbitDB</strong></a> — where the data is stored (provided by 3Box, so we won’t need to touch this directly, no need to install separately )</li><li><a href="https://metamask.io/"><strong>MetaMask</strong></a> — Web3 wallet integration (required to facilitate signing and encryption of data)</li><li><a href="https://docs.3box.io/build/web-apps"><strong>3Box.js</strong></a> — 3Box SDK that connects wallets to IPFS database storage via 3ID</li><li><a href="https://docs.3box.io/build/plugins/profile-hover"><strong>Profile Hover</strong></a>, and <a href="https://docs.3box.io/build/plugins/profile-edit"><strong>Profile Edit Plugins</strong></a> — drop-in React components that we will use to speed up UI development</li><li><a href="https://react-bootstrap.github.io/"><strong>React Bootstrap</strong></a>— UI Library</li></ul><h4>1. User flow for joining confidential members threads</h4><p>Before we start coding, let’s describe the process we will use to handle users joining the confidential thread:</p><ul><li>Start with a hardcoded list of ethereum addresses for team members</li><li>The moderator will also be hardcoded</li><li>When the moderator logs in, we create the confidential thread and save its address in a public space (called waitingRoom)</li><li>In order to be added to the thread, we need to ensure each team member has opened the space previously</li><li>Once a team member opens the space, this will be recoded in a public thread</li><li>Whenever the moderator logs in, they will check the public thread for team members to add to the thread. On adding them, the record in the public thread is also updated</li><li>Returning to the site, team members will be able to add and modify todos on the team page</li></ul><p>Lets start by adding the hardcoded list of team members and moderator to the component’s react state (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L8">see example</a>):</p><pre>state = {<br>    posts: [],<br>    newTodo: &quot;&quot;,<br>    moderatorsAddress: &#39;0x2f4cE4f714C68A3fC871d1f543FFC24b9b3c2386&#39;,<br>    addresses :[<br>      &#39;0xab74207ee35fBe1Fb949bdcf676899e9e72Ec530&#39;, <br>      &#39;0xFF326878D13b33591D286372E67B4AF05cD100bd&#39;, <br>      &#39;0xbaeBB7d18f8b16B0A970FDa91f1EfA626D67423E&#39;, <br>      &#39;0x5c44E8982fa3C3239C6E3C5be2cc6663c7C9387E&#39;, <br>      &#39;0xa8eE0BABE72cD9A80Ae45dD74Cd3eaE7a82fd5d1&#39;, <br>      &#39;0x5a7246af4fefe777e32399310b50bb7fe2d04f8a&#39;, <br>      &#39;0x18B14A7d061B504C75C7027738d16dcED739b2E9&#39;, <br>      &#39;0x5031f308AD02Ed86F44c586aD2B01ae55D034C7a&#39;,<br>      &#39;0xB3B30f49384093eE32d26C2C8E38e6566482C6a8&#39;<br>    ] // replace these with ethereum addresses you control<br>  }</pre><p>🚨 <em>Note, these are the addresses for the 3Box team, update the moderator to use your own address. Add another address you own to the team members array so you can test. You can create multiple accounts in MetaMask’s My Accounts section.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/344/1*PNABIcWP4ZT16Myjz6WB_g.png" /></figure><p>To handle the logic detailed in the bullet points, we are going to be adding a reasonable amount of code in the <a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L25"><strong>componentDidMount</strong> method</a>. We start by adding the necessary constants:</p><pre>async componentDidMount() {<br>    const teamMembers = this.state.addresses.map(member =&gt; member.toLowerCase()) //prevents capitalisation errors</pre><pre>    const spaceName = &quot;todo-space&quot;<br>    const confidentialThreadName = &quot;confidential-todos&quot;<br>    const waitingRoomName = &quot;waitingroom&quot;<br>    let teamThread // we will set this later<br>    const isModerator = this.state.moderatorsAddress.toLowerCase() === this.props.accounts[0].toLowerCase()</pre><pre>    // Access the moderators public space<br>    const moderatorsSpace = await   Box.getSpace(this.state.moderatorsAddress.toUpperCase(), spaceName)<br>    const isTeamMember =  teamMembers.includes(this.props.accounts[0]) </pre><pre>    if(!isModerator &amp;&amp; !isTeamMember){<br>      this.setState({notAModOrTeam: true})<br>      } <br>  }</pre><p>In addition to setting the names of the space and two threads we will be using, we need to know if the current this.props.accounts[0] is either the moderator or a team member.</p><p>We also need to access the moderators public space, as this is where we save the thread addresses. Because we are using 3Box.js to access this, we need to import the library at the top of the file:</p><pre>import Box from &#39;3box&#39;</pre><h4>2. Creating a confidential members thread</h4><p>Inside <strong>componentDidMount</strong> we can add the following block of code (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L47">see example</a>):</p><pre>if (!moderatorsSpace[confidentialThreadName] &amp;&amp; isModerator) {<br>      // if theconfidentialThreadname is not saved in the mods space<br>      // it means it theconfidentialThreadhas has not been created. <br>      // create the confidentialconfidentialThreadand save the  <br>      // address in the moderators public space</pre><pre>      const confidentialThread = await this.props.space.createConfidentialThread(confidentialThreadName)<br>      await this.props.space.public.set(confidentialThreadName, confidentialThread.address)<br>      const waitingRoom = await this.props.space.joinThread(waitingRoomName)<br>      await this.props.space.public.set(waitingRoomName, waitingRoom.address)<br>      this.setState({teamThread : confidentialThread})<br>      console.log(&quot;confidential thread &amp; waiting room thread made&quot;)<br>    }</pre><p>The if statement means this will only be accessed when the confidential thread hasn’t been created and saved to the moderators public space. We are also using <a href="https://docs.3box.io/api/messaging#space-jointhread-name-opts"><strong>space.joinThread</strong></a> to create and join the public thread which stores the team members progress of opening the space (needed to be added to the thread). The address of this public, <strong>waitingRoom</strong> thread, is saved to the moderator’s public space, so team members can access it. We save the confidential thread to react state, so the moderator can add todo straight away.</p><p>For this to work, we need to pass space in as property to the <strong>Team</strong> component in <a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/App.js#L81">App.js:</a></p><pre>&lt;Route path=&quot;/team&quot;&gt;<br>    &lt;Team <br>      accounts={this.state.accounts}<br>      space={this.state.space} /&gt;<br>  &lt;/Route&gt;</pre><p>Visiting the browser, you should now see the console log &quot;confidential thread and waiting room thread made&quot;.</p><p>We can also add some logic to handle for the case when a team member logs in ahead of the moderator (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L65">see example</a>):</p><pre>if(!moderatorsSpace[confidentialThreadName] &amp;&amp; !isModerator &amp;&amp; isTeamMember){<br>      this.setState({moderatorLoginToCreate: true})<br>  }</pre><h4>3. Recording team members opening the applications space</h4><p>Now let’s handle the flow for users when the confidential thread has been created. Starting with team members the first time they visit. Here the first thing they need to do is open the same space the confidential thread lives in, and save this update to the public waitingRoom thread (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L69">see example</a>).</p><pre>// when the confidential thread has been created<br>if (moderatorsSpace[confidentialThreadName]) {<br>	<br>	if(isTeamMember &amp;&amp; !isModerator){<br>	// check for the space opening status of the team member in <br>        // the waitingRoom public thread    <br>	const waitingRoom = await this.props.space.joinThreadByAddress(moderatorsSpace[waitingRoomName])<br>	 const rawPosts = await waitingRoom.getPosts()<br>	<br>	  // where we handle the logic of adding team members to the <br>	  // waiting room and confidential thread<br>			<br>    }<br>	// Add the moderator login here <br> }</pre><p>As we need to store data in the <strong>waitingRoom</strong> thread in string form, we will be creating an object and JSON stringifying it to store in a thread. This object will record the addresses of team members which are in the waitingRoom (opened space but not added to the thread) and added (once they have been added by the moderator). For example:</p><pre>{<br>	waitingRoom: [<br>             &#39;0xa8eE0BABE72cD9A80Ae45dD74Cd3eaE7a82fd5d1&#39;,<br>             &#39;0x5031f308AD02Ed86F44c586aD2B01ae55D034C7a&#39;],<br>	added: [&#39;0xB3B30f49384093eE32d26C2C8E38e6566482C6a8&#39;]<br>}</pre><p>Later we will add the code which handles the moderator adding team members to the confidential thread and moving them in to the added array.</p><p>Now after <strong>rawPosts</strong> lets add the following code for the case when there are no posts in the waiting room thread (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L76">see example</a>):</p><pre>if(rawPosts.length &lt; 1){<br>  await waitingRoom.post(JSON.stringify({<br>        waitingRoom: [this.props.accounts[0]], <br>        added: []}))<br>  this.setState({moderatorWillAdd: true})<br>	console.log(&quot;first team member added&quot;)<br>}</pre><p>As user has opened the space, we can add them to the <strong>waitingRoom</strong> array. We are also updating the react state so we can indicate to the user that they should revisit after their moderator has logged in.</p><p>Wen will add the next if statement to process the <strong>waitingRoom</strong> thread when it contains posts (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L85">see example</a>).</p><pre>if(rawPosts.length &gt; 0) {<br>      const mostRecent = JSON.parse(rawPosts[rawPosts.length -1].message)<br>      // check user has been added to the confidential thread<br>      if(mostRecent.added.includes(this.props.accounts[0])){<br>        const confidentialThread = await this.props.space.joinThreadByAddress(moderatorsSpace[confidentialThreadName])<br>        console.log(&quot;joinedconfidentialThreadas team&quot;)<br>        this.setState({<br>             teamThread: confidentialThread, <br>             teamMembersAdded: mostRecent.added<br>             })<br>             // TODO get posts<br>	}<br>		    if(mostRecent.waitingRoom.includes(this.props.accounts[0])){<br>          this.setState({moderatorWillAdd: true})<br>	 return<br>      } else {<br>        // add user to waiting room in prep for adding to thread<br>        console.log(&quot;adding user to waiting room&quot;)<br>        mostRecent.waitingRoom.push(this.props.accounts[0])<br>        await waitingRoom.post(JSON.stringify(mostRecent))<br>        this.setState({<br>              moderatorWillAdd: true})<br>	return <br>      }<br>    }</pre><p>Here we are parsing the most recent post to read from. Then checking if the current user is present in the added array (meaning they have been added by the moderator) we join the confidential thread with <strong>joinThreadByAddress.</strong></p><p>Then we check the mostRecent post to see if the user is already in the waiting room array. In this case we do not need to do anything except update the react state.</p><p>If they are neither in the waiting room or added array, it means it’s their first visit to the application. We need to record them as having opened the space, and indicate to the moderator they should be added to the thread. To do this we record their ethereum address in the waitingRoom array.</p><h4>4. Adding team members to the thread</h4><p>The final part we need to add to the moderatorsSpace[confidentialThreadName] if statement, is the flow where the moderator revisits the application to add the team members in the <strong>waitingList</strong> to the todo thread (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L119">see example</a>).</p><pre>// Add the moderator login here </pre><pre>if(isModerator){<br>        // moderator joins the confidential thread and adds users in <br>        // waiting room. Then move these users to the added array<br>        const confidentialThread= await this.props.space.joinThreadByAddress(moderatorsSpace[confidentialThreadName])<br>        console.log(&quot;moderator joinedconfidentialThreads&quot;)<br>        const waitingRoom = await this.props.space.joinThreadByAddress(moderatorsSpace[waitingRoomName])<br>        const rawPosts = await waitingRoom.getPosts()<br>       <br>        if(rawPosts.length &gt; 0) {<br>        const mostRecent = JSON.parse(rawPosts[rawPosts.length -1 ].message)<br>        mostRecent.waitingRoom.map(async address =&gt; {<br>            await confidentialThread.addMember(address)<br>        });</pre><pre>	// Once team members have been added to the waiting room,<br>	// move them to the added array<br>        const newWaitingRoom = {<br>          waitingRoom: [], <br>          added: mostRecent.added.concat(mostRecent.waitingRoom)}<br>          const inConfidentialThread = await confidentialThread.listMembers()<br>          await waitingRoom.deletePost(rawPosts[rawPosts.length -1].postId)<br>          await waitingRoom.post(JSON.stringify(newWaitingRoom))<br>	  console.log(&quot;updated waiting room arr&quot;, newWaitingRoom)<br>        }</pre><pre>      this.setState({teamThread : confidentialThread})<br>      // TODO get posts<br>  }</pre><p>Now that we have completed this flow, we can check in the console that it is working correctly.</p><ul><li>When the moderator logs in for the first time — confidential thread and waiting room thread made</li><li>The first team member logs in — first team member added logged and moderatorWillAdd: true in react state</li><li>Moderator rejoins after team member logs in — moderator joinedconfidentialThreads , updated waiting room array with an updated waiting room object</li><li>Same team member rejoins — joinedconfidentialThreadas team and teamThread: confidentialThread, teamMembersAdded: mostRecent.added in react state.</li></ul><h4>5. Retrieving team posts</h4><p>Now we have the logic to add members to a confidential thread, the next thing is to add the functionality to retrieve posts. Luckily we can reuse some of the logic we used in personal confidential threads . We can add the <strong>getPosts</strong> and <strong>parsePosts</strong> methods to the <strong>Team</strong> component (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L154">see example</a>):</p><pre>async getPosts() {<br>    const rawPosts = await this.state.teamThread.getPosts()<br>    const posts = this.parsePosts(rawPosts)<br>    this.setState({ posts })<br>  }</pre><pre>parsePosts = (postArr) =&gt; {<br>    return postArr.map((rawPost) =&gt; {<br>      let post = JSON.parse(rawPost.message)<br>      post.id = rawPost.postId<br>      return post<br>    })<br>  }</pre><p>We call the <strong>getPosts</strong> function just after a team member has joined the confidential thread, we will also add a return statement here. (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L98">see example</a>):</p><pre>console.log(&quot;joinedconfidentialThreadas team&quot;)<br>this.setState({ teamThread: confidentialThread, teamMembersAdded: mostRecent.added })<br>// TODO get posts<br>this.getPosts()<br>return</pre><p><a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L149">And after the moderator has joined add the line:</a></p><pre>// TODO get posts<br>  this.getPosts()</pre><p>After this, you should see posts: [] saved to the react state for the team component. We have not added any posts yet so this is expected.</p><h4>6. Adding posts</h4><p>To add posts, let’s add the modal component to the render function:</p><pre>&lt;ModalComponent<br>    buttonText={&quot;Add a ToDo&quot;}<br>    ModalHeader={&quot;Add a Todo&quot;}<br>    ModalBodyText={&quot;One more thing on the list.&quot;}<br>    submitFunc={this.onSubmit} &gt;<br>    &lt;Container&gt;<br>      &lt;Form&gt;<br>        &lt;Form.Group controlId=&quot;formBasicEmail&quot;&gt;<br>          &lt;Form.Label&gt;New Item&lt;/Form.Label&gt;<br>          &lt;Form.Control<br>            type=&quot;text&quot;<br>            value={this.state.newTodo}<br>            onChange={(e) =&gt; (this.setState({ newTodo: e.target.value }))}<br>          /&gt;<br>        &lt;/Form.Group&gt;<br>      &lt;/Form&gt;<br>    &lt;/Container&gt;<br>  &lt;/ModalComponent&gt;</pre><p>This component works similarly to the one we used for personal todos. We also need to add the <strong>onSubmit</strong> function:</p><pre>onSubmit = async () =&gt; {<br>    if (this.state.newTodo) {<br>      const orderNumber = this.state.posts.length &gt; 0 ? (this.state.posts[this.state.posts.length - 1].order + 1) : (1)<br>      const post = JSON.stringify({<br>        text: this.state.newTodo,<br>        completed: false,<br>        show: true,<br>        order: orderNumber,<br>        postedBy: this.props.accounts[0]<br>      })<br>      await this.state.teamThread.post(post)<br>      this.setState({ newTodo: null })<br>      this.getPosts()<br>    }<br>  }</pre><p>Let’s also add the UI component to render todos.</p><pre>{this.state.posts &amp;&amp;<br>    &lt;TODO<br>      posts={this.state.posts}<br>      deletePost={this.deletePost}<br>      toggleDone={this.toggleDone}<br>      accounts={this.props.accounts} /&gt;<br>  }</pre><p>Finally let’s add the <strong>deletePost</strong> and <strong>toggleDone</strong> methods:</p><pre>toggleDone = async (todo) =&gt; {<br>    const post = JSON.stringify({<br>      text: todo.text,<br>      completed: !todo.completed,<br>      show: true,<br>      order: todo.order,<br>      postedBy: todo.postedBy<br>    });<br>    await this.state.teamThread.post(post);<br>    await this.state.teamThread.deletePost(todo.id)<br>    this.getPosts()<br>  }<br>  <br>  deletePost = async (postId) =&gt; {<br>    await this.state.teamThread.deletePost(postId)<br>    await this.getPosts()<br>  }</pre><p>Testing in the UI, you should now be able to add a post, delete a post you have created and select a post you have created.</p><h4>7. Updating the UI</h4><p>Now that the core functionality is working, we should update the UI to communicate the flow to the user. Making use of the react state we created earlier in <strong>componentDidMount</strong>, we can create an <strong>isActiveMember</strong> constant to indicate when a user is logged in and active. We will also add some brief messaging to indicate to the user their status when they are not an active member (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Team.js#L205">see example</a>).</p><pre>render() {<br>   const isActiveMember =  !this.state.notAModOrTeam &amp;&amp; !this.state.moderatorWillAdd &amp;&amp; !this.state.moderatorLoginToCreate &amp;&amp; this.state.teamThread</pre><pre>    return (<br>      &lt;div&gt;<br>        &lt;h2&gt;Team TODOs&lt;/h2&gt;<br>        {/* {TODO Section} */}<br>        {this.state.notAModOrTeam &amp;&amp; (<br>              &lt;h1&gt;You are not part of this team&lt;/h1&gt;)}<br>        {this.state.moderatorLoginToCreate &amp;&amp; (<br>              &lt;h1&gt;Ask your moderator to login to start&lt;/h1&gt;)}<br>        {this.state.moderatorWillAdd &amp;&amp; (<br>               &lt;h1&gt;Wait for your moderator to log in and add you&lt;/h1&gt;)}<br>        {this.state.posts &amp;&amp; isActiveMember &amp;&amp; (<br>          &lt;TODO<br>            posts={this.state.posts}<br>            deletePost={this.deletePost}<br>            toggleDone={this.toggleDone}<br>            accounts={this.props.accounts}<br>          /&gt;<br>        )}<br>        {isActiveMember &amp;&amp; (<br>          &lt;&gt;<br>            &lt;ModalComponent<br>              buttonText={&quot;Add a ToDo&quot;}<br>              ModalHeader={&quot;Add a Todo&quot;}<br>              ModalBodyText={&quot;One more thing on the list.&quot;}<br>              submitFunc={this.onSubmit}<br>            &gt;<br>              &lt;Container&gt;<br>                &lt;Form&gt;<br>                  &lt;Form.Group controlId=&quot;formBasicEmail&quot;&gt;<br>                    &lt;Form.Label&gt;New Item&lt;/Form.Label&gt;<br>                    &lt;Form.Control<br>                      type=&quot;text&quot;<br>                      value={this.state.newTodo}<br>                      onChange={(e) =&gt;<br>                        this.setState({ newTodo: e.target.value })<br>                      }<br>                    /&gt;<br>                  &lt;/Form.Group&gt;<br>                &lt;/Form&gt;<br>              &lt;/Container&gt;<br>            &lt;/ModalComponent&gt;<br>          &lt;/&gt;<br>        )}<br>      &lt;/div&gt;<br>    )<br>  }</pre><h4>8. Testing the UI</h4><p>Our frontend is almost finished, now we can check that it is functioning as expected. Try the following:</p><ul><li>A users who is neither a moderator or a team member — the UI will render “You are not part of this team”.</li><li>A team member logging in ahead of the moderator — the UI will render “Ask your moderator to login to start”.</li><li>A moderator logging in for the first time — “confidential thread and waiting room thread made” will be logged in the console. It should be possible to post, check done and delete a todo.</li><li>A team member after a moderator has created the thread:</li><li>First login — “Wait for your moderator to log in and add you” will be rendered in the UI.</li><li>Returning to login in after the moderator has logged in again — you should be able to post, delete and check done todos (that they have created themselves).</li></ul><p>If your application works as above, congrats you have completed the core functionality of this tutorial.🎉</p><h4>9. Adding the profile hover component</h4><p>One final thing we are going to do as part of this tutorial is make use of the profile hover component to show the users profile picture and 3Box name. If you haven’t already set a profile picture and name, you can do this in <a href="https://3box.io/hub">3Box Hub</a> (editing 3Box profiles can also coded to be functional inside any application).</p><p>First use npm to install the component:</p><pre>npm i profile-hover</pre><p>We will import it to the top of our TODO.js component:</p><pre>import ProfileHover from &#39;profile-hover&#39;</pre><p><a href="https://docs.3box.io/build/plugins/profile-hover">Profile hover</a> is the most minimal to add a <a href="https://docs.3box.io/build/plugins">3Box plugin</a>, so all we need to do is add the following inside the render function on <a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Components/TODO.js#L36">line 36</a>:</p><pre>{item.postedBy &amp;&amp; &lt;ProfileHover address={item.postedBy} showName={true} /&gt;}</pre><p>You will now see each users 3Box profile render in the UI.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cytWIFhFUiseL-b43Oynyg.png" /></figure><p>With that we complete this two part tutorial series.</p><p><em>If you have any questions or feedback, head over to our </em><a href="https://chat.3box.io"><em>discord channel</em></a><em>. We are excited to follow what the community builds with confidential threads!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=da15aa2e2640" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/building-an-encrypted-todo-list-with-3box-part-2-2-da15aa2e2640">Building an encrypted todo list with 3Box (part 2/2)</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an encrypted todo list with 3Box (part 1/2)]]></title>
            <link>https://medium.com/3box/building-an-encrypted-todo-list-with-3box-part-1-2-d1619cd02e5b?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/d1619cd02e5b</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[decentralized-apps]]></category>
            <category><![CDATA[web3]]></category>
            <dc:creator><![CDATA[Rachel Black]]></dc:creator>
            <pubDate>Wed, 29 Jul 2020 13:09:37 GMT</pubDate>
            <atom:updated>2020-07-29T13:09:37.562Z</atom:updated>
            <content:encoded><![CDATA[<h4>Make privacy preserving, collaborative and censorship resistant applications with frontend code.</h4><h3>Part 1 : Personal lists</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/283/1*b2TlxnympvVX4Vtg613Ylg.gif" /></figure><h4>Intro</h4><p>Earlier this year we were <a href="https://medium.com/3box/confidential-threads-api-17df60b34431">excited to launch confidential threads.</a> Private and encrypted messaging opens up the possibilities of what can be built with 3Box.</p><p>This two part series will guide you step by step through creating an individual and team todo application. <em>The first part will get us set up with a personal to do app. The second part will extend this to include team functionality.</em></p><p>As with all products built with <a href="https://docs.3box.io/build/web-apps?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1">3Box.js</a>, there is no need for a server to manage data. This application is built client side. 3Box.js will persist the data in encrypted form on IPFS without the need for you to run your own node. To take a deep dive in to <a href="https://docs.3box.io/network/architecture?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1">3Box’s architecture, check out this blog</a>.</p><p>👉 <a href="https://silly-carson-76f98d.netlify.app/">Check out the demo here</a></p><p>🛠 <a href="https://github.com/RachBLondon/3box-todo-app">Completed tutorial codebase</a></p><p>Read on for part one, building a todo application with <a href="https://docs.3box.io/build/web-apps/messaging/choose?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#persistent-personal-confidential">personal confidential threads</a>.</p><h3>What you will learn in this tutorial</h3><h4>Personal Confidential Threads</h4><p>We start by learning how to use confidential threads by creating a todo list application for a single user. Here you will learn how to join, save, read and delete data from a confidential thread.</p><ol><li>Getting started with the boilerplate code</li><li>Installing 3Box.js and opening a space for the application</li><li>Joining a personal confidential thread</li><li>Saving and getting todos from a confidential thread</li><li>Checking done and deleting todos</li></ol><p>In part 2 we will be building out this application out to work for groups and teams.</p><h4>Setup and Tech Stack</h4><p>For the tutorial, some familiarity with react is required. You can complete by copying and pasting each step, but for a more meaningful understanding, it is recommended you are familiar with the basics.</p><ul><li><a href="https://reactjs.org/"><strong>React</strong></a> — frontend framework</li><li><a href="https://ipfs.io/"><strong>IPFS</strong></a> + <a href="https://orbitdb.org/"><strong>OrbitDB</strong></a> — where the data is stored (provided by 3Box, so we won’t need to touch this directly, no need to install separately )</li><li><a href="https://metamask.io/"><strong>MetaMask</strong></a> — Web3 wallet integration (required to facilitate signing and encryption of data)</li><li><a href="https://docs.3box.io/build/web-apps"><strong>3Box.js</strong></a> — 3Box SDK that connects wallets to IPFS database storage via 3ID</li><li><a href="https://docs.3box.io/build/plugins/profile-hover"><strong>Profile Hover</strong></a>, and <a href="https://docs.3box.io/build/plugins/profile-edit"><strong>Profile Edit Plugins</strong></a> — drop-in React components that we will use to speed up UI development</li><li><a href="https://react-bootstrap.github.io/"><strong>React Bootstrap</strong></a> — UI Library</li></ul><h4>1. Getting started with the boilerplate code</h4><p>To get started let’s clone and install the <a href="https://github.com/RachBLondon/todo-template">boilerplate code</a> :</p><pre>git clone &lt;https://github.com/RachBLondon/todo-template.git&gt;<br>cd todo-template<br>npm i<br>npm start</pre><p>This boilerplate code is made with create react app. It connects with MetaMask to enable the provider and obtain the users ethereum address. <a href="https://github.com/RachBLondon/todo-template/blob/master/src/App.js">This happens in lines 15–30 in App.js</a></p><pre>async getAddressFromMetaMask() {<br>    if (typeof window.ethereum == &quot;undefined&quot;) {<br>      this.setState({ needToAWeb3Browser: true })<br>    } else {<br>      window.ethereum.autoRefreshOnNetworkChange = false; <br>      //silences warning about no autofresh on network change<br>      const accounts = await window.ethereum.enable();<br>      this.setState({ accounts })<br>    }<br>  }<br>  async componentDidMount() {<br>    await this.getAddressFromMetaMask()<br>    if (this.state.accounts) {</pre><pre>    }<br>  }</pre><p>This repo also contains some frontend boilerplate components which will be used later in the tutorial (modals, todo lists etc).</p><h4>2. Installing 3Box and opening a space for the application</h4><p>First we will install 3Box.js</p><pre>npm i 3box</pre><p>and import it to our App.js file</p><pre>import Box from &#39;3box&#39;</pre><p><em>Note do not import as 3Box as variables cannot start with numbers in JavaScript</em></p><p>Now that we have 3Box.js installed, we are going to add the following code to <strong>componentDidMount</strong></p><pre>async componentDidMount() {<br>    // creates an instance of 3Box <br>    const box = await Box.create(window.ethereum)<br>    await this.getAddressFromMetaMask()</pre><pre>    if (this.state.accounts) {<br>      await box.auth([&#39;todo-space&#39;], {<br>        address : this.state.accounts[0]<br>      })</pre><pre>      // opens the space we are using for the TODO app<br>      const space = await box.openSpace(&#39;todo-space&#39;)<br>      this.setState({ space })<br>    }<br>  }</pre><p>First we use <a href="https://docs.3box.io/api/auth?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#box-create-ethereumprovider"><strong>Box.create</strong></a> to create an instance of 3Box. This takes a single argument of the ethereum provider so can be called straight away in <strong>componentDidMount</strong>. The page needs to be loaded, as we are dependant on MetaMask injecting the provider in to the frontend.</p><p>Next once the provider has been enabled using the boilerplate function, <strong>getAddressFromMetaMask</strong> and the address saved to state, we call <a href="https://docs.3box.io/api/auth?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#box-auth"><strong>box.auth</strong></a><strong>.</strong> This authenticates the instance of 3Box we have created with an array of spaces (in this case we only have one, but it supports multiple) and the users ethereum address.</p><p>If you have worked with 3Box previously, you may have used a different authentication method, <a href="https://docs.3box.io/api/auth?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#box-openbox-address-ethereumprovider-opts"><strong>Box. openBox.</strong></a> This method is still supported, but there are a number of benefits to using <a href="https://docs.3box.io/api/auth?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#box-create-ethereumprovider"><strong>Box.create</strong></a> and <a href="https://docs.3box.io/api/auth?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#box-auth"><strong>box.auth</strong></a><strong>.</strong> Firstly you can create the 3Box instance earlier (you do not need to wait for the user to enable the ethereum provider in their wallet). Second you can authenticate with multiple spaces at once. For new projects, we recommend using the approach detailed in this tutorial.</p><p>Then we use <a href="https://docs.3box.io/api/auth?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#box-openspace-name-opts"><strong>box.openSpace</strong></a> to open the space which has been authenticated in the previous step. Finally setting the space to the component’s react state for use throughout the application.</p><p>When revisiting the app in a browser, you should now be prompted by MetaMask to sign access to the todo space.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/325/1*A1cvoA3pgpbfTN4NZtrkrg.png" /><figcaption>Signing a request in MetaMask</figcaption></figure><p>We are creating a space first, as confidential threads live inside a user’s space. We will also be using this space to store public and private data later in this tutorial.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/594/1*Wwl0PdHM-jUF2YmCDvclZQ.png" /></figure><h4>3. Joining a personal confidential thread</h4><p>Now we will start working on personal todos. Here we will be working with the <a href="https://github.com/RachBLondon/todo-template/blob/master/src/Pages/Personal.js">pages/Personal.js component.</a> First we will pass the space we just opened in to the component as a property (<a href="https://github.com/RachBLondon/todo-template/blob/master/src/App.js">this is done in App.js</a>)</p><pre>&lt;Personal <br>      accounts={this.state.accounts}<br>      space={this.state.space}/&gt;</pre><p>We can also wrap the <strong>Personal, Team, Profile</strong> routes in a conditional preventing them loading before the space. This will allow for easier logic in the components, as they will not render without the space.</p><pre>{this.state.space &amp;&amp; (<br>        &lt;&gt;<br>          &lt;Route path=&quot;/personal&quot;&gt;<br>            &lt;Personal <br>              accounts={this.state.accounts}<br>              space={this.state.space}/&gt;<br>          &lt;/Route&gt;<br>          &lt;Route path=&quot;/team&quot;&gt;<br>            &lt;Team <br>	            accounts={this.state.accounts} /&gt;<br>          &lt;/Route&gt;<br>          &lt;Route path=&quot;/profile&quot;&gt;<br>            &lt;Profile /&gt;<br>          &lt;/Route&gt;<br>        &lt;/&gt;<br>)}</pre><p>Similarly we can wrap the navigation in the same logic.</p><pre>{this.state.space &amp;&amp; (<br>      &lt;&gt;<br>        &lt;Nav.Item&gt;&lt;Link to=&quot;/team&quot;&gt;Team TODOs&lt;/Link&gt;&lt;/Nav.Item&gt;<br>        &lt;Nav.Item&gt;&lt;Link to=&quot;/personal&quot;&gt;Personal TODOs&lt;/Link&gt;&lt;/Nav.Item&gt;<br>        &lt;Nav.Item&gt;&lt;Link to=&quot;/profile&quot;&gt;Profile Update&lt;/Link&gt;&lt;/Nav.Item&gt;<br>      &lt;/&gt;)}</pre><p>Now opening the <a href="https://github.com/RachBLondon/todo-template/blob/master/src/Pages/Personal.js">Personal Component</a>. Before we start coding, it’s useful to describe the flow in which we will create and join the <strong>Confidential Thread.</strong></p><ul><li>Create a personal confidential thread</li><li>Save thread address to the user’s private space</li><li>When revisiting the user will check for the thread address in their private space</li><li>If the thread address is saved in space, they will join using <a href="https://docs.3box.io/api/messaging?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#space-jointhreadbyaddress-address-opts"><strong>joinThreadByAddress</strong></a> method</li></ul><p>In <strong>componentDidMount</strong> we will add the following code to achieve the flow described above:</p><pre>async componentDidMount() {<br>    <br>    const threadName = &quot;personal-list&quot;<br>    const confidentialThreadAddress = await      this.props.space.private.get(threadName)<br>    let personalThread</pre><pre>    if (confidentialThreadAddress) {<br>    // the personal confidential list has been created already<br>    // use it&#39;s adddress to join<br>      personalThread = await this.props.space.joinThreadByAddress(confidentialThreadAddress)<br>    } </pre><pre>   if (!confidentialThreadAddress) {<br>      // the personal confidential list does not exist<br>      // create it and save the address to the user&#39;s private space<br>      personalThread = await     this.props.space.createConfidentialThread(threadName)<br>      await this.props.space.private.set(threadName,  personalThread._address)<br>    }</pre><pre>    this.setState({ personalThread })<br>    // TODO add getPosts<br>  }</pre><p>Once this is done, you should be able to see the personal thread saved to the component’s react state.</p><h4>4. Saving and getting todos from a confidential thread</h4><p>For the personal todo list we will be using a <a href="https://docs.3box.io/build/web-apps/messaging/choose?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#persistent-personal-confidential">personal confidential thread</a>. Each post within a thread comprises of a single string. We would like to store data for our todo app in the form of a JavaScript object. This can be achieved by using json stringify to turn the object in to a JSON string for storage as a thread post.</p><p>First lets look at an example todo object:</p><pre>const demoToDos = [{<br>	  completed: false, // check true when done<br>	  id: &quot;1&quot;, <br>	  order: 1, // used to order the todo in the UI<br>	  postedBy: &quot;0xab74207ee35fbe1fb949bdcf676899e9e72ec530&quot;, <br>          // user&#39;s address<br>	  show: true, <br>	  text: &quot;Laundry &quot; // todo text<br>	}<br>]</pre><p>Now we are going to add the following two methods to retrieve posts:</p><pre>parsePosts = (postArr) =&gt; {<br>    return postArr.map((rawPost) =&gt; {<br>      let post = JSON.parse(rawPost.message)<br>      post.id = rawPost.postId<br>      return post<br>    })<br>  }</pre><pre>async getPosts() {<br>  const rawPosts = await this.state.personalThread.getPosts()<br>  const posts = this.parsePosts(rawPosts)<br>  this.setState({ posts })<br>}</pre><p>Here we can see we are calling the <a href="https://docs.3box.io/api/messaging?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#thread-getposts"><strong>getPosts</strong></a> method on the personal confidential thread to retrieve the posts. We wont have any posts saved yet, so we won’t see any content. However after calling <strong>getPosts</strong> in <strong>componentDidMount</strong> after we set the personal thread to state (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Personal.js#L47">see example</a>), you should see an empty array of posts saved in the component’s react state.</p><pre>// TODO add getPosts<br>this.getPosts()</pre><p>Next let’s add some boilerplate code to create a modal to add todos. Inside the render method, after the <strong>h2</strong>, add the following (<a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Personal.js#L85">see link</a>):</p><pre>&lt;ModalComponent<br>  buttonText={&quot;Add a ToDo&quot;}<br>  ModalHeader={&quot;Add a Todo&quot;}<br>  ModalBodyText={&quot;One more thing on the list.&quot;}<br>  submitFunc={()=&gt;(console.log(`submit a new TODO   ${this.state.newTodo}`))} &gt;<br>  &lt;Container&gt;<br>    &lt;Form&gt;<br>      &lt;Form.Group controlId=&quot;formBasicEmail&quot;&gt;<br>        &lt;Form.Label&gt;New Item&lt;/Form.Label&gt;<br>        &lt;Form.Control<br>          type=&quot;text&quot;<br>          value={this.state.newTodo}<br>          onChange={(e) =&gt; (this.setState({ newTodo: e.target.value }))}<br>        /&gt;<br>      &lt;/Form.Group&gt;<br>    &lt;/Form&gt;<br>  &lt;/Container&gt;<br>&lt;/ModalComponent&gt;</pre><p>The modal component is already imported in to the top of the Personal Component, so the modal should work. Check it by adding some text to the input inside the modal, clicking submit you should be able to see the text logged out in the browser console.</p><p>The modal component adds the new todo to react state (this.state.newTodo), so far however, it is not being saved to 3Box. To fix this we need to modify the <strong>submitFunc</strong> which is passed as a property to the modal component. To handle this, let’s create the following method:</p><pre>onSubmit = async () =&gt; {<br>    // only submit to 3Box if there is a new todo<br>    if (this.state.newTodo) {<br>	// keeps a consistent order of the todo posts in the UI<br>      const orderNumber = this.state.posts.length &gt; 0 ? (this.state.posts[this.state.posts.length - 1].order + 1 ): (1)</pre><pre>      const post = JSON.stringify({ <br>          text: this.state.newTodo,    <br>          completed: false, <br>          show: true, <br>          order : orderNumber, <br>          postedBy: this.props.accounts[0]})</pre><pre>      await this.state.personalThread.post(post)<br>      this.setState({ newTodo: &quot;&quot; })<br>      this.getPosts()<br>    }<br>  }</pre><p>On submit we add an order number to keep a consistent order of the todo posts, stringify the object so it can be saved as a post in the thread, use <a href="https://docs.3box.io/api/messaging?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#box-space-thread-post-message"><strong>thread.posts</strong></a> method to post to 3box, set to react state and finally call the <a href="https://docs.3box.io/api/messaging?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#thread-getposts"><strong>thread.getPosts</strong></a> method we have just made.</p><p>Now lets replace the <strong>submitFun</strong> property in the modal component with the <a href="https://github.com/RachBLondon/3box-todo-app/blob/master/src/Pages/Personal.js#L89"><strong>onSubmit</strong></a> method:</p><pre>submitFunc={this.onSubmit}</pre><p>Once has been added, you will be able to save a personal todo to the users personal confidential thread. You can check this is working by adding a new todo and checking react state that it is being saved in there. We can render the posts in the UI by adding the code below:</p><pre>{this.state.posts &amp;&amp;<br>          &lt;TODO <br>              posts={this.state.posts} <br>              deletePost={()=&gt;(console.log(&quot;deletePost&quot;))}<br>              toggleDone={()=&gt;(console.log(&quot;toggleDone&quot;))}<br>              accounts={this.props.accounts} /&gt;<br>        }</pre><h4>5. Checking done and deleting todos</h4><p>As you can see, we still need to add the code to check done / undone (<strong>toggleDone</strong>) and delete the todos (<strong>deletePost</strong>). To do this add the following methods:</p><pre>toggleDone = async(todo)=&gt; {<br>    const post = JSON.stringify({ <br>        text: todo.text, <br>        completed: !todo.completed, <br>        show: true, <br>        order : todo.order, <br>        postedBy: todo.postedBy <br>     })<br>    await this.state.personalThread.post(post)<br>    await this.state.personalThread.deletePost(todo.id)<br>    this.getPosts()<br>  }</pre><pre>  deletePost = async (postId) =&gt; {<br>    await this.state.personalThread.deletePost(postId)<br>    await this.getPosts()<br>  }</pre><p>Here we can see we are creating a new todo object with the inverse completed property of the selected one. We then use the <a href="https://docs.3box.io/api/messaging?utm_source=medium&amp;utm_medium=blog&amp;utm_campaign=todo-part-1#box-space-thread-deletepost-id"><strong>thread.deletePost</strong></a> method to remove the original post. Similarly in <strong>deletePost</strong> we also make use of this method to remove the todo. In both cases we are calling the <strong>getPosts</strong> method to update the todos in the app.</p><p>Now let’s add the TODO component, so we can view in the UI.</p><pre>&lt;h2&gt;Personal TODOs&lt;/h2&gt;<br>        {this.state.posts &amp;&amp;<br>          &lt;TODO <br>              posts={this.state.posts} <br>              deletePost={this.deletePost}<br>              toggleDone={this.toggleDone}<br>              accounts={this.props.accounts} /&gt;<br>        }</pre><p>Checking it out in the browser, you should be able to add a todo, delete a todo and toggle the status of a todo.</p><p>🎉Congrats, you have built your own decentralised, user controlled todo list! Join us for part two where we will building this out further to include team todos, stay tuned!</p><p><em>If you have any questions or feedback, jump in to </em><a href="https://chat.3box.io"><em>our discord channel!</em></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d1619cd02e5b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/building-an-encrypted-todo-list-with-3box-part-1-2-d1619cd02e5b">Building an encrypted todo list with 3Box (part 1/2)</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Spinning up a 3Box Ghost Pinbot server ]]></title>
            <link>https://medium.com/3box/spinning-up-a-3box-ghost-pinbot-server-ab718cc8737e?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/ab718cc8737e</guid>
            <category><![CDATA[3box]]></category>
            <category><![CDATA[messaging]]></category>
            <category><![CDATA[distributed-data]]></category>
            <category><![CDATA[decentralization]]></category>
            <category><![CDATA[identity]]></category>
            <dc:creator><![CDATA[Janko Simonovic]]></dc:creator>
            <pubDate>Tue, 21 Jul 2020 13:09:09 GMT</pubDate>
            <atom:updated>2020-07-25T15:46:46.608Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*ymSy2j-JWF1pGmXDba-KXg.png" /></figure><blockquote>Boost your 3Box Ghost Threads messaging</blockquote><h3>Introduction</h3><p>We’ve described the 3Box Ghost Threads API and its benefits in the previous blogpost <a href="https://medium.com/3box/introducing-3box-ghost-threads-api-e5b2ad92060d">Introducing 3Box Ghost Threads API</a>. In order to provide you with better experience for using the Ghost Threads API we created a Ghost Pinbot service. This service lets you specify the one or more threads whose messages will be pinned, and in that way help you overcome the common issues in the decentralised realm of messaging such as peer discovery, the initial state sync time and others.</p><p>By serving as an equal thread participant the Ghost Pinbot server preserves previous messaging history and list of participants in the thread. Its purpose is to serve as a bootstrap peer and decrease the participants time for joining the thread and loading the most relevant thread state.</p><p>It should be noted that the thread state in the Ghost Pinbot is not persistent and will reside in the servers memory only. This is not an issue here since the whole purpose of Ghost Threads API is to provide a performant, in-memory, decentralised messaging. If persistence is crucial for the application you’re building you can find more information about <em>persistent</em> threads <a href="https://docs.3box.io/build/web-apps/messaging/persistent-threads">here</a>.</p><h3>Motivation</h3><p>Decentralised architectures come with huge benefits opposed to the centralised ones in many cases. One of the most common cases is decentralised messaging. The benefits against the centralised solutions are the following:</p><ul><li>Censorship resistent</li><li>More stable, more flexible, and safer</li><li>No single point of failure.</li></ul><p>There are some cons as well. The most significant one is the efficiency. Upon joining the chatroom the peer has to find other peers, exchange information about previous messages, etc. This really depends on the algorithms and data structures used for implementing the solution, but one fact is for certain — joining the chatroom can last.</p><p>That’s why we’ve provided the Ghost Pinbot. Once it’s deployed, it can listen to as many threads as you want and keep their state in sync. It can serve as a bootstrap node and provide the joining peer with the most recent state of the thread.</p><h3>Deployment</h3><p>The 3Box Ghost Pinbot Server provides a couple of templates to ease up the deployment on different providers. The server can be deployed in different modes as well:</p><ul><li>API service for communicating with the Ghost Pinbot API</li><li>PEER service for handling Ghost Thread functionalities</li><li>BUNDLED service which bundles both the API and PEER services.</li></ul><p>The service itself does not imply any specific requirements. The following set of instructions describe how to deploy the Ghost Pinbot server on <a href="https://www.heroku.com/">Heroku</a> environment — <em>easy and for free</em>!</p><h3>Instructions</h3><p>The pre-requirements needed for this particular deployment are:</p><ul><li><a href="https://docs.docker.com/get-docker">Docker</a></li><li><a href="https://devcenter.heroku.com/articles/heroku-cli">Heroku CLI</a></li></ul><p>Deploying Ghost Pinbot on Heroku is easy. There are a couple of limitations though:</p><ul><li>One listening port per application</li><li>Unique application names.</li></ul><p>The following steps will deploy the Ghost Pinbot as a set of two services: API and PEER.</p><p><strong>Note</strong>: please make sure that the API_APP_NAME and PEER_APP_NAME variables in the script are unique.</p><pre><strong>#</strong> Login to Heroku <br><strong>$</strong> heroku login <br><strong>#</strong> Clone the 3box-ghostpinbot repo <br><strong>$</strong> git clone https://github.com/3box/3box-ghostpinbot.git<br><strong>$</strong> cd 3box-ghostpinbot<br><strong>#</strong> Run the command to generate the deployment script<br><strong>$</strong> ./deploy/heroku/build.sh <em>&lt;API_APP_NAME&gt;</em> <em>&lt;PEER_APP_NAME&gt;</em><strong> </strong><br><strong>#</strong> Run the script<br><strong>$</strong> ./deploy/heroku/build/deploy.sh</pre><p>The services should be deployed now. For example, if you ran:</p><pre>$ ./deploy/heroku/build.sh <em>ghostpinbot-api</em> <em>ghostpinbot-peer</em></pre><p>the deployed services should be available at:</p><ul><li>API: <a href="https://ghostpinbot-api.herokuapp.com">https://ghostpinbot-api.herokuapp.com</a></li><li>PEER: <a href="https://ghostpinbot-peer.herokuapp.com">https://ghostpinbot-peer.herokuapp.com</a></li></ul><p>The PEER service registers on the API service upon bootstrap. You can query the API service in order to get the <em>multiaddress</em> of the peer node:</p><ul><li>GET PEER INFO: <a href="https://ghostpinbot-api.herokuapp.com/api/v0/peer">https://ghostpinbot-api.herokuapp.com/api/v0/peer</a></li></ul><p>The multiaddress will be listed in the response. This multiaddress can be used as a bootstrap address for future participants. You can swarm connect to it from your IPFS instance or just pass it as an option ghostPinbot while creating a 3Box instance.</p><pre>Box.create(provider, { ghostPinbot: <strong><em>multiaddress </em></strong>}) </pre><p>That’s it! For more information about the Ghost Pinbot and available API(s) please visit <a href="https://github.com/3box/3box-ghostpinbot">3box-ghostpinbot</a> repository.</p><h3>Want to learn more?</h3><p>We’re always available on <a href="https://chat.3box.io/">Discord</a> to help answer your questions. Drop by if you have questions or if you need help integrating. <a href="https://chat.3box.io/">Join us!</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ab718cc8737e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/spinning-up-a-3box-ghost-pinbot-server-ab718cc8737e">Spinning up a 3Box Ghost Pinbot server 👻</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How Ren used 3Box to enable BTC<>ETH swaps]]></title>
            <link>https://medium.com/3box/how-ren-used-3box-to-enable-btc-eth-swaps-eaa0032939bd?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/eaa0032939bd</guid>
            <category><![CDATA[defi]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[self-sovereign-identity]]></category>
            <category><![CDATA[identity]]></category>
            <category><![CDATA[distributed-data]]></category>
            <dc:creator><![CDATA[Danny Zuckerman]]></dc:creator>
            <pubDate>Mon, 13 Jul 2020 13:40:08 GMT</pubDate>
            <atom:updated>2020-07-13T13:40:08.525Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hR0taqIoUxugOxo60YF04A.png" /></figure><p><em>3Box partner series highlights 3Box partners and their innovative use cases.</em></p><p>Last month <a href="https://renproject.io/">Ren</a> launched RenVM: a private, permissionless and decentralized way to transfer assets across chains. This enables inter-blockchain liquidity, locking up assets on one blockchain and minting them on another. Just a month after launch, $20M worth of crypto has been sent through the network.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/997/1*H_HmtVIL7Bi1doYjk2nYKg.png" /></figure><p>To facilitate these swaps Ren built RenBridge, a decentralized application that allows individuals to mint real Bitcoin, ZCash and Bitcoin Cash on Ethereum as an ERC20, and then convert these ERC20s back. This lets holders of those currencies leverage them in Ethereum, including the exploding DeFi ecosystem.</p><p>To make this work with complete resilience and user privacy, Ren leveraged 3Box spaces to store in flight transactions.</p><h3>The challenge: pending transactions</h3><p>RenBridge provides a simple interface to lockup assets on one chain and mint them on another.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1AQmxnJbOr3se9_3" /></figure><p>Transactions on Ren can take ~1 hour or more as it’s necessary to wait for deposits on other chains to be safely confirmed before minting ERC20s on Ethereum. During this period, RenBridge needs to keep track of the pending transaction.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*he6vEPIrKumG2GeFqx-Ulg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/914/0*Hq_kEUylZ_1X5oi0" /></figure><p>One option would be local storage. However, this is a very fragile place to store data critical to the transaction, which may be for large sums. If a user were to clear their browser, suffer a crash, or simply change computers then the record of the transaction would be lost.</p><p>Another option would be to run a database keeping track of user addresses and transaction IDs. However, this creates a single point of failure and centralization, with reliance on Ren (or other server operators) for an otherwise decentralized process.</p><p>The relevant info could be stored in a smart contract, but this creates cost, complexity and may compromise user and transaction privacy.</p><h3>The solution: “global local storage” with 3Box</h3><p>Ren turned to 3Box to backup transactions so there would be a record of all past and pending transactions associated directly to a users keys.</p><p>From Ren’s documentation:</p><blockquote>3Box syncs with Metmask to store your past transaction(s) on RenBridge. So if you shut down your computer, close your browser, etc. while waiting for Confirmations, you can find or pick up your past/pending transaction.</blockquote><p>By using 3Box, Ren could assure that transactions were tracked for users without running their own centralized DB to keep track. Instead, each user could maintain their own log of transactions, fully in their control and fully available across their devices.</p><p>It also made it possible for them to build more quickly without the need to build a centralized backend. Eventually, Ren did add their own storage solution to keep track of pending transactions to completely ensure safe tracking and value transfer themselves, as more than $20M flowed through their protocol in the first weeks.</p><h3>Next up</h3><p>Ren is quickly growing into the top BTC&lt;&gt;ETH bridge, and helping power the current wave of DeFi activity. They will be expanding the assets they support over time. Try out RenBridge at <a href="http://renproject.io">renproject.io</a> and follow them on twitter <a href="https://twitter.com/renprotocol">@RenProtocol</a> for more coming soon.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/893/1*tvbE9Ra4OLGqxcjAyF5g3Q.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=eaa0032939bd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/how-ren-used-3box-to-enable-btc-eth-swaps-eaa0032939bd">How Ren used 3Box to enable BTC&lt;&gt;ETH swaps</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Hack with 3Box at HackFS ]]></title>
            <link>https://medium.com/3box/hack-with-3box-at-hackfs-9bff5f298ff?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/9bff5f298ff</guid>
            <category><![CDATA[ipfs]]></category>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[hackathons]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[3box]]></category>
            <dc:creator><![CDATA[Michael Sena]]></dc:creator>
            <pubDate>Thu, 09 Jul 2020 13:51:47 GMT</pubDate>
            <atom:updated>2020-07-09T13:51:46.976Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_lAvSima2F-VbFQuMvEL7Q.png" /></figure><h4>We’re giving away more than 3,000 DAI in prizes!</h4><p><em>We’re excited to announce that </em><a href="http://3box.io"><em>3Box</em></a><em> is a proud sponsor of the </em><a href="http://hackfs.com"><em>HackFS</em></a><em> hackathon along with other amazing sponsors like Protocol Labs, the Ethereum Foundation, Consensys, Textile, and others. 3Box is offering three bounties worth a total of more than 3,000 DAI in prizes! Read more below.</em></p><h4>What is HackFS?</h4><p>HackFS is a month-long hackathon run by <a href="https://ethglobal.co/">ETHGlobal</a> and <a href="http://protocol.ai">Protocol Labs</a> dedicated to realizing the vision of Web3 by encouraging hackers to build projects that combine blockchains (such as Ethereum), linked data (IPFS), and p2p storage (such as OrbitDB). 3Box uses all three of these technologies and so is a great fit for anyone looking to hack on a new project.</p><h4>Details</h4><p>Sign up: <a href="http://hackfs.com">hackfs.com</a><br>Dates: July 6 — Aug 6, 2020</p><h3>3Box Bounties</h3><p>As a sponsor of the hackathon, we get to offer prizes to developers for building with 3Box’s technology.</p><p><strong>About 3Box:</strong> <a href="http://3box.io/">3Box</a> is the leading platform for decentralized identity, profiles, databases, and messaging that helps Web3 developers build amazing applications.</p><h4>1. Best Overall Use of 3Box</h4><p>Builders choice! Create something truly awesome using 3Box and surprise us with your creativity. For this bounty you can create a new project that uses 3Box, or integrate 3Box into an existing project.</p><p>3Box offers a <a href="https://www.notion.so/threebox/HackFS-3Box-Bounties-e2c1f618095d4c92b25ef8afe646988b#751dee5b6c7d46919c81d361142f1289">JavaScript SDK</a> that delivers everything you need to get going in a single, easy-to-use library. 3Box also offers <a href="https://www.notion.so/threebox/HackFS-3Box-Bounties-e2c1f618095d4c92b25ef8afe646988b#751dee5b6c7d46919c81d361142f1289">plugins</a> that make it easy to add various 3Box-powered functionalities, such as profile hovers, comments, or trollboxes, into to any React app.</p><p><strong>Prize: </strong>1,000 DAI</p><p><a href="https://www.notion.so/threebox/HackFS-3Box-Ceramic-Bounties-e2c1f618095d4c92b25ef8afe646988b#d2d541b563af4d9bb04d330f3f1202e2">Learn more</a></p><h4>2. Interoperable #Defi Chat Platform</h4><p>Create a home for discussions about DeFi protocols and take the DeFi ecosystem to the next level! This bounty is to create a completely decentralized platform for discussing DeFi protocols that can be used across every DeFi interface. Contribute a massive value-add to the thriving DeFi ecosystem.</p><p>The goals of this bounty are to:</p><ol><li>Create a standalone DeFi chat application (name idea: DeFi Talk!) using the <a href="https://docs.3box.io/build/web-apps/messaging/ghost-threads">3Box Ghost Threads API</a></li><li>Integrate chatrooms into 2+ existing DeFi interfaces (i.e. Zerion, Instadapp, DeFi Market Cap, DEXs, etc) using the <a href="https://docs.3box.io/build/plugins/chatbox">3Box Chatbox plugin</a></li></ol><p>3Box offers a <a href="https://www.notion.so/threebox/HackFS-3Box-Bounties-e2c1f618095d4c92b25ef8afe646988b#380562285564485b8d15447509d75a2f">Ghost Threads API</a> that allows developers to create highly-scalable p2p, decentralized chatrooms that are decoupled from any single interface. 3Box also has a Chatbox Plugin which is a simple way to drop Ghost Threads chatrooms into any react app.</p><p><strong>Prize: </strong>1,500 DAI</p><p><a href="https://www.notion.so/threebox/HackFS-3Box-Ceramic-Bounties-e2c1f618095d4c92b25ef8afe646988b#763b5316702549aa8759ce28fe2a17ab">Learn more</a></p><h4>3. Ethereum Leaderboard (Yield Farming, Dapp Usage, and more!)</h4><p>Gamify the DeFi and dapp ecosystem! Create a leaderboard of Ethereum users based on usage of certain apps and protocols.</p><p>3Box offers a <a href="https://docs.3box.io/build/web-apps/profiles">Profiles API </a>that allows developers to create populate their application with rich social user profiles. This API is great for creating delightful and engaging leaderboards. There are already more than 22,000 profiles created!</p><p><strong>Prize: </strong>1,000 DAI</p><p><a href="https://www.notion.so/threebox/HackFS-3Box-Ceramic-Bounties-e2c1f618095d4c92b25ef8afe646988b#12b075b49c874969bbca702a18cb2141">Learn more</a></p><h4>4. Create a new doctype for Ceramic Network</h4><p>Contribute to early development of the <a href="http://ceramic.network">Ceramic Network</a> by expanding what’s possible! This bounty is for creating a new doctype that can run on the protocol. Doctypes are the primitives that define content requirements and state transition rules for documents published on the network. You can read the general doctype specification <a href="https://github.com/ceramicnetwork/CIP/issues/37">here</a>.</p><p>You can create any doctype you’d like but if you need help getting started, a Verifiable Claims doctype that complies with the <a href="https://www.w3.org/TR/vc-data-model/">W3C Verifiable Claims</a> standard would be awesome! Some examples of existing doctypes include: <a href="https://github.com/ceramicnetwork/specs/blob/master/doctypes/3id.md">3ID</a>, <a href="https://github.com/ceramicnetwork/specs/blob/master/doctypes/account-link.md">Account Link</a>, and <a href="https://github.com/ceramicnetwork/specs/blob/master/doctypes/tile.md">Tile</a>.</p><p><strong>About Ceramic: </strong>Ceramic is a cross-platform information graph that allows DIDs to publish unstoppable content in the form of mutable documents. Each document on the network essentially forms its own doc-chain (of updates) and has it’s own verifiable state. Ceramic network uses DIDs to sign messages and author content, doctypes to define document rules, IPFS (IPLD) to store content, and blockchains (or Filecoin) to anchor updates. Each document gets a permalink in the form of ceramic://bafy.... <em>Ceramic is currenly in early alpha testnet. We will have a fully-functional testnet live in a month or so.</em></p><p><strong>Prize: </strong>500 DAI<br><strong>Questions &amp; Support:</strong> Join <a href="https://discord.gg/bt5yPMa">Ceramic Discord</a><br><strong>Docs:</strong> <a href="https://www.notion.so/threebox/HackFS-2022b67e249540a5a7fc5009701ee09f#c7ef133fb7e34583a9fe64566c330ade">Doctype specification guidelines</a>, <a href="https://github.com/ceramicnetwork/specs">Ceramic Specs</a>, <a href="https://github.com/ceramicnetwork/js-ceramic">js-ceramic</a></p><p><a href="https://www.notion.so/threebox/HackFS-3Box-Ceramic-Bounties-e2c1f618095d4c92b25ef8afe646988b#9fce9a2a7fea4de9b1db237a9737a068">Learn more</a></p><h3>Happy hacking and good luck to all! 🚀</h3><p>We’re always available for questions or support in the <a href="https://discord.gg/669BQHv">3Box Discord</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9bff5f298ff" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/hack-with-3box-at-hackfs-9bff5f298ff">Hack with 3Box at HackFS 🚀</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Case study: how 3Box boosts engagement and retention for Zerion]]></title>
            <link>https://medium.com/3box/case-study-how-3box-boosts-engagement-and-retention-for-zerion-96871132c12f?source=rss----32f96b75b1ef---4</link>
            <guid isPermaLink="false">https://medium.com/p/96871132c12f</guid>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[defi]]></category>
            <category><![CDATA[crypto]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <dc:creator><![CDATA[Danny Zuckerman]]></dc:creator>
            <pubDate>Mon, 06 Jul 2020 14:55:15 GMT</pubDate>
            <atom:updated>2020-07-06T14:55:15.664Z</atom:updated>
            <content:encoded><![CDATA[<h3>Case Study: How Zerion uses 3Box to boost engagement and retention</h3><p><em>3Box partner series highlights innovative use cases in the ecosystem</em></p><p><a href="http://zerion.io">Zerion</a> makes DeFi simple, beautiful and delightful for both developers and users. With their web and mobile apps and developer SDK, they are making money legos accessible and powerful to builders and consumers alike.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kpLYZ5fhRjuQSYArAWNnDg.png" /><figcaption>Zerion has always focused on UX, and their users love them for delivering a delightful experience.</figcaption></figure><p>Given this focus on the user, it’s no surprise that Zerion was one of the <a href="https://medium.com/3box/how-3box-profiles-help-zerion-deliver-a-more-human-defi-ux-4191250f4df1">first dapps to integrate 3Box profiles</a>. They understand the need to build for the user, not just the technical capability: apps for humans need profiles, not hex addresses. This is true even when the focus is on financial transactions.</p><h3>Major boost to usage metrics</h3><p><em>Zerion highly respects user privacy and strives to continuously minimize the amount of user data collected. Anonymized meta-data is only used for product improvements and never sold externally.</em></p><p>With the little and anonymized data they collect, the Zerion team wanted to see how basic read-only profiles impacted usage of their web app. Does this simple UX improvement help business goals?</p><h4>Users have far higher retention and engagement when a 3Box profile is attached.</h4><p>First, they looked at retention on the platform for all users versus users with a wallet connected to 3Box. They found that the benefits started on Day 1. Users with 3Box profiles were retained at far higher rates than other users. While exact data by cohort is not available because Zerion takes steps to ensure user privacy and anonymity, this effect continues throughout the first month. Users without 3Box continued to fall off, while users with a 3Box profile remained much more sticky.</p><p>Next, Zerion looked at activity between the two user groups. Data fluctuates throughout the month, but users with 3Box consistently engage more than other users, with spiking at times to 2–2.5x the average usage.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7rRLhfvA2Z6GczVLcU9cuw.png" /></figure><h3>Opportunity for more growth</h3><p>Finally, the Zerion team looked at how users with and without 3Box contributed to their overall user base.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O8R--NFFtpphDcdJ6sFpvQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-Qx1IfrcM1ghYEo0PDex0w.png" /></figure><h4>Users with 3Box profiles contributed 20%+ of all activity on Zerion despite making up a much smaller portion of all active users.</h4><p>As suggested by the earlier data, users with 3Box profiles are adding disproportionate activity and value to the platform compared to those without.</p><p>What to make of this data? First, it shows correlation — not causation. We cannot infer that all of the difference in activity comes from signing up for a 3Box profile. In fact, it’s highly likely that the most active users</p><p>It does suggest that a clear path to growth is to (a) focus on the users who care about UX, and (b) give them a great experience with rich and social features. These are the users that are retained and engaged, and they have 3Box profiles.</p><p>These profiles — along with their data, chat, and other content — can be leveraged across apps. Users and data can be composable alongside money legos in DeFi.</p><h3>Making DeFi more human</h3><p>Zerion has known that a great UX is important to users even when their app was primarily focused on monitoring individual crypto accounts and trades. But their thinking and analysis highlights an important point for the whole ecosystem:</p><blockquote>DeFi may be about money, but its users are people. Our money legos need to be fun, familiar and human to play with.</blockquote><p>It’s likely that encouraging users to sign up for 3Box profiles will drive more engagement. But it’s also important to recognize the users that get the most value from your product. Zerion now knows they can target users with 3Box profiles and likely be speaking to their highest value customers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HoszuOVwW3n9bMbl.png" /><figcaption>Profiles in Zerion</figcaption></figure><p>In addition to profiles they can offer personalized content, leverage interoperable data from their 3Box spaces (e.g., Metamask watch lists), and offer features like chat or comments to engage them.</p><p>What Zerion has shown itself and others is that personalized, human UX is essential to serve the most active DeFi users. And they’ve also shown that we still have a ton of opportunity to grow that base — most of their users still don’t have 3Box, after all.</p><h3>More coming soon</h3><p>The Zerion team has big product plans in store for this summer that you’ll want to be sure to watch. Follow <a href="https://twitter.com/zerion_io">Zerion on twitter </a>and if you aren’t already a user check out <a href="http://zerion.io">zerion.io</a> for a best-in-class DeFi experience.</p><p>If you’re working on a dapp and want to add profiles, user storage or identity, come by 3Box.io, <a href="https://twitter.com/3boxdb">follow us on twitter</a>, or drop into <a href="http://chat.3box.io">our community</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=96871132c12f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/3box/case-study-how-3box-boosts-engagement-and-retention-for-zerion-96871132c12f">Case study: how 3Box boosts engagement and retention for Zerion</a> was originally published in <a href="https://medium.com/3box">3Box Labs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>