Ethden 2020 Textile Bounty Resources

Using Textile, Threads, & IPFS in your EthDen Hack

Textile is a set of tools to help you and your team build decentralized apps, fast. Textile is primrarily built on IPFS and makes it easy for you or your application to store and distribute data over the IPFS network. Some features of Textile you may find useful include:

  • Push files, directories and websites to the IPFS network. Textile's Buckets tool allows you to not only pin files and folders, it allows you to manage those files and folders just like a normal directory, with static paths and names. No CIDs to remember!
  • Collaboratively update and manage those files and folders with your team through simple team creation and sharing. Your team can quickly host app assets or entire webpages on IPFS.
  • Add decentralized databases to your web, mobile, or desktop applicatin. Create databases on IPFS that are private for one user or shared with many. Threads is an advanced decentralized data protocol and database for IPFS.
  • Specify that Threads databases should be private or shared depending on your requirements.

Other things about Textile and Threads you may like include their open source, MIT licenses, active support on the ground at EthDen, and their public Slack group.

Why use Textile at EthDen?

  • Pin your first file to a remote IPFS node.
  • Pin your website or dApp assets
  • Run decentralized databases (called threads) in your app.
  • Host a dynamic "public" folder on IPFS.

Getting Started with Textile

Textile is a command-line interface that gives you access to everything listed above and more. To get started, here's what you need to do:

  1. Download Textile to your computer. You can find the latest release for on our GitHub releases page. Textile is built for all the common architectures used in Mac (Darwin), Windows, and Linux. If your architecture isn't listed, ping us on Slack and we can give you instructions to build a version ready for your system.
  2. Run Textile for the first time, the help command is a useful place to start.
textile --help

The Textile client.

Usage:
  textile [command]

Available Commands:
  buckets     Manage project buckets
  help        Help about any command
  init        Init a new project
  login       Login
  logout      Logout
  projects    Manage projects
  switch      Switch teams or personal account
  teams       Team management
  whoami      Show user or team


Login to Textile

Textile provides a simple login tool that only requires your valid email. By logging in, you will immediately get access to remote IPFS pinning, hosted database services, and more, all of which we'll show you below.

To login:

textile login
Enter your email: [email protected]█
> We sent an email to [email protected] Please follow the steps provided inside it.

Now, go to your inbox and look for the verification email and follow the instructions inside. After complete, your terminal should output a confirmation:

✔ Email confirmed
> Success! You are now logged in. Initialize a new project directory with `textile init`.

That's it, you can now start using Textile, IPFS, and Threads.

Collaborative teams on Textile

By default, you'll be on your own in Textile, you'll probably want to create (or join) a team before you start building.

Create a team
textile teams add <name>
Switch to your new team

You wont be using your new team until you switch to it in your current session. Use the switch team and select your newly created team as follows:

textile switch
Use the arrow keys to navigate: ↓ ↑ → ← 
? Switch to: 
  ▸ [email protected] (current)
  faketeam 
  winners 
Invite another member to your team
textile teams invite
Enter email to invite: [email protected]█
> Success! We sent [email protected] an invitation to the faketeam team
Join a team

If someone else has already created a team for you to join, they'll invite you by the email address you used when logging in. Their invite will be sent to you as an email containing a verified link to join the team. Click the link and the team should become part of your available team options.

List your teams
textile teams ls
NAME  		ID                                    
faketeam 	f62cdc2b-9404-40ed-8467-ea804fcc35f1	
winners		af5ad38d-0e20-4699-8862-b0d2015ffcac	

> Found 2 teams

Projects on Textile

Teams on Textile may create different Projects. Projects are useful to organize resources or user groups in your app. Creating a new one is simple.

First, navigate to the directory where you'd like to build your project,

mkdir ethden
cd ethden/

Next, tell Textile to create a project in this directory. Similar to Git, Textile will create a simple config file in this directly under, .textile/config.yaml.

textile projects init ethden
> Success! Initialized empty project in /Users/me/ethden/.textile

Because you are have switched to your team, this project should now be available to other members of your team also.

Pin your first file to a remote IPFS node.

