• Stars
    star
    176
  • Rank 216,987 (Top 5 %)
  • Language
    TypeScript
  • Created over 4 years ago
  • Updated 4 months ago

Reviews

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

Repository Details

Standard development kit for creating Web UIs that work with Holo Hosting.

Holo Hosting Web SDK

Web SDK is the core interface for accessing Holo-Hosted Holochain apps from a web UI. Web SDK provides the same methods for manipulating a Holochain agent as AppWebsocket from holochain-client-js (callZome and appInfo), but additionally provides methods for determining which hosted agent to access (signIn, signUp, and signOut).

Prelease warning: These docs are for a prelease version of web sdk. See here for docs for the latest released verson (0.5.3)

Credentials overlay

Web SDK is not just a library for connecting to a HoloPort. It also inserts an iframe into the web page. This iframe is display: none by default, but when you call signIn or signUp, it covers the whole screen with a "Create Credentials" overlay.

"Create Credentials" sign up form login form

We guard Login inside of an iframe so that the happ UI cannot directly access the agent's private keys or passwords. The web page contained in this iframe is called "Chaperone". The URL for the official production Chaperone is https://chaperone.holo.hosting. (Chaperone source repository)

Local dev environment (holo-dev-server)

The production Chaperone at https://chaperone.holo.hosting is configured to connect to real HoloPorts, so it only works if you've already published your hApp to the Holo Hosting network. If you're still developing your happ, you can create a local Chaperone which directs all agents to a locally simulated HoloPort using a program called holo-dev-server.

Examples

If you have access to its repo, check out dummy-ui, especially holo.js.

Commiting to the source chain

import WebSdk from '@holo-host/web-sdk'

const main = async () => {
  // Establish a connection to a chaperone iframe
  const client = await WebSdk.connect({
    chaperoneUrl: 'http://localhost:24274' // Connect to holo-dev-server
    
    // Alternatively, connect to a production holoport:
    //
    // chaperoneUrl: 'https://chaperone.holo.hosting'

    // Customize the Credentials Overlay
    authFormCustomization: {
      logoUrl: "my-logo.png",
      appName: "My App",
      requireRegistrationCode: false
    }
  })

  // Check what kind of agent we have
  console.log(client.agent)
  /*
  {
    "id": "uhCAkFUJ7PAIodGIzUjeHOAu5K8vUizQqZYgmig5PL05G8QPTpyce",
    "isAnonymous": true,
    "isAvailable": false,
    "hostUrl": "localhost:9999",
    "unrecoverableError": null
  }
  */

  // We just started up, so we're still connecting. Let's wait for isAvailable == true
  const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
  while (!client.agent.isAvailable) {
    await sleep(50)
    // ATTN! This is not production quality code. In a real UI, you should register an event handler for `client.on('agent-state')`
    // and store the agent state in reactive state so that your components can just branch on isAvailable.
  }

  // Check what kind of agent we have
  console.log(client.agent)
  /*
  {
    "id": "uhCAkFUJ7PAIodGIzUjeHOAu5K8vUizQqZYgmig5PL05G8QPTpyce",
    "isAnonymous": true,
    "isAvailable": true,
    "hostUrl": "localhost:9999",
    "unrecoverableError": null
  }
  */

  // WebSdk defaults to an anonymous connection where you can't write to the source chain. Sign in so we can commit something
  await client.signIn()
  
  // The credentials overlay is now visible to the user. Wait for them to sign in
  while (client.agent.isAnonymous || !client.agentState.isAvailable) {
    await sleep(50)
    // Again, this while/sleep pattern is for demo only. See comment above about doing this using an event handler
  }

  console.log(client.agentState)
  /*
  {
    "id": "uhCAkRr1W12kUrY7SlSfwUpH_eJOxQGTZrIQxTQaV5-7kkh15Ewwg",
    "isAnonymous": false,
    "isAvailable": true,
    "hostUrl": "localhost:9999",
    "unrecoverableError": null
  }
  */

  // Commit an entry to the test DNA
  const result = await client.callZome({
    roleId: "test",
    zomeName: "test",
    fnName: "create_link",
    payload: null
  })
  console.log(result)
  /*
  {
    "type": "ok",
    "data": null
  }
  */

  // Any error returned by Holochain or the DNA itself is passed through as a normal value
  const error_result = await client.callZome({
    roleId: "test",
    zomeName: "test",
    fnName: "create_link",
    payload: { some_garbage_payload: true }
  })
  console.log(error_result)
  /*
  {
    "type": "error",
    "data": "Holochain returned error response: RibosomeError(\"Wasm error while working with Ribosome: Deserialize([129, 180, 115, 111, 109, 101, 95, 103, 97, 114, 98, 97, 103, 101, 95, 112, 97, 121, 108, 111, 97, 100, 195])\")"
  }
  */
}

