chore(nostr-client): move dev scripts to dev/ folder
Move 9 development/testing .mjs scripts out of the package root into dev/ to keep the published package clean. Update relative imports and dev.sh reference. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
01bac04cdf
commit
5448a620a9
10 changed files with 3 additions and 3 deletions
182
packages/nostr-client/dev/test-debit.mjs
Normal file
182
packages/nostr-client/dev/test-debit.mjs
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* Test CLINK Debit flow
|
||||
*
|
||||
* This simulates what ShockWallet does when scanning an ndebit:
|
||||
* 1. Decode the ndebit to get pubkey, relay, pointer
|
||||
* 2. Create a bolt11 invoice (we'll get one from Alice)
|
||||
* 3. Send Kind 21002 debit request to Lightning.Pub
|
||||
* 4. Wait for payment response
|
||||
*/
|
||||
|
||||
import { Relay } from 'nostr-tools/relay'
|
||||
import { finalizeEvent, getPublicKey } from 'nostr-tools'
|
||||
import { nip44 } from 'nostr-tools'
|
||||
import { bech32 } from '@scure/base'
|
||||
import { randomBytes } from 'crypto'
|
||||
|
||||
// Generate a random keypair for this test (simulates ShockWallet)
|
||||
const WALLET_PRIVATE_KEY = randomBytes(32)
|
||||
const WALLET_PUBLIC_KEY = getPublicKey(WALLET_PRIVATE_KEY)
|
||||
|
||||
// The ndebit to test
|
||||
const NDEBIT = process.argv[2]
|
||||
// The bolt11 invoice to be paid
|
||||
const BOLT11 = process.argv[3]
|
||||
|
||||
if (!NDEBIT || !BOLT11) {
|
||||
console.log('Usage: node test-debit.mjs <ndebit> <bolt11>')
|
||||
console.log('')
|
||||
console.log('Example:')
|
||||
console.log(' # First create an invoice on Alice:')
|
||||
console.log(' docker exec lamassu-lnd-alice lncli --network=regtest addinvoice --amt 1000')
|
||||
console.log('')
|
||||
console.log(' # Then test the debit:')
|
||||
console.log(' node test-debit.mjs ndebit1... lnbcrt...')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
function decodeNdebit(ndebit) {
|
||||
const { prefix, words } = bech32.decode(ndebit, 5000)
|
||||
if (prefix !== 'ndebit') throw new Error('Invalid ndebit prefix')
|
||||
|
||||
const data = new Uint8Array(bech32.fromWords(words))
|
||||
|
||||
let pubkey, relay, pointer
|
||||
let offset = 0
|
||||
|
||||
while (offset < data.length) {
|
||||
const type = data[offset]
|
||||
const length = data[offset + 1]
|
||||
const value = data.slice(offset + 2, offset + 2 + length)
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
pubkey = Buffer.from(value).toString('hex')
|
||||
break
|
||||
case 1:
|
||||
relay = new TextDecoder().decode(value)
|
||||
break
|
||||
case 2:
|
||||
pointer = new TextDecoder().decode(value)
|
||||
break
|
||||
}
|
||||
|
||||
offset += 2 + length
|
||||
}
|
||||
|
||||
return { pubkey, relay, pointer }
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('=== CLINK Debit Test ===')
|
||||
console.log('')
|
||||
console.log('Test wallet pubkey:', WALLET_PUBLIC_KEY)
|
||||
console.log('')
|
||||
|
||||
// Decode ndebit
|
||||
const debit = decodeNdebit(NDEBIT)
|
||||
console.log('Decoded ndebit:')
|
||||
console.log(' Pubkey:', debit.pubkey)
|
||||
console.log(' Relay:', debit.relay)
|
||||
console.log(' Pointer:', debit.pointer || '(none)')
|
||||
console.log('')
|
||||
|
||||
// Connect to relay (override Docker internal hostnames with localhost for local testing)
|
||||
const relayUrl = debit.relay
|
||||
.replace('host.docker.internal', 'localhost')
|
||||
.replace('ws://strfry:', 'ws://localhost:')
|
||||
console.log('Connecting to relay:', relayUrl)
|
||||
const relay = await Relay.connect(relayUrl)
|
||||
console.log('Connected!')
|
||||
console.log('')
|
||||
|
||||
// Build debit request payload
|
||||
const requestPayload = {
|
||||
pointer: debit.pointer,
|
||||
bolt11: BOLT11,
|
||||
}
|
||||
|
||||
console.log('Request payload:', JSON.stringify(requestPayload, null, 2))
|
||||
console.log('')
|
||||
|
||||
// Encrypt with NIP-44
|
||||
const conversationKey = nip44.getConversationKey(WALLET_PRIVATE_KEY, debit.pubkey)
|
||||
const encryptedContent = nip44.encrypt(JSON.stringify(requestPayload), conversationKey)
|
||||
|
||||
// Create Kind 21002 event
|
||||
const event = finalizeEvent(
|
||||
{
|
||||
kind: 21002,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags: [
|
||||
['p', debit.pubkey],
|
||||
['clink_version', '1'],
|
||||
],
|
||||
content: encryptedContent,
|
||||
},
|
||||
WALLET_PRIVATE_KEY
|
||||
)
|
||||
|
||||
console.log('Publishing debit request (event id:', event.id.substring(0, 16) + '...)...')
|
||||
|
||||
// Subscribe to responses
|
||||
let responseReceived = false
|
||||
const sub = relay.subscribe(
|
||||
[
|
||||
{
|
||||
kinds: [21002],
|
||||
authors: [debit.pubkey],
|
||||
'#p': [WALLET_PUBLIC_KEY],
|
||||
'#e': [event.id],
|
||||
since: Math.floor(Date.now() / 1000) - 5,
|
||||
},
|
||||
],
|
||||
{
|
||||
onevent(evt) {
|
||||
console.log('')
|
||||
console.log('Got response event:', evt.id.substring(0, 16) + '...')
|
||||
try {
|
||||
const decrypted = nip44.decrypt(evt.content, conversationKey)
|
||||
const response = JSON.parse(decrypted)
|
||||
console.log('Response:', JSON.stringify(response, null, 2))
|
||||
|
||||
if (response.res === 'ok') {
|
||||
console.log('')
|
||||
console.log('✅ DEBIT SUCCESS!')
|
||||
if (response.preimage) {
|
||||
console.log('Preimage:', response.preimage)
|
||||
}
|
||||
} else if (response.res === 'GFY') {
|
||||
console.log('')
|
||||
console.log('❌ DEBIT FAILED:', response.error)
|
||||
}
|
||||
|
||||
responseReceived = true
|
||||
} catch (err) {
|
||||
console.log('Failed to decrypt:', err.message)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Publish request
|
||||
await relay.publish(event)
|
||||
console.log('Request published, waiting for response...')
|
||||
|
||||
// Wait for response
|
||||
for (let i = 0; i < 30; i++) {
|
||||
await new Promise((r) => setTimeout(r, 1000))
|
||||
if (responseReceived) break
|
||||
if (i % 5 === 4) console.log('Still waiting... (' + (i + 1) + 's)')
|
||||
}
|
||||
|
||||
if (!responseReceived) {
|
||||
console.log('')
|
||||
console.log('❌ No response received within timeout')
|
||||
}
|
||||
|
||||
sub.close()
|
||||
relay.close()
|
||||
}
|
||||
|
||||
main().catch(console.error)
|
||||
Loading…
Add table
Add a link
Reference in a new issue