Sign events from NIP-07 ext
This commit is contained in:
parent
987ef0ed7b
commit
523d1951fa
@ -3,6 +3,9 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@noble/secp256k1": "^1.7.0",
|
||||
"@reduxjs/toolkit": "^1.9.1",
|
||||
"bech32": "^2.0.0",
|
||||
|
@ -39,12 +39,17 @@ code {
|
||||
user-select: none;
|
||||
background-color: #000;
|
||||
border: 1px solid;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
input[type="text"], input[type="password"] {
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
@ -93,6 +98,7 @@ div.form-group {
|
||||
|
||||
div.form-group > div {
|
||||
padding: 3px 5px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
div.form-group > div:first-child {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { setPrivateKey, setPublicKey } from "../state/Login";
|
||||
import { setPrivateKey, setNip07PubKey } from "../state/Login";
|
||||
import * as secp from '@noble/secp256k1';
|
||||
import { bech32 } from "bech32";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
@ -32,12 +32,11 @@ export default function LoginPage() {
|
||||
|
||||
async function doNip07Login() {
|
||||
let pubKey = await window.nostr.getPublicKey();
|
||||
dispatch(setPublicKey(pubKey));
|
||||
dispatch(setNip07PubKey(pubKey));
|
||||
}
|
||||
|
||||
function altLogins() {
|
||||
let nip07 = 'nostr' in window;
|
||||
|
||||
if (!nip07) {
|
||||
return null;
|
||||
}
|
||||
|
@ -8,8 +8,8 @@
|
||||
}
|
||||
|
||||
.profile .avatar {
|
||||
width: 256px;
|
||||
height: 256px;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
background-size: contain;
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -27,3 +27,14 @@
|
||||
.profile .avatar .edit:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@media(max-width: 720px) {
|
||||
.profile {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.profile > div:last-child {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import Nostrich from "../nostrich.jpg";
|
||||
import useEventPublisher from "./feed/EventPublisher";
|
||||
import useTimelineFeed from "./feed/TimelineFeed";
|
||||
import Note from "../element/Note";
|
||||
import { bech32 } from "bech32";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faQrcode } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
export default function ProfilePage() {
|
||||
const dispatch = useDispatch();
|
||||
@ -37,6 +40,23 @@ export default function ProfilePage() {
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
useEffect(() => {
|
||||
// some clients incorrectly set this to LNURL service, patch this
|
||||
if (lud16.toLowerCase().startsWith("lnurl")) {
|
||||
let decoded = bech32.decode(lud16, 1000);
|
||||
let url = new TextDecoder().decode(Uint8Array.from(bech32.fromWords(decoded.words)));
|
||||
if (url.startsWith("http")) {
|
||||
let parsedUri = new URL(url);
|
||||
// is lightning address
|
||||
if (parsedUri.pathname.startsWith("/.well-known/lnurlp/")) {
|
||||
let pathParts = parsedUri.pathname.split('/');
|
||||
let username = pathParts[pathParts.length - 1];
|
||||
setLud16(`${username}@${parsedUri.hostname}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [lud16]);
|
||||
|
||||
async function saveProfile() {
|
||||
let ev = await publisher.metadata({
|
||||
name,
|
||||
@ -79,7 +99,7 @@ export default function ProfilePage() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div>Lightning Address:</div>
|
||||
<div>LN Address:</div>
|
||||
<div>
|
||||
<input type="text" value={lud16} onChange={(e) => setLud16(e.target.value)} />
|
||||
</div>
|
||||
@ -116,18 +136,23 @@ export default function ProfilePage() {
|
||||
{website}
|
||||
</div>
|
||||
</div> : null}
|
||||
{nip05 ?
|
||||
<div className="form-group">
|
||||
<div>NIP-05:</div>
|
||||
<div>
|
||||
{nip05}
|
||||
</div>
|
||||
</div>
|
||||
</div> : null}
|
||||
{lud16 ?
|
||||
<div className="form-group">
|
||||
<div>Lightning Address:</div>
|
||||
<div>LN Address:</div>
|
||||
<div>
|
||||
{lud16}
|
||||
{lud16}
|
||||
<div className="btn btn-sm" onClick={() => { }}>
|
||||
<FontAwesomeIcon icon={faQrcode} size="lg" />
|
||||
</div>
|
||||
</div>
|
||||
</div> : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -135,7 +160,6 @@ export default function ProfilePage() {
|
||||
return (
|
||||
<>
|
||||
<div className="profile">
|
||||
<div>
|
||||
<div style={{ backgroundImage: `url(${picture})` }} className="avatar">
|
||||
{isMe ?
|
||||
<div className="edit">
|
||||
@ -144,7 +168,6 @@ export default function ProfilePage() {
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{isMe ? editor() : details()}
|
||||
</div>
|
||||
|
@ -9,6 +9,26 @@ export default function useEventPublisher() {
|
||||
const system = useContext(NostrContext);
|
||||
const pubKey = useSelector(s => s.login.publicKey);
|
||||
const privKey = useSelector(s => s.login.privateKey);
|
||||
const nip07 = useSelector(s => s.login.nip07);
|
||||
const hasNip07 = 'nostr' in window;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Event} ev
|
||||
* @param {*} privKey
|
||||
* @returns
|
||||
*/
|
||||
async function signEvent(ev, privKey) {
|
||||
if(nip07 === true && hasNip07) {
|
||||
ev.Id = await ev.CreateId();
|
||||
let tmpEv = await window.nostr.signEvent(ev.ToObject());
|
||||
console.log(tmpEv);
|
||||
return Event.FromObject(tmpEv);
|
||||
} else {
|
||||
await ev.Sign(privKey);
|
||||
}
|
||||
return ev;
|
||||
}
|
||||
|
||||
return {
|
||||
broadcast: (ev) => {
|
||||
@ -19,8 +39,7 @@ export default function useEventPublisher() {
|
||||
let ev = Event.ForPubKey(pubKey);
|
||||
ev.Kind = EventKind.SetMetadata;
|
||||
ev.Content = JSON.stringify(obj);
|
||||
await ev.Sign(privKey);
|
||||
return ev;
|
||||
return await signEvent(ev, privKey);
|
||||
},
|
||||
note: async (msg) => {
|
||||
if(typeof msg !== "string") {
|
||||
@ -29,8 +48,7 @@ export default function useEventPublisher() {
|
||||
let ev = Event.ForPubKey(pubKey);
|
||||
ev.Kind = EventKind.TextNote;
|
||||
ev.Content = msg;
|
||||
await ev.Sign(privKey);
|
||||
return ev;
|
||||
return await signEvent(ev, privKey);
|
||||
},
|
||||
like: async (evRef) => {
|
||||
let ev = Event.ForPubKey(pubKey);
|
||||
@ -38,8 +56,7 @@ export default function useEventPublisher() {
|
||||
ev.Content = "+";
|
||||
ev.Tags.push(new Tag(["e", evRef.Id], 0));
|
||||
ev.Tags.push(new Tag(["p", evRef.PubKey], 1));
|
||||
await ev.Sign(privKey);
|
||||
return ev;
|
||||
return await signEvent(ev, privKey);
|
||||
},
|
||||
dislike: async (evRef) => {
|
||||
let ev = Event.ForPubKey(pubKey);
|
||||
@ -47,8 +64,7 @@ export default function useEventPublisher() {
|
||||
ev.Content = "-";
|
||||
ev.Tags.push(new Tag(["e", evRef.Id], 0));
|
||||
ev.Tags.push(new Tag(["p", evRef.PubKey], 1));
|
||||
await ev.Sign(privKey);
|
||||
return ev;
|
||||
return await signEvent(ev, privKey);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,7 +24,12 @@ const LoginSlice = createSlice({
|
||||
/**
|
||||
* A list of pubkeys this user follows
|
||||
*/
|
||||
follows: []
|
||||
follows: [],
|
||||
|
||||
/**
|
||||
* Login keys are managed by extension
|
||||
*/
|
||||
nip07: false,
|
||||
},
|
||||
reducers: {
|
||||
init: (state) => {
|
||||
@ -47,6 +52,10 @@ const LoginSlice = createSlice({
|
||||
setPublicKey: (state, action) => {
|
||||
state.publicKey = action.payload;
|
||||
},
|
||||
setNip07PubKey: (state, action) => {
|
||||
state.publicKey = action.payload;
|
||||
state.nip07 = true;
|
||||
},
|
||||
setRelays: (state, action) => {
|
||||
state.relays = action.payload;
|
||||
},
|
||||
@ -60,5 +69,5 @@ const LoginSlice = createSlice({
|
||||
}
|
||||
});
|
||||
|
||||
export const { init, setPrivateKey, setPublicKey, setRelays, setFollows, logout } = LoginSlice.actions;
|
||||
export const { init, setPrivateKey, setPublicKey, setNip07PubKey, setRelays, setFollows, logout } = LoginSlice.actions;
|
||||
export const reducer = LoginSlice.reducer;
|
26
yarn.lock
26
yarn.lock
@ -1200,6 +1200,32 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@fortawesome/fontawesome-common-types@6.2.1":
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.1.tgz#411e02a820744d3f7e0d8d9df9d82b471beaa073"
|
||||
integrity sha512-Sz07mnQrTekFWLz5BMjOzHl/+NooTdW8F8kDQxjWwbpOJcnoSg4vUDng8d/WR1wOxM0O+CY9Zw0nR054riNYtQ==
|
||||
|
||||
"@fortawesome/fontawesome-svg-core@^6.2.1":
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.1.tgz#e87e905e444b5e7b715af09b64d27b53d4c8f9d9"
|
||||
integrity sha512-HELwwbCz6C1XEcjzyT1Jugmz2NNklMrSPjZOWMlc+ZsHIVk+XOvOXLGGQtFBwSyqfJDNgRq4xBCwWOaZ/d9DEA==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "6.2.1"
|
||||
|
||||
"@fortawesome/free-solid-svg-icons@^6.2.1":
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.1.tgz#2290ea5adcf1537cbd0c43de6feb38af02141d27"
|
||||
integrity sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "6.2.1"
|
||||
|
||||
"@fortawesome/react-fontawesome@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4"
|
||||
integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==
|
||||
dependencies:
|
||||
prop-types "^15.8.1"
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.6":
|
||||
version "0.11.8"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
|
||||
|
Loading…
x
Reference in New Issue
Block a user