Skip to content

cmdruid/nostr-storage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nostr-storage

A shared, encrypted cloud data store using Nostr.

Installation

This package is designed to work in both the browser and nodejs.

<!-- Browser import -->
<script src='https://bundle.run/noble-secp256k1@1.2.14'></script>
<script src="https://unpkg.com/@cmdcode/nostr-emitter"></script>
<script src="https://unpkg.com/@cmdcode/nostr-storage"></script>
// Commonjs import.
const NostrStorage = require('@cmdcode/nostr-storage')
// ES6 import.
import NostrStorage from '@cmdcode/nostr-storage'

How to Use

To get started, define a new NostrStore() object, then provide a relay server and shared secret to store.connect(). Once connected, the store behaves like a typical localStorage object.

// Declare a new store object.
const store = new NostrStore()

// Connect your store to the relay.
await store.connect(
  'wss://nostr-relay.wlvs.space',
  'secret-string'
)

// NostrStore exposes a basic Map / localStorage API.
store
  .has('key') => Promise(true || false)
  .get('key') => Promise('value')
  .keys()     => [ 'key1', 'key2' ... ]
  .values()   => [ 'val1', 'val2' ... ]
  .entries()  => [ ['key1', 'val1'], ['key2', 'val2'] ... ]

// You can use NostrStore in an iterator.
for (let [ key, val ] of store) {
  console.log(key, val)
}

// These methods will return whether the data operation suceeded.
store
  .set('key', 'value') => Promise(true || false)
  .delete('key')       => Promise(true || false)
  .clear()             => Promise(true || false)

// These methods assist with data fetching under the hood.
store
  .refresh()  // Fetch the latest copy of data from the relay.
  .commit()   // Commit the current data store to the relay.
  .destroy()  // Marks the data store for deletion (using NIP 9).

// NostrStore is configurable with some basic options.
const store = new NostrStore({
  refreshTimeout: 5000,  // Timeout to refresh data before a has/get op.
  commitTimeout: 5000,   // Timeout on confirming a commit op suceeded.
  emitter: { /* You can also configure the emitter here. */ }
})

How it Works

Nostr Storage uses replace-able events in order to store a serialized (and encrypted) copy of the data store. The shared secret is hashed multiple times, with each round used to generate the signature keys, encryption keys, and finally a label for filtering the events.

It is safe to reveal the encryption key, without revealing the signature key.

This project uses nostr-emitter. To fully understand how it all works, see this link: https://github.com/cmdruid/nostr-emitter

Resources

Nostr Emitter
Used under-the-hood for talking to relays.
https://github.com/cmdruid/nostr-emitter

Nostr Implementation Possibilities
https://github.com/nostr-protocol/nips

Nostr-tools
https://github.com/fiatjaf/nostr-tools

Contributions

All contributions are welcome!