tmp
This commit is contained in:
@ -4,49 +4,49 @@ import { base64 } from "@scure/base";
|
||||
import { secp256k1 } from "@noble/curves/secp256k1";
|
||||
|
||||
export class Nip4WebCryptoEncryptor implements MessageEncryptor {
|
||||
getSharedSecret(privateKey: string, publicKey: string) {
|
||||
const sharedPoint = secp256k1.getSharedSecret(privateKey, "02" + publicKey);
|
||||
const sharedX = sharedPoint.slice(1, 33);
|
||||
return sharedX;
|
||||
}
|
||||
getSharedSecret(privateKey: string, publicKey: string) {
|
||||
const sharedPoint = secp256k1.getSharedSecret(privateKey, "02" + publicKey);
|
||||
const sharedX = sharedPoint.slice(1, 33);
|
||||
return sharedX;
|
||||
}
|
||||
|
||||
async encryptData(content: string, sharedSecet: Uint8Array) {
|
||||
const key = await this.#importKey(sharedSecet);
|
||||
const iv = window.crypto.getRandomValues(new Uint8Array(16));
|
||||
const data = new TextEncoder().encode(content);
|
||||
const result = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-CBC",
|
||||
iv: iv,
|
||||
},
|
||||
key,
|
||||
data
|
||||
);
|
||||
const uData = new Uint8Array(result);
|
||||
return `${base64.encode(uData)}?iv=${base64.encode(iv)}`;
|
||||
}
|
||||
async encryptData(content: string, sharedSecet: Uint8Array) {
|
||||
const key = await this.#importKey(sharedSecet);
|
||||
const iv = window.crypto.getRandomValues(new Uint8Array(16));
|
||||
const data = new TextEncoder().encode(content);
|
||||
const result = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-CBC",
|
||||
iv: iv,
|
||||
},
|
||||
key,
|
||||
data
|
||||
);
|
||||
const uData = new Uint8Array(result);
|
||||
return `${base64.encode(uData)}?iv=${base64.encode(iv)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the content of the message
|
||||
*/
|
||||
async decryptData(cyphertext: string, sharedSecet: Uint8Array) {
|
||||
const key = await this.#importKey(sharedSecet);
|
||||
const cSplit = cyphertext.split("?iv=");
|
||||
const data = base64.decode(cSplit[0]);
|
||||
const iv = base64.decode(cSplit[1]);
|
||||
/**
|
||||
* Decrypt the content of the message
|
||||
*/
|
||||
async decryptData(cyphertext: string, sharedSecet: Uint8Array) {
|
||||
const key = await this.#importKey(sharedSecet);
|
||||
const cSplit = cyphertext.split("?iv=");
|
||||
const data = base64.decode(cSplit[0]);
|
||||
const iv = base64.decode(cSplit[1]);
|
||||
|
||||
const result = await window.crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-CBC",
|
||||
iv: iv,
|
||||
},
|
||||
key,
|
||||
data
|
||||
);
|
||||
return new TextDecoder().decode(result);
|
||||
}
|
||||
const result = await window.crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-CBC",
|
||||
iv: iv,
|
||||
},
|
||||
key,
|
||||
data
|
||||
);
|
||||
return new TextDecoder().decode(result);
|
||||
}
|
||||
|
||||
async #importKey(sharedSecet: Uint8Array) {
|
||||
return await window.crypto.subtle.importKey("raw", sharedSecet, { name: "AES-CBC" }, false, ["encrypt", "decrypt"]);
|
||||
}
|
||||
}
|
||||
async #importKey(sharedSecet: Uint8Array) {
|
||||
return await window.crypto.subtle.importKey("raw", sharedSecet, { name: "AES-CBC" }, false, ["encrypt", "decrypt"]);
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +1,39 @@
|
||||
import { MessageEncryptor } from "index";
|
||||
|
||||
import { base64 } from "@scure/base";
|
||||
import { randomBytes } from '@noble/hashes/utils'
|
||||
import { streamXOR as xchacha20 } from '@stablelib/xchacha20'
|
||||
import { randomBytes } from "@noble/hashes/utils";
|
||||
import { streamXOR as xchacha20 } from "@stablelib/xchacha20";
|
||||
import { secp256k1 } from "@noble/curves/secp256k1";
|
||||
import { sha256 } from '@noble/hashes/sha256'
|
||||
import { sha256 } from "@noble/hashes/sha256";
|
||||
|
||||
export enum Nip44Version {
|
||||
Reserved = 0x00,
|
||||
XChaCha20 = 0x01
|
||||
Reserved = 0x00,
|
||||
XChaCha20 = 0x01,
|
||||
}
|
||||
|
||||
export class Nip44Encryptor implements MessageEncryptor {
|
||||
getSharedSecret(privateKey: string, publicKey: string) {
|
||||
const key = secp256k1.getSharedSecret(privateKey, '02' + publicKey)
|
||||
return sha256(key.slice(1, 33));
|
||||
}
|
||||
getSharedSecret(privateKey: string, publicKey: string) {
|
||||
const key = secp256k1.getSharedSecret(privateKey, "02" + publicKey);
|
||||
return sha256(key.slice(1, 33));
|
||||
}
|
||||
|
||||
encryptData(content: string, sharedSecret: Uint8Array) {
|
||||
const nonce = randomBytes(24)
|
||||
const plaintext = new TextEncoder().encode(content)
|
||||
const ciphertext = xchacha20(sharedSecret, nonce, plaintext, plaintext);
|
||||
const ctb64 = base64.encode(Uint8Array.from(ciphertext))
|
||||
const nonceb64 = base64.encode(nonce)
|
||||
return JSON.stringify({ ciphertext: ctb64, nonce: nonceb64, v: Nip44Version.XChaCha20 })
|
||||
}
|
||||
encryptData(content: string, sharedSecret: Uint8Array) {
|
||||
const nonce = randomBytes(24);
|
||||
const plaintext = new TextEncoder().encode(content);
|
||||
const ciphertext = xchacha20(sharedSecret, nonce, plaintext, plaintext);
|
||||
const ctb64 = base64.encode(Uint8Array.from(ciphertext));
|
||||
const nonceb64 = base64.encode(nonce);
|
||||
return JSON.stringify({ ciphertext: ctb64, nonce: nonceb64, v: Nip44Version.XChaCha20 });
|
||||
}
|
||||
|
||||
decryptData(cyphertext: string, sharedSecret: Uint8Array) {
|
||||
const dt = JSON.parse(cyphertext)
|
||||
if (dt.v !== 1) throw new Error('NIP44: unknown encryption version')
|
||||
decryptData(cyphertext: string, sharedSecret: Uint8Array) {
|
||||
const dt = JSON.parse(cyphertext);
|
||||
if (dt.v !== 1) throw new Error("NIP44: unknown encryption version");
|
||||
|
||||
const ciphertext = base64.decode(dt.ciphertext)
|
||||
const nonce = base64.decode(dt.nonce)
|
||||
const plaintext = xchacha20(sharedSecret, nonce, ciphertext, ciphertext)
|
||||
const text = new TextDecoder().decode(plaintext)
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
const ciphertext = base64.decode(dt.ciphertext);
|
||||
const nonce = base64.decode(dt.nonce);
|
||||
const plaintext = xchacha20(sharedSecret, nonce, ciphertext, ciphertext);
|
||||
const text = new TextDecoder().decode(plaintext);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
@ -12,204 +12,213 @@ import EventKind from "../event-kind";
|
||||
const NIP46_KIND = 24_133;
|
||||
|
||||
interface Nip46Metadata {
|
||||
name: string
|
||||
url?: string
|
||||
description?: string
|
||||
icons?: Array<string>
|
||||
name: string;
|
||||
url?: string;
|
||||
description?: string;
|
||||
icons?: Array<string>;
|
||||
}
|
||||
|
||||
interface Nip46Request {
|
||||
id: string
|
||||
method: string
|
||||
params: Array<any>
|
||||
id: string;
|
||||
method: string;
|
||||
params: Array<any>;
|
||||
}
|
||||
|
||||
interface Nip46Response {
|
||||
id: string
|
||||
result: any
|
||||
error: string
|
||||
id: string;
|
||||
result: any;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface QueueObj {
|
||||
resolve: (o: any) => void;
|
||||
reject: (e: Error) => void;
|
||||
resolve: (o: any) => void;
|
||||
reject: (e: Error) => void;
|
||||
}
|
||||
|
||||
export class Nip46Signer implements EventSigner {
|
||||
#conn?: Connection;
|
||||
#relay: string;
|
||||
#localPubkey: string;
|
||||
#remotePubkey?: string;
|
||||
#token?: string;
|
||||
#insideSigner: EventSigner;
|
||||
#commandQueue: Map<string, QueueObj> = new Map();
|
||||
#log = debug("NIP-46");
|
||||
#proto: string;
|
||||
#didInit: boolean = false;
|
||||
#conn?: Connection;
|
||||
#relay: string;
|
||||
#localPubkey: string;
|
||||
#remotePubkey?: string;
|
||||
#token?: string;
|
||||
#insideSigner: EventSigner;
|
||||
#commandQueue: Map<string, QueueObj> = new Map();
|
||||
#log = debug("NIP-46");
|
||||
#proto: string;
|
||||
#didInit: boolean = false;
|
||||
|
||||
constructor(config: string, insideSigner?: EventSigner) {
|
||||
const u = new URL(config);
|
||||
this.#proto = u.protocol;
|
||||
this.#localPubkey = u.pathname.substring(2);
|
||||
constructor(config: string, insideSigner?: EventSigner) {
|
||||
const u = new URL(config);
|
||||
this.#proto = u.protocol;
|
||||
this.#localPubkey = u.pathname.substring(2);
|
||||
|
||||
if (u.hash.length > 1) {
|
||||
this.#token = u.hash.substring(1);
|
||||
}
|
||||
if (this.#localPubkey.startsWith("npub")) {
|
||||
this.#localPubkey = bech32ToHex(this.#localPubkey);
|
||||
}
|
||||
|
||||
this.#relay = unwrap(u.searchParams.get("relay"));
|
||||
this.#insideSigner = insideSigner ?? new PrivateKeySigner(secp256k1.utils.randomPrivateKey())
|
||||
if (u.hash.length > 1) {
|
||||
this.#token = u.hash.substring(1);
|
||||
}
|
||||
if (this.#localPubkey.startsWith("npub")) {
|
||||
this.#localPubkey = bech32ToHex(this.#localPubkey);
|
||||
}
|
||||
|
||||
get relays() {
|
||||
return [this.#relay];
|
||||
}
|
||||
this.#relay = unwrap(u.searchParams.get("relay"));
|
||||
this.#insideSigner = insideSigner ?? new PrivateKeySigner(secp256k1.utils.randomPrivateKey());
|
||||
}
|
||||
|
||||
get privateKey() {
|
||||
if(this.#insideSigner instanceof PrivateKeySigner) {
|
||||
return this.#insideSigner.privateKey;
|
||||
}
|
||||
}
|
||||
get relays() {
|
||||
return [this.#relay];
|
||||
}
|
||||
|
||||
get privateKey() {
|
||||
if (this.#insideSigner instanceof PrivateKeySigner) {
|
||||
return this.#insideSigner.privateKey;
|
||||
}
|
||||
}
|
||||
|
||||
async init() {
|
||||
const isBunker = this.#proto === "bunker:";
|
||||
if (isBunker) {
|
||||
this.#remotePubkey = this.#localPubkey;
|
||||
this.#localPubkey = await this.#insideSigner.getPubKey();
|
||||
}
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
this.#conn = new Connection(this.#relay, { read: true, write: true });
|
||||
this.#conn.OnEvent = async (sub, e) => {
|
||||
await this.#onReply(e);
|
||||
};
|
||||
this.#conn.OnConnected = async () => {
|
||||
this.#conn!.QueueReq(
|
||||
[
|
||||
"REQ",
|
||||
"reply",
|
||||
{
|
||||
kinds: [NIP46_KIND],
|
||||
"#p": [this.#localPubkey],
|
||||
},
|
||||
],
|
||||
() => {}
|
||||
);
|
||||
|
||||
async init() {
|
||||
const isBunker = this.#proto === "bunker:";
|
||||
if (isBunker) {
|
||||
this.#remotePubkey = this.#localPubkey;
|
||||
this.#localPubkey = await this.#insideSigner.getPubKey();
|
||||
await this.#connect(unwrap(this.#remotePubkey));
|
||||
resolve();
|
||||
} else {
|
||||
this.#commandQueue.set("connect", {
|
||||
reject,
|
||||
resolve,
|
||||
});
|
||||
}
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
this.#conn = new Connection(this.#relay, { read: true, write: true });
|
||||
this.#conn.OnEvent = async (sub, e) => {
|
||||
await this.#onReply(e);
|
||||
}
|
||||
this.#conn.OnConnected = async () => {
|
||||
this.#conn!.QueueReq(["REQ", "reply", {
|
||||
kinds: [NIP46_KIND],
|
||||
"#p": [this.#localPubkey]
|
||||
}], () => { });
|
||||
};
|
||||
this.#conn.Connect();
|
||||
this.#didInit = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (isBunker) {
|
||||
await this.#connect(unwrap(this.#remotePubkey));
|
||||
resolve();
|
||||
} else {
|
||||
this.#commandQueue.set("connect", {
|
||||
reject,
|
||||
resolve
|
||||
})
|
||||
}
|
||||
}
|
||||
this.#conn.Connect();
|
||||
this.#didInit = true;
|
||||
})
|
||||
async close() {
|
||||
if (this.#conn) {
|
||||
await this.#disconnect();
|
||||
this.#conn.CloseReq("reply");
|
||||
this.#conn.Close();
|
||||
this.#conn = undefined;
|
||||
this.#didInit = false;
|
||||
}
|
||||
}
|
||||
|
||||
async describe() {
|
||||
return await this.#rpc<Array<string>>("describe", []);
|
||||
}
|
||||
|
||||
async getPubKey() {
|
||||
return await this.#rpc<string>("get_public_key", []);
|
||||
}
|
||||
|
||||
async nip4Encrypt(content: string, otherKey: string) {
|
||||
return await this.#rpc<string>("nip04_encrypt", [otherKey, content]);
|
||||
}
|
||||
|
||||
async nip4Decrypt(content: string, otherKey: string) {
|
||||
return await this.#rpc<string>("nip04_decrypt", [otherKey, content]);
|
||||
}
|
||||
|
||||
async sign(ev: NostrEvent) {
|
||||
const evStr = await this.#rpc<string>("sign_event", [JSON.stringify(ev)]);
|
||||
return JSON.parse(evStr);
|
||||
}
|
||||
|
||||
async #disconnect() {
|
||||
return await this.#rpc("disconnect", []);
|
||||
}
|
||||
|
||||
async #connect(pk: string) {
|
||||
const connectParams = [pk];
|
||||
if (this.#token) {
|
||||
connectParams.push(this.#token);
|
||||
}
|
||||
return await this.#rpc<string>("connect", connectParams);
|
||||
}
|
||||
|
||||
async #onReply(e: NostrEvent) {
|
||||
if (e.kind !== NIP46_KIND) {
|
||||
throw new Error("Unknown event kind");
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (this.#conn) {
|
||||
await this.#disconnect();
|
||||
this.#conn.CloseReq("reply");
|
||||
this.#conn.Close();
|
||||
this.#conn = undefined;
|
||||
this.#didInit = false;
|
||||
}
|
||||
const decryptedContent = await this.#insideSigner.nip4Decrypt(e.content, e.pubkey);
|
||||
const reply = JSON.parse(decryptedContent) as Nip46Request | Nip46Response;
|
||||
|
||||
let id = reply.id;
|
||||
this.#log("Recv: %O", reply);
|
||||
if ("method" in reply && reply.method === "connect") {
|
||||
this.#remotePubkey = reply.params[0];
|
||||
await this.#sendCommand(
|
||||
{
|
||||
id: reply.id,
|
||||
result: "ack",
|
||||
error: "",
|
||||
},
|
||||
unwrap(this.#remotePubkey)
|
||||
);
|
||||
id = "connect";
|
||||
}
|
||||
const pending = this.#commandQueue.get(id);
|
||||
if (!pending) {
|
||||
throw new Error("No pending command found");
|
||||
}
|
||||
|
||||
async describe() {
|
||||
return await this.#rpc<Array<string>>("describe", []);
|
||||
pending.resolve(reply);
|
||||
this.#commandQueue.delete(reply.id);
|
||||
}
|
||||
|
||||
async #rpc<T>(method: string, params: Array<any>) {
|
||||
if (!this.#didInit) {
|
||||
await this.init();
|
||||
}
|
||||
if (!this.#conn) throw new Error("Connection error");
|
||||
|
||||
async getPubKey() {
|
||||
return await this.#rpc<string>("get_public_key", []);
|
||||
}
|
||||
const payload = {
|
||||
id: uuid(),
|
||||
method,
|
||||
params,
|
||||
} as Nip46Request;
|
||||
|
||||
async nip4Encrypt(content: string, otherKey: string) {
|
||||
return await this.#rpc<string>("nip04_encrypt", [otherKey, content]);
|
||||
}
|
||||
this.#sendCommand(payload, unwrap(this.#remotePubkey));
|
||||
return await new Promise<T>((resolve, reject) => {
|
||||
this.#commandQueue.set(payload.id, {
|
||||
resolve: async (o: Nip46Response) => {
|
||||
resolve(o.result as T);
|
||||
},
|
||||
reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async nip4Decrypt(content: string, otherKey: string) {
|
||||
return await this.#rpc<string>("nip04_decrypt", [otherKey, content]);
|
||||
}
|
||||
async #sendCommand(payload: Nip46Request | Nip46Response, target: string) {
|
||||
if (!this.#conn) return;
|
||||
|
||||
async sign(ev: NostrEvent) {
|
||||
const evStr = await this.#rpc<string>("sign_event", [JSON.stringify(ev)]);
|
||||
return JSON.parse(evStr);
|
||||
}
|
||||
const eb = new EventBuilder();
|
||||
eb.kind(NIP46_KIND as EventKind)
|
||||
.content(await this.#insideSigner.nip4Encrypt(JSON.stringify(payload), target))
|
||||
.tag(["p", target]);
|
||||
|
||||
async #disconnect() {
|
||||
return await this.#rpc("disconnect", []);
|
||||
}
|
||||
|
||||
async #connect(pk: string) {
|
||||
const connectParams = [pk];
|
||||
if (this.#token) {
|
||||
connectParams.push(this.#token);
|
||||
}
|
||||
return await this.#rpc<string>("connect", connectParams);
|
||||
}
|
||||
|
||||
async #onReply(e: NostrEvent) {
|
||||
if (e.kind !== NIP46_KIND) {
|
||||
throw new Error("Unknown event kind");
|
||||
}
|
||||
|
||||
const decryptedContent = await this.#insideSigner.nip4Decrypt(e.content, e.pubkey);
|
||||
const reply = JSON.parse(decryptedContent) as Nip46Request | Nip46Response;
|
||||
|
||||
let id = reply.id;
|
||||
this.#log("Recv: %O", reply);
|
||||
if ("method" in reply && reply.method === "connect") {
|
||||
this.#remotePubkey = reply.params[0];
|
||||
await this.#sendCommand({
|
||||
id: reply.id,
|
||||
result: "ack",
|
||||
error: ""
|
||||
}, unwrap(this.#remotePubkey));
|
||||
id = "connect";
|
||||
}
|
||||
const pending = this.#commandQueue.get(id);
|
||||
if (!pending) {
|
||||
throw new Error("No pending command found");
|
||||
}
|
||||
|
||||
pending.resolve(reply);
|
||||
this.#commandQueue.delete(reply.id);
|
||||
}
|
||||
|
||||
async #rpc<T>(method: string, params: Array<any>) {
|
||||
if (!this.#didInit) {
|
||||
await this.init();
|
||||
}
|
||||
if (!this.#conn) throw new Error("Connection error");
|
||||
|
||||
const payload = {
|
||||
id: uuid(),
|
||||
method,
|
||||
params,
|
||||
} as Nip46Request;
|
||||
|
||||
this.#sendCommand(payload, unwrap(this.#remotePubkey));
|
||||
return await new Promise<T>((resolve, reject) => {
|
||||
this.#commandQueue.set(payload.id, {
|
||||
resolve: async (o: Nip46Response) => {
|
||||
resolve(o.result as T);
|
||||
},
|
||||
reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async #sendCommand(payload: Nip46Request | Nip46Response, target: string) {
|
||||
if (!this.#conn) return;
|
||||
|
||||
const eb = new EventBuilder();
|
||||
eb.kind(NIP46_KIND as EventKind)
|
||||
.content(await this.#insideSigner.nip4Encrypt(JSON.stringify(payload), target))
|
||||
.tag(["p", target]);
|
||||
|
||||
this.#log("Send: %O", payload);
|
||||
const evCommand = await eb.buildAndSign(this.#insideSigner);
|
||||
await this.#conn.SendAsync(evCommand);
|
||||
}
|
||||
this.#log("Send: %O", payload);
|
||||
const evCommand = await eb.buildAndSign(this.#insideSigner);
|
||||
await this.#conn.SendAsync(evCommand);
|
||||
}
|
||||
}
|
||||
|
@ -6,56 +6,55 @@ const Nip7Queue: Array<WorkQueueItem> = [];
|
||||
processWorkQueue(Nip7Queue);
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
nostr?: {
|
||||
getPublicKey: () => Promise<HexKey>;
|
||||
signEvent: <T extends NostrEvent>(event: T) => Promise<T>;
|
||||
interface Window {
|
||||
nostr?: {
|
||||
getPublicKey: () => Promise<HexKey>;
|
||||
signEvent: <T extends NostrEvent>(event: T) => Promise<T>;
|
||||
|
||||
getRelays?: () => Promise<Record<string, { read: boolean; write: boolean }>>;
|
||||
getRelays?: () => Promise<Record<string, { read: boolean; write: boolean }>>;
|
||||
|
||||
nip04?: {
|
||||
encrypt?: (pubkey: HexKey, plaintext: string) => Promise<string>;
|
||||
decrypt?: (pubkey: HexKey, ciphertext: string) => Promise<string>;
|
||||
};
|
||||
};
|
||||
}
|
||||
nip04?: {
|
||||
encrypt?: (pubkey: HexKey, plaintext: string) => Promise<string>;
|
||||
decrypt?: (pubkey: HexKey, ciphertext: string) => Promise<string>;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class Nip7Signer implements EventSigner {
|
||||
init(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
init(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
async getPubKey(): Promise<string> {
|
||||
if (!window.nostr) {
|
||||
throw new Error("Cannot use NIP-07 signer, not found!");
|
||||
}
|
||||
return await barrierQueue(Nip7Queue, () => unwrap(window.nostr).getPublicKey());
|
||||
async getPubKey(): Promise<string> {
|
||||
if (!window.nostr) {
|
||||
throw new Error("Cannot use NIP-07 signer, not found!");
|
||||
}
|
||||
return await barrierQueue(Nip7Queue, () => unwrap(window.nostr).getPublicKey());
|
||||
}
|
||||
|
||||
async nip4Encrypt(content: string, key: string): Promise<string> {
|
||||
if (!window.nostr) {
|
||||
throw new Error("Cannot use NIP-07 signer, not found!");
|
||||
}
|
||||
return await barrierQueue(Nip7Queue, () =>
|
||||
unwrap(window.nostr?.nip04?.encrypt).call(window.nostr?.nip04, key, content)
|
||||
);
|
||||
async nip4Encrypt(content: string, key: string): Promise<string> {
|
||||
if (!window.nostr) {
|
||||
throw new Error("Cannot use NIP-07 signer, not found!");
|
||||
}
|
||||
return await barrierQueue(Nip7Queue, () =>
|
||||
unwrap(window.nostr?.nip04?.encrypt).call(window.nostr?.nip04, key, content)
|
||||
);
|
||||
}
|
||||
|
||||
async nip4Decrypt(content: string, otherKey: string): Promise<string> {
|
||||
if (!window.nostr) {
|
||||
throw new Error("Cannot use NIP-07 signer, not found!");
|
||||
}
|
||||
return await barrierQueue(Nip7Queue, () =>
|
||||
unwrap(window.nostr?.nip04?.decrypt).call(window.nostr?.nip04, otherKey, content)
|
||||
);
|
||||
async nip4Decrypt(content: string, otherKey: string): Promise<string> {
|
||||
if (!window.nostr) {
|
||||
throw new Error("Cannot use NIP-07 signer, not found!");
|
||||
}
|
||||
return await barrierQueue(Nip7Queue, () =>
|
||||
unwrap(window.nostr?.nip04?.decrypt).call(window.nostr?.nip04, otherKey, content)
|
||||
);
|
||||
}
|
||||
|
||||
async sign(ev: NostrEvent): Promise<NostrEvent> {
|
||||
if (!window.nostr) {
|
||||
throw new Error("Cannot use NIP-07 signer, not found!");
|
||||
}
|
||||
return await barrierQueue(Nip7Queue, () => unwrap(window.nostr).signEvent(ev));
|
||||
async sign(ev: NostrEvent): Promise<NostrEvent> {
|
||||
if (!window.nostr) {
|
||||
throw new Error("Cannot use NIP-07 signer, not found!");
|
||||
}
|
||||
|
||||
}
|
||||
return await barrierQueue(Nip7Queue, () => unwrap(window.nostr).signEvent(ev));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user