Skip to content

Commit

Permalink
Alex/lightning docs (#97)
Browse files Browse the repository at this point in the history
* chore: update balance docs

* feat: add payInvoiceSync to lightning service

* feat: add createInvoice, payInvoice docs pages

* feat: add timeout param to waitForReceive

* feat: improve lightning docs

* chore: add changesets
  • Loading branch information
alexlwn123 authored Nov 10, 2024
1 parent 9468ef5 commit 21f94f9
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 21 deletions.
6 changes: 6 additions & 0 deletions .changeset/hot-shirts-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@fedimint/core-web': patch
---

Added optional timeout parameter to lightning.waitForReceive()
Added lightning.waitForSend()
5 changes: 4 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ packages/wasm-bundler/**
examples/bare-js/**
tmp/**
*.html
packages/*/dist/**
packages/*/dist/**
docs/core/FedimintWallet/BalanceService/subscribeBalance.md
docs/core/FedimintWallet/LightningService/createInvoice.md
docs/core/FedimintWallet/LightningService/payInvoice.md
16 changes: 7 additions & 9 deletions docs/.vitepress/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function getSidebar() {

const FedimintWalletSidebar = [
{
text: 'FedimintWallet',
text: 'Core',
link: '.',
base: '/core/FedimintWallet/',
items: [
Expand All @@ -50,10 +50,10 @@ const FedimintWalletSidebar = [
text: 'joinFederation()',
link: 'joinFederation',
},
{
text: 'initialize()',
link: 'initialize',
},
// {
// text: 'initialize()',
// link: 'initialize',
// },
{
text: 'isOpen()',
link: 'isOpen',
Expand All @@ -78,15 +78,13 @@ const FedimintWalletSidebar = [
text: 'LightningService',
base: '/core/FedimintWallet/LightningService/',
items: [
{ text: 'Docs TODO' },
// { text: 'payInvoice()', link: 'payInvoice' },
// { text: 'createInvoice()', link: 'createInvoice' },
{ text: 'payInvoice()', link: 'payInvoice' },
{ text: 'createInvoice()', link: 'createInvoice' },
// {
// text: 'createInvoiceWithGateway()',
// link: 'createInvoiceWithGateway',
// },
// { text: 'subscribeInvoiceStatus()', link: 'subscribeInvoiceStatus' },
// { text: 'subscribeLnPay()', link: 'subscribeLnPay' },
// { text: 'subscribeLnReceive()', link: 'subscribeLnReceive' },
// { text: 'listGateways()', link: 'listGateways' },
// { text: 'getGateway()', link: 'getGateway' },
Expand Down
5 changes: 2 additions & 3 deletions docs/core/FedimintWallet/BalanceService/getBalance.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ Get the current balance of the wallet.
import { FedimintWallet } from '@fedimint/core-web'

const wallet = new FedimintWallet()
wallet.open()
await wallet.open()

// ---cut---
const mSats = await wallet.balance.getBalance()
const mSats = await wallet.balance.getBalance() // [!code focus]

// 1000 mSats = 1 satoshi
```
9 changes: 4 additions & 5 deletions docs/core/FedimintWallet/BalanceService/subscribeBalance.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import { FedimintWallet } from '@fedimint/core-web'
const wallet = new FedimintWallet()
wallet.open()

// ---cut---
const unsubscribe = wallet.balance.subscribeBalance((mSats) => {
console.log('Balance updated:', mSats)
// 1000 mSats = 1 satoshi
})
const unsubscribe = wallet.balance.subscribeBalance((mSats) => { // [!code focus]
console.log('Balance updated:', mSats) // [!code focus]
// 1000 mSats = 1 satoshi // [!code focus]
}) // [!code focus]

// ...Cleanup Later
unsubscribe()
Expand Down
41 changes: 41 additions & 0 deletions docs/core/FedimintWallet/LightningService/createInvoice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Receive Lightning

### `lightning.createInvoice()`

Create a Lightning Invoice for a given amount. Returns a `CreateBolt11Response` object containing details about the created invoice.

You can use `subscribeLnReceive` to track the payment status and `waitForReceive` to wait for the payment to be received.

```ts twoslash
// @esModuleInterop
import { FedimintWallet } from '@fedimint/core-web'
import type { LnReceiveState } from '@fedimint/core-web'

const wallet = new FedimintWallet()
wallet.open()

const { operation_id, invoice } = await wallet.lightning.createInvoice( // [!code focus]
10_000, // msats // [!code focus]
'This is an invoice description', // [!code focus]
) // [!code focus]

console.log(operation_id) // operation id for the invoice
console.log(invoice) // bolt11 invoice

const unsubscribe = wallet.lightning.subscribeLnReceive( // [!code focus]
operation_id, // [!code focus]
(state: LnReceiveState) => console.log(state), // [!code focus]
(error: string) => console.error(error), // [!code focus]
) // [!code focus]

// ...Cleanup Later
unsubscribe()

try {
const timeoutMs = 10000
await wallet.lightning.waitForReceive(operation_id, timeoutMs) // [!code focus]
console.log('Payment Received!')
} catch (error) {
console.error(error) // Timeout waiting for payment
}
```
58 changes: 58 additions & 0 deletions docs/core/FedimintWallet/LightningService/payInvoice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Send Lightning

### `lightning.payInvoiceSync(invoice: string)`

Helper function to pay an invoice and resolve when the payment is confirmed or fails.

```ts twoslash
// @esModuleInterop
import { FedimintWallet } from '@fedimint/core-web'

const wallet = new FedimintWallet()
wallet.open()

const result = await wallet.lightning.payInvoiceSync( // [!code focus]
'lnbc...', // bolt11 invoice // [!code focus]
) // [!code focus]

if (result.success) {
console.log(result.data.preimage) // preimage of the settled payment
console.log(result.data.feeMsats) // fee paid in msats
}
```

### `lightning.payInvoice(invoice: string)`

Attempt to pay a lightning invoice. Returns an `OutgoingLightningPayment` object containing details about the in-flight payment.

You can use `subscribeLnPay` to track the payment status and `waitForPay` to wait for the payment to be confirmed or fail.

```ts twoslash
// @esModuleInterop
import { FedimintWallet } from '@fedimint/core-web'
import type { LnPayState } from '@fedimint/core-web'

const wallet = new FedimintWallet()
wallet.open()

const { contract_id, fee } = await wallet.lightning.payInvoice( // [!code focus]
'lnbc...', // bolt11 invoice // [!code focus]
) // [!code focus]

console.log(contract_id) // in flight lightning payment id

const unsubscribe = wallet.lightning.subscribeLnPay( // [!code focus]
contract_id, // [!code focus]
(state: LnPayState) => console.log(state), // State of the payment // [!code focus]
(error: string) => console.error(error), // [!code focus]
)

// ...Cleanup Later
unsubscribe()

const result = await wallet.lightning.waitForPay(contract_id) // [!code focus]

if (result.success) {
console.log(result.data.preimage) // preimage of the settled payment
}
```
79 changes: 76 additions & 3 deletions packages/core-web/src/services/LightningService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,43 @@ export class LightningService {
})
}

async payInvoiceSync(
invoice: string,
timeoutMs: number = 10000,
gatewayInfo?: GatewayInfo,
extraMeta?: JSONObject,
): Promise<
| { success: false }
| {
success: true
data: { feeMsats: number; preimage: string }
}
> {
return new Promise(async (resolve, reject) => {
const { contract_id, fee } = await this.payInvoice(
invoice,
gatewayInfo,
extraMeta,
)

const unsubscribe = this.subscribeLnPay(contract_id, (res) => {
if (typeof res !== 'string' && 'success' in res) {
clearTimeout(timeoutId)
unsubscribe()
resolve({
success: true,
data: { feeMsats: fee, preimage: res.success.preimage },
})
}
})

const timeoutId = setTimeout(() => {
unsubscribe()
reject(new Error('Timeout waiting for pay'))
}, timeoutMs)
})
}

// TODO: Document
subscribeLnClaim(
operationId: string,
Expand Down Expand Up @@ -122,6 +159,40 @@ export class LightningService {
return unsubscribe
}

async waitForPay(operationId: string): Promise<
| { success: false }
| {
success: true
data: { preimage: string }
}
> {
return new Promise((resolve, reject) => {
let unsubscribe: () => void
const timeoutId = setTimeout(() => {
reject(new Error('Timeout waiting for receive'))
}, 15000)

unsubscribe = this.subscribeLnPay(
operationId,
(res) => {
if (typeof res !== 'string' && 'success' in res) {
clearTimeout(timeoutId)
unsubscribe()
resolve({
success: true,
data: { preimage: res.success.preimage },
})
}
},
(error) => {
clearTimeout(timeoutId)
unsubscribe()
reject(error)
},
)
})
}

// TODO: Document
subscribeLnReceive(
operationId: string,
Expand All @@ -139,13 +210,15 @@ export class LightningService {
return unsubscribe
}

// TODO: Document
async waitForReceive(operationId: string): Promise<LnReceiveState> {
async waitForReceive(
operationId: string,
timeoutMs: number = 15000,
): Promise<LnReceiveState> {
return new Promise((resolve, reject) => {
let unsubscribe: () => void
const timeoutId = setTimeout(() => {
reject(new Error('Timeout waiting for receive'))
}, 15000)
}, timeoutMs)

unsubscribe = this.subscribeLnReceive(
operationId,
Expand Down

0 comments on commit 21f94f9

Please sign in to comment.