mirror of
https://github.com/nbd-wtf/nostr-tools.git
synced 2025-12-08 16:28:49 +00:00
add helper functions for nip-47
This commit is contained in:
1
event.ts
1
event.ts
@@ -31,6 +31,7 @@ export enum Kind {
|
|||||||
Zap = 9735,
|
Zap = 9735,
|
||||||
RelayList = 10002,
|
RelayList = 10002,
|
||||||
ClientAuth = 22242,
|
ClientAuth = 22242,
|
||||||
|
NwcRequest = 23194,
|
||||||
HttpAuth = 27235,
|
HttpAuth = 27235,
|
||||||
ProfileBadge = 30008,
|
ProfileBadge = 30008,
|
||||||
BadgeDefinition = 30009,
|
BadgeDefinition = 30009,
|
||||||
|
|||||||
1
index.ts
1
index.ts
@@ -20,6 +20,7 @@ export * as nip28 from './nip28.ts'
|
|||||||
export * as nip39 from './nip39.ts'
|
export * as nip39 from './nip39.ts'
|
||||||
export * as nip42 from './nip42.ts'
|
export * as nip42 from './nip42.ts'
|
||||||
export * as nip44 from './nip44.ts'
|
export * as nip44 from './nip44.ts'
|
||||||
|
export * as nip47 from './nip47.ts'
|
||||||
export * as nip57 from './nip57.ts'
|
export * as nip57 from './nip57.ts'
|
||||||
export * as nip98 from './nip98.ts'
|
export * as nip98 from './nip98.ts'
|
||||||
|
|
||||||
|
|||||||
83
nip47.test.ts
Normal file
83
nip47.test.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import {makeNwcRequestEvent, parseConnectionString} from './nip47'
|
||||||
|
import {Kind} from './event'
|
||||||
|
import {decrypt} from './nip04.ts'
|
||||||
|
import crypto from 'node:crypto'
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
globalThis.crypto = crypto
|
||||||
|
|
||||||
|
describe('parseConnectionString', () => {
|
||||||
|
test('returns pubkey, relay, and secret if connection string is valid', () => {
|
||||||
|
const connectionString =
|
||||||
|
'nostr+walletconnect:b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c'
|
||||||
|
const {pubkey, relay, secret} = parseConnectionString(connectionString)
|
||||||
|
|
||||||
|
expect(pubkey).toBe(
|
||||||
|
'b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4'
|
||||||
|
)
|
||||||
|
expect(relay).toBe('wss://relay.damus.io')
|
||||||
|
expect(secret).toBe(
|
||||||
|
'71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('throws an error if no pubkey in connection string', async () => {
|
||||||
|
const connectionString =
|
||||||
|
'nostr+walletconnect:relay=wss%3A%2F%2Frelay.damus.io&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c'
|
||||||
|
|
||||||
|
expect(() => parseConnectionString(connectionString)).toThrow(
|
||||||
|
'invalid connection string'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('throws an error if no relay in connection string', async () => {
|
||||||
|
const connectionString =
|
||||||
|
'nostr+walletconnect:b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c'
|
||||||
|
|
||||||
|
expect(() => parseConnectionString(connectionString)).toThrow(
|
||||||
|
'invalid connection string'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('throws an error if no secret in connection string', async () => {
|
||||||
|
const connectionString =
|
||||||
|
'nostr+walletconnect:b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io'
|
||||||
|
|
||||||
|
expect(() => parseConnectionString(connectionString)).toThrow(
|
||||||
|
'invalid connection string'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('makeNwcRequestEvent', () => {
|
||||||
|
test('returns a valid NWC request event', async () => {
|
||||||
|
const pubkey =
|
||||||
|
'b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4'
|
||||||
|
const secret =
|
||||||
|
'71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c'
|
||||||
|
const invoice =
|
||||||
|
'lnbc210n1pjdgyvupp5x43awdarnfd4mdlsklelux0nyckwfu5c708ykuet8vcjnjp3rnpqdqu2askcmr9wssx7e3q2dshgmmndp5scqzzsxqyz5vqsp52l7y9peq9pka3vd3j7aps7gjnalsmy46ndj2mlkz00dltjgqfumq9qyyssq5fasr5dxed8l4qjfnqq48a02jzss3asf8sly7sfaqtr9w3yu2q9spsxhghs3y9aqdf44zkrrg9jjjdg6amade4h0hulllkwk33eqpucp6d5jye'
|
||||||
|
const timeBefore = Date.now() / 1000
|
||||||
|
const result = await makeNwcRequestEvent({
|
||||||
|
pubkey,
|
||||||
|
secret,
|
||||||
|
invoice
|
||||||
|
})
|
||||||
|
const timeAfter = Date.now() / 1000
|
||||||
|
expect(result.kind).toBe(Kind.NwcRequest)
|
||||||
|
expect(result.created_at).toBeGreaterThan(timeBefore)
|
||||||
|
expect(result.created_at).toBeLessThan(timeAfter)
|
||||||
|
expect(await decrypt(secret, pubkey, result.content)).toEqual(
|
||||||
|
JSON.stringify({
|
||||||
|
method: 'pay_invoice',
|
||||||
|
params: {
|
||||||
|
invoice
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
expect(result.tags).toEqual([['p', pubkey]])
|
||||||
|
expect(result.id).toEqual(expect.any(String))
|
||||||
|
expect(result.sig).toEqual(expect.any(String))
|
||||||
|
})
|
||||||
|
})
|
||||||
46
nip47.ts
Normal file
46
nip47.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import {finishEvent} from './event.ts'
|
||||||
|
import {encrypt} from './nip04.ts'
|
||||||
|
import {Kind} from './event'
|
||||||
|
|
||||||
|
export function parseConnectionString(connectionString: string) {
|
||||||
|
const {pathname, searchParams} = new URL(connectionString)
|
||||||
|
const pubkey = pathname
|
||||||
|
const relay = searchParams.get('relay')
|
||||||
|
const secret = searchParams.get('secret')
|
||||||
|
|
||||||
|
if (!pubkey || !relay || !secret) {
|
||||||
|
throw new Error('invalid connection string')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {pubkey, relay, secret}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function makeNwcRequestEvent({
|
||||||
|
pubkey,
|
||||||
|
secret,
|
||||||
|
invoice
|
||||||
|
}: {
|
||||||
|
pubkey: string
|
||||||
|
secret: string
|
||||||
|
invoice: string
|
||||||
|
}) {
|
||||||
|
const content = {
|
||||||
|
method: 'pay_invoice',
|
||||||
|
params: {
|
||||||
|
invoice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const encryptedContent = await encrypt(
|
||||||
|
secret,
|
||||||
|
pubkey,
|
||||||
|
JSON.stringify(content)
|
||||||
|
)
|
||||||
|
const eventTemplate = {
|
||||||
|
kind: Kind.NwcRequest,
|
||||||
|
created_at: Math.round(Date.now() / 1000),
|
||||||
|
content: encryptedContent,
|
||||||
|
tags: [['p', pubkey]]
|
||||||
|
}
|
||||||
|
|
||||||
|
return finishEvent(eventTemplate, secret)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user