Skip to content

Commit

Permalink
add Nillion Storage APIs docs for ethglobal hackathon
Browse files Browse the repository at this point in the history
  • Loading branch information
oceans404 committed Nov 14, 2024
1 parent b6b7856 commit a04ab65
Show file tree
Hide file tree
Showing 3 changed files with 526 additions and 656 deletions.
235 changes: 235 additions & 0 deletions docs/storage-apis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
# Nillion Storage APIs

The Nillion Storage APIs provide a simple HTTP interface for storing and retrieving secrets on the Nillion Network Testnet, with built-in management of store IDs and secret names.

:::info
The Storage APIs are suitable for quick hackathon projects. If you need lower-level control or want to handle store ID management yourself, check out our [Python Client](/python-client) for backend applications and [Javascript Client](https://github.com/NillionNetwork/client-ts) for frontend applications.
:::

## Overview

The Nillion Storage APIs make it easy to quickly bootstrap a hackathon project that securely stores and retrieves secret data from the Nillion Network Testnet. APIs include built-in management of store IDs (locations of your secrets on Nillion) and abstract away Testnet payments. You can use Nillion Storage APIs to:

- Create an app id
- Store 2 types of secrets (numbers and strings/blobs)
- Customize secret permissions: grant retrieve, update, delete, and compute permissions to specific User IDs when storing secrets
- List all store IDs and names of secrets for your app id
- Retrieve secret values from Nillion using their store IDs

## Storage APIs Quickstart

This guide shows how to store secrets, list all store IDs and secret names for your app, and retrieve secrets using the Nillion Storage APIs.

### Prerequisites

All you need is a way to make HTTP requests. The examples below use `curl` and JavaScript. You can explore and test all API endpoints directly from the [Nillion Storage API Reference](https://nillion-storage-apis-v0.onrender.com/docs).

### Step 0: Register Your App

First run the following command from your terminal to register a new app:

```bash
curl -X POST https://nillion-storage-apis-v0.onrender.com/api/apps/register
```

This returns an `app_id` to track the store IDs for your secrets. Save the `app_id` from the response. This is your app's unique identifier.

### 1. [Optional] Check Your User ID

Check the deterministic user ID generated by your user seed using POST `/api/user`. You can share this user ID with others so they can give you permissions to retrieve their secrets.

:::warning
Never share user seeds - they're like private keys! Only share user_ids.
:::

```javascript
const USER_SEED = 'user_123'; // your seed generates a deterministic nillion user id
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// 1. Check your deterministic user ID
console.log('Checking user ID generated by your seed...');
const user = await fetch(`${API_BASE}/api/user`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nillion_seed: USER_SEED,
}),
}).then((res) => res.json());
console.log('Your User ID:', user.nillion_user_id);
```

### 2. Store a Secret Number

Store a number secret using POST `/api/apps/{app_id}/secrets`. The empty permissions arrays mean only the storing user has access.

**Make sure to update the `APP_ID` below with your app_id from step 0 before running the code:**

```javascript
const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // your seed generates a deterministic nillion user id
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// 2. Store first secret (number)
console.log('\nStoring first secret...');
const storeResult1 = await fetch(`${API_BASE}/api/apps/${APP_ID}/secrets`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: {
nillion_seed: USER_SEED,
secret_value: 16,
secret_name: 'my_secret_number',
},
permissions: {
retrieve: [],
update: [],
delete: [],
compute: {},
},
}),
}).then((res) => res.json());
console.log('First secret stored at:', storeResult1);
```

### 3. Store a Secret String

Store a string/blob secret using the same endpoint.

**Make sure to update the `APP_ID` below with your app_id from step 0 before running the code:**

```javascript
const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // your seed generates a deterministic nillion user id
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// 3. Store second secret (string/blob)
console.log('\nStoring second secret...');
const storeResult2 = await fetch(`${API_BASE}/api/apps/${APP_ID}/secrets`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: {
nillion_seed: USER_SEED,
secret_value: 'gm!',
secret_name: 'my_secret_blob',
},
permissions: {
retrieve: [],
update: [],
delete: [],
compute: {},
},
}),
}).then((res) => res.json());
console.log('Second secret stored at:', storeResult2);
```

### 4. List Store IDs

Get all store IDs for your app using GET `/api/apps/{app_id}/store_ids` to find your secrets.

**Make sure to update the `APP_ID` below with your app_id from step 0 before running the code:**

```javascript
const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // your seed generates a deterministic nillion user id
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// 4. List store IDs
const storeIds = await fetch(`${API_BASE}/api/apps/${APP_ID}/store_ids`)
.then((res) => res.json())
.then((data) => data.store_ids);
console.log('Store IDs:', storeIds);
```

### 5. Retrieve Secrets

Get each secret's value using GET `/api/secret/retrieve/{store_id}` with the correct secret name and user seed.

**Make sure to update the `APP_ID` below with your app_id from step 0 before running the code:**

```javascript
const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // your seed generates a deterministic nillion user id
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';
const storeIds = await fetch(`${API_BASE}/api/apps/${APP_ID}/store_ids`)
.then((res) => res.json())
.then((data) => data.store_ids);

// 5. Retrieve both secrets using the store IDs we just created
console.log('\nRetrieving secrets...');
const secret1 = await fetch(
`${API_BASE}/api/secret/retrieve/${storeIds[0].store_id}?retrieve_as_nillion_user_seed=${USER_SEED}&secret_name=${storeIds[0].secret_name}`
).then((res) => res.json());
console.log('First secret retrieved:', secret1);

const secret2 = await fetch(
`${API_BASE}/api/secret/retrieve/${storeIds[1].store_id}?retrieve_as_nillion_user_seed=${USER_SEED}&secret_name=${storeIds[1].secret_name}`
).then((res) => res.json());
console.log('Second secret retrieved:', secret2);
```

## Quickstart Complete Code

**Make sure to update the `APP_ID` below with your app_id from step 0 before running the code:**

```javascript reference showGithubLink
https://github.com/oceans404/nillion-storage-apis-v0/blob/main/Quickstart.md?plain=1#L48-L131
```

## How to Share Secrets with Other Users

### Store with Permissions

To give another user access to your secrets, include their user_id in the permissions arrays when storing.

**Make sure to update the `APP_ID` below with your app_id from step 0 before running the code:**

```javascript
const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // your seed generates a deterministic nillion user id
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// Example using a "test" user seed - your friend should use their own unique seed in production
const friend_user_id =
'63P5NjU6a2zkjJqengfuDuwMUF9Yu3ogrrqMPNjidc4ogfcvefDchZgRNNJQg9T3WKiyZ4L7kF4zGwFurpxCo5bP';

const storeResultForFriend = await fetch(
`${API_BASE}/api/apps/${APP_ID}/secrets`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: {
nillion_seed: USER_SEED,
secret_value: 'secret message to my friend!',
secret_name: 'message_to_friend',
},
permissions: {
retrieve: [friend_user_id], // give friend retrieve permission
update: [],
delete: [],
compute: {},
},
}),
}
).then((res) => res.json());
console.log('Secret stored for friend:', storeResultForFriend);
```

### Retrieve with Permissions

If you tell your friend the store id, that friend can then retrieve the secret using their seed:

**Make sure to update the `store_id` below before running the code:**

```javascript
const store_id = 'store_id_from_above';
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';
const friend_user_seed = 'test'; // friends should use their own unique seed

const secret = await fetch(
`${API_BASE}/api/secret/retrieve/${store_id}?retrieve_as_nillion_user_seed=${friend_user_seed}&secret_name=message_to_friend`
).then((res) => res.json());
console.log('Secret retrieved by friend:', secret);
```
25 changes: 19 additions & 6 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ const sidebars = {
label: 'nada',
link: {
type: 'doc',
id: 'nada'
id: 'nada',
},
items: [
{
Expand All @@ -194,9 +194,9 @@ const sidebars = {
{
type: 'doc',
label: 'Nada Execution Plan',
id: 'nada-execution-plan'
id: 'nada-execution-plan',
},
]
],
},
'pynadac',
'nada-run',
Expand Down Expand Up @@ -350,15 +350,28 @@ const sidebars = {
],
},
'network-configuration',
{type: 'category',
{
type: 'category',
label: 'Nillion AIVM',
link: {
type: 'doc',
id: 'aivm',
},
items: ['aivm-reference', 'aivm-supported-models'],
},
{
type: 'category',
label: 'Nillion Storage APIs',
link: {
type: 'doc',
id: 'storage-apis',
},
items: [
'aivm-reference',
'aivm-supported-models',
{
type: 'link',
label: 'API Reference',
href: 'https://nillion-storage-apis-v0.onrender.com/docs',
},
],
},
'limitations',
Expand Down
Loading

0 comments on commit a04ab65

Please sign in to comment.