mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 16:31:04 +00:00
Move over nip05 and settings
This commit is contained in:
parent
6af41363cd
commit
2597a18411
@ -1,4 +1,5 @@
|
||||
import "./nip02"
|
||||
import "./nip05"
|
||||
import "./nip65"
|
||||
import "./alerts"
|
||||
|
||||
|
28
src/engine2/projections/nip05.ts
Normal file
28
src/engine2/projections/nip05.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import {tryFunc, Fetch} from "hurdak"
|
||||
import {tryJson} from "src/util/misc"
|
||||
import {people} from "src/engine2/state"
|
||||
import {dufflepud} from "src/engine2/queries"
|
||||
import {projections, updateKey} from "src/engine2/projections/core"
|
||||
|
||||
projections.addHandler(0, e => {
|
||||
tryJson(async () => {
|
||||
const {
|
||||
kind0: {nip05: address},
|
||||
} = JSON.parse(e.content)
|
||||
|
||||
if (!address) {
|
||||
return
|
||||
}
|
||||
|
||||
const profile = await tryFunc(() => Fetch.postJson(dufflepud("handle/info"), {handle: address}))
|
||||
|
||||
if (profile?.pubkey === e.pubkey) {
|
||||
updateKey(people.key(e.pubkey), e.created_at, {
|
||||
handle: {
|
||||
profile,
|
||||
address,
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
23
src/engine2/projections/settings.ts
Normal file
23
src/engine2/projections/settings.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import {tryJson} from "src/util/misc"
|
||||
import {Tags, appDataKeys} from "src/util/nostr"
|
||||
import {settings} from "src/engine2/state"
|
||||
import {getSetting, canSign, nip04, user} from "src/engine2/queries"
|
||||
import {projections} from "src/engine2/projections/core"
|
||||
|
||||
projections.addHandler(30078, e => {
|
||||
if (
|
||||
canSign.get() &&
|
||||
Tags.from(e).getMeta("d") === appDataKeys.USER_SETTINGS &&
|
||||
e.created_at > getSetting("updated_at")
|
||||
) {
|
||||
tryJson(async () => {
|
||||
const updates = await nip04.get().decryptAsUser(e.content, user.get().pubkey)
|
||||
|
||||
settings.update($settings => ({
|
||||
...$settings,
|
||||
...updates,
|
||||
updated_at: e.created_at,
|
||||
}))
|
||||
})
|
||||
}
|
||||
})
|
@ -1,4 +1,5 @@
|
||||
export * from "./session"
|
||||
export * from "./settings"
|
||||
export * from "./nip02"
|
||||
export * from "./nip65"
|
||||
export * from "./alerts"
|
||||
|
5
src/engine2/queries/nip05.ts
Normal file
5
src/engine2/queries/nip05.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import {last} from "ramda"
|
||||
import type {Handle} from "src/engine2/model"
|
||||
|
||||
export const displayHandle = (handle: Handle) =>
|
||||
handle.address.startsWith("_@") ? last(handle.address.split("@")) : handle.address
|
@ -1,31 +0,0 @@
|
||||
import {switcherFn} from "hurdak"
|
||||
import type {KeyState} from "src/engine2/model"
|
||||
import {encryptFor, decryptFor} from "src/engine2/util/nip44"
|
||||
|
||||
export class Crypto {
|
||||
constructor(readonly user: KeyState) {}
|
||||
|
||||
encryptWithKey(event, pk: string, sk: string) {
|
||||
return encryptFor(sk, pk, JSON.stringify(event))
|
||||
}
|
||||
|
||||
decryptWithKey(event, sk: string) {
|
||||
return JSON.parse(decryptFor(sk, event.pubkey, event.content))
|
||||
}
|
||||
|
||||
encryptAsUser(event, pk: string) {
|
||||
const {method, privkey} = this.user
|
||||
|
||||
return switcherFn(method, {
|
||||
privkey: () => this.encryptWithKey(event, pk, privkey),
|
||||
})
|
||||
}
|
||||
|
||||
decryptAsUser(event) {
|
||||
const {method, privkey} = this.user
|
||||
|
||||
return switcherFn(method, {
|
||||
privkey: () => this.decryptWithKey(event, privkey),
|
||||
})
|
||||
}
|
||||
}
|
@ -1,17 +1,23 @@
|
||||
import {find, defaultTo, whereEq} from "ramda"
|
||||
import type {KeyState} from "src/engine2/model"
|
||||
import {derived} from "src/engine2/util/store"
|
||||
import {pubkey, keys} from "src/engine2/state"
|
||||
import {prepareNdk, ndkInstances} from "./ndk"
|
||||
import {Signer} from "./signer"
|
||||
import {Crypto} from "./crypto"
|
||||
import {Nip04} from "./nip04"
|
||||
import {Nip44} from "./nip44"
|
||||
import {Wrapper} from "./wrapper"
|
||||
|
||||
export const stateKey = pubkey.derived(defaultTo("anonymous"))
|
||||
|
||||
export const user = derived([pubkey, keys], ([$pubkey, $keys]) => {
|
||||
return find(whereEq({pubkey: $pubkey}), $keys)
|
||||
return find(whereEq({pubkey: $pubkey}), $keys) as KeyState | null
|
||||
})
|
||||
|
||||
export const canSign = user.derived(({method}) =>
|
||||
["bunker", "privkey", "extension"].includes(method)
|
||||
)
|
||||
|
||||
export const ndk = derived([user, ndkInstances], ([$user, $instances]) => {
|
||||
if (!$user?.bunkerToken) {
|
||||
return null
|
||||
@ -24,11 +30,13 @@ export const ndk = derived([user, ndkInstances], ([$user, $instances]) => {
|
||||
return $instances.get($user.pubkey)
|
||||
})
|
||||
|
||||
export const crypto = derived([user], ([$user]) => new Crypto($user))
|
||||
export const nip04 = derived([user, ndk], ([$user, $ndk]) => new Nip04($user, $ndk))
|
||||
|
||||
export const nip44 = derived([user], ([$user]) => new Nip44($user))
|
||||
|
||||
export const signer = derived([user, ndk], ([$user, $ndk]) => new Signer($user, $ndk))
|
||||
|
||||
export const wrapper = derived(
|
||||
[user, crypto, signer],
|
||||
([$user, $crypto, $signer]) => new Wrapper($user, $crypto, $signer)
|
||||
[user, nip44, signer],
|
||||
([$user, $nip44, $signer]) => new Wrapper($user, $nip44, $signer)
|
||||
)
|
||||
|
63
src/engine2/queries/session/nip04.ts
Normal file
63
src/engine2/queries/session/nip04.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import {nip04} from "nostr-tools"
|
||||
import type NDK from "@nostr-dev-kit/ndk"
|
||||
import {switcherFn, sleep, tryFunc} from "hurdak"
|
||||
import {withExtension} from "src/engine2/util/nip07"
|
||||
import type {KeyState} from "src/engine2/model"
|
||||
|
||||
export class Nip04 {
|
||||
constructor(readonly user: KeyState | null, readonly ndk: NDK | null) {}
|
||||
|
||||
async encrypt(message: string, pk: string, sk: string) {
|
||||
return nip04.encrypt(sk, pk, message)
|
||||
}
|
||||
|
||||
async decrypt(message: string, pk: string, sk: string) {
|
||||
return tryFunc(() => nip04.decrypt(sk, pk, message)) || `<Failed to decrypt message>`
|
||||
}
|
||||
|
||||
async encryptAsUser(message: string, pk: string) {
|
||||
const {method, privkey} = this.user
|
||||
|
||||
return switcherFn(method, {
|
||||
privkey: () => this.encrypt(message, pk, privkey),
|
||||
extension: () => withExtension(ext => ext.nip04.encrypt(pk, message)),
|
||||
bunker: async () => {
|
||||
const user = this.ndk.getUser({hexpubkey: pk})
|
||||
|
||||
return this.ndk.signer.encrypt(user, message)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async decryptAsUser(message: string, pk: string) {
|
||||
const {method, privkey} = this.user
|
||||
|
||||
return switcherFn(method, {
|
||||
privkey: () => this.decrypt(message, pk, privkey),
|
||||
extension: () =>
|
||||
withExtension((ext: any) => {
|
||||
return new Promise(async resolve => {
|
||||
let result
|
||||
|
||||
// Alby gives us a bunch of bogus errors, try multiple times
|
||||
for (let i = 0; i < 3; i++) {
|
||||
result = await tryFunc(() => ext.nip04.decrypt(pk, message))
|
||||
|
||||
if (result) {
|
||||
break
|
||||
}
|
||||
|
||||
await sleep(30)
|
||||
}
|
||||
|
||||
resolve(result || `<Failed to decrypt message>`)
|
||||
})
|
||||
}),
|
||||
bunker: async () => {
|
||||
const user = this.ndk.getUser({hexpubkey: pk})
|
||||
|
||||
return this.ndk.signer.decrypt(user, message)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
31
src/engine2/queries/session/nip44.ts
Normal file
31
src/engine2/queries/session/nip44.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import {switcherFn} from "hurdak"
|
||||
import type {KeyState} from "src/engine2/model"
|
||||
import {encryptFor, decryptFor} from "src/engine2/util/nip44"
|
||||
|
||||
export class Nip44 {
|
||||
constructor(readonly user: KeyState) {}
|
||||
|
||||
encrypt(message: string, pk: string, sk: string) {
|
||||
return encryptFor(sk, pk, message)
|
||||
}
|
||||
|
||||
decrypt(message: string, pk: string, sk: string) {
|
||||
return decryptFor(sk, pk, message)
|
||||
}
|
||||
|
||||
encryptAsUser(message: string, pk: string) {
|
||||
const {method, privkey} = this.user
|
||||
|
||||
return switcherFn(method, {
|
||||
privkey: () => this.encrypt(message, pk, privkey),
|
||||
})
|
||||
}
|
||||
|
||||
decryptAsUser(message: string, pk: string) {
|
||||
const {method, privkey} = this.user
|
||||
|
||||
return switcherFn(method, {
|
||||
privkey: () => this.decrypt(message, pk, privkey),
|
||||
})
|
||||
}
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
import type {UnsignedEvent} from "nostr-tools"
|
||||
import {getPublicKey} from "nostr-tools"
|
||||
import {tryJson} from "src/util/misc"
|
||||
import {nip59} from "src/engine2/util"
|
||||
import type {KeyState} from "src/engine2/model"
|
||||
import type {Signer} from "./signer"
|
||||
import type {Crypto} from "./crypto"
|
||||
import type {Nip44} from "./nip44"
|
||||
|
||||
export type WrapperParams = {
|
||||
author?: string
|
||||
@ -14,7 +15,7 @@ export type WrapperParams = {
|
||||
}
|
||||
|
||||
export class Wrapper {
|
||||
constructor(readonly user: KeyState, readonly crypto: Crypto, readonly signer: Signer) {}
|
||||
constructor(readonly user: KeyState, readonly nip44: Nip44, readonly signer: Signer) {}
|
||||
|
||||
getAuthorPubkey(sk?: string) {
|
||||
return sk ? getPublicKey(sk) : this.user.pubkey
|
||||
@ -29,11 +30,18 @@ export class Wrapper {
|
||||
}
|
||||
|
||||
encrypt(event, pk: string, sk?: string) {
|
||||
return sk ? this.crypto.encryptWithKey(event, pk, sk) : this.crypto.encryptAsUser(event, pk)
|
||||
const message = JSON.stringify(event)
|
||||
|
||||
return sk ? this.nip44.encrypt(message, pk, sk) : this.nip44.encryptAsUser(message, pk)
|
||||
}
|
||||
|
||||
decrypt(event, sk?: string) {
|
||||
return sk ? this.crypto.decryptWithKey(event, sk) : this.crypto.decryptAsUser(event)
|
||||
const {pubkey, content} = event
|
||||
const message = sk
|
||||
? this.nip44.decrypt(content, pubkey, sk)
|
||||
: this.nip44.decryptAsUser(content, pubkey)
|
||||
|
||||
return tryJson(() => JSON.parse(message))
|
||||
}
|
||||
|
||||
getSeal(rumor, {author, wrap: {recipient}}: WrapperParams) {
|
||||
|
19
src/engine2/queries/settings.ts
Normal file
19
src/engine2/queries/settings.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {settings} from "src/engine2/state"
|
||||
|
||||
export const getSetting = k => settings.get()[k]
|
||||
|
||||
export const imgproxy = (url: string, {w = 640, h = 1024} = {}) => {
|
||||
const base = getSetting("imgproxy_url")
|
||||
|
||||
if (!url || url.match("gif$")) {
|
||||
return url
|
||||
}
|
||||
|
||||
try {
|
||||
return base && url ? `${base}/x/s:${w}:${h}/${btoa(url)}` : url
|
||||
} catch (e) {
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
export const dufflepud = (path: string) => `${getSetting("dufflepud_url")}/${path}`
|
Loading…
Reference in New Issue
Block a user