bug: fix build for older browsers
This commit is contained in:
@ -29,8 +29,8 @@
|
||||
"semi": false
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/curves": "^1.0.0",
|
||||
"@noble/hashes": "^1.2.0",
|
||||
"@noble/secp256k1": "^1.7.1",
|
||||
"@types/chai": "^4.3.4",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"base64-js": "^1.5.1",
|
||||
@ -47,8 +47,22 @@
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
"chrome >= 67",
|
||||
"edge >= 79",
|
||||
"firefox >= 68",
|
||||
"opera >= 54",
|
||||
"safari >= 14"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": ""
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ export class Conn {
|
||||
onError,
|
||||
}: {
|
||||
url: URL
|
||||
onMessage: (msg: IncomingMessage) => Promise<void>
|
||||
onMessage: (msg: IncomingMessage) => void
|
||||
onOpen: () => Promise<void>
|
||||
onClose: () => void
|
||||
onError: (err: unknown) => void
|
||||
@ -55,7 +55,7 @@ export class Conn {
|
||||
throw new NostrError(`invalid message data: ${value}`)
|
||||
}
|
||||
const msg = parseIncomingMessage(value)
|
||||
await onMessage(msg)
|
||||
onMessage(msg)
|
||||
} catch (err) {
|
||||
onError(err)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { NostrError } from "../common"
|
||||
import { RawEvent, parseEvent } from "../event"
|
||||
import { Conn } from "./conn"
|
||||
import * as secp from "@noble/secp256k1"
|
||||
import * as utils from "@noble/curves/abstract/utils";
|
||||
import { EventEmitter } from "./emitter"
|
||||
import { fetchRelayInfo, ReadyState, Relay } from "./relay"
|
||||
import { Filters } from "../filters"
|
||||
@ -71,21 +71,21 @@ export class Nostr extends EventEmitter {
|
||||
opts?.fetchInfo === false
|
||||
? Promise.resolve({})
|
||||
: fetchRelayInfo(relayUrl).catch((e) => {
|
||||
this.#error(e)
|
||||
return {}
|
||||
})
|
||||
this.#error(e)
|
||||
return {}
|
||||
})
|
||||
|
||||
// If there is no existing connection, open a new one.
|
||||
const conn = new Conn({
|
||||
url: relayUrl,
|
||||
|
||||
// Handle messages on this connection.
|
||||
onMessage: async (msg) => {
|
||||
onMessage: (msg) => {
|
||||
if (msg.kind === "event") {
|
||||
this.emit(
|
||||
"event",
|
||||
{
|
||||
event: await parseEvent(msg.event),
|
||||
event: parseEvent(msg.event),
|
||||
subscriptionId: msg.subscriptionId,
|
||||
},
|
||||
this
|
||||
@ -128,8 +128,7 @@ export class Nostr extends EventEmitter {
|
||||
if (conn.relay.readyState !== ReadyState.CONNECTING) {
|
||||
this.#error(
|
||||
new NostrError(
|
||||
`bug: expected connection to ${relayUrl.toString()} to have readyState CONNECTING, got ${
|
||||
conn.relay.readyState
|
||||
`bug: expected connection to ${relayUrl.toString()} to have readyState CONNECTING, got ${conn.relay.readyState
|
||||
}`
|
||||
)
|
||||
)
|
||||
@ -294,7 +293,7 @@ export class Nostr extends EventEmitter {
|
||||
relay.info === undefined
|
||||
? undefined
|
||||
: // Deep copy of the info.
|
||||
JSON.parse(JSON.stringify(relay.info))
|
||||
JSON.parse(JSON.stringify(relay.info))
|
||||
return { ...relay, info }
|
||||
}
|
||||
})
|
||||
@ -330,5 +329,5 @@ interface ConnState {
|
||||
export type SubscriptionId = string
|
||||
|
||||
function randomSubscriptionId(): SubscriptionId {
|
||||
return secp.utils.bytesToHex(secp.utils.randomBytes(32))
|
||||
return utils.bytesToHex(globalThis.crypto.getRandomValues(new Uint8Array(32)))
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import * as secp from "@noble/secp256k1"
|
||||
import * as secp from "@noble/curves/secp256k1"
|
||||
import * as utils from "@noble/curves/abstract/utils";
|
||||
import {sha256 as sha} from "@noble/hashes/sha256";
|
||||
import base64 from "base64-js"
|
||||
import { bech32 } from "bech32"
|
||||
|
||||
@ -43,7 +45,7 @@ export function getPublicKey(priv: HexOrBechPrivateKey): PublicKey {
|
||||
* Convert the data to lowercase hex.
|
||||
*/
|
||||
function toHex(data: Uint8Array): Hex {
|
||||
return secp.utils.bytesToHex(data).toLowerCase()
|
||||
return utils.bytesToHex(data).toLowerCase()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,15 +78,15 @@ function parseKey(key: string, bechPrefix: string): Hex {
|
||||
/**
|
||||
* Get the SHA256 hash of the data, in hex format.
|
||||
*/
|
||||
export async function sha256(data: Uint8Array): Promise<Hex> {
|
||||
return toHex(await secp.utils.sha256(data))
|
||||
export function sha256(data: Uint8Array): Hex {
|
||||
return toHex(sha(data))
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the data using elliptic curve cryptography.
|
||||
*/
|
||||
export async function schnorrSign(data: Hex, priv: PrivateKey): Promise<Hex> {
|
||||
return toHex(await secp.schnorr.sign(data, priv))
|
||||
export function schnorrSign(data: Hex, priv: PrivateKey): Hex {
|
||||
return toHex(secp.schnorr.sign(data, priv))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,7 +96,7 @@ export function schnorrVerify(
|
||||
sig: Hex,
|
||||
data: Hex,
|
||||
key: PublicKey
|
||||
): Promise<boolean> {
|
||||
): boolean {
|
||||
return secp.schnorr.verify(sig.toString(), data.toString(), key.toString())
|
||||
}
|
||||
|
||||
@ -103,7 +105,7 @@ export async function aesEncryptBase64(
|
||||
recipient: PublicKey,
|
||||
plaintext: string
|
||||
): Promise<AesEncryptedBase64> {
|
||||
const sharedPoint = secp.getSharedSecret(sender, "02" + recipient)
|
||||
const sharedPoint = secp.secp256k1.getSharedSecret(sender, "02" + recipient)
|
||||
const sharedKey = sharedPoint.slice(1, 33)
|
||||
if (typeof window === "object") {
|
||||
const key = await window.crypto.subtle.importKey(
|
||||
@ -149,7 +151,7 @@ export async function aesDecryptBase64(
|
||||
recipient: PrivateKey,
|
||||
{ data, iv }: AesEncryptedBase64
|
||||
): Promise<string> {
|
||||
const sharedPoint = secp.getSharedSecret(recipient, "02" + sender)
|
||||
const sharedPoint = secp.secp256k1.getSharedSecret(recipient, "02" + sender)
|
||||
const sharedKey = sharedPoint.slice(1, 33)
|
||||
if (typeof window === "object") {
|
||||
const decodedData = base64.toByteArray(data)
|
||||
|
@ -128,12 +128,12 @@ export async function signEvent<T extends RawEvent>(
|
||||
if (priv !== undefined) {
|
||||
priv = parsePrivateKey(priv)
|
||||
event.pubkey = getPublicKey(priv)
|
||||
const id = await serializeEventId(
|
||||
const id = serializeEventId(
|
||||
// This conversion is safe because the pubkey field is set above.
|
||||
event as unknown as UnsignedWithPubkey<T>
|
||||
)
|
||||
event.id = id
|
||||
event.sig = await schnorrSign(id, priv)
|
||||
event.sig = schnorrSign(id, priv)
|
||||
return event as T
|
||||
} else {
|
||||
if (typeof window === "undefined" || window.nostr === undefined) {
|
||||
@ -158,15 +158,15 @@ export async function signEvent<T extends RawEvent>(
|
||||
/**
|
||||
* Parse an event from its raw format.
|
||||
*/
|
||||
export async function parseEvent(event: RawEvent): Promise<Event> {
|
||||
if (event.id !== (await serializeEventId(event))) {
|
||||
export function parseEvent(event: RawEvent): Event {
|
||||
if (event.id !== (serializeEventId(event))) {
|
||||
throw new NostrError(
|
||||
`invalid id ${event.id} for event ${JSON.stringify(
|
||||
event
|
||||
)}, expected ${await serializeEventId(event)}`
|
||||
)}, expected ${serializeEventId(event)}`
|
||||
)
|
||||
}
|
||||
if (!(await schnorrVerify(event.sig, event.id, event.pubkey))) {
|
||||
if (!(schnorrVerify(event.sig, event.id, event.pubkey))) {
|
||||
throw new NostrError(`invalid signature for event ${JSON.stringify(event)}`)
|
||||
}
|
||||
|
||||
@ -221,9 +221,9 @@ export async function parseEvent(event: RawEvent): Promise<Event> {
|
||||
}
|
||||
}
|
||||
|
||||
async function serializeEventId(
|
||||
function serializeEventId(
|
||||
event: UnsignedWithPubkey<RawEvent>
|
||||
): Promise<EventId> {
|
||||
): EventId {
|
||||
const serialized = JSON.stringify([
|
||||
0,
|
||||
event.pubkey,
|
||||
@ -232,7 +232,7 @@ async function serializeEventId(
|
||||
event.tags,
|
||||
event.content,
|
||||
])
|
||||
return await sha256(Uint8Array.from(charCodes(serialized)))
|
||||
return sha256(Uint8Array.from(charCodes(serialized)))
|
||||
}
|
||||
|
||||
function* charCodes(data: string): Iterable<number> {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import * as secp from "@noble/secp256k1";
|
||||
import * as utils from "@noble/curves/abstract/utils";
|
||||
import { bech32 } from "bech32";
|
||||
import { HexKey } from ".";
|
||||
|
||||
@ -29,7 +29,7 @@ export interface TLVEntry {
|
||||
|
||||
export function encodeTLV(prefix: NostrPrefix, id: string, relays?: string[], kind?: number, author?: string) {
|
||||
const enc = new TextEncoder();
|
||||
const buf = prefix === NostrPrefix.Address ? enc.encode(id) : secp.utils.hexToBytes(id);
|
||||
const buf = prefix === NostrPrefix.Address ? enc.encode(id) : utils.hexToBytes(id);
|
||||
|
||||
const tl0 = [0, buf.length, ...buf];
|
||||
const tl1 =
|
||||
@ -40,7 +40,7 @@ export function encodeTLV(prefix: NostrPrefix, id: string, relays?: string[], ki
|
||||
})
|
||||
.flat() ?? [];
|
||||
|
||||
const tl2 = author ? [2, 32, ...secp.utils.hexToBytes(author)] : [];
|
||||
const tl2 = author ? [2, 32, ...utils.hexToBytes(author)] : [];
|
||||
const tl3 = kind ? [3, 4, ...new Uint8Array(new Uint32Array([kind]).buffer).reverse()] : []
|
||||
|
||||
return bech32.encode(prefix, bech32.toWords([...tl0, ...tl1, ...tl2, ...tl3]), 1_000);
|
||||
@ -72,11 +72,11 @@ function decodeTLVEntry(type: TLVEntryType, prefix: string, data: Uint8Array) {
|
||||
if (prefix === NostrPrefix.Address) {
|
||||
return new TextDecoder("ASCII").decode(data);
|
||||
} else {
|
||||
return secp.utils.bytesToHex(data);
|
||||
return utils.bytesToHex(data);
|
||||
}
|
||||
}
|
||||
case TLVEntryType.Author: {
|
||||
return secp.utils.bytesToHex(data);
|
||||
return utils.bytesToHex(data);
|
||||
}
|
||||
case TLVEntryType.Kind: {
|
||||
return new Uint32Array(new Uint8Array(data.reverse()).buffer)[0];
|
||||
|
@ -1,4 +1,4 @@
|
||||
import * as secp from "@noble/secp256k1";
|
||||
import * as utils from "@noble/curves/abstract/utils";
|
||||
import { bech32 } from "bech32";
|
||||
|
||||
export function unwrap<T>(v: T | undefined | null): T {
|
||||
@ -17,7 +17,7 @@ export function hexToBech32(hrp: string, hex?: string) {
|
||||
}
|
||||
|
||||
try {
|
||||
const buf = secp.utils.hexToBytes(hex);
|
||||
const buf = utils.hexToBytes(hex);
|
||||
return bech32.encode(hrp, bech32.toWords(buf));
|
||||
} catch (e) {
|
||||
console.warn("Invalid hex", hex, e);
|
||||
|
Reference in New Issue
Block a user