Textile includes a textile buckets tool that makes it simple for you to pin files to IFPS. The files you pin can be used as part or all of the interface to your dApp. You can think of buckets much like you might already think of buckets on S3 (or if you aren't familiar, just think of them as folders). As an extra bonus, if any bucket you create contains an index.html file, Textile will host the bucket as a web site at https://<bucket-name>.textile.cafe. Read on to see an example.

Push files to a bucket

To start pinning files in your Textile project, use the push sub command. You can push a single file to a bucket or an entire directory, in which case all contained files and directories are pushed recursively. All paths will be created if they don't exist and you can use push repeatedly to keep adding more files to a bucket.

Here, we push files for a static web site to a bucket called aaron:

textile buckets push public/* aaron
Add 44 files? Press ENTER to confirm: █
> Pushing mySite/public/404/index.html to aaron/404/index.html
9.87 kB / 9.87 kB [--------------------------------] 100.00% 78.69 kB p/s 0s
> Pushing mySite/public/404.html to aaron/404.html
9.88 kB / 9.88 kB [--------------------------------] 100.00% 260.14 kB p/s 1s
> Pushing mySite/public/app-b1262bbd5ce4afcb17ea.js to aaron/app-b1262bbd5ce4afcb17ea.js
98.14 kB / 98.14 kB [--------------------------------] 100.00% 307.59 kB p/s 0s
> Pushing mySite/public/app-b1262bbd5ce4afcb17ea.js.map to aaron/app-b1262bbd5ce4afcb17ea.js.map
390.09 kB / 390.09 kB [--------------------------------] 100.00% 376.47 kB p/s 1s
> Pushing mySite/public/chunk-map.json to aaron/chunk-map.json

...

> Success! Pushed 44 files to aaron

Inspecting buckets

You can list the files in a bucket or at any depth in the bucket, similar to listing files locally on your computer:

textile buckets ls aaron/icons
NAME             	SIZE  	DIR   	ITEMS 	PATH                                                                         
icon-144x144.png	9130 	false	n/a  	/ipfs/QmSe8nSJsAW7eJXvMP5gYM6TCkuyJKeU8MusHs2kVBdFMZ/icons/icon-144x144.png	
icon-192x192.png	12422	false	n/a  	/ipfs/QmSe8nSJsAW7eJXvMP5gYM6TCkuyJKeU8MusHs2kVBdFMZ/icons/icon-192x192.png	
icon-256x256.png	16837	false	n/a  	/ipfs/QmSe8nSJsAW7eJXvMP5gYM6TCkuyJKeU8MusHs2kVBdFMZ/icons/icon-256x256.png	
icon-384x384.png	29004	false	n/a  	/ipfs/QmSe8nSJsAW7eJXvMP5gYM6TCkuyJKeU8MusHs2kVBdFMZ/icons/icon-384x384.png	
icon-48x48.png  	2813 	false	n/a  	/ipfs/QmSe8nSJsAW7eJXvMP5gYM6TCkuyJKeU8MusHs2kVBdFMZ/icons/icon-48x48.png  	
icon-512x512.png	22446	false	n/a  	/ipfs/QmSe8nSJsAW7eJXvMP5gYM6TCkuyJKeU8MusHs2kVBdFMZ/icons/icon-512x512.png	
icon-72x72.png  	4425 	false	n/a  	/ipfs/QmSe8nSJsAW7eJXvMP5gYM6TCkuyJKeU8MusHs2kVBdFMZ/icons/icon-72x72.png  	
icon-96x96.png  	5926 	false	n/a  	/ipfs/QmSe8nSJsAW7eJXvMP5gYM6TCkuyJKeU8MusHs2kVBdFMZ/icons/icon-96x96.png  	

> Found 8 items

Pulling files from a bucket

Use the buckets pull command to download files from a bucket to your computer. You can pull an entire bucket, a sub tree of a bucket, or a single file.

textile buckets pull aaron/icons/icon-512x512.png ./
> Pulling aaron/icons/icon-512x512.png to icon-512x512.png
22.45 kB / 22.45 kB [--------------------------------] 100.00% 818.35 kB p/s 0s
> Success! Pulled 1 files to ./

Removing files from a bucket

The buckets rm command is used to remove files or directories from a bucket. Once a bucket is empty, the root bucket directory is deleted and will no longer appear in the list of buckets output from textile buckets ls.

textile buckets rm aaron/aaron.txt
> Success! Removed aaron/aaron.txt

Accessing bucket files on cloud.textile.io

You can access the latest version of the files in your bucket (without needing to know any CID!) at https://cloud.textile.io/dashboard/<project name>/<bucket name>. Of course since the data is all stored in IPFS, it's also available over https://gateway.ipfs.io/ipfs/<CID>. The CID for any Textile bucket or bucket sub directory is listed at the top of the corresponding cloud.textile.io/dahsboard page and in the output from textile buckets ls.

Viewing web sites hosted in buckets

Any bucket that contains an index.html file will be hosted as a web site at https://<bucket-name>.textile.cafe. In the textile buckets push example above, we pushed files that make up a static web site to a bucket named aaron. That web site is automatically available (with TLS!) at https://aaron.textile.cafe.

Threads: add decentralized databases to your app

Want simple Filebase or MongoDB type functionality in your app? Textile provides Threads - A decentralized database built on IPFS. Threads give your app a way to store private data for one user or synchronize data across many peers. For a deep dive over breakfast, read the Threads Whitepaper. For now, here's a quick tour.

The Threads Whitepaper outlines a number of new innovations, some highlights include:

  • Standardized key management for securing data created in your apps
  • An easy interface to create and update models (think MongoDB)
  • A simple way for data owners to invite new members to their database

Technically,

  • Each thread is contains a store (where data is kept) and models (the data structures you store and update).
  • Threads are collaborative, for one to many users. By default, each thread your app creates for a user is private (fully encrypted) but can then be shared with other users who can then have access to just read or read & write to the same Thread.
  • Data is transferred over IPFS, but it is encrypted by keys only available to people invited to the thread.

Getting started with hosted Threads

The easiest way to get started with Threads is through Textile's hosted service. In this case, Threads can leverage your team's Textile resources (buckets, pinning, and networking). First, you'll need to create a Textile app token using the textile CLI.

Create an app token

App tokens allow you to access Textile resources from within apps you build. You can create new app tokens in your project in just a few seconds.

textile project tokens add
> Selected ethden
> Success! Added new token <your new token>

Use the token in your app

To use your token with your app, simply follow the instructions available in either of the Textile client libraries here (support for other languages and platfirms coming soon!):

  • js-textile: a library to authenticate your textile app token and use
  • dart-textile: a library to authenticate your textile app token and use dart-threads-client in your app.

Voila, now you have an app running a Threads database over IPFS with Textile ensuring that database content is pinned to the network no matter when or if your users remain online.

Threads app example

The best way to learn how to use Threads is by checkout out our todo list and folder sync example apps.

Local debugging with the Threads daemon

The preceding instructions have you set up to use Textile's hosted Threads server. Sometimes when developing with Threads, it can be helpful to use a local Threads server called threadsd instead. You can connect an app using any of the Threads client libraries to the local threadsd, and then use the threads shell to view models, data, and watch events as they change data in real-time.

Install the local Threads daemon and shell

  1. Visit the threads releases page. https://github.com/textileio/go-threads/releases
  2. Download the latest release for your platform, Linux, Windows, or Mac (darwin).
  3. Installthreadsd and threads (or the .exes on Windows) application.
  4. Run the threadsd application without any parameters.
tar -xzvf go-threads_v0.1.9_darwin-amd64.tar.gz
x install-threads/
x install-threads/install
x install-threads/threadsd
x install-threads/LICENSE
x install-threads/README.md
x install-threads/threads

cd install-threads/

./install 
Moved ./threads to /usr/local/bin
Moved ./threadsd to /usr/local/bin

threadsd 
Welcome to Threads!
Your peer ID is 12D3KooWFFCiJt6B8Dog9ECpt7KGfqxjUxNktzpTK4e4mzQ51WPG

Note for MacOS: By default, MacOS will prevent threadsd from running. After trying and failing once, you'll have to visit System Preferences > Security & Privacy > General, choose to allow threadsd to run, and then run threadsd again.

Update your project to use local daemon

Updating your project to use the locally running threadsd is as simple as setting the dev flag in the Textile.API constructor. Here's an example in Javascript:

import {API} from '@textile/textile'
import {Client} from '@textile/threads-client'

const api = new API({
  token: "<textile project token>",
  deviceId: "<user id>",
  dev: true // causes the below client to use the local threadsd
})
await api.start()
const threadsClient = new Client(api.threadsConfig)

Use threads shell to monitor data updates

Start up the threads shell which will connect to your local threadsd:

threads
Successfully connected.
>>>

You first need to specify a store id to operate on using the use command:

>>> use <store id>
Switched to <store id>
>>>

Note: You can find your store id by logging it or setting a breakpoint in your app when you create a Theads store.

Another note: In reality, you'll want to keep track of store ids you app creates so you can access those stores at a later time.

View all updates to the data in the current store using the listen command:

>>> listen
<enter> to cancel
{
  "ID": "5389d030-22b4-4327-aed5-10ae1f1f14d8",
  "files": [],
  "owner": "myFolder"
}
{
  "ID": "5389d030-22b4-4327-aed5-10ae1f1f14d8",
  "files": [
    {
      "ID": "25ea5bc5-cbef-4619-9380-9725388f873b",
      "cid": "",
      "files": [],
      "isDirectory": false,
      "name": "filecoin.pdf"
    }
  ],
  "owner": "myFolder"
}

Explore data using the modelFind and modelFindById commands.

Happy hacking ::)