Skip to content

Commit

Permalink
Merge pull request #14 from holochain-open-dev/11-api-docs-for-holoom…
Browse files Browse the repository at this point in the history
…-client

11 api docs for holoom client
  • Loading branch information
nphias authored Jun 18, 2024
2 parents 5fe8236 + d884580 commit 1e8e2f8
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 8 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/typedoc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Deploy TypeDoc to GitHub Pages

on:
push:
branches:
- main
paths:
- 'packages/client/**' # directories to monitor
- '**.md'

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: "https://registry.npmjs.org"

- name: Install dependencies
run: npm install

- name: Generate TypeDoc documentation
working-directory: ./packages/client
run: npx typedoc

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./packages/client/docs
publish_branch: gh-pages
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
"cSpell.words": [
"Dalek",
"Faceit",
"happ",
"Holochain",
"Holoom",
"PKCE",
"pubkey",
"Solana",
"zome",
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ The above script enables caching of `holoom_rocket_server` build artefacts. (CI
```
npm run test:e2e
```

## API documents

[Holoom API docs](https://holochain-open-dev.github.io/holoom)

3 changes: 2 additions & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"/dist"
],
"scripts": {
"build": "tsc --build"
"build": "tsc --build",
"generate:docs": "npx typedoc"
},
"dependencies": {
"@msgpack/msgpack": "^2.7.2",
Expand Down
28 changes: 25 additions & 3 deletions packages/client/src/external-id-attestation-requestor-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,35 @@ class RequestResolver {
}
}

/**
* This client is used for obtaining `ExternalIdAttestation`s from the holoom
* network's authority agent. It should be invoked after receiving an
* authorization code (by callback) from the identity provider in question.
*
* Currently the only PKCE Authorization Code flow is supported.
*/

export class ExternalIdAttestationRequestorClient {
constructor(readonly appAgent: AppAgentWebsocket) {
appAgent.on("signal", (signal) => this.handleAppSignal(signal));
}

resolvers: { [requestId: string]: RequestResolver } = {};

/**
*
* Submits sign-in flow related secrets to the holoom network's authority
* agent, which in turn makes use of them as evidence that the user controls
* the corresponding external web2 account. The authority subsequently
* creates an `ExternalIdAttestation` entry to attest this is so.
*
* @param codeVerifier The pre-image to the PKCE challenge that was submitted
* to the identity provider's sign-in flow
* @param code The secret received from the identity provider on sign-in
* callback. The holoom network's authority agent exchanges this for an
* access token.
* @returns The `ExternalIdAttestation` entry created by the authority
*/
async requestExternalIdAttestation(
codeVerifier: string,
code: string
Expand All @@ -52,7 +74,7 @@ export class ExternalIdAttestationRequestorClient {
return attestation;
}

handleAppSignal(signal: AppSignal) {
private handleAppSignal(signal: AppSignal) {
if (signal.zome_name !== "username_registry") return;
const localSignal = signal.payload as LocalHoloomSignal;
switch (localSignal.type) {
Expand All @@ -67,7 +89,7 @@ export class ExternalIdAttestationRequestorClient {
}
}

handleExternalIdAttested(signal: ExternalIdAttested) {
private handleExternalIdAttested(signal: ExternalIdAttested) {
try {
const attestation = decodeAppEntry<ExternalIdAttestation>(signal.record);

Expand All @@ -90,7 +112,7 @@ export class ExternalIdAttestationRequestorClient {
}
}

handleExternalIdRejected(signal: ExternalIdRejected) {
private handleExternalIdRejected(signal: ExternalIdRejected) {
const resolver = this.resolvers[signal.request_id];
if (!resolver) {
console.error(`Resolver for ${signal.request_id} not found`);
Expand Down
1 change: 1 addition & 0 deletions packages/client/src/faceit-auth-flow-client.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @ignore */
export class FaceitAuthFlowClient {
constructor(
readonly config: {
Expand Down
85 changes: 81 additions & 4 deletions packages/client/src/holoom-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@ import {
} from "viem";
import bs58 from "bs58";

/**
* This client is intended to be the primary and most convenient method of
* interaction for apps built on the holoom platform. It provides tools for:
* - Username registration and attestation with an authority
* - Management of a metadata for an agent
* - Binding Solana and Ethereum wallets to the user's AgentPubKey
*/
export class HoloomClient {
constructor(readonly appAgent: AppAgentWebsocket) {}

async ping(): Promise<void> {
/** @ignore */
private async ping(): Promise<void> {
await this.appAgent.callZome({
role_name: "holoom",
zome_name: "ping",
Expand All @@ -29,6 +37,10 @@ export class HoloomClient {
});
}

/**
* Returns a promise that resolves once the holoom happ is loaded and ready
* to use.
*/
async untilReady(interval = 1000, timeout = 30_000) {
const start = Date.now();
while (Date.now() - start < timeout) {
Expand All @@ -41,9 +53,15 @@ export class HoloomClient {
}
throw new Error("HoloomClient.untilReady timed out");
}
/**
* usernames are verified for uniqueness by the authority agent
*/

/**
* Returns the user's username if they have registered one.
*
* Returning `null` doesn't guarantee that the user has never registered, as
* this can also happen if the holochain conductor hasn't yet received gossip
* of an existing registration - this is likely to happen when switching
* hosts on the holo network.
*/
async getUsername(): Promise<string | null> {
const record = await this.appAgent.callZome({
role_name: "holoom",
Expand All @@ -59,6 +77,12 @@ export class HoloomClient {
return entry.username;
}

/**
* Submits a username for registration.
*
* The user's conductor will sign the username and submit it to the authority
* agent, which checks the signature and attests the username's uniqueness.
*/
async registerUsername(username: string) {
await this.appAgent.callZome({
role_name: "holoom",
Expand All @@ -68,6 +92,13 @@ export class HoloomClient {
});
}

/**
* Sets a value for an item in the user's metadata key-value store.
*
* Each user has a public freeform (i.e. without specific validation)
* string-to-string K-V store, where K-V pairs are encoded into link tags
* on the agent in question.
*/
async setMetadata(name: string, value: string) {
await this.appAgent.callZome({
role_name: "holoom",
Expand All @@ -77,6 +108,14 @@ export class HoloomClient {
});
}

/**
* Retrieves the latest value (if any) of an item in the user's metadata K-V
* store.
*
* It is possible for this value to be stale (or `null`) if the agent's
* conductor hasn't received gossip of the latest information - this is
* likely to happen when switching hosts on the holo network.
*/
async getMetadata(name: string): Promise<string | null> {
const value = await this.appAgent.callZome({
role_name: "holoom",
Expand All @@ -88,6 +127,14 @@ export class HoloomClient {
return value;
}

/**
* Retrieves a message to be signed by the specified EVM wallet in order to
* bind it to the user's agent.
*
* This signing message includes the agent's chain head and thus becomes
* stale if the user performs another action that progresses their chain
* before first submitting their binding signature.
*/
async getEvmWalletBindingMessage(evmAddress: Hex) {
const message: string = await this.appAgent.callZome({
role_name: "holoom",
Expand All @@ -98,6 +145,13 @@ export class HoloomClient {
return message;
}

/**
* Creates a verifiable entry that shows that the user has control over the
* specified EVM wallet.
*
* The provided signature must be over the current binding message - see
* `getEvmWalletBindingMessage`.
*/
async submitEvmWalletBinding(evmAddress: Hex, evmSignature: Hex) {
const chain_wallet_signature: ChainWalletSignature_Evm = {
Evm: {
Expand All @@ -113,6 +167,14 @@ export class HoloomClient {
});
}

/**
* Retrieves a message to be signed by the specified Solana wallet in order
* to bind it to the user's agent.
*
* This signing message includes the agent's chain head and thus becomes
* stale if the user performs another action that progresses their chain
* before first submitting their binding signature.
*/
async getSolanaWalletBindingMessage(solanaPublicKey: SolanaPublicKey) {
const message: string = await this.appAgent.callZome({
role_name: "holoom",
Expand All @@ -123,6 +185,13 @@ export class HoloomClient {
return message;
}

/**
* Creates a verifiable entry that shows that the user has control over the
* specified Solana wallet.
*
* The provided signature must be over the current binding message - see
* `getSolanaWalletBindingMessage`.
*/
async submitSolanaWalletBinding(
solanaPublicKey: SolanaPublicKey,
solanaSignature: Uint8Array
Expand All @@ -141,6 +210,13 @@ export class HoloomClient {
});
}

/**
* Retrieves an array of all EVM and Solana addresses under the user's control.
*
* It is possible for this information to be stale if the agent's conductor
* hasn't received gossip of the latest information - this is likely to
* happen when switching hosts on the holo network.
*/
async getBoundWallets(): Promise<BoundWallet[]> {
const records: Record[] = await this.appAgent.callZome({
role_name: "holoom",
Expand All @@ -163,6 +239,7 @@ export class HoloomClient {
});
}

/** @ignore */
async refreshJq(arg: {
program: string;
input: { collection: string };
Expand Down

0 comments on commit 1e8e2f8

Please sign in to comment.