• Stars
    star
    130
  • Rank 277,575 (Top 6 %)
  • Language
    TypeScript
  • License
    Apache License 2.0
  • Created almost 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An SDK for building apps with decentralized identity and storage.

ODD SDK

NPM License Built by FISSION Discord Discourse

The ODD SDK empowers developers to build fully distributed web applications without needing a complex back-end. The SDK provides:

  • User accounts via the browser's Web Crypto API or by using a blockchain wallet as a ODD plugin.
  • Authorization using UCAN.
  • Encrypted file storage using WNFS backed by IPLD.
  • Key management using websockets and a two-factor auth-like flow.

ODD applications work offline and store data encrypted for the user by leveraging the power of the web platform. You can read more about the ODD SDK in Fission's ODD SDK Guide. There's also an API reference which can be found at api.odd.dev

Installation

The ts-odd package is published on yarn, pnpm and npm as @oddjs/odd:

npm

npm install @oddjs/odd

pnpm

pnpm install @oddjs/odd

yarn

yarn add @oddjs/odd

Getting started

// ESM
import * as odd from "@oddjs/odd"

// Browser/UMD build
const odd = globalThis.oddjs

Creating a Program

An ODD program is an assembly of components that make up a distributed web application. Several of the components can be customized. Let's stick with the default components for now, which means we'll be using the Web Crypto API.

const program = await odd.program({
  // Can also be a string, used as an identifier for caches.
  // If you're developing multiple apps on the same localhost port,
  // make sure these differ.
  namespace: { creator: "Nullsoft", name: "Winamp" }

}).catch(error => {
  switch (error) {
    case odd.ProgramError.InsecureContext:
      // The ODD SDK requires HTTPS
      break;
    case odd.ProgramError.UnsupportedBrowser:
      break;
  }

})

odd.program returns a Program object, which can create a new user session or reuse an existing session. There are two ways to create a user session, either by using an authentication strategy or by requesting access from another app through the "capabilities" system. Let's start with the default authentication strategy.

let session

// Do we have an existing session?
if (program.session) {
  session = program.session

// If not, let's authenticate.
// (a) new user, register a new Fission account
} else if (userChoseToRegister) {
  const { success } = await program.auth.register({ username: "llama" })
  session = success ? program.auth.session() : null

// (b) existing user, link a new device
} else {
  // On device with existing session:
  const producer = await program.auth.accountProducer(program.session.username)

  producer.on("challenge", challenge => {
    // Either show `challenge.pin` or have the user input a PIN and see if they're equal.
    if (userInput === challenge.pin) challenge.confirmPin()
    else challenge.rejectPin()
  })

  producer.on("link", ({ approved }) => {
    if (approved) console.log("Link device successfully")
  })

  // On device without session:
  //     Somehow you'll need to get ahold of the username.
  //     Few ideas: URL query param, QR code, manual input.
  const consumer = await program.auth.accountConsumer(username)

  consumer.on("challenge", ({ pin }) => {
    showPinOnUI(pin)
  })

  consumer.on("link", async ({ approved, username }) => {
    if (approved) {
      console.log(`Successfully authenticated as ${username}`)
      session = await program.auth.session()
    }
  })
}

Alternatively you can use the "capabilities" system when you want partial access to a file system. At the moment of writing, capabilities are only supported through the "Fission auth lobby", which is an ODD app that uses the auth strategy shown above.

This Fission auth lobby flow works as follows:

  1. You get redirected to the Fission lobby from your app.
  2. Here you create an account like in the normal auth strategy flow shown above.
  3. The lobby shows what your app wants to access in your file system.
  4. You approve or deny these permissions and get redirected back to your app.
  5. Your app collects the encrypted information (UCANs & file system secrets).
  6. Your app can create a user session.
// We define a `Permissions` object,
// this represents what permissions to ask the user.
const permissions = {
  // Ask permission to write to and read from the directory:
  // private/Apps/Nullsoft/Winamp
  app: { creator: "Nullsoft", name: "Winamp" }
}

// We need to pass this object to our program
const program = await odd.program({
  namespace: { creator: "Nullsoft", name: "Winamp" },
  permissions
})

// (a) Whenever you are ready to redirect to the lobby, call this:
program.capabilities.request()

// (b) When you get redirected back and your program is ready,
// you will have access to your user session.
session = program.session

Once you have your Session, you have access to your file system πŸŽ‰

const fs = session.fs

Notes:

  • You can use alternative authentication strategies, such as odd-walletauth.
  • You can remove all traces of the user using await session.destroy()
  • You can load the file system separately if you're using a web worker. This is done using the combination of configuration.fileSystem.loadImmediately = false and program.fileSystem.load()
  • You can recover a file system if you've downloaded a Recovery Kit by calling program.fileSystem.recover({ newUsername, oldUsername, readKey }). The oldUsername and readKey can be parsed from the uploaded Recovery Kit and the newUsername can be generated before calling the function. Please refer to this example from Fission's ODD App Template. Additionally, if you would like to see how to generate a Recovery Kit, you can reference this example