Javascript API

TypeScript-style API reference

// Inserts a Chaperone iframe into the DOM and returns an object for sending requests to it.
export async function connect (opts?: {
  // The URL for the Chaperone iframe
  //
  // Defaults to `"https://chaperone.holo.hosting"`
  // If using holo-dev-server, then you want `"http://localhost:24274"`
  //
  // It is good practice make this a build-time parameter of your UI,
  // and then have a variety of scripts in `package.json` that specify different Chaperone URLs for different use-cases
  chaperoneUrl?: string
  // Customization parameters for the Credentials Overlay (all fields OPTIONAL)
  //
  // The above screenshots of the Login and Create Credentials screens
  // were generated with
  // {
  //   appName: 'appName',
  //   logoUrl: '/docs_images/placeholder-logo.png',
  // }
  // So you can check those to see where these fields will end up.
  authFormCustomization?: {
    // The name of the hosted hApp. Currently shows up as "appName Login"
    appName?: string
    // The URL of the hApp logo. Currently displayed on a white background with no `width` or `height` constraints.
    logoUrl?: string
    // Determines whether the "REGISTRATION CODE" field is shown.
    // 
    // Set this to `true` if you want to prompt the user for a registration code that will be passed directly to your happ as a mem_proof (ie, not using a memproof server). This field does nothing if the membraneProofServer option (see below) is set.
    requireRegistrationCode?: boolean
    // Publishers may provide a "Membrane Proof Server" if they want control over sign-ups of new agents in the hApp.
    //
    // If `membraneProofServer` is not specified, then the "REGISTRATION CODE" field will be base64 decoded and passed as a Membrane Proof when installing the DNA for the hApp.
    //
    // If `membraneProofServer` is specified, it works as follows:
    // 1. When the user clicks "Submit" on the "Create Credentials" form, an HTTP request is made to `membraneProofServer.url` containing information like
    //   - The public key of newly created agent
    //   - The value entered into the "REGISTRATION CODE" field
    //   - The contents of `membraneProofServer.payload`
    // 2. The `membraneProofServer` returns with a Membrane Proof or an error.
    //
    // See here for an example implementation of the unstable Membrane Proof Server Protocol https://github.com/Holo-Host/holo-nixpkgs/tree/develop/overlays/holo-nixpkgs/membrane-proof-service
    membraneProofServer?: {
      url: string
      // An arbitrary value that will be passed to the Membrane Proof Server as additional information
      payload: unknown
    }
  }
}): Promise<WebSdk>

