bitspire/packages/nostr-client/dev/generate-ndebit.mjs
Patrick Mulligan 5448a620a9 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>
2026-02-16 17:48:49 -05:00

84 lines
2.1 KiB
JavaScript

/**
* Generate an ndebit string for ShockWallet to scan
*
* Usage: node generate-ndebit.mjs [pointer]
*
* The ndebit allows ShockWallet to send an invoice that Lightning.Pub will pay.
* This is the LNURL-withdraw equivalent for CLINK.
*/
import { bech32 } from '@scure/base'
const LIGHTNING_PUB_PUBKEY =
process.env.LIGHTNING_PUB_PUBKEY ||
'4a72e400a254bf74a70cc711ab97e461b8d4fd9738b1ac3b5194cdeb3192ab91'
const RELAY_URL = process.env.NOSTR_RELAY_URL || 'wss://strfry.shock.network'
const POINTER = process.argv[2] || 'atm-cashin-' + Date.now()
function hexToBytes(hex) {
const bytes = new Uint8Array(hex.length / 2)
for (let i = 0; i < hex.length; i += 2) {
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16)
}
return bytes
}
function encodeTLV(tlv) {
const entries = []
Object.entries(tlv)
.reverse()
.forEach(([t, vs]) => {
vs.forEach((v) => {
const entry = new Uint8Array(v.length + 2)
entry.set([parseInt(t)], 0)
entry.set([v.length], 1)
entry.set(v, 2)
entries.push(entry)
})
})
// Concatenate all entries
const totalLength = entries.reduce((sum, e) => sum + e.length, 0)
const result = new Uint8Array(totalLength)
let offset = 0
for (const entry of entries) {
result.set(entry, offset)
offset += entry.length
}
return result
}
function ndebitEncode(debit) {
const encoder = new TextEncoder()
const tlv = {
0: [hexToBytes(debit.pubkey)],
1: [encoder.encode(debit.relay)],
}
if (debit.pointer) {
tlv[2] = [encoder.encode(debit.pointer)]
}
const data = encodeTLV(tlv)
const words = bech32.toWords(data)
return bech32.encode('ndebit', words, 5000)
}
// Generate ndebit
const ndebit = ndebitEncode({
pubkey: LIGHTNING_PUB_PUBKEY,
relay: RELAY_URL,
pointer: POINTER,
})
console.log('=== NDEBIT for ShockWallet ===')
console.log('')
console.log('Pubkey:', LIGHTNING_PUB_PUBKEY)
console.log('Relay:', RELAY_URL)
console.log('Pointer:', POINTER)
console.log('')
console.log('ndebit string:')
console.log(ndebit)
console.log('')
console.log('ShockWallet should scan this QR code to receive sats from the ATM.')