Working with the file system

The Webnative File System (WNFS) is a file system built on top of IPLD. It supports operations similar to your macOS, Windows, or Linux desktop file system. It consists of a public and private branch: The public branch is "live" and publicly accessible on the Internet. The private branch is encrypted so that only the owner can see the contents. Read more about it here.

const { Branch } = odd.path

// List the user's private files
await fs.ls(
  odd.path.directory(Branch.Private)
)

// Create a sub directory and add some content
const contentPath = odd.file(
  Branch.Private, "Sub Directory", "hello.txt"
)

await fs.write(
  contentPath,
  new TextEncoder().encode("πŸ‘‹") // Uint8Array
)

// Persist changes and announce them to your other devices
await fs.publish()

// Read the file
const content = new TextDecoder().decode(
  await fs.read(contentPath)
)

That's it, you have successfully created an ODD app! πŸš€

POSIX Interface

WNFS exposes a familiar POSIX-style interface:

  • exists: check if a file or directory exists
  • ls: list a directory
  • mkdir: create a directory
  • mv: move a file or directory
  • read: read from a file
  • rm: remove a file or directory
  • write: write to a file

Versioning

Each file and directory has a history property, which you can use to get an earlier version of that item. We use the delta variable as the order index. Primarily because the timestamps can be slightly out of sequence, due to device inconsistencies.

const file = await fs.get(odd.path.file("private", "Blog Posts", "article.md"))

file.history.list()
// { delta: -1, timestamp: 1606236743 }
// { delta: -2, timestamp: 1606236532 }

// Get the previous version
file.history.back()

// Go back two versions
const delta = -2
file.history.back(delta)

// Get the first version (ie. delta -2)
// by providing a timestamp
file.history.prior(1606236743)

Sharing Private Data

https://docs.odd.dev/sharing-private-data

Migration

Some versions of the ODD SDK require apps to migrate their codebase to address breaking changes. Please see our migration guide for help migrating your apps to the latest ODD SDK version.

Debugging

Debugging mode can be enable by setting debug to true in your configuration object that you pass to your Program. By default this will add your programs to the global context object (eg. window) under globalThis.__odd.programs (can be disabled, see API docs).

const appInfo = { creator: "Nullsoft", name: "Winamp" }

await odd.program({
  namespace: appInfo,
  debug: true
})

// Automatically exposed Program in debug mode
const program = globalThis.__odd[ odd.namespace(appInfo) ] // namespace: "Nullsoft/Winamp"

More Repositories

1

fission

Fission CLI & server
Haskell
119
star
2

keystore-idb

In-browser key management with IndexedDB and the Web Crypto API
TypeScript
56
star
3

ipfs-haskell

IPFS wrapper for Haskell
Haskell
43
star
4

haskell-for-typescript-devs

Onboarding Material: Haskell for TypeScript Developers
40
star
5

rust-template

Fission-focused Rust and Rust+Wasm project templates
Rust
38
star
6

fission-codes

Status codes for smart contracts powering microservices for Web3
JavaScript
37
star
7

drive

A file manager for your webnative filesystem.
Elm
24
star
8

ipfs-cluster-aws

HCL
23
star
9

get-ipfs

Utility to get a contextual js-ipfs instance, with graceful web fallbacks
TypeScript
22
star
10

ipfs-photo-gallery

An InterPlanetary File System (IPFS) photo gallery - example usage of the Fission IPFS Add-on for Heroku
TypeScript
21
star
11

whitepaper

The Fission Technical Whitepaper
18
star
12

nextjs-blog-starter-typescript-ghost

Same as official nextjs-blog-starter-typescript, with added support for fetching content from Ghost via its API
TypeScript
16
star
13

heroku-ipfs-ghost

The Ghost blog system upgraded with Heroku deploys & IPFS support.
JavaScript
15
star
14

fission-guide

Fission App Documentation
13
star
15

webnative-elm

Thin wrapper around webnative for Elm.
Elm
13
star
16

fission-vscode

A vscode extension for fast app publishing powered by IPFS ⚑️
TypeScript
13
star
17

auth-lobby

The authentication service that Fission services run.
Elm
12
star
18

ghost-storage-adapter-ipfs

A storage adapter for the Ghost blogging platform that stores files in IPFS with Fission
JavaScript
11
star
19

spec

11
star
20

publish-action

Github action to publish your project with fission
Nix
10
star
21

kubo-car-mirror

Implementation of the CAR Mirror protocol for Kubo
Go
10
star
22

cli

Command-line interface for Fission
Haskell
9
star
23