// Methods for switching hosted agents, querying state about the current agent, and making Zome Calls on the agent
interface WebSdk {
  // Triggers a request to show the credentials form
  // and start on the "Create Credentials" page.
  //  
  // The returned promise resolves as soon as the iframe (Chaperone)
  // has received the request.
  //  
  // - If `cancellable == true`,
  //   - the form will have a close button.
  //   - if the user clicks on it or presses the back arrow,
  //     the credentials overlay will close.
  //
  // If `cancellable == false`, then there is no way to for the user to close the overlay without logging in (aside from closing the tab/refreshing).
  //
  // Tip: If you want to do something once the user has signed up/in, write an event handler for the `agent-state` event.
  async signUp(opts?: { cancellable?: boolean }): Promise<void>
  // Same as signUp, but starts on the "Login" page instead.
  async signIn(opts?: { cancellable?: boolean }): Promise<void>
  // Triggers a request to switch to an anonymous agent.
  //
  // The returned promise resolves as soon as the iframe (Chaperone)
  // has received the request.
  async signOut(): Promise<void>
  // Makes a zome call on the installed hApp for the current agent.
  //
  // The returned promise resolves when the client has received a response from the host.
  //
  // This returns the zome call result directly on success, and throws an error on failure
  //
  // `zomeName`, `fnName` and `payload` have the same meaning as in [AppWebsocket.callZome].
  //
  // [AppWebsocket.callZome]: https://github.com/holochain/holochain-client-js/blob/develop/docs/API_appwebsocket.md#appwebsocketcallzome-cell_id-zome_name-fn_name-payload-provenance-cap-
  async callZome(args: {
    // The role ID of the DNA to call into. Determined by the `happ.yaml` for your hApp
    roleId: string
    // The name of the zome to call into. Determined by the `dna.yaml` of your hApp
    zomeName: string
    // The name of the Zome Function to call. Determined by the Rust source
    fnName: string
    // The payload to pass to the function.
    // 
    // The HDK will produce a MessagePack deserialization error if does not match the format expected by the DNA. You can `msgpack.decode()` the bytes in the error message to debug.
    payload: unknown,
    // A CapSecret, returned from a holochain `generate_cap_secret` call. Internally it's a 64 byte Uint8Array
    capSecret?: CapSecret
  }): Promise<any>
  // The state of the current hosted agent. See `AgentState` below for structure.
  agent: AgentState
  // The unique ID within the Holo Hosting network for the current hApp. 
  happId: string
  // Emitted whenever any field of `this.agentState` changes.
  //
  // The event passes one argument, the current value of `this.agent`.
  // It's possible for duplicate `agent-state` events to be emitted.
  on(event: 'agent-state', callback: (agentState: AgentState) => void): void
  // Emitted whenever the Chaperone UI becomes visible or hidden, and whenever the particular UI page shown changes.
  //
  // It's possible for duplicate `ui-state` events to be emitted.
  on(event: 'ui-state', callback: (uiState: UIState) => void): void
  // Emitted whenever either of the above events is emitted. This event is passed a combination of the above two values.
  //
  // It's possible for duplicate `chaperone-state` events to be emitted.
  on(event: 'chaperone-state', callback: (chaperoneState: ChaperoneState) => void): void
  // Emitted whenever the DNA emits a signal.
  //
  // `callback` takes an object containing the payload and the hash of the DNA which emitted it.
  on(event: 'signal', callback: (signal: Signal) => void): void

  // Returns the InstalledAppInfo for the initial agent.
  //
  // (May 2022: Due to a bug in the current implementation, this does not update if you switch agents, so this can only return the app info for the first agent that Chaperone tries to create after `connect` is called)
  //
  // Known issue: This promise will currently never resolve if the initial agent fails to load.
  //
  // The main use case for appInfo is determining what roleId to use for Zome calls, but now that it's recommeneded to hardcode the roleId in the UI, there is not much reason to use this method.
  async appInfo(): Promise<InstalledAppInfo>
  // (NOT IMPLEMENTED) Calls StateDump using the Holochain admin websocket on the hosted agent's sourcechain, and returns the result.
  async stateDump(): Promise<StateDump>
}

// AgentState type is exported from this package

type AgentState = {
  // The base64-encoded public key of the current hosted agent
  id: string
  // If true, then the agent is anonymous.
  // This means that the user did not have to log in, and will have limited access to mutating the source chain.
  isAnonymous: boolean
  // If true, the agent is connected to a host, the app is installed, and you can make zome calls.
  isAvailable: boolean
  // If defined, then the agent has encountered an unrecoverable state, and the best course of action may be to notify the user or sign out.
  unrecoverableError: UnrecoverableError | undefined
  // The URL of the HoloPort that is hosting the current agent. Useful for debugging.
  hostUrl: string
}

export type UIState = {
  // true when the Chaperone UI overlay is visible
  isVisible: boolean,
  // the particular Chaperone UI page that's displayed, or 'hidden'
  uiMode: UIMode
}

export type UIMode = 'login' | 'signup' | 'hidden'

export type ChaperoneState = {
  agentState: AgentState,
  uiState: UIState
}

type UnrecoverableError = {
  // Returned if the *publisher* has paused the happ in Publisher Portal. 
  type: 'paused'
} | {
  // Returned if envoy cannot find the happ, likely because the publisher hasn't published it to the Holo network
  type: 'not_hosted'
} | {
  // Internal holochain error
  type: 'error_getting_app_info'
  data: string
} | {
  // Internal holochain error
  type: 'error_enabling'
  data: string
} | 

// TODO: Once this feature is implemented, update this to match the state dump structure in holochain-client-js 
type StateDump = void

// BELOW THIS LINE COPIED FROM
// https://github.com/holochain/holochain-client-js/blob/develop/src/api/types.ts
type InstalledCell = {
  cell_id: [Uint8Array, Uint8Array]
  role_id: string
}

