@fedimint/core-web 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FedimintWallet.d.ts +34 -62
- package/dist/FedimintWallet.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/BalanceService.d.ts +8 -0
- package/dist/services/BalanceService.d.ts.map +1 -0
- package/dist/services/FederationService.d.ts +12 -0
- package/dist/services/FederationService.d.ts.map +1 -0
- package/dist/services/LightningService.d.ts +17 -0
- package/dist/services/LightningService.d.ts.map +1 -0
- package/dist/services/MintService.d.ts +15 -0
- package/dist/services/MintService.d.ts.map +1 -0
- package/dist/services/RecoveryService.d.ts +13 -0
- package/dist/services/RecoveryService.d.ts.map +1 -0
- package/dist/services/index.d.ts +6 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/worker/WorkerClient.d.ts +41 -0
- package/dist/worker/WorkerClient.d.ts.map +1 -0
- package/dist/worker/index.d.ts +2 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/node_modules/{fedimint-client-wasm → @fedimint/fedimint-client-wasm}/package.json +3 -6
- package/package.json +9 -7
- package/src/FedimintWallet.test.ts +74 -0
- package/src/FedimintWallet.ts +77 -465
- package/src/services/BalanceService.ts +24 -0
- package/src/services/FederationService.ts +32 -0
- package/src/services/LightningService.ts +128 -0
- package/src/services/MintService.ts +93 -0
- package/src/services/RecoveryService.ts +26 -0
- package/src/services/index.ts +5 -0
- package/src/worker/WorkerClient.ts +190 -0
- package/src/worker/index.ts +1 -0
- package/src/{worker.js → worker/worker.js} +14 -9
- package/wasm/fedimint_client_wasm.d.ts +0 -49
- package/wasm/fedimint_client_wasm.js +0 -4
- package/wasm/fedimint_client_wasm_bg.js +0 -1411
- package/wasm/fedimint_client_wasm_bg.wasm +0 -0
- package/wasm/fedimint_client_wasm_bg.wasm.d.ts +0 -110
- package/wasm/package.json +0 -26
- /package/node_modules/{fedimint-client-wasm → @fedimint/fedimint-client-wasm}/fedimint_client_wasm.d.ts +0 -0
- /package/node_modules/{fedimint-client-wasm → @fedimint/fedimint-client-wasm}/fedimint_client_wasm.js +0 -0
- /package/node_modules/{fedimint-client-wasm → @fedimint/fedimint-client-wasm}/fedimint_client_wasm_bg.js +0 -0
- /package/node_modules/{fedimint-client-wasm → @fedimint/fedimint-client-wasm}/fedimint_client_wasm_bg.wasm +0 -0
package/src/FedimintWallet.ts
CHANGED
|
@@ -1,90 +1,89 @@
|
|
|
1
|
+
import { WorkerClient } from './worker/WorkerClient'
|
|
1
2
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
StreamResult,
|
|
9
|
-
StreamError,
|
|
10
|
-
CreateBolt11Response,
|
|
11
|
-
ModuleKind,
|
|
12
|
-
GatewayInfo,
|
|
13
|
-
CancelFunction,
|
|
14
|
-
} from './types/wallet'
|
|
3
|
+
BalanceService,
|
|
4
|
+
MintService,
|
|
5
|
+
LightningService,
|
|
6
|
+
FederationService,
|
|
7
|
+
RecoveryService,
|
|
8
|
+
} from './services'
|
|
15
9
|
|
|
16
10
|
const DEFAULT_CLIENT_NAME = 'fm-default' as const
|
|
17
11
|
|
|
18
12
|
export class FedimintWallet {
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
private client: WorkerClient
|
|
14
|
+
|
|
15
|
+
public balance: BalanceService
|
|
16
|
+
public mint: MintService
|
|
17
|
+
public lightning: LightningService
|
|
18
|
+
public federation: FederationService
|
|
19
|
+
public recovery: RecoveryService
|
|
20
|
+
|
|
21
|
+
private openPromise: Promise<void> | null = null
|
|
22
22
|
private resolveOpen: () => void = () => {}
|
|
23
23
|
private _isOpen: boolean = false
|
|
24
|
-
private requestCounter: number = 0
|
|
25
|
-
private requestCallbacks: Map<number, (value: any) => void> = new Map()
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new instance of FedimintWallet.
|
|
27
|
+
*
|
|
28
|
+
* @description
|
|
29
|
+
* This constructor initializes a FedimintWallet instance, which manages communication
|
|
30
|
+
* with a Web Worker. The Web Worker is responsible for running WebAssembly code that
|
|
31
|
+
* handles the core Fedimint Client operations.
|
|
32
|
+
*
|
|
33
|
+
* (default) When not in lazy mode, the constructor immediately initializes the
|
|
34
|
+
* Web Worker and begins loading the WebAssembly module in the background. This
|
|
35
|
+
* allows for faster subsequent operations but may increase initial load time.
|
|
36
|
+
*
|
|
37
|
+
* In lazy mode, the Web Worker and WebAssembly initialization are deferred until
|
|
38
|
+
* the first operation that requires them, reducing initial overhead at the cost
|
|
39
|
+
* of a slight delay on the first operation.
|
|
40
|
+
*
|
|
41
|
+
* @param {boolean} lazy - If true, delays Web Worker and WebAssembly initialization
|
|
42
|
+
* until needed. Default is false.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // Create a wallet with immediate initialization
|
|
46
|
+
* const wallet = new FedimintWallet();
|
|
47
|
+
* wallet.open();
|
|
48
|
+
*
|
|
49
|
+
* // Create a wallet with lazy initialization
|
|
50
|
+
* const lazyWallet = new FedimintWallet(true);
|
|
51
|
+
* // Some time later...
|
|
52
|
+
* lazyWallet.initialize();
|
|
53
|
+
* lazyWallet.open();
|
|
54
|
+
*/
|
|
55
|
+
constructor(lazy: boolean = false) {
|
|
28
56
|
this.openPromise = new Promise((resolve) => {
|
|
29
57
|
this.resolveOpen = resolve
|
|
30
58
|
})
|
|
31
|
-
|
|
32
|
-
this.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return this.openPromise
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private getNextRequestId(): number {
|
|
41
|
-
return ++this.requestCounter
|
|
42
|
-
}
|
|
59
|
+
this.client = new WorkerClient()
|
|
60
|
+
this.mint = new MintService(this.client)
|
|
61
|
+
this.lightning = new LightningService(this.client)
|
|
62
|
+
this.balance = new BalanceService(this.client)
|
|
63
|
+
this.federation = new FederationService(this.client)
|
|
64
|
+
this.recovery = new RecoveryService(this.client)
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return new Promise((resolve, reject) => {
|
|
48
|
-
const requestId = this.getNextRequestId()
|
|
49
|
-
this.requestCallbacks.set(requestId, (data) => {
|
|
50
|
-
this.requestCallbacks.delete(requestId)
|
|
51
|
-
if (data.data) resolve(data.data)
|
|
52
|
-
else if (data.error) reject(data.error)
|
|
53
|
-
})
|
|
54
|
-
try {
|
|
55
|
-
this.worker!.postMessage({ type, payload, requestId })
|
|
56
|
-
} catch (e) {
|
|
57
|
-
reject(e)
|
|
58
|
-
}
|
|
59
|
-
})
|
|
66
|
+
if (!lazy) {
|
|
67
|
+
this.initialize()
|
|
68
|
+
}
|
|
60
69
|
}
|
|
61
70
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (this.initPromise) return this.initPromise
|
|
65
|
-
this.worker = new Worker(new URL('./worker.js', import.meta.url))
|
|
66
|
-
this.worker.onmessage = this.handleWorkerMessage.bind(this)
|
|
67
|
-
this.initPromise = this.sendSingleMessage('init')
|
|
68
|
-
return this.initPromise
|
|
71
|
+
async initialize() {
|
|
72
|
+
await this.client.initialize()
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
// TODO: Handle errors... maybe have another callbacks list for errors?
|
|
75
|
-
if (streamCallback) {
|
|
76
|
-
streamCallback(data) // {data: something} OR {error: something}
|
|
77
|
-
}
|
|
75
|
+
async waitForOpen() {
|
|
76
|
+
if (this._isOpen) return Promise.resolve()
|
|
77
|
+
return this.openPromise
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
async open(clientName: string = DEFAULT_CLIENT_NAME) {
|
|
81
|
-
await this.initialize()
|
|
81
|
+
await this.client.initialize()
|
|
82
82
|
// TODO: Determine if this should be safe or throw
|
|
83
|
-
if (this._isOpen)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const { success } = await this.sendSingleMessage('open', { clientName })
|
|
83
|
+
if (this._isOpen) throw new Error('The FedimintWallet is already open.')
|
|
84
|
+
const { success } = await this.client.sendSingleMessage('open', {
|
|
85
|
+
clientName,
|
|
86
|
+
})
|
|
88
87
|
if (success) {
|
|
89
88
|
this._isOpen = !!success
|
|
90
89
|
this.resolveOpen()
|
|
@@ -96,234 +95,20 @@ export class FedimintWallet {
|
|
|
96
95
|
inviteCode: string,
|
|
97
96
|
clientName: string = DEFAULT_CLIENT_NAME,
|
|
98
97
|
) {
|
|
99
|
-
await this.initialize()
|
|
98
|
+
await this.client.initialize()
|
|
100
99
|
// TODO: Determine if this should be safe or throw
|
|
101
100
|
if (this._isOpen)
|
|
102
101
|
throw new Error(
|
|
103
|
-
'
|
|
102
|
+
'The FedimintWallet is already open. You can only call `joinFederation` on closed clients.',
|
|
104
103
|
)
|
|
105
|
-
const response = await this.sendSingleMessage('join', {
|
|
104
|
+
const response = await this.client.sendSingleMessage('join', {
|
|
106
105
|
inviteCode,
|
|
107
106
|
clientName,
|
|
108
107
|
})
|
|
109
|
-
if (response.success)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
* @summary Initiates an RPC stream with the specified module and method.
|
|
114
|
-
*
|
|
115
|
-
* @description
|
|
116
|
-
* This function sets up an RPC stream by sending a request to a worker and
|
|
117
|
-
* handling responses asynchronously. It ensures that unsubscription is handled
|
|
118
|
-
* correctly, even if the unsubscribe function is called before the subscription
|
|
119
|
-
* is fully established, by deferring the unsubscription attempt using `setTimeout`.
|
|
120
|
-
*
|
|
121
|
-
* The function operates in a non-blocking manner, leveraging Promises to manage
|
|
122
|
-
* asynchronous operations and callbacks to handle responses.
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* @template Response - The expected type of the successful response.
|
|
126
|
-
* @template Body - The type of the request body.
|
|
127
|
-
* @param module - The module kind to interact with.
|
|
128
|
-
* @param method - The method name to invoke on the module.
|
|
129
|
-
* @param body - The request payload.
|
|
130
|
-
* @param onSuccess - Callback invoked with the response data on success.
|
|
131
|
-
* @param onError - Callback invoked with error information if an error occurs.
|
|
132
|
-
* @param onEnd - Optional callback invoked when the stream ends.
|
|
133
|
-
* @returns A function that can be called to cancel the subscription.
|
|
134
|
-
*
|
|
135
|
-
*/
|
|
136
|
-
private _rpcStream<
|
|
137
|
-
Response extends JSONValue = JSONValue,
|
|
138
|
-
Body extends JSONValue = JSONValue,
|
|
139
|
-
>(
|
|
140
|
-
module: ModuleKind,
|
|
141
|
-
method: string,
|
|
142
|
-
body: Body,
|
|
143
|
-
onSuccess: (res: Response) => void,
|
|
144
|
-
onError: (res: StreamError['error']) => void,
|
|
145
|
-
onEnd: () => void = () => {},
|
|
146
|
-
): CancelFunction {
|
|
147
|
-
const requestId = this.getNextRequestId()
|
|
148
|
-
|
|
149
|
-
let unsubscribe: (value: void) => void = () => {}
|
|
150
|
-
let isSubscribed = false
|
|
151
|
-
|
|
152
|
-
const unsubscribePromise = new Promise<void>((resolve) => {
|
|
153
|
-
unsubscribe = () => {
|
|
154
|
-
if (isSubscribed) {
|
|
155
|
-
// If already subscribed, resolve immediately to trigger unsubscription
|
|
156
|
-
resolve()
|
|
157
|
-
} else {
|
|
158
|
-
// If not yet subscribed, defer the unsubscribe attempt to the next event loop tick
|
|
159
|
-
// This ensures that subscription setup has time to complete
|
|
160
|
-
setTimeout(() => unsubscribe(), 0)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
// Initiate the inner RPC stream setup asynchronously
|
|
166
|
-
this._rpcStreamInner(
|
|
167
|
-
requestId,
|
|
168
|
-
module,
|
|
169
|
-
method,
|
|
170
|
-
body,
|
|
171
|
-
onSuccess,
|
|
172
|
-
onError,
|
|
173
|
-
onEnd,
|
|
174
|
-
unsubscribePromise,
|
|
175
|
-
).then(() => {
|
|
176
|
-
isSubscribed = true
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
return unsubscribe
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private async _rpcStreamInner<
|
|
183
|
-
Response extends JSONValue = JSONValue,
|
|
184
|
-
Body extends JSONValue = JSONValue,
|
|
185
|
-
>(
|
|
186
|
-
requestId: number,
|
|
187
|
-
module: ModuleKind,
|
|
188
|
-
method: string,
|
|
189
|
-
body: Body,
|
|
190
|
-
onSuccess: (res: Response) => void,
|
|
191
|
-
onError: (res: StreamError['error']) => void,
|
|
192
|
-
onEnd: () => void = () => {},
|
|
193
|
-
unsubscribePromise: Promise<void>,
|
|
194
|
-
// Unsubscribe function
|
|
195
|
-
): Promise<void> {
|
|
196
|
-
await this.openPromise
|
|
197
|
-
if (!this.worker || !this._isOpen)
|
|
198
|
-
throw new Error('FedimintWallet is not open')
|
|
199
|
-
|
|
200
|
-
this.requestCallbacks.set(requestId, (response: StreamResult<Response>) => {
|
|
201
|
-
if (response.error !== undefined) {
|
|
202
|
-
onError(response.error)
|
|
203
|
-
} else if (response.data !== undefined) {
|
|
204
|
-
onSuccess(response.data)
|
|
205
|
-
} else if (response.end !== undefined) {
|
|
206
|
-
this.requestCallbacks.delete(requestId)
|
|
207
|
-
onEnd()
|
|
208
|
-
}
|
|
209
|
-
})
|
|
210
|
-
this.worker.postMessage({
|
|
211
|
-
type: 'rpc',
|
|
212
|
-
payload: { module, method, body },
|
|
213
|
-
requestId,
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
unsubscribePromise.then(() => {
|
|
217
|
-
console.trace('UNSUBSCRIBING', requestId)
|
|
218
|
-
this.worker?.postMessage({
|
|
219
|
-
type: 'unsubscribe',
|
|
220
|
-
requestId,
|
|
221
|
-
})
|
|
222
|
-
this.requestCallbacks.delete(requestId)
|
|
223
|
-
})
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
private async _rpcSingle<Response extends JSONValue = JSONValue>(
|
|
227
|
-
module: ModuleKind,
|
|
228
|
-
method: string,
|
|
229
|
-
body: JSONValue,
|
|
230
|
-
): Promise<Response> {
|
|
231
|
-
return new Promise((resolve, reject) => {
|
|
232
|
-
this._rpcStream<Response>(module, method, body, resolve, reject)
|
|
233
|
-
})
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
async getBalance(): Promise<number> {
|
|
237
|
-
return await this._rpcSingle('', 'get_balance', {})
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Mint module methods
|
|
241
|
-
|
|
242
|
-
async redeemEcash(notes: string): Promise<void> {
|
|
243
|
-
await this._rpcSingle('mint', 'reissue_external_notes', {
|
|
244
|
-
oob_notes: notes, // "out of band notes"
|
|
245
|
-
extra_meta: null,
|
|
246
|
-
})
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
async reissueExternalNotes(
|
|
250
|
-
oobNotes: string,
|
|
251
|
-
extraMeta: JSONObject,
|
|
252
|
-
): Promise<string> {
|
|
253
|
-
return await this._rpcSingle('mint', 'reissue_external_notes', {
|
|
254
|
-
oob_notes: oobNotes,
|
|
255
|
-
extra_meta: extraMeta,
|
|
256
|
-
})
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
subscribeReissueExternalNotes(
|
|
260
|
-
operationId: string,
|
|
261
|
-
onSuccess: (state: JSONValue) => void = () => {},
|
|
262
|
-
onError: (error: string) => void = () => {},
|
|
263
|
-
) {
|
|
264
|
-
type ReissueExternalNotesState =
|
|
265
|
-
| 'Created'
|
|
266
|
-
| 'Issuing'
|
|
267
|
-
| 'Done'
|
|
268
|
-
| { Failed: { error: string } }
|
|
269
|
-
|
|
270
|
-
const unsubscribe = this._rpcStream<ReissueExternalNotesState>(
|
|
271
|
-
'mint',
|
|
272
|
-
'subscribe_reissue_external_notes',
|
|
273
|
-
{ operation_id: operationId },
|
|
274
|
-
(res) => onSuccess(res),
|
|
275
|
-
onError,
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
return unsubscribe
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
async spendNotes(
|
|
282
|
-
minAmount: number,
|
|
283
|
-
tryCancelAfter: number,
|
|
284
|
-
includeInvite: boolean,
|
|
285
|
-
extraMeta: JSONValue,
|
|
286
|
-
): Promise<JSONValue> {
|
|
287
|
-
return await this._rpcSingle('mint', 'spend_notes', {
|
|
288
|
-
min_amount: minAmount,
|
|
289
|
-
try_cancel_after: tryCancelAfter,
|
|
290
|
-
include_invite: includeInvite,
|
|
291
|
-
extra_meta: extraMeta,
|
|
292
|
-
})
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
async validateNotes(oobNotes: string): Promise<number> {
|
|
296
|
-
return await this._rpcSingle('mint', 'validate_notes', {
|
|
297
|
-
oob_notes: oobNotes,
|
|
298
|
-
})
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
async tryCancelSpendNotes(operationId: string): Promise<void> {
|
|
302
|
-
await this._rpcSingle('mint', 'try_cancel_spend_notes', {
|
|
303
|
-
operation_id: operationId,
|
|
304
|
-
})
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
subscribeSpendNotes(
|
|
308
|
-
operationId: string,
|
|
309
|
-
onSuccess: (state: JSONValue) => void = () => {},
|
|
310
|
-
onError: (error: string) => void = () => {},
|
|
311
|
-
) {
|
|
312
|
-
const unsubscribe = this._rpcStream(
|
|
313
|
-
'mint',
|
|
314
|
-
'subscribe_spend_notes',
|
|
315
|
-
{ operation_id: operationId },
|
|
316
|
-
(res) => onSuccess(res),
|
|
317
|
-
onError,
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
return unsubscribe
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
async awaitSpendOobRefund(operationId: string): Promise<JSONValue> {
|
|
324
|
-
return await this._rpcSingle('mint', 'await_spend_oob_refund', {
|
|
325
|
-
operation_id: operationId,
|
|
326
|
-
})
|
|
108
|
+
if (response.success) {
|
|
109
|
+
this._isOpen = true
|
|
110
|
+
this.resolveOpen()
|
|
111
|
+
}
|
|
327
112
|
}
|
|
328
113
|
|
|
329
114
|
/**
|
|
@@ -331,185 +116,12 @@ export class FedimintWallet {
|
|
|
331
116
|
* After this call, the FedimintWallet instance should be discarded.
|
|
332
117
|
*/
|
|
333
118
|
async cleanup() {
|
|
334
|
-
this.
|
|
335
|
-
this.
|
|
336
|
-
this.
|
|
337
|
-
this.requestCallbacks.clear()
|
|
119
|
+
this.openPromise = null
|
|
120
|
+
this._isOpen = false
|
|
121
|
+
this.client.cleanup()
|
|
338
122
|
}
|
|
339
123
|
|
|
340
124
|
isOpen() {
|
|
341
|
-
return this.
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
async getConfig(): Promise<JSONValue> {
|
|
345
|
-
return await this._rpcSingle('', 'get_config', {})
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
async getFederationId(): Promise<string> {
|
|
349
|
-
return await this._rpcSingle('', 'get_federation_id', {})
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
async getInviteCode(peer: number): Promise<string | null> {
|
|
353
|
-
return await this._rpcSingle('', 'get_invite_code', { peer })
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
async listOperations(): Promise<JSONValue[]> {
|
|
357
|
-
return await this._rpcSingle('', 'list_operations', {})
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
async hasPendingRecoveries(): Promise<boolean> {
|
|
361
|
-
return await this._rpcSingle('', 'has_pending_recoveries', {})
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
async waitForAllRecoveries(): Promise<void> {
|
|
365
|
-
await this._rpcSingle('', 'wait_for_all_recoveries', {})
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/// STREAMING RPCs --------------------
|
|
369
|
-
|
|
370
|
-
subscribeBalance(
|
|
371
|
-
onSuccess: (balance: number) => void = () => {},
|
|
372
|
-
onError: (error: string) => void = () => {},
|
|
373
|
-
) {
|
|
374
|
-
const unsubscribe = this._rpcStream<string>(
|
|
375
|
-
'',
|
|
376
|
-
'subscribe_balance_changes',
|
|
377
|
-
{},
|
|
378
|
-
(res) => onSuccess(parseInt(res)),
|
|
379
|
-
onError,
|
|
380
|
-
)
|
|
381
|
-
|
|
382
|
-
return unsubscribe
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
subscribeToRecoveryProgress(
|
|
386
|
-
onSuccess: (progress: {
|
|
387
|
-
module_id: number
|
|
388
|
-
progress: JSONValue
|
|
389
|
-
}) => void = () => {},
|
|
390
|
-
onError: (error: string) => void = () => {},
|
|
391
|
-
) {
|
|
392
|
-
const unsubscribe = this._rpcStream<{
|
|
393
|
-
module_id: number
|
|
394
|
-
progress: JSONValue
|
|
395
|
-
}>('', 'subscribe_to_recovery_progress', {}, onSuccess, onError)
|
|
396
|
-
|
|
397
|
-
return unsubscribe
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// Lightning Network module methods
|
|
401
|
-
|
|
402
|
-
async createBolt11InvoiceWithGateway(
|
|
403
|
-
amount: number,
|
|
404
|
-
description: string,
|
|
405
|
-
expiryTime: number | null = null,
|
|
406
|
-
extraMeta: JSONObject = {},
|
|
407
|
-
gatewayInfo: GatewayInfo,
|
|
408
|
-
) {
|
|
409
|
-
return await this._rpcSingle('ln', 'create_bolt11_invoice', {
|
|
410
|
-
amount,
|
|
411
|
-
description,
|
|
412
|
-
expiry_time: expiryTime,
|
|
413
|
-
extra_meta: extraMeta,
|
|
414
|
-
gateway: gatewayInfo,
|
|
415
|
-
})
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
async createBolt11Invoice(
|
|
419
|
-
amount: number,
|
|
420
|
-
description: string,
|
|
421
|
-
expiryTime: number | null = null,
|
|
422
|
-
extraMeta: JSONObject = {},
|
|
423
|
-
): Promise<CreateBolt11Response> {
|
|
424
|
-
await this.updateGatewayCache()
|
|
425
|
-
const gateway = await this._getDefaultGatewayInfo()
|
|
426
|
-
return await this._rpcSingle('ln', 'create_bolt11_invoice', {
|
|
427
|
-
amount,
|
|
428
|
-
description,
|
|
429
|
-
expiry_time: expiryTime,
|
|
430
|
-
extra_meta: extraMeta,
|
|
431
|
-
gateway: gateway.info,
|
|
432
|
-
})
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
async payBolt11InvoiceWithGateway(
|
|
436
|
-
invoice: string,
|
|
437
|
-
gatewayInfo: GatewayInfo,
|
|
438
|
-
extraMeta: JSONObject = {},
|
|
439
|
-
) {
|
|
440
|
-
return await this._rpcSingle('ln', 'pay_bolt11_invoice', {
|
|
441
|
-
maybe_gateway: gatewayInfo,
|
|
442
|
-
invoice,
|
|
443
|
-
extra_meta: extraMeta,
|
|
444
|
-
})
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
async _getDefaultGatewayInfo(): Promise<LightningGateway> {
|
|
448
|
-
const gateways = await this.listGateways()
|
|
449
|
-
return gateways[0]
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
async payBolt11Invoice(
|
|
453
|
-
invoice: string,
|
|
454
|
-
extraMeta: JSONObject = {},
|
|
455
|
-
): Promise<OutgoingLightningPayment> {
|
|
456
|
-
await this.updateGatewayCache()
|
|
457
|
-
const gateway = await this._getDefaultGatewayInfo()
|
|
458
|
-
return await this._rpcSingle('ln', 'pay_bolt11_invoice', {
|
|
459
|
-
maybe_gateway: gateway.info,
|
|
460
|
-
invoice,
|
|
461
|
-
extra_meta: extraMeta,
|
|
462
|
-
})
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
subscribeLnPay(
|
|
466
|
-
operationId: string,
|
|
467
|
-
onSuccess: (state: LnPayState) => void = () => {},
|
|
468
|
-
onError: (error: string) => void = () => {},
|
|
469
|
-
) {
|
|
470
|
-
const unsubscribe = this._rpcStream(
|
|
471
|
-
'ln',
|
|
472
|
-
'subscribe_ln_pay',
|
|
473
|
-
{ operation_id: operationId },
|
|
474
|
-
onSuccess,
|
|
475
|
-
onError,
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
return unsubscribe
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
subscribeLnReceive(
|
|
482
|
-
operationId: string,
|
|
483
|
-
onSuccess: (state: LnReceiveState) => void = () => {},
|
|
484
|
-
onError: (error: string) => void = () => {},
|
|
485
|
-
) {
|
|
486
|
-
const unsubscribe = this._rpcStream(
|
|
487
|
-
'ln',
|
|
488
|
-
'subscribe_ln_receive',
|
|
489
|
-
{ operation_id: operationId },
|
|
490
|
-
onSuccess,
|
|
491
|
-
onError,
|
|
492
|
-
)
|
|
493
|
-
|
|
494
|
-
return unsubscribe
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
async getGateway(
|
|
498
|
-
gatewayId: string | null = null,
|
|
499
|
-
forceInternal: boolean = false,
|
|
500
|
-
): Promise<LightningGateway | null> {
|
|
501
|
-
return await this._rpcSingle('ln', 'get_gateway', {
|
|
502
|
-
gateway_id: gatewayId,
|
|
503
|
-
force_internal: forceInternal,
|
|
504
|
-
})
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
async listGateways(): Promise<LightningGateway[]> {
|
|
508
|
-
return await this._rpcSingle('ln', 'list_gateways', {})
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
async updateGatewayCache(): Promise<void> {
|
|
512
|
-
console.trace('Updating gateway cache')
|
|
513
|
-
await this._rpcSingle('ln', 'update_gateway_cache', {})
|
|
125
|
+
return this._isOpen
|
|
514
126
|
}
|
|
515
127
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { WorkerClient } from '../worker'
|
|
2
|
+
|
|
3
|
+
export class BalanceService {
|
|
4
|
+
constructor(private client: WorkerClient) {}
|
|
5
|
+
|
|
6
|
+
async getBalance(): Promise<number> {
|
|
7
|
+
return await this.client.rpcSingle('', 'get_balance', {})
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
subscribeBalance(
|
|
11
|
+
onSuccess: (balance: number) => void = () => {},
|
|
12
|
+
onError: (error: string) => void = () => {},
|
|
13
|
+
) {
|
|
14
|
+
const unsubscribe = this.client.rpcStream<string>(
|
|
15
|
+
'',
|
|
16
|
+
'subscribe_balance_changes',
|
|
17
|
+
{},
|
|
18
|
+
(res) => onSuccess(parseInt(res)),
|
|
19
|
+
onError,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
return unsubscribe
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { JSONValue } from '../types/wallet'
|
|
2
|
+
import { WorkerClient } from '../worker'
|
|
3
|
+
|
|
4
|
+
export class FederationService {
|
|
5
|
+
constructor(private client: WorkerClient) {}
|
|
6
|
+
|
|
7
|
+
async getConfig(): Promise<JSONValue> {
|
|
8
|
+
return await this.client.rpcSingle('', 'get_config', {})
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async getFederationId(): Promise<string> {
|
|
12
|
+
return await this.client.rpcSingle('', 'get_federation_id', {})
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async getInviteCode(peer: number): Promise<string | null> {
|
|
16
|
+
return await this.client.rpcSingle('', 'get_invite_code', { peer })
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async joinFederation(inviteCode: string, clientName: string): Promise<void> {
|
|
20
|
+
const response = await this.client.sendSingleMessage('join', {
|
|
21
|
+
inviteCode,
|
|
22
|
+
clientName,
|
|
23
|
+
})
|
|
24
|
+
if (!response.success) {
|
|
25
|
+
throw new Error('Failed to join federation')
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async listOperations(): Promise<JSONValue[]> {
|
|
30
|
+
return await this.client.rpcSingle('', 'list_operations', {})
|
|
31
|
+
}
|
|
32
|
+
}
|