Compare commits
5 Commits
266e9a892d
...
3af43d74d3
Author | SHA1 | Date |
---|---|---|
Keyan | 3af43d74d3 | |
ekzyis | 4cec369005 | |
ekzyis | d09f7c5427 | |
ekzyis | ec6124ca62 | |
ekzyis | 9f194c5d8e |
|
@ -122,3 +122,5 @@ Gudnessuche,issue,#1264,#1226,good-first-issue,,,,2k,everythingsatoshi@getalby.c
|
|||
aniskhalfallah,pr,#1289,,easy,,,,100k,aniskhalfallah@blink.sv,2024-08-12
|
||||
riccardobl,pr,#1293,#1142,medium,high,,,500k,rblb@getalby.com,2024-08-18
|
||||
tsmith123,pr,#1306,#832,medium,,,,250k,stickymarch60@walletofsatoshi.com,2024-08-20
|
||||
riccardobl,pr,#1311,#864,medium,high,,pending unrelated refactor,500k,rblb@getalby.com,2024-08-27
|
||||
brugeman,issue,#1311,#864,medium,high,,,50k,brugeman@stacker.news,2024-08-27
|
||||
|
|
|
|
@ -9,4 +9,6 @@ RUN apt-get update -y \
|
|||
&& apt-get install -y cmake \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
RUN cargo build --release && cargo install --path .
|
||||
RUN cargo build --release && cargo install --path .
|
||||
|
||||
COPY keys.json .
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"server_key":"4463b828d1950885de82b518efbfbe3dd6c35278e8ee5f6389721515b4c5e021","user_key":"0d1ef06059c9b1acf8c424cfe357c5ffe2d5f3594b9081695771a363ee716b67","sent_info":true}
|
25
lib/cln.js
25
lib/cln.js
|
@ -1,30 +1,11 @@
|
|||
import fetch from 'cross-fetch'
|
||||
import https from 'https'
|
||||
import crypto from 'crypto'
|
||||
import { HttpProxyAgent, HttpsProxyAgent } from '@/lib/proxy'
|
||||
import { TOR_REGEXP } from '@/lib/url'
|
||||
import { getAgent } from '@/lib/proxy'
|
||||
|
||||
export const createInvoice = async ({ socket, rune, cert, label, description, msats, expiry }) => {
|
||||
let protocol, agent
|
||||
const httpsAgentOptions = { ca: cert ? Buffer.from(cert, 'base64') : undefined }
|
||||
const isOnion = TOR_REGEXP.test(socket)
|
||||
if (isOnion) {
|
||||
// we support HTTP and HTTPS over Tor
|
||||
protocol = cert ? 'https:' : 'http:'
|
||||
// we need to use our Tor proxy to resolve onion addresses
|
||||
const proxyOptions = { proxy: process.env.TOR_PROXY }
|
||||
agent = protocol === 'https:'
|
||||
? new HttpsProxyAgent({ ...proxyOptions, ...httpsAgentOptions, rejectUnauthorized: false })
|
||||
: new HttpProxyAgent(proxyOptions)
|
||||
} else if (process.env.NODE_ENV === 'development' && !cert) {
|
||||
protocol = 'http:'
|
||||
} else {
|
||||
// we only support HTTPS over clearnet
|
||||
agent = new https.Agent(httpsAgentOptions)
|
||||
protocol = 'https:'
|
||||
}
|
||||
const agent = getAgent({ hostname: socket, cert })
|
||||
|
||||
const url = `${protocol}//${socket}/v1/invoice`
|
||||
const url = `${agent.protocol}//${socket}/v1/invoice`
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
|
@ -69,6 +69,9 @@ export class Relay {
|
|||
|
||||
try {
|
||||
return await withTimeout(checkPromise, timeout)
|
||||
} catch (err) {
|
||||
this.close()
|
||||
throw err
|
||||
} finally {
|
||||
clearInterval(interval)
|
||||
}
|
||||
|
@ -187,7 +190,11 @@ export function nostrZapDetails (zap) {
|
|||
async function publishNostrEvent (signedEvent, relayUrl) {
|
||||
const timeout = 3000
|
||||
const relay = await Relay.connect(relayUrl, { timeout })
|
||||
await relay.publish(signedEvent, { timeout })
|
||||
try {
|
||||
await relay.publish(signedEvent, { timeout })
|
||||
} finally {
|
||||
relay.close()
|
||||
}
|
||||
}
|
||||
|
||||
export async function crosspost (event, relays = DEFAULT_CROSSPOSTING_RELAYS) {
|
||||
|
|
26
lib/proxy.js
26
lib/proxy.js
|
@ -1,5 +1,6 @@
|
|||
import http from 'http'
|
||||
import https from 'https'
|
||||
import { TOR_REGEXP } from '@/lib/url'
|
||||
|
||||
// from https://github.com/delvedor/hpagent
|
||||
|
||||
|
@ -118,3 +119,28 @@ export class HttpsProxyAgent extends https.Agent {
|
|||
request.end()
|
||||
}
|
||||
}
|
||||
|
||||
export function getAgent ({ hostname, cert }) {
|
||||
let agent
|
||||
|
||||
const httpsAgentOptions = { ca: cert ? Buffer.from(cert, 'base64') : undefined }
|
||||
|
||||
const isOnion = TOR_REGEXP.test(hostname)
|
||||
if (isOnion) {
|
||||
// we support HTTP and HTTPS over Tor
|
||||
const protocol = cert ? 'https:' : 'http:'
|
||||
// we need to use our Tor proxy to resolve onion addresses
|
||||
const proxyOptions = { proxy: process.env.TOR_PROXY }
|
||||
agent = protocol === 'https:'
|
||||
? new HttpsProxyAgent({ ...proxyOptions, ...httpsAgentOptions, rejectUnauthorized: false })
|
||||
: new HttpProxyAgent(proxyOptions)
|
||||
return agent
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'development' && !cert) {
|
||||
return new http.Agent()
|
||||
}
|
||||
|
||||
// we only support HTTPS over clearnet
|
||||
return new https.Agent(httpsAgentOptions)
|
||||
}
|
||||
|
|
|
@ -163,11 +163,11 @@ This function must throw an error if the configuration was found to be invalid.
|
|||
|
||||
The `context` argument is an object. It makes the wallet logger for this wallet as returned by `useWalletLogger` available under `context.logger`. See [components/wallet-logger.js](../components/wallet-logger.js).
|
||||
|
||||
- `sendPayment: async (bolt11: string, config, context) => Promise<{ preimage: string }>`
|
||||
- `sendPayment: async (bolt11: string, config, context) => Promise<string>`
|
||||
|
||||
`sendPayment` will be called if a payment is required. Therefore, this function should implement the code to pay invoices from this wallet.
|
||||
|
||||
The first argument is the [BOLT11 payment request](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md). The `config` argument is the current configuration of this wallet (that was validated before). The `context` argument is the same as for `testSendPayment`.
|
||||
The first argument is the [BOLT11 payment request](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md). The `config` argument is the current configuration of this wallet (that was validated before). The `context` argument is the same as for `testSendPayment`. The function should return the preimage on payment success.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> As mentioned above, this file must exist for every wallet and at least reexport everything in index.js so make sure that the following line is included:
|
||||
|
|
|
@ -10,8 +10,7 @@ export async function testSendPayment ({ apiKey, currency }, { logger }) {
|
|||
|
||||
export async function sendPayment (bolt11, { apiKey, currency }) {
|
||||
const wallet = await getWallet(apiKey, currency)
|
||||
const preImage = await payInvoice(apiKey, wallet, bolt11)
|
||||
return { preImage }
|
||||
return await payInvoice(apiKey, wallet, bolt11)
|
||||
}
|
||||
|
||||
async function payInvoice (authToken, wallet, invoice) {
|
||||
|
|
|
@ -59,7 +59,7 @@ export function useWallet (name) {
|
|||
const hash = bolt11Tags(bolt11).payment_hash
|
||||
logger.info('sending payment:', `payment_hash=${hash}`)
|
||||
try {
|
||||
const { preimage } = await wallet.sendPayment(bolt11, config, { me, logger, status, showModal })
|
||||
const preimage = await wallet.sendPayment(bolt11, config, { me, logger, status, showModal })
|
||||
logger.ok('payment successful:', `payment_hash=${hash}`, `preimage=${preimage}`)
|
||||
} catch (err) {
|
||||
const message = err.message || err.toString?.()
|
||||
|
|
|
@ -19,8 +19,7 @@ export async function sendPayment (bolt11, { url, adminKey }) {
|
|||
throw new Error('No preimage')
|
||||
}
|
||||
|
||||
const preimage = checkResponse.preimage
|
||||
return { preimage }
|
||||
return checkResponse.preimage
|
||||
}
|
||||
|
||||
async function getWallet ({ url, adminKey, invoiceKey }) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { msatsToSats } from '@/lib/format'
|
||||
import { getAgent } from '@/lib/proxy'
|
||||
|
||||
export * from 'wallets/lnbits'
|
||||
|
||||
|
@ -27,7 +28,15 @@ export async function createInvoice (
|
|||
out: false
|
||||
})
|
||||
|
||||
const res = await fetch(url + path, { method: 'POST', headers, body })
|
||||
const hostname = url.replace(/^https?:\/\//, '')
|
||||
const agent = getAgent({ hostname })
|
||||
|
||||
const res = await fetch(`${agent.protocol}//${hostname}${path}`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
agent,
|
||||
body
|
||||
})
|
||||
if (!res.ok) {
|
||||
const errBody = await res.json()
|
||||
throw new Error(errBody.detail)
|
||||
|
|
|
@ -67,7 +67,7 @@ export async function sendPayment (bolt11, credentials, { logger }) {
|
|||
if (paymentError) throw new Error(paymentError)
|
||||
if (!preimage) throw new Error('No preimage in response')
|
||||
|
||||
return { preimage }
|
||||
return preimage
|
||||
} catch (err) {
|
||||
const msg = err.message || err.toString?.()
|
||||
if (msg.includes('invoice expired')) {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
The nwc string is printed in the nwc container logs on startup ...
|
||||
Use this NWC string to attach the wallet for payments:
|
||||
|
||||
Open the nwc container logs like this:
|
||||
```
|
||||
nostr+walletconnect://5224c44600696216595a70982ee7387a04bd66248b97fefb803f4ed6d4af1972?relay=wss%3A%2F%2Frelay.damus.io&secret=0d1ef06059c9b1acf8c424cfe357c5ffe2d5f3594b9081695771a363ee716b67
|
||||
```
|
||||
|
||||
```bash
|
||||
$ sndev logs nwc
|
||||
```
|
||||
This won't work for receives since it allows `pay_invoice`.
|
||||
|
||||
TODO: generate NWC string with only `make_invoice` as permission
|
||||
|
|
|
@ -35,5 +35,5 @@ export async function sendPayment (bolt11, { url, primaryPassword }) {
|
|||
throw new Error(payment.reason)
|
||||
}
|
||||
|
||||
return payment.paymentPreimage
|
||||
return preimage
|
||||
}
|
||||
|
|
|
@ -54,7 +54,11 @@ export async function nip57 ({ data: { hash }, boss, lnd, models }) {
|
|||
relays.map(async r => {
|
||||
const timeout = 1000
|
||||
const relay = await Relay.connect(r, { timeout })
|
||||
await relay.publish(e, { timeout })
|
||||
try {
|
||||
await relay.publish(e, { timeout })
|
||||
} finally {
|
||||
relay.close()
|
||||
}
|
||||
})
|
||||
)
|
||||
} catch (e) {
|
||||
|
|
Loading…
Reference in New Issue