@fedimint/core-web 0.0.3 → 0.0.5

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 (61) hide show
  1. package/README.md +4 -4
  2. package/dist/FedimintWallet.d.ts +42 -65
  3. package/dist/FedimintWallet.d.ts.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/services/BalanceService.d.ts +34 -0
  7. package/dist/services/BalanceService.d.ts.map +1 -0
  8. package/dist/services/FederationService.d.ts +11 -0
  9. package/dist/services/FederationService.d.ts.map +1 -0
  10. package/dist/services/LightningService.d.ts +18 -0
  11. package/dist/services/LightningService.d.ts.map +1 -0
  12. package/dist/services/MintService.d.ts +15 -0
  13. package/dist/services/MintService.d.ts.map +1 -0
  14. package/dist/services/RecoveryService.d.ts +13 -0
  15. package/dist/services/RecoveryService.d.ts.map +1 -0
  16. package/dist/services/index.d.ts +6 -0
  17. package/dist/services/index.d.ts.map +1 -0
  18. package/dist/types/wallet.d.ts +16 -11
  19. package/dist/types/wallet.d.ts.map +1 -1
  20. package/dist/utils/logger.d.ts +17 -0
  21. package/dist/utils/logger.d.ts.map +1 -0
  22. package/dist/worker/WorkerClient.d.ts +44 -0
  23. package/dist/worker/WorkerClient.d.ts.map +1 -0
  24. package/dist/worker/index.d.ts +2 -0
  25. package/dist/worker/index.d.ts.map +1 -0
  26. package/dist/worker.js +1 -1
  27. package/dist/worker.js.map +1 -1
  28. package/package.json +9 -9
  29. package/src/FedimintWallet.test.ts +77 -0
  30. package/src/FedimintWallet.ts +91 -466
  31. package/src/services/BalanceService.test.ts +50 -0
  32. package/src/services/BalanceService.ts +50 -0
  33. package/src/services/FederationService.test.ts +58 -0
  34. package/src/services/FederationService.ts +22 -0
  35. package/src/services/LightningService.test.ts +168 -0
  36. package/src/services/LightningService.ts +144 -0
  37. package/src/services/MintService.test.ts +19 -0
  38. package/src/services/MintService.ts +96 -0
  39. package/src/services/RecoveryService.ts +26 -0
  40. package/src/services/index.ts +5 -0
  41. package/src/test/TestFedimintWallet.ts +17 -0
  42. package/src/test/TestingService.ts +59 -0
  43. package/src/test/setupTests.ts +43 -0
  44. package/src/types/wallet.ts +20 -13
  45. package/src/utils/logger.ts +61 -0
  46. package/src/worker/WorkerClient.ts +229 -0
  47. package/src/worker/index.ts +1 -0
  48. package/src/worker/worker.js +96 -0
  49. package/src/worker/worker.test.ts +90 -0
  50. package/node_modules/fedimint-client-wasm/fedimint_client_wasm.d.ts +0 -49
  51. package/node_modules/fedimint-client-wasm/fedimint_client_wasm.js +0 -4
  52. package/node_modules/fedimint-client-wasm/fedimint_client_wasm_bg.js +0 -1411
  53. package/node_modules/fedimint-client-wasm/fedimint_client_wasm_bg.wasm +0 -0
  54. package/node_modules/fedimint-client-wasm/package.json +0 -26
  55. package/src/worker.js +0 -80
  56. package/wasm/fedimint_client_wasm.d.ts +0 -49
  57. package/wasm/fedimint_client_wasm.js +0 -4
  58. package/wasm/fedimint_client_wasm_bg.js +0 -1411
  59. package/wasm/fedimint_client_wasm_bg.wasm +0 -0
  60. package/wasm/fedimint_client_wasm_bg.wasm.d.ts +0 -110
  61. package/wasm/package.json +0 -26
@@ -47,22 +47,22 @@ type PayType = {
47
47
  }
48
48
 
49
49
  type LnPayState =
50
- | 'Created'
51
- | 'Canceled'
52
- | { Funded: { block_height: number } }
53
- | { WaitingForRefund: { error_reason: string } }
54
- | 'AwaitingChange'
50
+ | 'created'
51
+ | 'canceled'
52
+ | { funded: { block_height: number } }
53
+ | { waiting_for_refund: { error_reason: string } }
54
+ | 'awaiting_change'
55
55
  | { Success: { preimage: string } }
