@fedimint/core-web 0.0.6 → 0.0.8

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.
Files changed (74) hide show
  1. package/README.md +6 -71
  2. package/dist/{FedimintWallet.d.ts → dts/FedimintWallet.d.ts} +3 -3
  3. package/dist/dts/FedimintWallet.d.ts.map +1 -0
  4. package/dist/dts/index.d.ts +3 -0
  5. package/dist/dts/index.d.ts.map +1 -0
  6. package/dist/{services → dts/services}/BalanceService.d.ts +5 -4
  7. package/dist/dts/services/BalanceService.d.ts.map +1 -0
  8. package/dist/{services → dts/services}/FederationService.d.ts +1 -1
  9. package/dist/dts/services/FederationService.d.ts.map +1 -0
  10. package/dist/dts/services/LightningService.d.ts +21 -0
  11. package/dist/dts/services/LightningService.d.ts.map +1 -0
  12. package/dist/{services → dts/services}/MintService.d.ts +6 -5
  13. package/dist/dts/services/MintService.d.ts.map +1 -0
  14. package/dist/{services → dts/services}/RecoveryService.d.ts +1 -1
  15. package/dist/dts/services/RecoveryService.d.ts.map +1 -0
  16. package/dist/dts/services/index.d.ts.map +1 -0
  17. package/dist/dts/types/index.d.ts +4 -0
  18. package/dist/dts/types/index.d.ts.map +1 -0
  19. package/dist/dts/types/utils.d.ts +16 -0
  20. package/dist/dts/types/utils.d.ts.map +1 -0
  21. package/dist/{types → dts/types}/wallet.d.ts +4 -14
  22. package/dist/dts/types/wallet.d.ts.map +1 -0
  23. package/dist/dts/types/worker.d.ts +4 -0
  24. package/dist/dts/types/worker.d.ts.map +1 -0
  25. package/dist/dts/utils/logger.d.ts.map +1 -0
  26. package/dist/{worker → dts/worker}/WorkerClient.d.ts +4 -4
  27. package/dist/dts/worker/WorkerClient.d.ts.map +1 -0
  28. package/dist/dts/worker/index.d.ts.map +1 -0
  29. package/dist/index.d.ts +298 -5
  30. package/dist/index.js +1 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/worker.js +1 -1
  33. package/dist/worker.js.map +1 -1
  34. package/package.json +8 -5
  35. package/src/FedimintWallet.test.ts +43 -60
  36. package/src/FedimintWallet.ts +20 -14
  37. package/src/index.ts +2 -22
  38. package/src/services/BalanceService.ts +5 -4
  39. package/src/services/FederationService.test.ts +1 -1
  40. package/src/services/FederationService.ts +1 -1
  41. package/src/services/LightningService.test.ts +103 -63
  42. package/src/services/LightningService.ts +84 -47
  43. package/src/services/MintService.test.ts +16 -2
  44. package/src/services/MintService.ts +8 -8
  45. package/src/services/RecoveryService.ts +1 -1
  46. package/src/test/TestFedimintWallet.ts +10 -1
  47. package/src/test/TestingService.ts +49 -30
  48. package/src/test/crypto.ts +44 -0
  49. package/src/test/fixtures.test.ts +18 -0
  50. package/src/test/{setupTests.ts → fixtures.ts} +25 -4
  51. package/src/types/index.ts +3 -0
  52. package/src/types/utils.ts +25 -0
  53. package/src/types/wallet.ts +4 -23
  54. package/src/types/worker.ts +13 -0
  55. package/src/worker/WorkerClient.test.ts +6 -0
  56. package/src/worker/WorkerClient.ts +28 -20
  57. package/src/worker/worker.js +9 -0
  58. package/src/worker/worker.test.ts +2 -2
  59. package/dist/FedimintWallet.d.ts.map +0 -1
  60. package/dist/index.d.ts.map +0 -1
  61. package/dist/services/BalanceService.d.ts.map +0 -1
  62. package/dist/services/FederationService.d.ts.map +0 -1
  63. package/dist/services/LightningService.d.ts +0 -18
  64. package/dist/services/LightningService.d.ts.map +0 -1
  65. package/dist/services/MintService.d.ts.map +0 -1
  66. package/dist/services/RecoveryService.d.ts.map +0 -1
  67. package/dist/services/index.d.ts.map +0 -1
  68. package/dist/types/wallet.d.ts.map +0 -1
  69. package/dist/utils/logger.d.ts.map +0 -1
  70. package/dist/worker/WorkerClient.d.ts.map +0 -1
  71. package/dist/worker/index.d.ts.map +0 -1
  72. /package/dist/{services → dts/services}/index.d.ts +0 -0
  73. /package/dist/{utils → dts/utils}/logger.d.ts +0 -0
  74. /package/dist/{worker → dts/worker}/index.d.ts +0 -0