landing-page

Fission home page
Nunjucks
9
star
24

stored-wasm-example

Demonstration of stored wasm modules with webnative storage
HTML
9
star
25

fission-server

Rust
9
star
26

dashboard

The account dashboard for the Fission platform
Elm
8
star
27

kit

UI Kit for Fission projects
Elm
8
star
28

typescript-client

The Fission Web API TypeScript Client
TypeScript
7
star
29

fission-services

Open Services for Web3
Solidity
7
star
30

blog

Webnative blogging
TypeScript
7
star
31

zerowallet-poc

Proof of concept for identity derived from zerowallet
JavaScript
6
star
32

ipfs-user-settings

Portable & forkable user preferences
JavaScript
6
star
33

fission-codes-web

The website & documentation for the FISSION Suite
CSS
6
star
34

discourse-ipfs-file-store

A Discourse plugin to use IPFS to store files
Ruby
6
star
35

wasm-js

JavaScript
6
star
36

basquiat

Interplanetary Image Metadata Resizer
Rust
5
star
37

discourse-web3-login

Web3 Ethereum login plugin for Discourse
5
star
38

commons-funding

Commons funding, bounties, grants, and other funding opportunities sponsored by Fission.
5
star
39

ipfsconnect-istanbul-workshop-2023

Instructions and settings for Istanbul, 2023
5
star
40

wnfs-migration

TypeScript
4
star
41

skip-ratchet-paper

TeX
4
star
42

fil-cosigner

TypeScript
4
star
43

rs-car-mirror

Rust
4
star
44

Fission-Starmap

Roadmap render of all Fission projects in one place
4
star
45

one-webcrypto

Import the webcrypto API as a single module in both nodejs and browsers.
JavaScript
4
star
46

go-car-mirror

Generic Go implementation of the CAR Mirror protocol
Go
4
star
47

react-todomvc

React TodoMVC implementation backed by Webnative
JavaScript
4
star
48

notes

Demo React app built with webnative
TypeScript
4
star
49

ipfs-api-clients

Client libraries for the IPFS API - Clojure, C#, Elixir, Elm, Erlang, Go, Java, JS, Kotlin, PHP, Python, Rust, Scala, Swift, TypeScript
C#
4
star
50

stack

⌘ Fission Stack
JavaScript
4
star
51

homebrew-fission

Homebrew tap for Fission Tools
Ruby
3
star
52

pwa-generator

An app for generating PWAs on the Fission platform
Elm
3
star
53

filecoin-backup

Filecoin backup app with webnative integration
CSS
3
star
54

awesome-discord-announce

An awesome list of dev-focused Discord announce channels
3
star
55

webnative-walletauth

Use your blockchain wallet as a webnative authentication strategy.
TypeScript
3
star
56

webnative-filecoin

TypeScript
3
star
57

distributed-attire

A repository of liberally licensed designs for attire.
3
star
58

raycast-fission-talk

Raycast extension for Fission Talk
TypeScript
2
star
59

fission-translate

Human-readable translations of FISSION Codes (smart contracts)
JavaScript
2
star
60

js-template

⌘ Fission JS Template
JavaScript
2
star
61

typescript-boilerplate

Boilerplate for Typescript libraries wtih RollupJS, Jest, Prettier & TSLint
TypeScript
1
star
62

drive-serving-files-example

A demo app showing how to use Fission Drive to serve files
HTML
1
star
63

swag.fission.codes

Elm
1
star
64

whitepaper-old-format

The FISSION Techincal Whitepaper
1
star
65

zerowallet

Zerowallet Typescript Implementation
TypeScript
1
star
66

orbitdb-eventlog-demo

A small demo to try out orbit db
JavaScript
1
star
67

roam-research-discourse-sync

Sync between Roam Research and Discourse.
1
star
68

moon-garden

πŸŒ› Moon Garden 🌱 is a digital garden built on WebNative
Elm
1
star
69

contacts

Keep track of all your different wallet addresses.
Elm
1
star
70

platform-api-apps-example

A demo app showing the webnative platform API for publishing apps
JavaScript
1
star
71

ipfs-connection-poc

A proof of concept environment for testing IPFS peer connections
JavaScript
1
star
72

dialog

1
star
73

fission-tiddlywiki-edition

A bundle of plugins included in the TiddlyWiki on Fission app https://tiddlywiki.fission.app
HTML
1
star
74

fission-cli

Rewrite it in Rust πŸ¦€
Rust
1
star
75

community-guidelines

Community Guidelines for Fission and Fission-related events, channels, repositories
1
star
76

fission-elm-pages-starter

The elm-pages-starter with Fission auth and storage
Elm
1
star
77

fission-drop

Applescript "droplet" wrapper for Fission CLI.
AppleScript
1
star
78

.github

org-level github configuration
1
star