diff --git a/Nostore.xcodeproj/project.pbxproj b/Nostore.xcodeproj/project.pbxproj index f069b5d..b047ea1 100644 --- a/Nostore.xcodeproj/project.pbxproj +++ b/Nostore.xcodeproj/project.pbxproj @@ -77,6 +77,18 @@ 944A6DD72988BD230032C2E3 /* permission.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DD52988BD230032C2E3 /* permission.js */; }; 944A6DD92988D7900032C2E3 /* permission.build.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DD82988D7900032C2E3 /* permission.build.js */; }; 944A6DDA2988D7900032C2E3 /* permission.build.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DD82988D7900032C2E3 /* permission.build.js */; }; + 944A6DE02991DFC60032C2E3 /* delegation_wizard.build.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DDC2991DFC60032C2E3 /* delegation_wizard.build.js */; }; + 944A6DE12991DFC60032C2E3 /* delegation_wizard.build.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DDC2991DFC60032C2E3 /* delegation_wizard.build.js */; }; + 944A6DE22991DFC60032C2E3 /* delegation_wizard.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DDD2991DFC60032C2E3 /* delegation_wizard.js */; }; + 944A6DE32991DFC60032C2E3 /* delegation_wizard.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DDD2991DFC60032C2E3 /* delegation_wizard.js */; }; + 944A6DE52991E4550032C2E3 /* delegation_wizard.html in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DE42991E4550032C2E3 /* delegation_wizard.html */; }; + 944A6DE62991E4550032C2E3 /* delegation_wizard.html in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DE42991E4550032C2E3 /* delegation_wizard.html */; }; + 944A6DEA299682EF0032C2E3 /* experimental.html in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DE7299682EF0032C2E3 /* experimental.html */; }; + 944A6DEB299682EF0032C2E3 /* experimental.html in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DE7299682EF0032C2E3 /* experimental.html */; }; + 944A6DEC299682EF0032C2E3 /* experimental.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DE8299682EF0032C2E3 /* experimental.js */; }; + 944A6DED299682EF0032C2E3 /* experimental.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DE8299682EF0032C2E3 /* experimental.js */; }; + 944A6DEE299682EF0032C2E3 /* experimental.build.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DE9299682EF0032C2E3 /* experimental.build.js */; }; + 944A6DEF299682EF0032C2E3 /* experimental.build.js in Resources */ = {isa = PBXBuildFile; fileRef = 944A6DE9299682EF0032C2E3 /* experimental.build.js */; }; 948C69D9297F887600FB3574 /* options.html in Resources */ = {isa = PBXBuildFile; fileRef = 948C69D8297F887600FB3574 /* options.html */; }; 948C69DA297F887600FB3574 /* options.html in Resources */ = {isa = PBXBuildFile; fileRef = 948C69D8297F887600FB3574 /* options.html */; }; 948C69DD297F88A200FB3574 /* options.css in Resources */ = {isa = PBXBuildFile; fileRef = 948C69DB297F88A200FB3574 /* options.css */; }; @@ -180,6 +192,12 @@ 944A6DD22988BA200032C2E3 /* permission.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = permission.html; sourceTree = ""; }; 944A6DD52988BD230032C2E3 /* permission.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = permission.js; sourceTree = ""; }; 944A6DD82988D7900032C2E3 /* permission.build.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = permission.build.js; sourceTree = ""; }; + 944A6DDC2991DFC60032C2E3 /* delegation_wizard.build.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = delegation_wizard.build.js; sourceTree = ""; }; + 944A6DDD2991DFC60032C2E3 /* delegation_wizard.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = delegation_wizard.js; sourceTree = ""; }; + 944A6DE42991E4550032C2E3 /* delegation_wizard.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = delegation_wizard.html; sourceTree = ""; }; + 944A6DE7299682EF0032C2E3 /* experimental.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = experimental.html; sourceTree = ""; }; + 944A6DE8299682EF0032C2E3 /* experimental.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = experimental.js; sourceTree = ""; }; + 944A6DE9299682EF0032C2E3 /* experimental.build.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = experimental.build.js; sourceTree = ""; }; 948C69D8297F887600FB3574 /* options.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = options.html; sourceTree = ""; }; 948C69DB297F88A200FB3574 /* options.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = options.css; sourceTree = ""; }; 948C69DC297F88A200FB3574 /* options.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = options.js; sourceTree = ""; }; @@ -267,6 +285,12 @@ 941B03A2296FA90400CA291E /* Resources */ = { isa = PBXGroup; children = ( + 944A6DE9299682EF0032C2E3 /* experimental.build.js */, + 944A6DE7299682EF0032C2E3 /* experimental.html */, + 944A6DE8299682EF0032C2E3 /* experimental.js */, + 944A6DE42991E4550032C2E3 /* delegation_wizard.html */, + 944A6DDC2991DFC60032C2E3 /* delegation_wizard.build.js */, + 944A6DDD2991DFC60032C2E3 /* delegation_wizard.js */, 944A6DD82988D7900032C2E3 /* permission.build.js */, 944A6DD52988BD230032C2E3 /* permission.js */, 944A6DD22988BA200032C2E3 /* permission.html */, @@ -510,8 +534,12 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 944A6DEE299682EF0032C2E3 /* experimental.build.js in Resources */, 941B0413297110F100CA291E /* background.build.js in Resources */, + 944A6DE22991DFC60032C2E3 /* delegation_wizard.js in Resources */, + 944A6DE52991E4550032C2E3 /* delegation_wizard.html in Resources */, 948C69E82982DFE900FB3574 /* background.html in Resources */, + 944A6DEA299682EF0032C2E3 /* experimental.html in Resources */, 948C69DF297F88A200FB3574 /* options.js in Resources */, 944A6DD32988BA200032C2E3 /* permission.html in Resources */, 948C69DD297F88A200FB3574 /* options.css in Resources */, @@ -524,12 +552,14 @@ 941B042C2978CD8E00CA291E /* iOS-Icon-1024.png in Resources */, 941B03F6296FA90400CA291E /* popup.html in Resources */, 941B040D296FAD6900CA291E /* nostr.js in Resources */, + 944A6DE02991DFC60032C2E3 /* delegation_wizard.build.js in Resources */, 941B03EE296FA90400CA291E /* images in Resources */, 941B03F0296FA90400CA291E /* manifest.json in Resources */, 944A6DD62988BD230032C2E3 /* permission.js in Resources */, 941B04312978CDF900CA291E /* Icon-32.png in Resources */, 941B041A2971139000CA291E /* content.build.js in Resources */, 941B041C2971139000CA291E /* popup.build.js in Resources */, + 944A6DEC299682EF0032C2E3 /* experimental.js in Resources */, 941B03EC296FA90400CA291E /* _locales in Resources */, 941B04222977A25700CA291E /* Icon-512.png in Resources */, 948C69E5297F8BA600FB3574 /* options.build.css in Resources */, @@ -547,8 +577,12 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 944A6DEF299682EF0032C2E3 /* experimental.build.js in Resources */, 941B0414297110F100CA291E /* background.build.js in Resources */, + 944A6DE32991DFC60032C2E3 /* delegation_wizard.js in Resources */, + 944A6DE62991E4550032C2E3 /* delegation_wizard.html in Resources */, 948C69E92982DFE900FB3574 /* background.html in Resources */, + 944A6DEB299682EF0032C2E3 /* experimental.html in Resources */, 948C69E0297F88A200FB3574 /* options.js in Resources */, 944A6DD42988BA200032C2E3 /* permission.html in Resources */, 948C69DE297F88A200FB3574 /* options.css in Resources */, @@ -561,12 +595,14 @@ 941B042D2978CD8E00CA291E /* iOS-Icon-1024.png in Resources */, 941B03F7296FA90400CA291E /* popup.html in Resources */, 941B040E296FAD6900CA291E /* nostr.js in Resources */, + 944A6DE12991DFC60032C2E3 /* delegation_wizard.build.js in Resources */, 941B03EF296FA90400CA291E /* images in Resources */, 941B03F1296FA90400CA291E /* manifest.json in Resources */, 944A6DD72988BD230032C2E3 /* permission.js in Resources */, 941B04322978CDF900CA291E /* Icon-32.png in Resources */, 941B041B2971139000CA291E /* content.build.js in Resources */, 941B041D2971139000CA291E /* popup.build.js in Resources */, + 944A6DED299682EF0032C2E3 /* experimental.js in Resources */, 941B03ED296FA90400CA291E /* _locales in Resources */, 941B04232977A25700CA291E /* Icon-512.png in Resources */, 948C69E6297F8BA600FB3574 /* options.build.css in Resources */, diff --git a/Shared (Extension)/Resources/background.js b/Shared (Extension)/Resources/background.js index 68e37cf..e9fc234 100644 --- a/Shared (Extension)/Resources/background.js +++ b/Shared (Extension)/Resources/background.js @@ -4,6 +4,8 @@ import { signEvent, nip04, nip19, + nip26, + getEventHash, } from 'nostr-tools'; import { Mutex } from 'async-mutex'; import { @@ -12,6 +14,7 @@ import { getProfile, getPermission, setPermission, + feature, } from './utils'; const storage = browser.storage.local; @@ -19,20 +22,6 @@ const log = msg => console.log('Background: ', msg); const validations = {}; let prompt = { mutex: new Mutex(), release: null, tabId: null }; -browser.runtime.onInstalled.addListener(async ({ reason }) => { - // I would like to be able to skip this for development purposes - // let ignoreHook = (await storage.get({ ignoreInstallHook: false })) - // .ignoreInstallHook; - // if (ignoreHook === true) { - // return; - // } - // if (['install'].includes(reason)) { - // browser.tabs.create({ - // url: 'https://ursus.camp/nostore', - // }); - // } -}); - browser.runtime.onMessage.addListener((message, _sender, sendResponse) => { log(message); let uuid = crypto.randomUUID(); @@ -57,6 +46,10 @@ browser.runtime.onMessage.addListener((message, _sender, sendResponse) => { return getNpub(message.payload); case 'getNsec': return getNsec(message.payload); + case 'createDelegation': + return createDelegation(message.payload); + case 'calcPubKey': + return Promise.resolve(getPublicKey(message.payload)); // window.nostr case 'getPubKey': @@ -64,11 +57,9 @@ browser.runtime.onMessage.addListener((message, _sender, sendResponse) => { case 'nip04.encrypt': case 'nip04.decrypt': case 'getRelays': - console.log('asking'); validations[uuid] = sendResponse; - ask(uuid, message); + setDelegation(message).then(() => ask(uuid, message)); setTimeout(() => { - console.log('timeout release'); prompt.release?.(); }, 10_000); return true; @@ -98,9 +89,7 @@ async function ask(uuid, { kind, host, payload }) { let mKind = kind === 'signEvent' ? `signEvent:${payload.kind}` : kind; let permission = await getPermission(host, mKind); - console.log('existing permission: ', permission); if (permission === 'allow') { - console.log('already allowed'); complete({ payload: uuid, origKind: kind, @@ -113,13 +102,11 @@ async function ask(uuid, { kind, host, payload }) { } if (permission === 'deny') { - console.log('already denied'); deny({ payload: uuid, origKind: kind, host }); prompt.release(); return; } - console.log('creating asking popup'); let qs = new URLSearchParams({ uuid, kind, @@ -136,22 +123,18 @@ async function ask(uuid, { kind, host, payload }) { } function complete({ payload, origKind, event, remember, host }) { - console.log('complete'); sendResponse = validations[payload]; if (remember) { - console.log('saving permission'); let mKind = origKind === 'signEvent' ? `signEvent:${event.kind}` : origKind; setPermission(host, mKind, 'allow'); } if (sendResponse) { - console.log('sendResponse found'); switch (origKind) { case 'getPubKey': getPubKey().then(pk => { - console.log(pk); sendResponse(pk); }); break; @@ -172,11 +155,9 @@ function complete({ payload, origKind, event, remember, host }) { } function deny({ origKind, host, payload, remember, event }) { - console.log('denied'); sendResponse = validations[payload]; if (remember) { - console.log('saving permission'); let mKind = origKind === 'signEvent' ? `signEvent:${event.kind}` : origKind; setPermission(host, mKind, 'deny'); @@ -186,17 +167,6 @@ function deny({ origKind, host, payload, remember, event }) { return false; } -function keyDeleter(key) { - return new Promise(resolver => { - setTimeout(() => { - console.log('Validations: ', validations); - console.log('Deleting key validations: ', key); - resolver(); - delete validations[key]; - }, 1000); - }); -} - // Options async function savePrivateKey([index, privKey]) { if (privKey.startsWith('nsec')) { @@ -227,6 +197,11 @@ async function getPrivKey() { } async function getPubKey() { + let pi = await getProfileIndex(); + let profile = await getProfile(pi); + if (profile.delegate) { + return profile.delegator; + } let privKey = await getPrivKey(); let pubKey = getPublicKey(privKey); return pubKey; @@ -239,9 +214,13 @@ async function currentProfile() { } async function signEvent_(event) { - event = { ...event }; + event = JSON.parse(JSON.stringify(event)); let privKey = await getPrivKey(); + let pubKey = getPublicKey(privKey); + event.pubkey = pubKey; + event.id = getEventHash(event); event.sig = signEvent(event, privKey); + console.log(JSON.stringify(event)); return event; } @@ -266,3 +245,42 @@ async function getRelays() { }); return relayObj; } + +function createDelegation({ + kind, + delegatorPrivKey, + delegateePubKey, + until, + since, +}) { + delegatorPrivKey = nip19.decode(delegatorPrivKey).data; + let delegation = nip26.createDelegation(delegatorPrivKey, { + pubkey: delegateePubKey, + until, + // kind, + // since, + }); + return Promise.resolve(delegation); +} + +async function setDelegation({ payload }) { + if (!payload) return; + let active = await feature('delegation'); + if (!active) return; + + let { delegate, delegation } = await currentProfile(); + + // Nothing to do if this is not a delegate + if (!delegate) { + return; + } + + payload.tags = payload.tags || []; + + payload.tags.push([ + 'delegation', + delegation.from, + delegation.cond, + delegation.sig, + ]); +} diff --git a/Shared (Extension)/Resources/delegation_wizard.html b/Shared (Extension)/Resources/delegation_wizard.html new file mode 100644 index 0000000..a279232 --- /dev/null +++ b/Shared (Extension)/Resources/delegation_wizard.html @@ -0,0 +1,59 @@ + + + + + + + + + + + Delegation Wizard + + + +

New Delegated Profile

+ +

+ A delegated user, as laid out in the + NIP-26 + specification, + is a user that is authorized to sign events for a different user. Additional limits can be + put on the delegated account, such as time limits. +

+ +

+ This may be useful if you wish to keep your main key stored safely offline, but still post as that user + with a throwaway key. +

+ +
+

Delegator

+

The secure account to be delegated.

+ +
+ +
+ +

This is not stored, but only used to sign a token which is stored instead.

+
+ +
+ +
+ +
+
+ +
+ + +
+ + + \ No newline at end of file diff --git a/Shared (Extension)/Resources/delegation_wizard.js b/Shared (Extension)/Resources/delegation_wizard.js new file mode 100644 index 0000000..742ee9f --- /dev/null +++ b/Shared (Extension)/Resources/delegation_wizard.js @@ -0,0 +1,82 @@ +import Alpine from 'alpinejs'; +import { generateProfile, getProfiles, validateKey } from './utils'; +import { getPublicKey, nip26, nip19 } from 'nostr-tools'; + +const storage = browser.storage.local; + +Alpine.data('delegated', () => ({ + privKey: '', + duration: 7, + profile: {}, + + async init() { + this.profile = await generateProfile('New Delegate'); + this.profile.delegate = true; + }, + + openNip(event) { + browser.tabs.create({ url: event.target.href, active: true }); + }, + + goBack() { + window.location = browser.runtime.getURL('options.html'); + }, + + async save() { + let profiles = await getProfiles(); + + // We need to jankify this Alpine proxy object so it's in the right format + // when we save it to storage + let profile = JSON.parse(JSON.stringify(this.profile)); + profile.delegator = getPublicKey(this.decodedPrivKey); + profile.delegation = this.getDelegation(); + + profiles.push(profile); + let profileIndex = profiles.length - 1; + await storage.set({ profiles, profileIndex }); + + window.location = `${browser.runtime.getURL( + 'options.html' + )}?index=${profileIndex}`; + }, + + getDelegation() { + let pubkey = getPublicKey(this.profile.privKey); + + let delegation = nip26.createDelegation(this.decodedPrivKey, { + pubkey, + until: this.until, + since: Math.round(Date.now() / 1000) - 1, + }); + console.log(delegation); + return delegation; + }, + + // Properties + + get isKeyValid() { + return validateKey(this.privKey); + }, + + get validKeyClass() { + return this.isKeyValid + ? '' + : 'ring-2 ring-rose-500 focus:ring-2 focus:ring-rose-500 border-transparent focus:border-transparent'; + }, + + get until() { + return Math.round(Date.now() / 1000) + 60 * 60 * 24 * this.duration; + }, + + get decodedPrivKey() { + if (!this.isKeyValid) { + return null; + } + if (this.privKey.startsWith('nsec')) { + return nip19.decode(this.privKey).data; + } + return this.privKey; + }, +})); + +Alpine.start(); diff --git a/Shared (Extension)/Resources/experimental.html b/Shared (Extension)/Resources/experimental.html new file mode 100644 index 0000000..062d7a1 --- /dev/null +++ b/Shared (Extension)/Resources/experimental.html @@ -0,0 +1,34 @@ + + + + + + + + + + Experimental Features + + + +

+ ← Back +

+

Experimental Features

+

+ These things may only work partially, or not + work at all. Caveat + emptor! +

+ + + + + \ No newline at end of file diff --git a/Shared (Extension)/Resources/experimental.js b/Shared (Extension)/Resources/experimental.js new file mode 100644 index 0000000..4671490 --- /dev/null +++ b/Shared (Extension)/Resources/experimental.js @@ -0,0 +1,40 @@ +import Alpine from 'alpinejs'; + +const FEATURES = [ + [ + 'delegation', + 'NIP-26 Delegation Profiles', + 'Allow user to create delegated profiles that obey the NIP-26 standard. Requires client support.', + ], +]; + +Alpine.data('experimental', () => ({ + features: [], + + async init() { + await this.reloadFeatures(); + + console.log(this.features); + }, + + async reloadFeatures() { + this.features = await Promise.all( + FEATURES.map(async ([name, shortDesc, longDesc]) => { + name = `feature:${name}`; + let active = await browser.storage.local.get({ + [name]: false, + }); + active = active[name]; + return [name, active, shortDesc, longDesc]; + }) + ); + }, + + async change(feature, active) { + console.log(feature, active); + await browser.storage.local.set({ [feature]: active }); + await this.reloadFeatures(); + }, +})); + +Alpine.start(); diff --git a/Shared (Extension)/Resources/manifest.json b/Shared (Extension)/Resources/manifest.json index 908ef98..cb4edeb 100644 --- a/Shared (Extension)/Resources/manifest.json +++ b/Shared (Extension)/Resources/manifest.json @@ -49,7 +49,10 @@ "popup.build.js", "options.build.js", "options.build.css", - "options.html" + "options.html", + "delegation_wizard.html", + "delegation_wizard.build.js", + "delegation_wizard.build.css" ], "matches": [ "" diff --git a/Shared (Extension)/Resources/options.html b/Shared (Extension)/Resources/options.html index bf5e9fe..d5786c4 100644 --- a/Shared (Extension)/Resources/options.html +++ b/Shared (Extension)/Resources/options.html @@ -9,7 +9,7 @@ - +

Settings

@@ -22,7 +22,8 @@
- + +
@@ -158,6 +159,10 @@ + + \ No newline at end of file diff --git a/Shared (Extension)/Resources/options.js b/Shared (Extension)/Resources/options.js index e459118..6507e07 100644 --- a/Shared (Extension)/Resources/options.js +++ b/Shared (Extension)/Resources/options.js @@ -16,6 +16,7 @@ import { KINDS, humanPermission, validateKey, + feature, } from './utils'; const log = console.log; @@ -36,6 +37,7 @@ Alpine.data('options', () => ({ host: '', permHosts: [], hostPerms: [], + delegationActive: false, setPermission, async init(watch = true) { @@ -63,7 +65,10 @@ Alpine.data('options', () => ({ // on init to set the correct profile. await this.getProfileNames(); await this.getProfileIndex(); + this.setProfileIndexFromSearch(); await this.refreshProfile(); + + this.delegationActive = await feature('delegation'); }, async refreshProfile() { @@ -77,6 +82,15 @@ Alpine.data('options', () => ({ // Profile functions + setProfileIndexFromSearch() { + let p = new URLSearchParams(window.location.search); + let index = p.get('index'); + if (!index) { + return; + } + this.profileIndex = parseInt(index); + }, + async getProfileNames() { this.profileNames = await getProfileNames(); }, @@ -98,6 +112,10 @@ Alpine.data('options', () => ({ this.profileIndex = newIndex; }, + newDelegated() { + window.location = browser.runtime.getURL('delegation_wizard.html'); + }, + async deleteProfile() { if ( confirm( diff --git a/Shared (Extension)/Resources/popup.html b/Shared (Extension)/Resources/popup.html index 74a26c1..d5af6b5 100644 --- a/Shared (Extension)/Resources/popup.html +++ b/Shared (Extension)/Resources/popup.html @@ -27,7 +27,7 @@ relays now?
- +
diff --git a/Shared (Extension)/Resources/utils.js b/Shared (Extension)/Resources/utils.js index 94fb2c0..d3ef46b 100644 --- a/Shared (Extension)/Resources/utils.js +++ b/Shared (Extension)/Resources/utils.js @@ -1,4 +1,4 @@ -const DB_VERSION = 1; +const DB_VERSION = 2; const storage = browser.storage.local; export const RECOMMENDED_RELAYS = [ new URL('wss://relay.damus.io'), @@ -41,6 +41,14 @@ async function migrate(version, goal) { await storage.set({ profiles }); return version + 1; } + + if (version === 1) { + console.log('migrating to version 2.'); + let profiles = await getProfiles(); + profiles.forEach(profile => (profile.delegate = false)); + await storage.set({ profiles }); + return version + 1; + } } export async function getProfiles() { @@ -98,6 +106,7 @@ export async function generateProfile(name = 'Default') { privKey: await generatePrivateKey(), hosts: {}, relays: [], + delegate: false, }; } @@ -213,3 +222,9 @@ export function validateKey(key) { return hexMatch || b32Match; } + +export async function feature(name) { + let fname = `feature:${name}`; + let f = await browser.storage.local.get({ [fname]: false }); + return f[fname]; +} diff --git a/build.js b/build.js index 7476a90..9289a3a 100755 --- a/build.js +++ b/build.js @@ -19,6 +19,10 @@ require('esbuild') 'popup.build': './Shared (Extension)/Resources/popup.js', 'options.build': './Shared (Extension)/Resources/options.js', 'permission.build': './Shared (Extension)/Resources/permission.js', + 'experimental.build': + './Shared (Extension)/Resources/experimental.js', + 'delegation_wizard.build': + './Shared (Extension)/Resources/delegation_wizard.js', }, outdir: './Shared (Extension)/Resources', sourcemap: 'inline', diff --git a/package-lock.json b/package-lock.json index d3f1203..8e0aa53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "alpinejs": "^3.10.5", "async-mutex": "^0.4.0", "json-format-highlight": "^1.0.4", - "nostr-tools": "^1.2.1" + "nostr-tools": "^1.3.0" }, "devDependencies": { "@tailwindcss/forms": "^0.5.3", @@ -965,9 +965,9 @@ } }, "node_modules/nostr-tools": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.2.1.tgz", - "integrity": "sha512-SL0sst29mrQ7oUPGQn+NMH4yuTe69a8S4bliNpYB2IG0fDl3Cx+xSLnuCTb4nZiNalatYsA5l+751wQiDGA3+A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.3.0.tgz", + "integrity": "sha512-AJosFolIhMFfs34sAX1V9kXV2/kDDGzfIVVEFK3u92Q96zTn9dekED6PybZXmKGNniUKfuy1h76oBPeK1MRVQw==", "dependencies": { "@noble/hashes": "^0.5.7", "@noble/secp256k1": "^1.7.0", diff --git a/package.json b/package.json index e9a1a8c..d861795 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "alpinejs": "^3.10.5", "async-mutex": "^0.4.0", "json-format-highlight": "^1.0.4", - "nostr-tools": "^1.2.1" + "nostr-tools": "^1.3.0" }, "devDependencies": { "@tailwindcss/forms": "^0.5.3",