@@ -1,4 +1,4 @@
1
- import { WorkerClient } from './worker/WorkerClient'
1
+ import { WorkerClient } from './worker'
2
2
  import {
3
3
  BalanceService,
4
4
  MintService,
@@ -19,7 +19,7 @@ export class FedimintWallet {
19
19
  public federation: FederationService
20
20
  public recovery: RecoveryService
21
21
 
22
- private _openPromise: Promise<void> | null = null
22
+ private _openPromise: Promise<void> | undefined = undefined
23
23
  private _resolveOpen: () => void = () => {}
24
24
  private _isOpen: boolean = false
25
25
 
@@ -85,9 +85,9 @@ export class FedimintWallet {
85
85
  await this._client.initialize()
86
86
  // TODO: Determine if this should be safe or throw
87
87
  if (this._isOpen) throw new Error('The FedimintWallet is already open.')
88
- const { success } = await this._client.sendSingleMessage('open', {
89
- clientName,
90
- })
88
+ const { success } = await this._client.sendSingleMessage<{
89
+ success: boolean
90
+ }>('open', { clientName })
91
91
  if (success) {
92
92
  this._isOpen = !!success
93
93
  this._resolveOpen()
@@ -105,13 +105,19 @@ export class FedimintWallet {
105
105
  throw new Error(
106
106
  'The FedimintWallet is already open. You can only call `joinFederation` on closed clients.',
107
107
  )
108
- const response = await this._client.sendSingleMessage('join', {
109
- inviteCode,
110
- clientName,
111
- })
112
- if (response.success) {
113
- this._isOpen = true
114
- this._resolveOpen()
108
+ try {
109
+ const response = await this._client.sendSingleMessage<{
110
+ success: boolean
111
+ }>('join', { inviteCode, clientName })
112
+ if (response.success) {
113
+ this._isOpen = true
114
+ this._resolveOpen()
115
+ }
116
+
117
+ return response.success
118
+ } catch (e) {
119
+ logger.error('Error joining federation', e)
120
+ return false
115
121
  }
116
122
  }
117
123
 
@@ -120,9 +126,9 @@ export class FedimintWallet {
120
126
  * After this call, the FedimintWallet instance should be discarded.
121
127
  */
122
128
  async cleanup() {
123
- this._openPromise = null
129
+ this._openPromise = undefined
124
130
  this._isOpen = false
125
- this._client.cleanup()
131
+ await this._client.cleanup()
126
132
  }
127
133
 
128
134
  isOpen() {
package/src/index.ts CHANGED
@@ -1,22 +1,2 @@
1
- import { FedimintWallet } from './FedimintWallet.js'
2
- import {
3
- LightningGateway,
4
- RouteHint,
5
- FeeToAmount,
6
- OutgoingLightningPayment,
7
- PayType,
8
- LnPayState,
9
- CreateBolt11Response,
10
- } from './types/wallet.js'
11
-
12
- export { FedimintWallet }
13
-
14
- export type {
15
- LightningGateway,
16
- RouteHint,
17
- FeeToAmount,
18
- OutgoingLightningPayment,
19
- PayType,
20
- LnPayState,
21
- CreateBolt11Response,
22
- }
1
+ export { FedimintWallet } from './FedimintWallet'
2
+ export type * from './types'
@@ -1,3 +1,4 @@
1
+ import type { MSats } from '../types'
1
2
  import { WorkerClient } from '../worker'
2
3
 
3
4
  /**
@@ -9,19 +10,19 @@ export class BalanceService {
9
10
  constructor(private client: WorkerClient) {}
10
11
 
11
12
  /**
12
- * Get the balance of the current wallet
13
+ * Get the balance of the current wallet in milli-satoshis (MSats)
13
14
  *
14
15
  * @example
15
16
  * ```ts
16
17
  * const balance = await wallet.balance.getBalance()
17
18
  * ```
18
19
  */
19
- async getBalance(): Promise<number> {
20
+ async getBalance(): Promise<MSats> {
20
21
  return await this.client.rpcSingle('', 'get_balance', {})
21
22
  }
22
23
 
23
24
  /**
24
- * Subscribe to the balance of the current wallet
25
+ * Subscribe to the balance of the current wallet in milli-satoshis (MSats)
25
26
  *
26
27
  * @example
27
28
  * ```ts
@@ -34,7 +35,7 @@ export class BalanceService {
34
35
  * ```
35
36
  */
36
37
  subscribeBalance(
37
- onSuccess: (balance: number) => void = () => {},
38
+ onSuccess: (balance: MSats) => void = () => {},
38
39
  onError: (error: string) => void = () => {},
39
40
  ) {
40
41
  const unsubscribe = this.client.rpcStream<string>(
@@ -1,5 +1,5 @@
1
1
  import { expect } from 'vitest'
2
- import { walletTest } from '../test/setupTests'
2
+ import { walletTest } from '../test/fixtures'
3
3
 
4
4
  walletTest(
5
5
  'getConfig should return the federation config',
@@ -1,4 +1,4 @@
1
- import { JSONValue } from '../types/wallet'
1
+ import type { JSONValue } from '../types'
2
2
  import { WorkerClient } from '../worker'
3
3
 
4
4
  export class FederationService {
@@ -1,5 +1,6 @@
1
1
  import { expect } from 'vitest'
2
- import { walletTest } from '../test/setupTests'
2
+ import { keyPair } from '../test/crypto'
3
+ import { walletTest } from '../test/fixtures'
3
4
 
4
5
  walletTest(
5
6
  'createInvoice should create a bolt11 invoice',
@@ -20,11 +21,23 @@ walletTest(
20
21
 
21
22
  // Test with expiry time
22
23
  await expect(
23
- wallet.lightning.createInvoice(100, 'test', 1000, {}),
24
+ wallet.lightning.createInvoice(100, 'test', 1000),
24
25
  ).resolves.toBeDefined()
25
26
  },
26
27
  )
27
28
 
29
+ walletTest('createInvoice with expiry', async ({ wallet }) => {
30
+ expect(wallet).toBeDefined()
31
+ expect(wallet.isOpen()).toBe(true)
32
+
33
+ const invoice = await wallet.lightning.createInvoice(100, 'test', 1000)
34
+ expect(invoice).toBeDefined()
35
+ expect(invoice).toMatchObject({
36
+ invoice: expect.any(String),
37
+ operation_id: expect.any(String),
38
+ })
39
+ })
40
+
28
41
  walletTest(
29
42
  'listGateways should return a list of gateways',
30
43
  async ({ wallet }) => {
@@ -35,11 +48,7 @@ walletTest(
35
48
  const gateways = await wallet.lightning.listGateways()
36
49
  expect(wallet.testing.getRequestCounter()).toBe(counterBefore + 1)
37
50
  expect(gateways).toBeDefined()
38
- expect(gateways).toMatchObject([
39
- {
40
- info: expect.any(Object),
41
- },
42
- ])
51
+ expect(gateways).toMatchObject(expect.any(Array))
43
52
  },
44
53
  )
45
54
 
@@ -74,42 +83,6 @@ walletTest('getGateway should return a gateway', async ({ wallet }) => {
74
83
  })
75
84
  })
76
85
 
77
- walletTest(
78
- 'createInvoiceWithGateway should create a bolt11 invoice with a gateway',
79
- async ({ wallet }) => {
80
- expect(wallet).toBeDefined()
81
- expect(wallet.isOpen()).toBe(true)
82
-
83
- const gateways = await wallet.lightning.listGateways()
84
- const gateway = gateways[0]
85
- expect(gateway).toBeDefined()
86
-
87
- const counterBefore = wallet.testing.getRequestCounter()
88
- const invoice = await wallet.lightning.createInvoiceWithGateway(
89
- 100,
90
- 'test',
91
- null,
92
- {},
93
- gateway.info,
94
- )
95
- expect(invoice).toBeDefined()
96
- expect(invoice).toMatchObject({
97
- invoice: expect.any(String),
98
- operation_id: expect.any(String),
99
- })
100
- expect(wallet.testing.getRequestCounter()).toBe(counterBefore + 1)
101
- await expect(
102
- wallet.lightning.createInvoiceWithGateway(
103
- 100,
104
- 'test',
105
- 1000,
106
- {},
107
- gateway.info,
108
- ),
109
- ).resolves.toBeDefined()
110
- },
111
- )
112
-
113
86
  walletTest(
114
87
  'payInvoice should throw on insufficient funds',
115
88
  async ({ wallet }) => {
@@ -126,7 +99,7 @@ walletTest(
126
99
  const counterBefore = wallet.testing.getRequestCounter()
127
100
  // Insufficient funds
128
101
  try {
129
- await wallet.lightning.payInvoice(invoice.invoice, {})
102
+ await wallet.lightning.payInvoice(invoice.invoice)
130
103
  expect.unreachable('Should throw error')
131
104
  } catch (error) {
132
105
  expect(error).toBeDefined()
@@ -139,30 +112,97 @@ walletTest(
139
112
 
140
113
  walletTest(
141
114
  'payInvoice should pay a bolt11 invoice',
142
- { timeout: 45000 },
115
+ { timeout: 20_000 },
116
+ async ({ fundedWallet }) => {
117
+ expect(fundedWallet).toBeDefined()
118
+ expect(fundedWallet.isOpen()).toBe(true)
119
+ const initialBalance = await fundedWallet.balance.getBalance()
120
+ expect(initialBalance).toBeGreaterThan(0)
121
+ const externalInvoice = await fundedWallet.testing.createFaucetInvoice(1)
122
+ const gatewayInfo = await fundedWallet.testing.getFaucetGatewayInfo()
123
+ const payment = await fundedWallet.lightning.payInvoice(
124
+ externalInvoice,
125
+ gatewayInfo,
126
+ )
127
+ expect(payment).toMatchObject({
128
+ contract_id: expect.any(String),
129
+ fee: expect.any(Number),
130
+ payment_type: expect.any(Object),
131
+ })
132
+ const finalBalance = await fundedWallet.balance.getBalance()
133
+ expect(finalBalance).toBeLessThan(initialBalance)
134
+ },
135
+ )
136
+
137
+ walletTest(
138
+ 'createInvoiceTweaked should create a bolt11 invoice with a tweaked public key',
143
139
  async ({ wallet }) => {
144
140
  expect(wallet).toBeDefined()
145
141
  expect(wallet.isOpen()).toBe(true)
146
142
 
147
- const gateways = await wallet.lightning.listGateways()
148
- const gateway = gateways[0]
149
- if (!gateway) {
150
- expect.unreachable('Gateway not found')
151
- }
152
- const invoice = await wallet.lightning.createInvoice(10000, 'test')
143
+ // Make an ephemeral key pair
144
+ const { publicKey, secretKey } = keyPair()
145
+ const tweak = 1
146
+
147
+ // Create an invoice paying to the tweaked public key
148
+ const invoice = await wallet.lightning.createInvoiceTweaked(
149
+ 1000,
150
+ 'test tweaked',
151
+ publicKey,
152
+ tweak,
153
+ )
154
+ expect(invoice).toBeDefined()
155
+ expect(invoice).toMatchObject({
156
+ invoice: expect.any(String),
157
+ operation_id: expect.any(String),
158
+ })
159
+ },
160
+ )
161
+
162
+ walletTest(
163
+ 'scanReceivesForTweaks should return the operation id',
164
+ async ({ wallet }) => {
165
+ expect(wallet).toBeDefined()
166
+ expect(wallet.isOpen()).toBe(true)
167
+
168
+ // Make an ephemeral key pair
169
+ const { publicKey, secretKey } = keyPair()
170
+ const tweak = 1
171
+
172
+ const gatewayInfo = await wallet.testing.getFaucetGatewayInfo()
173
+
174
+ // Create an invoice paying to the tweaked public key
175
+ const invoice = await wallet.lightning.createInvoiceTweaked(
176
+ 1000,
177
+ 'test tweaked',
178
+ publicKey,
179
+ tweak,
180
+ undefined,
181
+ gatewayInfo,
182
+ )
153
183
  await expect(
154
- wallet.testing.payWithFaucet(invoice.invoice),
184
+ wallet.testing.payFaucetInvoice(invoice.invoice),
155
185
  ).resolves.toBeDefined()
156
- await wallet.lightning.waitForReceive(invoice.operation_id)
157
- // Wait for balance to fully update
158
- await new Promise((resolve) => setTimeout(resolve, 1000))
159
- const externalInvoice = await wallet.testing.getExternalInvoice(10)
160
- const payment = await wallet.lightning.payInvoice(externalInvoice.pr)
161
- expect(payment).toBeDefined()
162
- expect(payment).toMatchObject({
163
- contract_id: expect.any(String),
164
- fee: expect.any(Number),
165
- payment_type: expect.any(Object),
166
- })
186
+
187
+ // Scan for the receive
188
+ const operationIds = await wallet.lightning.scanReceivesForTweaks(
189
+ secretKey,
190
+ [tweak],
191
+ {},
192
+ )
193
+ expect(operationIds).toBeDefined()
194
+ expect(operationIds).toHaveLength(1)
195
+
196
+ // Subscribe to claiming the receive
197
+ const subscription = await wallet.lightning.subscribeLnClaim(
198
+ operationIds[0],
199
+ (state) => {
200
+ expect(state).toBeDefined()
201
+ expect(state).toMatchObject({
202
+ state: 'claimed',
203
+ })
204
+ },
205
+ )
206
+ expect(subscription).toBeDefined()
167
207
  },
168
208
  )
@@ -1,5 +1,5 @@
1
1
  import { WorkerClient } from '../worker'
2
- import {
2
+ import type {
3
3
  CreateBolt11Response,
4
4
  GatewayInfo,
5
5
  JSONObject,
@@ -7,75 +7,103 @@ import {
7
7
  LightningGateway,
8
8
  LnPayState,
9
9
  LnReceiveState,
10
+ MSats,
10
11
  OutgoingLightningPayment,
11
- } from '../types/wallet'
12
+ } from '../types'
12
13
 
13
14
  export class LightningService {
14
15
  constructor(private client: WorkerClient) {}
15
16
 
16
- async createInvoiceWithGateway(
17
- amount: number,
17
+ async createInvoice(
18
+ amount: MSats,
18
19
  description: string,
19
- expiryTime: number | null = null,
20
- extraMeta: JSONObject = {},
21
- gatewayInfo: GatewayInfo,
22
- ) {
20
+ expiryTime?: number, // in seconds
21
+ gatewayInfo?: GatewayInfo,
22
+ extraMeta?: JSONObject,
23
+ ): Promise<CreateBolt11Response> {
24
+ const gateway = gatewayInfo ?? (await this._getDefaultGatewayInfo())
23
25
  return await this.client.rpcSingle('ln', 'create_bolt11_invoice', {
24
26
  amount,
25
27
  description,
26
- expiry_time: expiryTime,
27
- extra_meta: extraMeta,
28
- gateway: gatewayInfo,
28
+ expiry_time: expiryTime ?? null,
29
+ extra_meta: extraMeta ?? {},
30
+ gateway,
29
31
  })
30
32
  }
31
33
 
32
- async createInvoice(
33
- amount: number,
34
+ async createInvoiceTweaked(
35
+ amount: MSats,
34
36
  description: string,
35
- expiryTime: number | null = null,
36
- extraMeta: JSONObject = {},
37
+ tweakKey: string,
38
+ index: number,
39
+ expiryTime?: number, // in seconds
40
+ gatewayInfo?: GatewayInfo,
41
+ extraMeta?: JSONObject,
37
42
  ): Promise<CreateBolt11Response> {
38
- await this.updateGatewayCache()
39
- const gateway = await this._getDefaultGatewayInfo()
40
- return await this.client.rpcSingle('ln', 'create_bolt11_invoice', {
41
- amount,
42
- description,
43
- expiry_time: expiryTime,
44
- extra_meta: extraMeta,
45
- gateway: gateway.info,
46
- })
43
+ const gateway = gatewayInfo ?? (await this._getDefaultGatewayInfo())
44
+ return await this.client.rpcSingle(
45
+ 'ln',
46
+ 'create_bolt11_invoice_for_user_tweaked',
47
+ {
48
+ amount,
49
+ description,
50
+ expiry_time: expiryTime ?? null,
51
+ user_key: tweakKey,
52
+ index,
53
+ extra_meta: extraMeta ?? {},
54
+ gateway,
55
+ },
56
+ )
47
57
  }
48
58
 
49
- async payInvoiceWithGateway(
50
- invoice: string,
51
- gatewayInfo: GatewayInfo,
52
- extraMeta: JSONObject = {},
53
- ) {
54
- return await this.client.rpcSingle('ln', 'pay_bolt11_invoice', {
55
- maybe_gateway: gatewayInfo,
56
- invoice,
57
- extra_meta: extraMeta,
59
+ // Returns the operation ids of payments received to the tweaks of the user secret key
60
+ async scanReceivesForTweaks(
61
+ tweakKey: string,
62
+ indices: number[],
63
+ extraMeta?: JSONObject,
64
+ ): Promise<string[]> {
65
+ return await this.client.rpcSingle('ln', 'scan_receive_for_user_tweaked', {
66
+ user_key: tweakKey,
67
+ indices,
68
+ extra_meta: extraMeta ?? {},
58
69
  })
59
70
  }
60
71
 
61
- private async _getDefaultGatewayInfo(): Promise<LightningGateway> {
72
+ private async _getDefaultGatewayInfo(): Promise<GatewayInfo> {
73
+ await this.updateGatewayCache()
62
74
  const gateways = await this.listGateways()
63
- return gateways[0]
75
+ return gateways[0]?.info
64
76
  }
65
77
 
66
78
  async payInvoice(
67
79
  invoice: string,
68
- extraMeta: JSONObject = {},
80
+ gatewayInfo?: GatewayInfo,
81
+ extraMeta?: JSONObject,
69
82
  ): Promise<OutgoingLightningPayment> {
70
- await this.updateGatewayCache()
71
- const gateway = await this._getDefaultGatewayInfo()
83
+ const gateway = gatewayInfo ?? (await this._getDefaultGatewayInfo())
72
84
  return await this.client.rpcSingle('ln', 'pay_bolt11_invoice', {
73
- maybe_gateway: gateway.info,
85
+ maybe_gateway: gateway,
74
86
  invoice,
75
- extra_meta: extraMeta,
87
+ extra_meta: extraMeta ?? {},
76
88
  })
77
89
  }
78
90
 
91
+ subscribeLnClaim(
92
+ operationId: string,
93
+ onSuccess: (state: LnReceiveState) => void = () => {},
94
+ onError: (error: string) => void = () => {},
95
+ ) {
96
+ const unsubscribe = this.client.rpcStream(
97
+ 'ln',
98
+ 'subscribe_ln_claim',
99
+ { operation_id: operationId },
100
+ onSuccess,
101
+ onError,
102
+ )
103
+
104
+ return unsubscribe
105
+ }
106
+
79
107
  subscribeLnPay(
80
108
  operationId: string,
81
109
  onSuccess: (state: LnPayState) => void = () => {},
@@ -110,17 +138,26 @@ export class LightningService {
110
138
 
111
139
  async waitForReceive(operationId: string): Promise<LnReceiveState> {
112
140
  return new Promise((resolve, reject) => {
113
- const unsubscribe = this.subscribeLnReceive(
141
+ let unsubscribe: () => void
142
+ const timeoutId = setTimeout(() => {
143
+ reject(new Error('Timeout waiting for receive'))
144
+ }, 15000)
145
+
146
+ unsubscribe = this.subscribeLnReceive(
114
147
  operationId,
115
148
  (res) => {
116
- if (res === 'claimed') resolve(res)
149
+ if (res === 'claimed') {
150
+ clearTimeout(timeoutId)
151
+ unsubscribe()
152
+ resolve(res)
153
+ }
154
+ },
155
+ (error) => {
156
+ clearTimeout(timeoutId)
157
+ unsubscribe()
158
+ reject(error)
117
159
  },
118
- reject,
119
160
  )
120
- setTimeout(() => {
121
- unsubscribe()
122
- reject(new Error('Timeout waiting for receive'))
123
- }, 10000)
124
161
  })
125
162
  }
126
163
 
@@ -1,5 +1,5 @@
1
1
  import { expect } from 'vitest'
2
- import { walletTest } from '../test/setupTests'
2
+ import { walletTest } from '../test/fixtures'
3
3
 
4
4
  walletTest('redeemEcash should error on invalid ecash', async ({ wallet }) => {
5
5
  expect(wallet).toBeDefined()
@@ -9,7 +9,7 @@ walletTest('redeemEcash should error on invalid ecash', async ({ wallet }) => {
9
9
  })
10
10
 
11
11
  walletTest(
12
- 'reissueExternalNotes should reissue external notes',
12
+ 'reissueExternalNotes should throw if wallet is empty',
13
13
  async ({ wallet }) => {
14
14
  expect(wallet).toBeDefined()
15
15
  expect(wallet.isOpen()).toBe(true)
@@ -17,3 +17,17 @@ walletTest(
17
17
  await expect(wallet.mint.reissueExternalNotes('test')).rejects.toThrow()
18
18
  },
19
19
  )
20
+
21
+ walletTest('spendNotes should throw if wallet is empty', async ({ wallet }) => {
22
+ expect(wallet).toBeDefined()
23
+ expect(wallet.isOpen()).toBe(true)
24
+
25
+ await expect(wallet.mint.spendNotes(100)).rejects.toThrow()
26
+ })
27
+
28
+ walletTest('parseNotes should parse notes', async ({ wallet }) => {
29
+ expect(wallet).toBeDefined()
30
+ expect(wallet.isOpen()).toBe(true)
31
+
32
+ await expect(wallet.mint.reissueExternalNotes('test')).rejects.toThrow()
33
+ })
@@ -1,11 +1,12 @@
1
1
  import { WorkerClient } from '../worker'
2
- import {
2
+ import type {
3
3
  Duration,
4
4
  JSONObject,
5
5
  JSONValue,
6
6
  MintSpendNotesResponse,
7
+ MSats,
7
8
  ReissueExternalNotesState,
8
- } from '../types/wallet'
9
+ } from '../types'
9
10
 
10
11
  export class MintService {
11
12
  constructor(private client: WorkerClient) {}
@@ -44,12 +45,11 @@ export class MintService {
44
45
  }
45
46
 
46
47
  async spendNotes(
47
- minAmount: number,
48
+ minAmount: MSats,
48
49
  // Tells the wallet to automatically try to cancel the spend if it hasn't completed
49
- // after the specified number of milliseconds.
50
- // If the receiver has already redeemed the notes at this time,
51
- // the notes will not be cancelled
52
- tryCancelAfter: number | Duration = 0,
50
+ // after the specified number of seconds. If the receiver has already redeemed
51
+ // the notes at this time, the notes will not be cancelled.
52
+ tryCancelAfter: number | Duration = 3600 * 24, // defaults to 1 day
53
53
  includeInvite: boolean = false,
54
54
  extraMeta: JSONValue = {},
55
55
  ): Promise<MintSpendNotesResponse> {
@@ -77,7 +77,7 @@ export class MintService {
77
77
  }
78
78
  }
79
79
 
80
- async validateNotes(oobNotes: string): Promise<number> {
80
+ async parseNotes(oobNotes: string): Promise<MSats> {
81
81
  return await this.client.rpcSingle('mint', 'validate_notes', {
82
82
  oob_notes: oobNotes,
83
83
  })
@@ -1,4 +1,4 @@
1
- import { JSONValue } from '../types/wallet'
1
+ import type { JSONValue } from '../types'
2
2
  import { WorkerClient } from '../worker'
3
3
 
4
4
  export class RecoveryService {
@@ -7,7 +7,16 @@ export class TestFedimintWallet extends FedimintWallet {
7
7
 
8
8
  constructor() {
9
9
  super()
10
- this.testing = new TestingService(this.getWorkerClient())
10
+ this.testing = new TestingService(this.getWorkerClient(), this.lightning)
11
+ }
12
+
13
+ async fundWallet(amount: number) {
14
+ const info = await this.testing.getFaucetGatewayInfo()
15
+ const invoice = await this.lightning.createInvoice(amount, '', 1000, info)
16
+ await Promise.all([
17
+ this.testing.payFaucetInvoice(invoice.invoice),
18
+ this.lightning.waitForReceive(invoice.operation_id),
19
+ ])
11
20
  }
12
21
 
13
22
  // Method to expose the WorkerClient