Skip to content

Commit

Permalink
svelte demo has feature parity with vanilla-js demoo
Browse files Browse the repository at this point in the history
  • Loading branch information
dskvr committed Oct 26, 2024
1 parent bc18363 commit b5b4768
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 90 deletions.
File renamed without changes
84 changes: 39 additions & 45 deletions demo/src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,56 +1,32 @@
<script>
import { writable, derived, get } from 'svelte/store';
import { generateSecretKey, getPublicKey, Relay, SimplePool } from 'nostr-tools';
import { generateSecretKey, getPublicKey } from 'nostr-tools';
import { onMount, onDestroy } from 'svelte';
import { Notemine } from '@notemine/wrapper';
import { user, relaySettings, miningState, contentState } from './lib/stores/index';
const POW_RELAYS = [
'wss://nostr.bitcoiner.social',
'wss://nostr.mom',
'wss://nos.lol',
'wss://powrelay.xyz',
'wss://labour.fiatjaf.com/',
'wss://nostr.lu.ke',
'wss://140.f7z.io'
];
import { user, relaySettings, miningState, contentState, activeRelays, usub, powRelays } from './lib/stores/index';
import { publishEvent } from './lib/nostr';
import { pool, onevent, oneose, onclose } from './lib/nostr';
let notemine;
let progressSub, successSub, errorSub, bestPowSub, workersPowSub;
const activeRelays = derived(
[relaySettings],
($relaySettings) => {
let relays = [];
if ($relaySettings.myRelays && $relaySettings.myRelays.length > 0) {
relays.push(...$relaySettings.myRelays);
}
if ($relaySettings.powRelaysEnabled) {
relays.push(...POW_RELAYS);
}
return relays;
}
);
function authAnon() {
const newSecret = generateSecretKey();
user.set({
isAnon: true,
secret: newSecret,
pubkey: getPublicKey(newSecret)
});
// relaySettings.update(r => ({ ...r, myRelays: [] }));
relaySettings.update(r => ({ ...r, myRelays: [] }));
}
async function authUser() {
try {
const userPubkey = await window.nostr.getPublicKey();
user.set({
isAnon: false,
pubkey: userPubkey,
secret: ''
});
relaySettings.update(r => ({ ...r, myRelays: [] }));
const pubkey = await window.nostr.getPublicKey();
const isAnon = false
const secret = ''
user.set({ isAnon, pubkey, secret });
await getUserData();
} catch (error) {
console.error('Authentication failed:', error);
}
Expand All @@ -69,11 +45,15 @@
relaySettings.update(r => ({ ...r, myRelaysVisible: !r.myRelaysVisible }));
}
function setMyRelays(relays) {
relaySettings.update(r => ({
...r,
myRelays: Array.from(new Set([...r.myRelays, ...relays]))
}));
async function getUserData(){
const currentUser = get(user);
return new Promise( async (resolve, reject) => {
$usub = pool.subscribeMany(
['wss://purplepag.es', 'wss://user.kindpag.es'],
[{kinds: [0,3,10002], authors: [currentUser.pubkey]}],
{ onevent, oneose, onclose: onclose(resolve) }
);
});
}
function startMining() {
Expand Down Expand Up @@ -126,13 +106,15 @@
});
});
successSub = notemine.success$.subscribe(({ result: minedResult }) => {
const currentActiveRelays = get(activeRelays);
successSub = notemine.success$.subscribe(async ({ result: minedResult }) => {
// const currentActiveRelays = get(activeRelays);
console.log(`currentActiveRelays: ${$activeRelays}`);
await publishEvent(minedResult.event)
miningState.update(m => ({
...m,
mining: false,
result: minedResult ? JSON.stringify(minedResult, null, 2) : 'No result received.',
relayStatus: `Published to relays: ${currentActiveRelays.join(', ')}`
relayStatus: `Published to relays: ${$activeRelays.join(', ')}`
}));
});
Expand Down Expand Up @@ -266,14 +248,18 @@

<div id="user">
posting as:
<!-- svelte-ignore a11y-img-redundant-alt -->
<img
id="userPhoto"
width="20"
height="20"
src={$user.isAnon ? './lib/img/anon.svg' : 'path_to_user_photo'}
src={$user.isAnon ? '/img/anon.svg' : $user.photo}
alt="User Photo"
/>
<span id="userName">{$user.isAnon ? 'anon' : $user.pubkey}</span>
<span id="userName">{$user.isAnon ? 'anon' : $user.name}</span>

<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<small
id="relaysToggle"
style="cursor: pointer; color:#333;"
Expand All @@ -285,17 +271,21 @@

{#if $relaySettings.myRelaysVisible}
<div id="relaysContainer">
{#if $relaySettings.myRelays.length > 0}
<strong>My Relays:</strong>
<ul>
{#each $relaySettings.myRelays as relay}
<li>{relay}</li>
{/each}
</ul>
{/if}
<br />
{#if $relaySettings.myRelays.length > 0}
<input type="checkbox" bind:checked={$relaySettings.powRelaysEnabled}>
{/if}
<strong>POW Relays: </strong>
<ul>
{#each POW_RELAYS as relay}
{#each $powRelays as relay}
<li>{relay}</li>
{/each}
</ul>
Expand Down Expand Up @@ -363,3 +353,7 @@

<h2>Relay Status:</h2>
<pre id="relayStatus">{$miningState.relayStatus}</pre>



{JSON.stringify($activeRelays)}
102 changes: 102 additions & 0 deletions demo/src/lib/nostr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { SimplePool } from "nostr-tools";
import { get } from 'svelte/store';
import { finalizeEvent, verifyEvent } from "nostr-tools";
import { relaySettings, user, events, activeRelays, usub } from './stores/index';
import { verifyPow } from './utils.js';

let pubs;

export const pool = new SimplePool();

export const publishEvent = async (ev) => {
console.log(ev)
const pow = verifyPow(ev);
console.log('Publishing event:', ev);
try {
const {isAnon, secret} = get(user);
if(isAnon) {
ev = finalizeEvent(ev, secret);
}
else {
ev = await window.nostr.signEvent(ev)
}
let isGood = verifyEvent(ev);
if (!isGood) throw new Error('Event is not valid');
const currentActiveRelays = get(activeRelays);
pubs = pool.publish(currentActiveRelays, ev);
await Promise.allSettled(pubs);
console.log('Event published successfully.');
} catch (error) {
console.error('Error publishing event:', error);
}
};

function setMyRelays(relays) {
console.log(`Setting my relays: ${relays}`);
relaySettings.update(r => ({
...r,
myRelays: Array.from(new Set([...r.myRelays, ...relays]))
}));
}

export function onK0(event){
let profile
try {
profile = JSON.parse(event.content)
let photo
if(profile?.photo) photo = profile.photo
else if(profile?.picture) photo = profile.picture
else if(profile?.avatar) photo = profile.avatar
user.update( u => ({...u, photo, name: profile.name }) )
}
catch(e){
console.error('Error parsing K0 content:', e)
}
console.log('K0 profile:', profile)
events.update( e => ({...e, k0: event}) )
}

export function onK3(event){
let relays = []
try{
relays = Object.keys(JSON.parse(event.content))
}
catch(e){
console.error('Error parsing K3 content:', e)
console.warn('K3 content:', event.content)
}

console.log('K3 relays:', relays)
setMyRelays(relays)
events.update( e => ({...e, k3: event}) )
}

export function onK10002(event){
const relays = event.tags.filter( t => t[0] === 'r' ).map( r => r[1] )
console.log('K10002 relays:', relays)
setMyRelays(relays?.length? relays : [])
events.update( e => ({...e, k10002: event}) )
}

export function onevent(event){
switch(event.kind){
case 0: return onK0(event)
case 3: return onK3(event)
case 10002: return onK10002(event)
}
}

export function oneose(){
try {
const _usub = get(usub)
_usub.close()
}
catch(e){
console.warn('Error closing subscription:', e)
}
}

export function onclose( resolve ){
user.update( u => ({...u, isAnon: false}) )
resolve()
}
41 changes: 0 additions & 41 deletions demo/src/lib/publish.ts

This file was deleted.

9 changes: 5 additions & 4 deletions demo/src/lib/stores/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { user } from './user';
export { miningState } from './mining-state';
export { relaySettings } from './relay-settings';
export { contentState } from './content-state';
export * from './user';
export * from './mining-state';
export * from './relay-settings';
export * from './content-state';
export * from './relays';
30 changes: 30 additions & 0 deletions demo/src/lib/stores/relays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { derived, readable, writable } from "svelte/store";
import { relaySettings } from "./relay-settings";

const POW_RELAYS = [
'wss://nostr.bitcoiner.social',
'wss://nostr.mom',
'wss://nos.lol',
'wss://powrelay.xyz',
'wss://labour.fiatjaf.com/',
'wss://nostr.lu.ke',
'wss://140.f7z.io'
]

export const usub = new writable(null)

export const activeRelays = derived(
relaySettings,
($relaySettings) => {
let relays = [];
if ($relaySettings.myRelays && $relaySettings.myRelays.length > 0) {
relays.push(...$relaySettings.myRelays);
}
if ($relaySettings.powRelaysEnabled) {
relays.push(...POW_RELAYS);
}
return relays;
}
);

export const powRelays = new readable(POW_RELAYS);
11 changes: 11 additions & 0 deletions demo/src/lib/stores/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,15 @@ export const user = writable({
isAnon: true,
pubkey: '',
secret: ''
});

export const profile = writable({
name: '',
photo: ''
});

export const events = writable({
k0: {},
k3: {},
k10002: {}
});
29 changes: 29 additions & 0 deletions demo/src/lib/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { getEventHash } from "nostr-tools";

export const getPow = (hex) => {
let count = 0;

for (let i = 0; i < hex.length; i++) {
const nibble = parseInt(hex[i], 16);
if (nibble === 0) {
count += 4;
} else {
count += Math.clz32(nibble) - 28;
break;
}
}

return count;
}

export const verifyPow = (event) => {
console.log(event)
const hash = getEventHash(event);
const count = getPow(hash);
const nonceTag = event.tags.find(tag => tag[0] === 'nonce');
if (!nonceTag || nonceTag.length < 3) {
return 0;
}
const targetDifficulty = parseInt(nonceTag[2], 10);
return Math.min(count, targetDifficulty);
}

0 comments on commit b5b4768

Please sign in to comment.