type InstalledAppInfo = {
  installed_app_id: string
  cell_data: Array<>
  status: InstalledAppInfoStatus
}

type InstalledAppInfoStatus =
  | {
      paused: { reason: { error: string } }
    }
  | {
      disabled: {
        reason: DisabledAppReason
      }
    }
  | {
      running: null
    }

type DisabledAppReason =
  | {
      never_started: null
    }
  | { user: null }
  | { error: string }

More Repositories

1

holo-envoy

Server that facilitates communication between hosted Agents and a Host's Holochain Conductor
JavaScript
158
star
2

hpos-config

HoloPortOS config initialization and management
JavaScript
147
star
3

holo-hosting-app-redux

Holo hosting app is an app that connects Providers and Hosts (DNA)
Rust
43
star
4

host-console-ui

Vue
40
star
5

holo-auth

Holo authentication infrastructure
Rust
40
star
6

holo-auto-installer

auto-pilot for managing hosted happs on holoport
Rust
39
star
7

ui-common-library

Common UI library code
Vue
39
star
8

hpos-service-crates

Install self-hosted hApps from a YAML file into holochain
Rust
37
star
9

hds-releases

For public releases of Holo-dev-server
Nix
34
star
10

deepkey-redux

A holochain core app to manage device and agent keys
Rust
33
star
11

hp-admin

The entry point into the world of Holo as a Host
JavaScript
32
star
12

dummy-dna

This is a test dna for Holo or Holochain services testing
TypeScript
32
star
13

hp-admin-crypto

A client for signing and server for verification of calls from HP Admin UI to HPOS
Rust
30
star
14

holo-cache

Cloudflare Worker that sets up max TTL for Nix binary cache artifacts at https://cache.holo.host
JavaScript
29
star
15

loader

A JavaScript framework to bootstrap loading of a P2P Holochain app in a web browser via Holo hosting services.
JavaScript
25
star
16

holo-host

[WIP] Holo Host container and CLI
Rust
24
star
17

holo-hosting-app-proto

Holo hosting app prototype (superseded by Holo Hosting App)
TypeScript
24
star
18

wasm-key-manager

Holochain-compatible key management for Holo web users
Rust
23
star
19

holojs-sample-app

Simple reference hApp for testing Holo Hosting and holo.js communication
HTML
23
star
20

dummy-ui

Example holo-rsm ui for dummy happ using the web-sdk
Vue
22
star
21

hclient

Client side javascript module for converting a Holochain web UI to be Holo enabled
CSS
22
star
22

ico

Ethereum smart contracts for the Holo ICO / crowd sale. Includes the ERC-20 token contract that models surrogate fuel tokens which will be replaced by Holo's final implementation on Holochain.
JavaScript
21
star
23

talking-stickies

Svelte
20
star
24

holo-host-tools

Command-line tools for working with the Holo Host whitelist, ZeroTier network, etc.
Ruby
20
star
25

holo-hosting-app-gui

A simple and clean UI pairing with the Holo Hosting App to provide a space for Hosts and App Providers to interact when hosting on Holo.
TypeScript
20
star
26

accountant-app

The DNA used by Holo Hosts to record service logs
Rust
18
star
27

hcadmin-proto-gui

App manager for Holochain prototype (superseded by Holoscape)
JavaScript
18
star
28

servicelogger

Holo Service Logger app
Rust
17
star
29

holo-communities-dna

DNA for the holo communities hApp
Rust
16
star
30

holofuel-model

A model of the Holo Fuel value-stable currency system.
Jupyter Notebook
15
star
31

cross-origin-message-bus

Facilitates communication between a hApp UI and Holo Chaperone
JavaScript
15
star
32

holo-communities

JavaScript
15
star
33

holofuel-service-crates

Crates that provide diffrent services for holofuel running on hpos
Rust
15
star
34

holofuel-gui

Simple and intuitive interface allowing users to transact with HoloFuel.
TypeScript
14
star
35

mock-conductor

Javascript library for mocking the Holochain Conductor.
JavaScript
13
star
36

did-holo-resolver

Prototype did:holo: method driver
JavaScript
13
star
37

net-stats-daemon

Rust
13
star
38

happ-template

Example for hApp CI and development environment setup
Rust
12
star
39

holo-proto

Prototypes of all services needed to demonstrate Holo hosting capability, orchestrated by Docker Compose
TypeScript
12
star
40

hosting-app

