Nip7os interface

Light theme tweaks
This commit is contained in:
Kieran 2023-08-29 14:55:30 +01:00
parent 8a3133af70
commit ec2b11bd75
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
9 changed files with 99 additions and 18 deletions

View File

@ -33,4 +33,4 @@ declare module "translations/*.json" {
declare module "emojilib" {
const value: Record<string, string>;
export default value;
}
}

View File

@ -36,6 +36,7 @@ export const ProxyImg = (props: ProxyImgProps) => {
<img
{...props}
src={props.src ? proxy(props.src, props.size) : ""}
width={props.size} height={props.size}
onError={e => {
if (props.onError) {
props.onError(e);

View File

@ -16,6 +16,7 @@ export default function useLoginHandler() {
defaultMessage:
"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead",
});
// private key logins
if (key.startsWith("nsec")) {
if (!hasSubtleCrypto) {
throw new Error(insecureMsg);
@ -26,12 +27,6 @@ export default function useLoginHandler() {
} else {
throw new Error("INVALID PRIVATE KEY");
}
} else if (key.startsWith("npub")) {
const hexKey = bech32ToHex(key);
LoginStore.loginWithPubkey(hexKey, LoginSessionType.PublicKey);
} else if (key.match(EmailRegex)) {
const hexKey = await getNip05PubKey(key);
LoginStore.loginWithPubkey(hexKey, LoginSessionType.PublicKey);
} else if (key.match(MnemonicRegex)?.length === 24) {
if (!hasSubtleCrypto) {
throw new Error(insecureMsg);
@ -44,6 +39,15 @@ export default function useLoginHandler() {
throw new Error(insecureMsg);
}
LoginStore.loginWithPrivateKey(key);
}
// public key logins
if (key.startsWith("npub")) {
const hexKey = bech32ToHex(key);
LoginStore.loginWithPubkey(hexKey, LoginSessionType.PublicKey);
} else if (key.match(EmailRegex)) {
const hexKey = await getNip05PubKey(key);
LoginStore.loginWithPubkey(hexKey, LoginSessionType.PublicKey);
} else if (key.startsWith("bunker://")) {
const nip46 = new Nip46Signer(key);
await nip46.init();

View File

@ -15,6 +15,7 @@ export enum LoginSessionType {
PublicKey = "public_key",
Nip7 = "nip7",
Nip46 = "nip46",
Nip7os = "nip7_os"
}
export interface LoginSession {

View File

@ -7,6 +7,7 @@ import { deepClone, sanitizeRelayUrl, unwrap, ExternalStore } from "@snort/share
import { DefaultRelays } from "Const";
import { LoginSession, LoginSessionType } from "Login";
import { DefaultPreferences, UserPreferences } from "./Preferences";
import { Nip7OsSigner } from "./Nip7OsSigner";
const AccountStoreKey = "sessions";
const LoggedOut = {
@ -146,6 +147,12 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
},
preferences: deepClone(DefaultPreferences),
} as LoginSession;
if("nostr_os" in window && window.nostr_os) {
window.nostr_os.saveKey(key);
newSession.type = LoginSessionType.Nip7os;
newSession.privateKey = undefined;
}
newSession.publisher = this.#createPublisher(newSession);
this.#accounts.set(pubKey, newSession);
@ -190,6 +197,9 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
const nip46 = new Nip46Signer(`bunker://${unwrap(l.publicKey)}?${[...relayArgs].join("&")}`, inner);
return new EventPublisher(nip46, unwrap(l.publicKey));
}
case LoginSessionType.Nip7os: {
return new EventPublisher(new Nip7OsSigner(), unwrap(l.publicKey));
}
default: {
if (l.publicKey) {
return new EventPublisher(new Nip7Signer(), l.publicKey);

View File

@ -0,0 +1,44 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { EventSigner, NostrEvent } from "@snort/system";
import { Nip7os } from "Login";
export class Nip7OsSigner implements EventSigner {
#interface: Nip7os;
constructor() {
if("nostr_os" in window && window.nostr_os) {
this.#interface = window.nostr_os;
} else {
throw new Error("Nost OS extension not available")
}
}
init(): Promise<void> {
return Promise.resolve();
}
getPubKey(): string | Promise<string> {
return this.#interface.getPublicKey();
}
nip4Encrypt(content: string, key: string): Promise<string> {
return Promise.resolve(this.#interface.nip04_encrypt(content, key));
}
nip4Decrypt(content: string, otherKey: string): Promise<string> {
return Promise.resolve(this.#interface.nip04_decrypt(content, otherKey));
}
nip44Encrypt(content: string, key: string): Promise<string> {
throw new Error("Method not implemented.");
}
nip44Decrypt(content: string, otherKey: string): Promise<string> {
throw new Error("Method not implemented.");
}
sign(ev: NostrEvent): Promise<NostrEvent> {
const ret = this.#interface.signEvent(JSON.stringify(ev));
return Promise.resolve(JSON.parse(ret) as NostrEvent);
}
}

View File

@ -1,6 +1,20 @@
import { MultiAccountStore } from "./MultiAccountStore";
export const LoginStore = new MultiAccountStore();
export interface Nip7os {
getPublicKey: () => string
signEvent: (ev: string) => string
saveKey: (key: string) => void
nip04_encrypt: (content:string, to: string) => string
nip04_decrypt: (content:string, from: string) => string
}
declare global {
interface Window {
nostr_os?: Nip7os;
}
}
export * from "./Preferences";
export * from "./LoginSession";
export * from "./Functions";

View File

@ -8,7 +8,7 @@ import { hexToBech32 } from "SnortUtils";
import { hexToMnemonic } from "nip6";
import useLogin from "Hooks/useLogin";
import { PROFILE } from ".";
import { DefaultPreferences, updatePreferences } from "Login";
import { DefaultPreferences, LoginStore, updatePreferences } from "Login";
import { AllLanguageCodes } from "Pages/settings/Preferences";
import messages from "./messages";
@ -136,7 +136,13 @@ export default function NewUserFlow() {
</h2>
<Copy text={hexToMnemonic(login.generatedEntropy ?? "")} />
<div className="next-actions">
<button type="button" onClick={() => navigate(PROFILE)}>
<button type="button" onClick={() => {
LoginStore.updateSession({
...login,
generatedEntropy: undefined
})
navigate(PROFILE)
}}>
<FormattedMessage {...messages.KeysSaved} />{" "}
</button>
</div>

View File

@ -3,7 +3,7 @@
--font-color: #fff;
--font-secondary-color: #a7a7a7;
--font-tertiary-color: #a3a3a3;
--border-color: rgba(163, 163, 163, 0.3);
--border-color: var(--gray-superdark);
--font-size: 15px;
--font-size-small: 13px;
--font-size-tiny: 11px;
@ -71,21 +71,22 @@ html {
html.light {
--bg-color: #f8f8f8;
--font-color: #27272a;
--font-color: #2F3F64;
--font-secondary-color: #71717a;
--font-tertiary-color: #52525b;
--border-color: rgba(167, 167, 167, 0.3);
--border-color: #DEE1E8;
--highlight: #7139f1;
--modal-bg-color: rgba(240, 240, 240, 0.8);
--gray: #aaa;
--gray-secondary: #bbb;
--gray-tertiary: #ccc;
--gray: #999;
--gray-secondary: #aaa;
--gray-tertiary: #bbb;
--gray-superlight: #333;
--gray-light: #555;
--gray-dark: #2b2b2b;
--gray-superdark: #eee;
--gray-dark: #ccc;
--gray-superdark: #ddd;
--gray-ultradark: #eee;
--dm-gradient: var(--gray);
--invoice-gradient: linear-gradient(45deg, var(--gray-superdark) 50%, #f7b73333, #fc4a1a33);
@ -125,7 +126,7 @@ code {
}
.main-content {
border: 1px solid var(--gray-superdark);
border: 1px solid var(--border-color);
}
}