56
- | { Refunded: { gateway_error: string } }
57
- | { UnexpectedError: { error_message: string } }
56
+ | { refunded: { gateway_error: string } }
57
+ | { unexpected_error: { error_message: string } }
58
58
 
59
59
  type LnReceiveState =
60
- | 'Created'
61
- | { WaitingForPayment: { invoice: string; timeout: number } }
62
- | { Canceled: { reason: string } }
63
- | 'Funded'
64
- | 'AwaitingFunds'
65
- | 'Claimed'
60
+ | 'created'
61
+ | { waiting_for_payment: { invoice: string; timeout: number } }
62
+ | { canceled: { reason: string } }
63
+ | 'funded'
64
+ | 'awaiting_funds'
65
+ | 'claimed'
66
66
 
67
67
  type CreateBolt11Response = {
68
68
  operation_id: string
@@ -94,6 +94,12 @@ type StreamResult<T extends JSONValue> =
94
94
 
95
95
  type CancelFunction = () => void
96
96
 
97
+ type ReissueExternalNotesState =
98
+ | 'Created'
99
+ | 'Issuing'
100
+ | 'Done'
101
+ | { Failed: { error: string } }
102
+
97
103
  export {
98
104
  JSONValue,
99
105
  JSONObject,
@@ -111,4 +117,5 @@ export {
111
117
  StreamResult,
112
118
  ModuleKind,
113
119
  CancelFunction,
120
+ ReissueExternalNotesState,
114
121
  }
@@ -0,0 +1,61 @@
1
+ const logLevels = ['debug', 'info', 'warn', 'error', 'none'] as const
2
+ export type LogLevel = (typeof logLevels)[number]
3
+
4
+ export class Logger {
5
+ private level: LogLevel
6
+
7
+ constructor(level: LogLevel = 'none') {
8
+ this.level = level
9
+ }
10
+
11
+ setLevel(level: LogLevel) {
12
+ this.level = level
13
+ }
14
+
15
+ coerceLevel(level: string): LogLevel {
16
+ if (logLevels.includes(level.toLocaleUpperCase() as LogLevel)) {
17
+ return level.toLocaleUpperCase() as LogLevel
18
+ }
19
+ return 'info'
20
+ }
21
+
22
+ log(level: string, message: string, ...args: any[]) {
23
+ const logLevel = this.coerceLevel(level)
24
+ if (!this.shouldLog(logLevel)) {
25
+ return
26
+ }
27
+ const consoleFn = console[logLevel]
28
+ consoleFn(`[${logLevel.toUpperCase()}] ${message}`, ...args)
29
+ }
30
+
31
+ debug(message: string, ...args: any[]) {
32
+ this.log('debug', message, ...args)
33
+ }
34
+
35
+ info(message: string, ...args: any[]) {
36
+ this.log('info', message, ...args)
37
+ }
38
+
39
+ warn(message: string, ...args: any[]) {
40
+ this.log('warn', message, ...args)
41
+ }
42
+
43
+ error(message: string, ...args: any[]) {
44
+ this.log('error', message, ...args)
45
+ }
46
+
47
+ private shouldLog(
48
+ messageLevel: LogLevel,
49
+ ): messageLevel is Exclude<LogLevel, 'none'> {
50
+ const levels: LogLevel[] = ['debug', 'info', 'warn', 'error', 'none']
51
+ const messageLevelIndex = levels.indexOf(messageLevel)
52
+ const currentLevelIndex = levels.indexOf(this.level)
53
+ return (
54
+ currentLevelIndex <= messageLevelIndex &&
55
+ this.level !== 'none' &&
56
+ messageLevel !== 'none'
57
+ )
58
+ }
59
+ }
60
+
61
+ export const logger = new Logger()
@@ -0,0 +1,229 @@
1
+ import {
2
+ CancelFunction,
3
+ JSONValue,
4
+ ModuleKind,
5
+ StreamError,
6
+ StreamResult,
7
+ } from '../types/wallet'
8
+ import { logger } from '../utils/logger'
9
+
10
+ // Handles communication with the wasm worker
11
+ // TODO: Move rpc stream management to a separate "SubscriptionManager" class
12
+ export class WorkerClient {
13
+ private worker: Worker
14
+ private requestCounter = 0
15
+ private requestCallbacks = new Map<number, (value: any) => void>()
16
+ private initPromise: Promise<void> | null = null
17
+
18
+ constructor() {
19
+ // Must create the URL inside the constructor for vite
20
+ this.worker = new Worker(new URL('./worker.js', import.meta.url), {
21
+ type: 'module',
22
+ })
23
+ this.worker.onmessage = this.handleWorkerMessage.bind(this)
24
+ this.worker.onerror = this.handleWorkerError.bind(this)
25
+ logger.info('WorkerClient instantiated')
26
+ logger.debug('WorkerClient', this.worker)
27
+ }
28
+
29
+ // Idempotent setup - Loads the wasm module
30
+ initialize() {
31
+ if (this.initPromise) return this.initPromise
32
+ this.initPromise = this.sendSingleMessage('init')
33
+ return this.initPromise
34
+ }
35
+
36
+ private handleWorkerLogs(event: MessageEvent) {
37
+ const { type, level, message, ...data } = event.data
38
+ logger.log(level, message, ...data)
39
+ }
40
+
41
+ private handleWorkerError(event: ErrorEvent) {
42
+ logger.error('Worker error', event)
43
+ }
44
+
45
+ private handleWorkerMessage(event: MessageEvent) {
46
+ const { type, requestId, ...data } = event.data
47
+ if (type === 'log') {
48
+ this.handleWorkerLogs(event.data)
49
+ }
50
+ const streamCallback = this.requestCallbacks.get(requestId)
51
+ // TODO: Handle errors... maybe have another callbacks list for errors?
52
+ logger.debug('WorkerClient - handleWorkerMessage', event.data)
53
+ if (streamCallback) {
54
+ streamCallback(data) // {data: something} OR {error: something}
55
+ } else {
56
+ logger.warn(
57
+ 'WorkerClient - handleWorkerMessage - received message with no callback',
58
+ requestId,
59
+ event.data,
60
+ )
61
+ }
62
+ }
63
+
64
+ // TODO: Handle errors... maybe have another callbacks list for errors?
65
+ // TODO: Handle timeouts
66
+ // TODO: Handle multiple errors
67
+
68
+ sendSingleMessage(type: string, payload?: any): Promise<any> {
69
+ return new Promise((resolve, reject) => {
70
+ const requestId = ++this.requestCounter
71
+ logger.debug('WorkerClient - sendSingleMessage', requestId, type, payload)
72
+ this.requestCallbacks.set(requestId, (response) => {
73
+ this.requestCallbacks.delete(requestId)
74
+ logger.debug(
75
+ 'WorkerClient - sendSingleMessage - response',
76
+ requestId,
77
+ response,
78
+ )
79
+ if (response.data) resolve(response.data)
80
+ else if (response.error) reject(response.error)
81
+ else
82
+ logger.warn(
83
+ 'WorkerClient - sendSingleMessage - malformed response',
84
+ requestId,
85
+ response,
86
+ )
87
+ })
88
+ this.worker.postMessage({ type, payload, requestId })
89
+ })
90
+ }
91
+
92
+ /**
93
+ * @summary Initiates an RPC stream with the specified module and method.
94
+ *
95
+ * @description
96
+ * This function sets up an RPC stream by sending a request to a worker and
97
+ * handling responses asynchronously. It ensures that unsubscription is handled
98
+ * correctly, even if the unsubscribe function is called before the subscription
99
+ * is fully established, by deferring the unsubscription attempt using `setTimeout`.
100
+ *
101
+ * The function operates in a non-blocking manner, leveraging Promises to manage
102
+ * asynchronous operations and callbacks to handle responses.
103
+ *
104
+ *
105
+ * @template Response - The expected type of the successful response.
106
+ * @template Body - The type of the request body.
107
+ * @param module - The module kind to interact with.
108
+ * @param method - The method name to invoke on the module.
109
+ * @param body - The request payload.
110
+ * @param onSuccess - Callback invoked with the response data on success.
111
+ * @param onError - Callback invoked with error information if an error occurs.
112
+ * @param onEnd - Optional callback invoked when the stream ends.
113
+ * @returns A function that can be called to cancel the subscription.
114
+ *
115
+ */
116
+ rpcStream<
117
+ Response extends JSONValue = JSONValue,
118
+ Body extends JSONValue = JSONValue,
119
+ >(
120
+ module: ModuleKind,
121
+ method: string,
122
+ body: Body,
123
+ onSuccess: (res: Response) => void,
124
+ onError: (res: StreamError['error']) => void,
125
+ onEnd: () => void = () => {},
126
+ ): CancelFunction {
127
+ const requestId = ++this.requestCounter
128
+ logger.debug('WorkerClient - rpcStream', requestId, module, method, body)
129
+ let unsubscribe: (value: void) => void = () => {}
130
+ let isSubscribed = false
131
+
132
+ const unsubscribePromise = new Promise<void>((resolve) => {
133
+ unsubscribe = () => {
134
+ if (isSubscribed) {
135
+ // If already subscribed, resolve immediately to trigger unsubscription
136
+ resolve()
137
+ } else {
138
+ // If not yet subscribed, defer the unsubscribe attempt to the next event loop tick
139
+ // This ensures that subscription setup has time to complete
140
+ setTimeout(() => unsubscribe(), 0)
141
+ }
142
+ }
143
+ })
144
+
145
+ // Initiate the inner RPC stream setup asynchronously
146
+ this._rpcStreamInner(
147
+ requestId,
148
+ module,
149
+ method,
150
+ body,
151
+ onSuccess,
152
+ onError,
153
+ onEnd,
154
+ unsubscribePromise,
155
+ ).then(() => {
156
+ isSubscribed = true
157
+ })
158
+
159
+ return unsubscribe
160
+ }
161
+
162
+ private async _rpcStreamInner<
163
+ Response extends JSONValue = JSONValue,
164
+ Body extends JSONValue = JSONValue,
165
+ >(
166
+ requestId: number,
167
+ module: ModuleKind,
168
+ method: string,
169
+ body: Body,
170
+ onSuccess: (res: Response) => void,
171
+ onError: (res: StreamError['error']) => void,
172
+ onEnd: () => void = () => {},
173
+ unsubscribePromise: Promise<void>,
174
+ // Unsubscribe function
175
+ ): Promise<void> {
176
+ // await this.openPromise
177
+ // if (!this.worker || !this._isOpen)
178
+ // throw new Error('FedimintWallet is not open')
179
+
180
+ this.requestCallbacks.set(requestId, (response: StreamResult<Response>) => {
181
+ if (response.error !== undefined) {
182
+ onError(response.error)
183
+ } else if (response.data !== undefined) {
184
+ onSuccess(response.data)
185
+ } else if (response.end !== undefined) {
186
+ this.requestCallbacks.delete(requestId)
187
+ onEnd()
188
+ }
189
+ })
190
+ this.worker.postMessage({
191
+ type: 'rpc',
192
+ payload: { module, method, body },
193
+ requestId,
194
+ })
195
+
196
+ unsubscribePromise.then(() => {
197
+ this.worker?.postMessage({
198
+ type: 'unsubscribe',
199
+ requestId,
200
+ })
201
+ this.requestCallbacks.delete(requestId)
202
+ })
203
+ }
204
+
205
+ rpcSingle<Response extends JSONValue = JSONValue>(
206
+ module: ModuleKind,
207
+ method: string,
208
+ body: JSONValue,
209
+ ): Promise<Response> {
210
+ logger.debug('WorkerClient - rpcSingle', module, method, body)
211
+ return new Promise((resolve, reject) => {
212
+ this.rpcStream<Response>(module, method, body, resolve, reject)
213
+ })
214
+ }
215
+
216
+ cleanup() {
217
+ this.worker.terminate()
218
+ this.initPromise = null
219
+ this.requestCallbacks.clear()
220
+ }
221
+
222
+ // For Testing
223
+ _getRequestCounter() {
224
+ return this.requestCounter
225
+ }
226
+ _getRequestCallbackMap() {
227
+ return this.requestCallbacks
228
+ }
229
+ }
@@ -0,0 +1 @@
1
+ export { WorkerClient } from './WorkerClient'
@@ -0,0 +1,96 @@
1
+ // Web Worker for fedimint-client-wasm to run in the browser
2
+
3
+ // HACK: Fixes vitest browser runner
4
+ // TODO: remove once https://github.com/vitest-dev/vitest/pull/6569 lands in a release
5
+ globalThis.__vitest_browser_runner__ = { wrapDynamicImport: (foo) => foo() }
6
+
7
+ // dynamically imported Constructor for WasmClient
8
+ let WasmClient = null
9
+ // client instance
10
+ let client = null
11
+
12
+ const streamCancelMap = new Map()
13
+
14
+ const handleFree = (requestId) => {
15
+ streamCancelMap.delete(requestId)
16
+ }
17
+
18
+ console.log('Worker - init')
19
+
20
+ self.onmessage = async (event) => {
21
+ const { type, payload, requestId } = event.data
22
+
23
+ try {
24
+ if (type === 'init') {
25
+ WasmClient = (await import('@fedimint/fedimint-client-wasm-bundler'))
26
+ .WasmClient
27
+ self.postMessage({ type: 'initialized', data: {}, requestId })
28
+ } else if (type === 'open') {
29
+ const { clientName } = payload
30
+ client = (await WasmClient.open(clientName)) || null
31
+ self.postMessage({
32
+ type: 'open',
33
+ data: { success: !!client },
34
+ requestId,
35
+ })
36
+ } else if (type === 'join') {
37
+ const { inviteCode, clientName: joinClientName } = payload
38
+ try {
39
+ client = await WasmClient.join_federation(joinClientName, inviteCode)
40
+ self.postMessage({
41
+ type: 'join',
42
+ data: { success: !!client },
43
+ requestId,
44
+ })
45
+ } catch (e) {
46
+ self.postMessage({ type: 'error', error: e.message, requestId })
47
+ }
48
+ } else if (type === 'rpc') {
49
+ const { module, method, body } = payload
50
+ console.log('RPC received', module, method, body)
51
+ if (!client) {
52
+ self.postMessage({
53
+ type: 'error',
54
+ error: 'WasmClient not initialized',
55
+ requestId,
56
+ })
57
+ return
58
+ }
59
+ const rpcHandle = await client.rpc(
60
+ module,
61
+ method,
62
+ JSON.stringify(body),
63
+ (res) => {
64
+ console.log('RPC response', requestId, res)
65
+ const data = JSON.parse(res)
66
+ self.postMessage({ type: 'rpcResponse', requestId, ...data })
67
+
68
+ if (data.end !== undefined) {
69
+ // Handle stream ending
70
+ const handle = streamCancelMap.get(requestId)
71
+ handle?.free()
72
+ }
73
+ },
74
+ )
75
+ streamCancelMap.set(requestId, rpcHandle)
76
+ } else if (type === 'unsubscribe') {
77
+ const rpcHandle = streamCancelMap.get(requestId)
78
+ if (rpcHandle) {
79
+ rpcHandle.cancel()
80
+ rpcHandle.free()
81
+ streamCancelMap.delete(requestId)
82
+ }
83
+ } else {
84
+ self.postMessage({
85
+ type: 'error',
86
+ error: 'Unknown message type',
87
+ requestId,
88
+ })
89
+ }
90
+ } catch (e) {
91
+ console.error('ERROR', e)
92
+ self.postMessage({ type: 'error', error: e, requestId })
93
+ }
94
+ }
95
+
96
+ // self.postMessage({ type: 'init', data: {} })
@@ -0,0 +1,90 @@
1
+ import { expect } from 'vitest'
2
+ import { JSONObject } from '../types/wallet'
3
+ import { TESTING_INVITE } from '../test/TestingService'
4
+ import { workerTest } from '../test/setupTests'
5
+
6
+ // Waits for a message of a given type from the worker
7
+ const waitForWorkerResponse = (
8
+ worker: Worker,
9
+ messageType: string,
10
+ ): Promise<JSONObject> => {
11
+ return new Promise((resolve, reject) => {
12
+ worker.onmessage = (event) => {
13
+ if (event.data.type === messageType) {
14
+ resolve(event.data)
15
+ } else if (event.data.type === 'error') {
16
+ reject(event.data.error)
17
+ }
18
+ }
19
+ worker.onerror = (error) => {
20
+ reject(error.message)
21
+ }
22
+ })
23
+ }
24
+
25
+ workerTest(
26
+ 'should initialize WasmClient on init message',
27
+ async ({ worker }) => {
28
+ worker.postMessage({ type: 'init', requestId: 1 })
29
+ const response = await waitForWorkerResponse(worker, 'initialized')
30
+ expect(response.data).toEqual({})
31
+ },
32
+ )
33
+
34
+ workerTest(
35
+ 'should return false on open for a new client',
36
+ async ({ worker, clientName }) => {
37
+ worker.postMessage({ type: 'init', requestId: 1 })
38
+ await waitForWorkerResponse(worker, 'initialized')
39
+
40
+ worker.postMessage({
41
+ type: 'open',
42
+ requestId: 2,
43
+ payload: { clientName },
44
+ })
45
+ const response = await waitForWorkerResponse(worker, 'open')
46
+ expect(response.data).toEqual({ success: false })
47
+ },
48
+ )
49
+
50
+ workerTest(
51
+ 'should error on fake federation invitation',
52
+ async ({ worker, clientName }) => {
53
+ worker.postMessage({ type: 'init', requestId: 1 })
54
+ await waitForWorkerResponse(worker, 'initialized')
55
+
56
+ worker.postMessage({
57
+ type: 'join',
58
+ requestId: 2,
59
+ payload: { inviteCode: 'fakefederationinvitation', clientName },
60
+ })
61
+ try {
62
+ await waitForWorkerResponse(worker, 'open')
63
+ expect.unreachable()
64
+ } catch (e) {
65
+ expect(e).toBe('parsing failed')
66
+ }
67
+ },
68
+ )
69
+
70
+ workerTest(
71
+ 'should handle joining a federation',
72
+ async ({ worker, clientName }) => {
73
+ worker.postMessage({ type: 'init', requestId: 1 })
74
+ await waitForWorkerResponse(worker, 'initialized')
75
+
76
+ worker.postMessage({
77
+ type: 'join',
78
+ requestId: 2,
79
+ payload: { inviteCode: TESTING_INVITE, clientName },
80
+ })
81
+ const response = await waitForWorkerResponse(worker, 'join')
82
+ expect(response.data).toEqual({ success: true })
83
+ },
84
+ )
85
+
86
+ workerTest('should handle unknown message type', async ({ worker }) => {
87
+ worker.postMessage({ type: 'unknown', requestId: 2 })
88
+ const response = await waitForWorkerResponse(worker, 'error')
89
+ expect(response.error).toBe('Unknown message type')
90
+ })
@@ -1,49 +0,0 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
- /**
4
- */
5
- export class RpcHandle {
6
- free(): void
7
- /**
8
- */
9
- cancel(): void
10
- }
11
- /**
12
- */
13
- export class WasmClient {
14
- free(): void
15
- /**
16
- * Open fedimint client with already joined federation.
17
- *
18
- * After you have joined a federation, you can reopen the fedimint client
19
- * with same client_name. Opening client with same name at same time is
20
- * not supported. You can close the current client by calling
21
- * `client.free()`. NOTE: The client will remain active until all the
22
- * running rpc calls have finished.
23
- * @param {string} client_name
24
- * @returns {Promise<WasmClient | undefined>}
25
- */
26
- static open(client_name: string): Promise<WasmClient | undefined>
27
- /**
28
- * Open a fedimint client by join a federation.
29
- * @param {string} client_name
30
- * @param {string} invite_code
31
- * @returns {Promise<WasmClient>}
32
- */
33
- static join_federation(
34
- client_name: string,
35
- invite_code: string,
36
- ): Promise<WasmClient>
37
- /**
38
- * Call a fedimint client rpc the responses are returned using `cb`
39
- * callback. Each rpc call *can* return multiple responses by calling
40
- * `cb` multiple times. The returned RpcHandle can be used to cancel the
41
- * operation.
42
- * @param {string} module
43
- * @param {string} method
44
- * @param {string} payload
45
- * @param {Function} cb
46
- * @returns {RpcHandle}
47
- */
48
- rpc(module: string, method: string, payload: string, cb: Function): RpcHandle
49
- }
@@ -1,4 +0,0 @@
1
- import * as wasm from './fedimint_client_wasm_bg.wasm'
2
- import { __wbg_set_wasm } from './fedimint_client_wasm_bg.js'
3
- __wbg_set_wasm(wasm)
4
- export * from './fedimint_client_wasm_bg.js'