[WIP] The Holo Hosting app used by Hosts and App Providers
Rust
12
star
41

hp-stats-api

Public API for Holo's match service
Rust
12
star
42

holo-cli

Command line tool for Holo developers
JavaScript
11
star
43

hc-multiplexer

Web connector for multiplexing a Holochain conductor to main UI instances.
JavaScript
11
star
44

holoports-monitor

Script for testing uptime of holoports assigned for test
JavaScript
11
star
45

chess-ui

Deployment repo for elemental chess UI. Required for cloudflare pages
HTML
11
star
46

holo-auth-notifier

script that monitors and notifies the status of a holoport
Rust
11
star
47

hcinstaller

Holochain installer (superseded by Holoscape)
JavaScript
10
star
48

MJB-holofuel-ui-deploy

Built files for Matt Brisebois's HoloFuel UI to test Holo-hosting infrastructure
JavaScript
10
star
49

holoportOS

Legacy HoloPortOS stripped down to upgrade to Holo Nixpkgs version
Nix
10
star
50

hrl-gateway-node

A gateway for agentless HTTP queries to hosted DHTs
JavaScript
10
star
51

dpki-lite.js

The browser-side crypto for holo light clients
JavaScript
10
star
52

cryptolib-js

Cross-compatible cryptographic utilities for node/web
JavaScript
9
star
53

identicon

JavaScript
9
star
54

kizuna-ui

temporary repo for built Kizuna UI files - needed for Cloudflare pages
HTML
9
star
55

hc-react-redux-framework

A react-redux framework for building Holo and Holochain applications
TypeScript
8
star
56

holo-envoy-legacy

Legacy server that facilitates communication between hosted agents and a host's conductor
TypeScript
8
star
57

lair-shim

JavaScript
8
star
58

web-sdk-ionic-demo

TypeScript
7
star
59

branding

A repository for information, tools, components, etc. for building Holo user interfaces.
7
star
60

chaperone-scaletest-deploy

HTML
7
star
61

hcrust-scaffold

Web wizard for generating Holochain application scaffolding
7
star
62

holo-api-test-template

Scaffold and template for api tests
Gherkin
6
star
63

saltmine

Cloudflare Worker that manages salt for Holochain identities derived from email/password pairs
JavaScript
6
star
64

chaperone-dev-deploy

Chaperone develop branch deployment to Github pages
HTML
6
star
65

chaperone-deploy

HTML
6
star
66

hpos-seed

Wormhole-based hpos-config.json transfer library, CLI, and desktop app for initializing HoloPortOS instances without USB access
Python
5
star
67

hpos-update

Simple channel update script to make testing easier
5
star
68

holoport-manager-ui

HoloPort Manager app UI (superseded by HPOS Admin UI)
CSS
5
star
69

holoport-manager

Holoport Manager app (superseded by HPOS Admin)
Python
5
star
70

el-chat-qa

5
star
71

service-worker-logger

A basic logging library for Node.js that works in a service worker context
JavaScript
5
star
72

data-translator-js

A tool for translating payloads across Holo services.
JavaScript
5
star
73

holo-cuckoo

JavaScript
4
star
74

self-hosted-happs-node

JavaScript
4
star
75

holofuel-python

Python modules supporting accessing and testing Holo Fuel APIs and models
Python
4
star
76

bump-dna

Bash script for quick altering of hashspace of selfhosted DNAs on HPOS
Shell
4
star
77

holo-update-conductor-config

Rust
3
star
78

hydra-testing-repo

Repository to test hydra, please ignore, this will be deleted in few hours
Nix
3
star
79

holofuel-ui

UI for holofuel app
JavaScript
3
star
80

chat-test

HTML
3
star
81

holo-cdn

JavaScript
2
star
82

holo-init

Script that sets up ZeroTier access, Cloudflare DNS entries and proxy routes for legacy Kong/Zato infrastructure (superseded by Holo Nixpkgs hpos-init)
Python
2
star
83

holo-zato-api

Holo Kong/Zato routing infrastructure (deprecated in favor of Holo Router)
Python
2
star
84

holo-monitor

JavaScript
2
star
85

hpstatus

Holo network authorization status pages (superseded by Holo Auth)
CSS
1
star
86

holofuel-issue-tracker

HoloFuel issue tracker
1
star
87

template

1
star
88

hpos-admin-server

HPOS Admin API backend (deprecated in favor of Holo Nixpkgs hpos-admin)
Python
1
star