mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 08:21:20 +00:00
Get connect create_account working
This commit is contained in:
parent
18c6f8b486
commit
0775915ae5
1
.env
1
.env
@ -15,3 +15,4 @@ VITE_CLIENT_NAME=Coracle
|
||||
VITE_CLIENT_ID=31990:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:1685968093690
|
||||
VITE_BUGSNAG_API_KEY=
|
||||
VITE_BUILD_HASH=
|
||||
VITE_LOG_LEVEL=warn
|
||||
|
@ -3,7 +3,7 @@
|
||||
import {sortBy, inc} from "ramda"
|
||||
import {closure, first, sleep} from "hurdak"
|
||||
import {generatePrivateKey} from "src/util/nostr"
|
||||
import FlexColumn from 'src/partials/FlexColumn.svelte'
|
||||
import FlexColumn from "src/partials/FlexColumn.svelte"
|
||||
import OnboardingIntro from "src/app/views/OnboardingIntro.svelte"
|
||||
import OnboardingProfile from "src/app/views/OnboardingProfile.svelte"
|
||||
import OnboardingFollows from "src/app/views/OnboardingFollows.svelte"
|
||||
@ -18,6 +18,7 @@
|
||||
publishNote,
|
||||
publishPetnames,
|
||||
publishProfile,
|
||||
publishRelays,
|
||||
loginWithPrivateKey,
|
||||
listenForNotifications,
|
||||
getFollowedPubkeys,
|
||||
@ -120,15 +121,15 @@
|
||||
{:else if stage === "profile"}
|
||||
<OnboardingProfile {setStage} {profile} />
|
||||
{:else if stage === "follows"}
|
||||
<OnboardingFollows {setStage} bind:petnames />
|
||||
<OnboardingFollows {setStage} bind:petnames bind:relays />
|
||||
{:else if stage === "note"}
|
||||
<OnboardingNote {setStage} {signup} />
|
||||
{/if}
|
||||
{/key}
|
||||
<div class="flex gap-2 m-auto">
|
||||
<div class="bg-mid rounded-full w-2 h-2" class:bg-lighter={stage === "intro"} />
|
||||
<div class="bg-mid rounded-full w-2 h-2" class:bg-lighter={stage === "profile"} />
|
||||
<div class="bg-mid rounded-full w-2 h-2" class:bg-lighter={stage === "follows"} />
|
||||
<div class="bg-mid rounded-full w-2 h-2" class:bg-lighter={stage === "note"} />
|
||||
<div class="m-auto flex gap-2">
|
||||
<div class="h-2 w-2 rounded-full bg-mid" class:bg-lighter={stage === "intro"} />
|
||||
<div class="h-2 w-2 rounded-full bg-mid" class:bg-lighter={stage === "profile"} />
|
||||
<div class="h-2 w-2 rounded-full bg-mid" class:bg-lighter={stage === "follows"} />
|
||||
<div class="h-2 w-2 rounded-full bg-mid" class:bg-lighter={stage === "note"} />
|
||||
</div>
|
||||
</FlexColumn>
|
||||
|
@ -2,11 +2,11 @@
|
||||
import {reject} from "ramda"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Heading from "src/partials/Heading.svelte"
|
||||
import PersonSummary from "src/app/shared/PersonSummary.svelte"
|
||||
import type {Person} from "src/engine"
|
||||
import {env, mention, loadPeople, searchPeople} from "src/engine"
|
||||
import {mention, loadPeople, searchPeople} from "src/engine"
|
||||
|
||||
export let relays
|
||||
export let petnames
|
||||
export let setStage
|
||||
|
||||
@ -29,7 +29,9 @@
|
||||
</script>
|
||||
|
||||
<div class="flex gap-3">
|
||||
<p class="bg-light rounded-full w-12 h-12 -mt-2 -ml-1 flex justify-center items-center text-lg">3/4</p>
|
||||
<p class="-ml-1 -mt-2 flex h-12 w-12 items-center justify-center rounded-full bg-light text-lg">
|
||||
3/4
|
||||
</p>
|
||||
<p class="text-2xl font-bold">Find your people</p>
|
||||
</div>
|
||||
<p>Search for people and topics, or browse our top suggestions below.</p>
|
||||
|
@ -1,15 +1,16 @@
|
||||
<script lang="ts">
|
||||
import {appName} from 'src/partials/state'
|
||||
import {appName} from "src/partials/state"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
|
||||
export let setStage
|
||||
|
||||
const tutorialUrl = "https://nostr.com/"
|
||||
const next = () => setStage("profile")
|
||||
</script>
|
||||
|
||||
<div class="flex gap-3">
|
||||
<p class="bg-light rounded-full w-12 h-12 -mt-2 -ml-1 flex justify-center items-center text-lg">1/4</p>
|
||||
<p class="-ml-1 -mt-2 flex h-12 w-12 items-center justify-center rounded-full bg-light text-lg">
|
||||
1/4
|
||||
</p>
|
||||
<p class="text-2xl font-bold">New to Nostr?</p>
|
||||
</div>
|
||||
<p class="sm:hidden">
|
||||
@ -18,18 +19,20 @@
|
||||
<p class="hidden sm:block">
|
||||
Learn about the protocol at your own pace by watching one of our tutorial videos.
|
||||
</p>
|
||||
<div class="flex gap-2 flex-col sm:flex-row">
|
||||
<Anchor class="relative aspect-[4/3] rounded-xl overflow-hidden flex justify-center items-center p-8 text-center sm:w-1/2">
|
||||
<div class="flex flex-col gap-2 sm:flex-row">
|
||||
<Anchor
|
||||
class="relative flex aspect-[4/3] items-center justify-center overflow-hidden rounded-xl p-8 text-center sm:w-1/2">
|
||||
<div
|
||||
class="absolute inset-0 opacity-75 hover:opacity-100 transition-opacity"
|
||||
class="absolute inset-0 opacity-75 transition-opacity hover:opacity-100"
|
||||
style="background: url('/images/jakob-owens-8tyCOqTqdqg-unsplash.png'" />
|
||||
<p class="relative staatliches text-5xl text-white">{appName} in 30 seconds</p>
|
||||
<p class="staatliches relative text-5xl text-white">{appName} in 30 seconds</p>
|
||||
</Anchor>
|
||||
<Anchor class="relative aspect-[4/3] rounded-xl overflow-hidden justify-center items-center p-8 text-center sm:w-1/2 hidden sm:flex">
|
||||
<Anchor
|
||||
class="relative hidden aspect-[4/3] items-center justify-center overflow-hidden rounded-xl p-8 text-center sm:flex sm:w-1/2">
|
||||
<div
|
||||
class="absolute inset-0 opacity-75 hover:opacity-100 transition-opacity"
|
||||
class="absolute inset-0 opacity-75 transition-opacity hover:opacity-100"
|
||||
style="background: url('/images/sean-105m46GatAg-unsplash.png'" />
|
||||
<p class="relative staatliches text-5xl text-white">{appName} deep dive</p>
|
||||
<p class="staatliches relative text-5xl text-white">{appName} deep dive</p>
|
||||
</Anchor>
|
||||
</div>
|
||||
<p>
|
||||
|
@ -1,9 +1,10 @@
|
||||
import {equals, pick} from "ramda"
|
||||
import {equals} from "ramda"
|
||||
import type {EventTemplate} from "nostr-tools"
|
||||
import {nip04, finalizeEvent} from "nostr-tools"
|
||||
import {Emitter, Subscription, createEvent} from "paravel"
|
||||
import {Emitter, now, Subscription, createEvent} from "paravel"
|
||||
import {randomId, sleep} from "hurdak"
|
||||
import {NostrConnect} from "nostr-tools/kinds"
|
||||
import logger from "src/util/logger"
|
||||
import {getPublicKey} from "src/util/nostr"
|
||||
import {tryJson} from "src/util/misc"
|
||||
import type {Event} from "src/engine/events/model"
|
||||
@ -39,12 +40,18 @@ export class NostrConnectBroker extends Emitter {
|
||||
|
||||
this.#sub = subscribePersistent({
|
||||
relays: this.handler.relays,
|
||||
filters: [{kinds: [NostrConnect], "#p": [getPublicKey(this.connectKey)]}],
|
||||
filters: [
|
||||
{
|
||||
since: now() - 30,
|
||||
kinds: [NostrConnect],
|
||||
"#p": [getPublicKey(this.connectKey)],
|
||||
},
|
||||
],
|
||||
onEvent: async (e: Event) => {
|
||||
const json = await nip04.decrypt(this.connectKey, e.pubkey, e.content)
|
||||
const {id, result, error} = tryJson(() => JSON.parse(json)) || {error: "invalid-response"}
|
||||
|
||||
console.info("NostrConnect response:", id, result, error)
|
||||
logger.info("NostrConnect response:", {id, result, error})
|
||||
|
||||
if (result === "auth_url") {
|
||||
window.open(error, "Coracle", "width=600,height=800,popup=yes")
|
||||
@ -59,17 +66,16 @@ export class NostrConnectBroker extends Emitter {
|
||||
// nsecbunker has a race condition
|
||||
await this.#ready
|
||||
|
||||
console.info("NostrConnect request:", method, params)
|
||||
|
||||
const id = randomId()
|
||||
const kind = admin ? 24134 : NostrConnect
|
||||
const pubkey = admin ? this.handler.pubkey : this.pubkey
|
||||
const payload = JSON.stringify({id, method, params})
|
||||
const content = await nip04.encrypt(this.connectKey, pubkey, payload)
|
||||
const template = createEvent(NostrConnect, {content, tags: [["p", pubkey]]})
|
||||
const event = finalizeEvent(template, this.connectKey as any)
|
||||
|
||||
Publisher.publish({event, relays: this.handler.relays})
|
||||
logger.info("NostrConnect request:", {id, method, params})
|
||||
|
||||
Publisher.publish({event, relays: this.handler.relays, silent: true})
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.once(`response-${id}`, ({result, error}) => {
|
||||
@ -103,7 +109,11 @@ export class NostrConnectBroker extends Emitter {
|
||||
}
|
||||
|
||||
signEvent(event: EventTemplate) {
|
||||
return this.request("sign_event", [event])
|
||||
return tryJson(async () => {
|
||||
const res = (await this.request("sign_event", [JSON.stringify(event)])) as string
|
||||
|
||||
return JSON.parse(res)
|
||||
})
|
||||
}
|
||||
|
||||
nip04Encrypt(pk: string, message: string) {
|
||||
|
@ -32,6 +32,7 @@ export const getClientTags = () => {
|
||||
|
||||
export type PublisherOpts = {
|
||||
timeout?: number
|
||||
silent?: boolean
|
||||
verb?: string
|
||||
}
|
||||
|
||||
@ -62,11 +63,13 @@ export class Publisher extends EventEmitter {
|
||||
return publisher
|
||||
}
|
||||
|
||||
publish(relays, {timeout = 10_000, verb}: PublisherOpts = {}) {
|
||||
publish(relays, {timeout = 10_000, verb, silent}: PublisherOpts = {}) {
|
||||
const urls = getUrls(relays)
|
||||
const executor = getExecutor(urls)
|
||||
|
||||
if (!silent) {
|
||||
info(`Publishing to ${urls.length} relays`, this.event, urls)
|
||||
}
|
||||
|
||||
const timeouts = new Set<string>()
|
||||
const succeeded = new Set<string>()
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type {SubscriptionOpts} from "paravel"
|
||||
import {Subscription, now} from "paravel"
|
||||
import {assoc, map} from "ramda"
|
||||
import {updateIn, sleep} from "hurdak"
|
||||
import {Subscription} from "paravel"
|
||||
import {sleep} from "hurdak"
|
||||
import {LOCAL_RELAY_URL} from "src/util/nostr"
|
||||
import type {Event} from "src/engine/events/model"
|
||||
import {deletes} from "src/engine/events/state"
|
||||
|
@ -1,5 +1,4 @@
|
||||
import {omit, assoc} from "ramda"
|
||||
import {createEvent} from "paravel"
|
||||
import {generatePrivateKey, getPublicKey, appDataKeys} from "src/util/nostr"
|
||||
import type {NostrConnectHandler} from "src/engine/network/model"
|
||||
import {createAndPublish, NostrConnectBroker} from "src/engine/network/utils"
|
||||
@ -44,7 +43,8 @@ export const loginWithNsecBunker = async (pubkey, connectToken, connectRelay) =>
|
||||
export const loginWithNostrConnect = async (username, connectHandler: NostrConnectHandler) => {
|
||||
const connectKey = generatePrivateKey()
|
||||
const {pubkey} = await fetchHandle(`${username}@${connectHandler.domain}`)
|
||||
const broker = NostrConnectBroker.get(pubkey, connectKey, connectHandler)
|
||||
|
||||
let broker = NostrConnectBroker.get(pubkey, connectKey, connectHandler)
|
||||
|
||||
// TODO: create account should return the new pubkey, we shouldn't have to call connect.
|
||||
// we're also leaking listeners because this promise never resolves. Hack a proper return
|
||||
@ -52,20 +52,21 @@ export const loginWithNostrConnect = async (username, connectHandler: NostrConne
|
||||
if (!pubkey) {
|
||||
broker.createAccount(username)
|
||||
|
||||
await new Promise(resolve => {
|
||||
await new Promise<void>(resolve => {
|
||||
const onMouseMove = () => {
|
||||
resolve()
|
||||
document.body.removeEventListener('mousemove', onMouseMove)
|
||||
document.body.removeEventListener("mousemove", onMouseMove)
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
document.body.addEventListener('mousemove', onMouseMove)
|
||||
document.body.addEventListener("mousemove", onMouseMove)
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
// Now that the account has ostensibly been created, get our new pubkey and set it to the broker
|
||||
const {pubkey} = await fetchHandle(`${username}@${connectHandler.domain}`)
|
||||
broker.pubkey = pubkey
|
||||
|
||||
broker = NostrConnectBroker.get(pubkey, connectKey, connectHandler)
|
||||
}
|
||||
|
||||
const result = await broker.connect()
|
||||
|
@ -9,9 +9,12 @@ export class Connect {
|
||||
const {pubkey, connectKey, connectHandler} = session
|
||||
|
||||
this.broker = NostrConnectBroker.get(pubkey, connectKey, connectHandler)
|
||||
|
||||
if (!this.broker.connected) {
|
||||
this.broker.connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isEnabled() {
|
||||
return this.session?.method === "connect"
|
||||
|
@ -1,3 +1,4 @@
|
||||
import {memoize} from "src/util/misc"
|
||||
import {sessions} from "../state"
|
||||
import {Nip04} from "./nip04"
|
||||
import {Nip44} from "./nip44"
|
||||
@ -15,13 +16,14 @@ export * from "./connect"
|
||||
|
||||
export const getSession = pubkey => sessions.get()[pubkey]
|
||||
|
||||
export const getConnect = session => new Connect(session)
|
||||
export const getConnect = memoize(session => new Connect(session))
|
||||
|
||||
export const getSigner = session => new Signer(session, getConnect(session))
|
||||
export const getSigner = memoize(session => new Signer(session, getConnect(session)))
|
||||
|
||||
export const getNip44 = session => new Nip44(session, getConnect(session))
|
||||
export const getNip44 = memoize(session => new Nip44(session, getConnect(session)))
|
||||
|
||||
export const getNip04 = session => new Nip04(session, getConnect(session))
|
||||
export const getNip04 = memoize(session => new Nip04(session, getConnect(session)))
|
||||
|
||||
export const getNip59 = session =>
|
||||
new Nip59(session, getNip04(session), getNip44(session), getSigner(session))
|
||||
export const getNip59 = memoize(
|
||||
session => new Nip59(session, getNip04(session), getNip44(session), getSigner(session)),
|
||||
)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {nip04} from "nostr-tools"
|
||||
import {switcherFn, sleep, tryFunc} from "hurdak"
|
||||
import {switcherFn, tryFunc} from "hurdak"
|
||||
import type {Session} from "src/engine/session/model"
|
||||
import type {Connect} from "./connect"
|
||||
import {withExtension} from "./nip07"
|
||||
|
@ -1,3 +1,27 @@
|
||||
export const info = (...message) => console.log(...message)
|
||||
export const warn = (...message) => console.warn(...message)
|
||||
export const error = (...message) => console.error(...message)
|
||||
const levels = ["info", "warn", "error"]
|
||||
|
||||
let level = import.meta.env.VITE_LOG_LEVEL
|
||||
|
||||
export const setLevel = l => {
|
||||
level = l
|
||||
}
|
||||
|
||||
export const info = (...message) => {
|
||||
if (levels.indexOf(level) <= levels.indexOf("info")) {
|
||||
console.log(...message)
|
||||
}
|
||||
}
|
||||
|
||||
export const warn = (...message) => {
|
||||
if (levels.indexOf(level) <= levels.indexOf("warn")) {
|
||||
console.warn(...message)
|
||||
}
|
||||
}
|
||||
|
||||
export const error = (...message) => {
|
||||
if (levels.indexOf(level) <= levels.indexOf("error")) {
|
||||
console.error(...message)
|
||||
}
|
||||
}
|
||||
|
||||
export default {info, warn, error}
|
||||
|
Loading…
Reference in New Issue
Block a user