@fedimint/transport-web 0.1.0 → 0.1.2

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.
@@ -1,12 +1,9 @@
1
- import type { Transport, TransportErrorHandler, TransportLogger, TransportMessageHandler, TransportRequest } from '@fedimint/types';
2
- export declare class WasmWorkerTransport implements Transport {
3
- private messageHandler;
4
- private errorHandler;
1
+ import type { TransportLogger, TransportRequest } from '@fedimint/types';
2
+ import { Transport } from '@fedimint/types';
3
+ export declare class WasmWorkerTransport extends Transport {
5
4
  private readonly worker;
6
5
  logger: TransportLogger;
7
6
  constructor();
8
7
  postMessage(message: TransportRequest): void;
9
- setMessageHandler(handler: TransportMessageHandler): void;
10
- setErrorHandler(handler: TransportErrorHandler): void;
11
8
  }
12
9
  //# sourceMappingURL=WasmWorkerTransport.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WasmWorkerTransport.d.ts","sourceRoot":"","sources":["../../src/WasmWorkerTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,iBAAiB,CAAA;AAExB,qBAAa,mBAAoB,YAAW,SAAS;IACnD,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAE/B,MAAM,EAAE,eAAe,CAAU;;IAcjC,WAAW,CAAC,OAAO,EAAE,gBAAgB;IAIrC,iBAAiB,CAAC,OAAO,EAAE,uBAAuB;IAIlD,eAAe,CAAC,OAAO,EAAE,qBAAqB;CAG/C"}
1
+ {"version":3,"file":"WasmWorkerTransport.d.ts","sourceRoot":"","sources":["../../src/WasmWorkerTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,qBAAa,mBAAoB,SAAQ,SAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAE/B,MAAM,EAAE,eAAe,CAAU;;IAejC,WAAW,CAAC,OAAO,EAAE,gBAAgB;CAGtC"}
package/dist/index.d.ts CHANGED
@@ -1,14 +1,10 @@
1
- import { Transport, TransportLogger, TransportRequest, TransportMessageHandler, TransportErrorHandler } from '@fedimint/types';
1
+ import { Transport, TransportLogger, TransportRequest } from '@fedimint/types';
2
2
 
3
- declare class WasmWorkerTransport implements Transport {
4
- private messageHandler;
5
- private errorHandler;
3
+ declare class WasmWorkerTransport extends Transport {
6
4
  private readonly worker;
7
5
  logger: TransportLogger;
8
6
  constructor();
9
7
  postMessage(message: TransportRequest): void;
10
- setMessageHandler(handler: TransportMessageHandler): void;
11
- setErrorHandler(handler: TransportErrorHandler): void;
12
8
  }
13
9
 
14
10
  declare const createWasmWorker: () => Worker;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- class e{constructor(){this.messageHandler=()=>{},this.errorHandler=()=>{},this.logger=console,this.worker=new Worker(new URL("./worker.js",import.meta.url),{type:"module"}),this.worker.onmessage=e=>{this.messageHandler(e.data)},this.worker.onerror=e=>{this.errorHandler(e)}}postMessage(e){this.worker.postMessage(e)}setMessageHandler(e){this.messageHandler=e}setErrorHandler(e){this.errorHandler=e}}const r=()=>new Worker(new URL("./worker.js",import.meta.url),{type:"module"}),s=()=>new e;export{e as WasmWorkerTransport,r as createWasmWorker,s as createWasmWorkerTransport};
1
+ import{Transport as e}from"@fedimint/types";class r extends e{constructor(){super(),this.logger=console,this.worker=new Worker(new URL("./worker.js",import.meta.url),{type:"module"}),this.worker.onmessage=e=>{this.messageHandler(e.data)},this.worker.onerror=e=>{this.errorHandler(e)}}postMessage(e){this.worker.postMessage(e)}}const o=()=>new Worker(new URL("./worker.js",import.meta.url),{type:"module"}),s=()=>new r;export{r as WasmWorkerTransport,o as createWasmWorker,s as createWasmWorkerTransport};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/WasmWorkerTransport.ts","../src/index.ts"],"sourcesContent":[null,null],"names":["WasmWorkerTransport","constructor","this","messageHandler","errorHandler","logger","console","worker","Worker","URL","url","type","onmessage","event","data","onerror","postMessage","message","setMessageHandler","handler","setErrorHandler","createWasmWorker","createWasmWorkerTransport"],"mappings":"MAQaA,EAOX,WAAAC,GANQC,KAAAC,eAA0C,OAC1CD,KAAAE,aAAsC,OAG9CF,KAAAG,OAA0BC,QAGxBJ,KAAKK,OAAS,IAAIC,OAAO,IAAIC,IAAI,0BAA2BC,KAAM,CAChEC,KAAM,WAERT,KAAKK,OAAOK,UAAaC,IACvBX,KAAKC,eAAeU,EAAMC,KAAK,EAEjCZ,KAAKK,OAAOQ,QAAWF,IACrBX,KAAKE,aAAaS,EAAM,CAE5B,CAEA,WAAAG,CAAYC,GACVf,KAAKK,OAAOS,YAAYC,EAC1B,CAEA,iBAAAC,CAAkBC,GAChBjB,KAAKC,eAAiBgB,CACxB,CAEA,eAAAC,CAAgBD,GACdjB,KAAKE,aAAee,CACtB,ECjCK,MAAME,EAAmB,IAC9B,IAAIb,OAAO,IAAIC,IAAI,0BAA2BC,KAAM,CAAEC,KAAM,WAEjDW,EAA4B,IAAM,IAAItB"}
1
+ {"version":3,"file":"index.js","sources":["../src/WasmWorkerTransport.ts","../src/index.ts"],"sourcesContent":[null,null],"names":["WasmWorkerTransport","Transport","constructor","super","this","logger","console","worker","Worker","URL","url","type","onmessage","event","messageHandler","data","onerror","errorHandler","postMessage","message","createWasmWorker","createWasmWorkerTransport"],"mappings":"4CAGM,MAAOA,UAA4BC,EAKvC,WAAAC,GACEC,QAHFC,KAAAC,OAA0BC,QAIxBF,KAAKG,OAAS,IAAIC,OAAO,IAAIC,IAAI,0BAA2BC,KAAM,CAChEC,KAAM,WAERP,KAAKG,OAAOK,UAAaC,IACvBT,KAAKU,eAAeD,EAAME,KAAK,EAEjCX,KAAKG,OAAOS,QAAWH,IACrBT,KAAKa,aAAaJ,EAAM,CAE5B,CAEA,WAAAK,CAAYC,GACVf,KAAKG,OAAOW,YAAYC,EAC1B,ECnBK,MAAMC,EAAmB,IAC9B,IAAIZ,OAAO,IAAIC,IAAI,0BAA2BC,KAAM,CAAEC,KAAM,WAEjDU,EAA4B,IAAM,IAAIrB"}
package/dist/worker.js CHANGED
@@ -1,2 +1,2 @@
1
- globalThis.__vitest_browser_runner__={wrapDynamicImport:e=>e()};let e=null,s=null;const t=new Map;console.log("Worker - init"),self.onmessage=async r=>{const{type:o,payload:a,requestId:i}=r.data;try{if("init"===o)e=(await import("@fedimint/fedimint-client-wasm-bundler")).WasmClient,self.postMessage({type:"initialized",data:{},requestId:i});else if("open"===o){const{clientName:t}=a;s=await e.open(t)||null,self.postMessage({type:"open",data:{success:!!s},requestId:i})}else if("join"===o){const{inviteCode:t,clientName:r}=a;try{s=await e.join_federation(r,t),self.postMessage({type:"join",data:{success:!!s},requestId:i})}catch(e){self.postMessage({type:"error",error:e.message,requestId:i})}}else if("previewFederation"===o){const{inviteCode:t}=a;try{s=await e.preview_federation(t);const r=JSON.parse(s);self.postMessage({type:"previewFederation",data:{success:!!s,config:r.config,federation_id:r.federation_id},requestId:i})}catch(e){self.postMessage({type:"error",error:e.message,requestId:i})}}else if("rpc"===o){const{module:e,method:r,body:o}=a;if(console.log("RPC received",e,r,o),!s)return void self.postMessage({type:"error",error:"WasmClient not initialized",requestId:i});const n=await s.rpc(e,r,JSON.stringify(o),(e=>{console.log("RPC response",i,e);const s=JSON.parse(e);if(self.postMessage({type:"rpcResponse",requestId:i,...s}),void 0!==s.end){const e=t.get(i);e?.free()}}));t.set(i,n)}else if("unsubscribe"===o){const e=t.get(i);e&&(e.cancel(),e.free(),t.delete(i))}else if("cleanup"===o)console.log("cleanup message received"),s?.free(),self.postMessage({type:"cleanup",data:{},requestId:i}),close();else if("parseInviteCode"===o){const{inviteCode:s}=a;try{const t=e.parse_invite_code(s),r=JSON.parse(t);self.postMessage({type:"parseInviteCode",data:r,requestId:i})}catch(e){self.postMessage({type:"error",error:`Failed to parse invite code: ${e.message}`,requestId:i})}}else if("parseBolt11Invoice"===o){const{invoiceStr:s}=a;try{const t=e.parse_bolt11_invoice(s),r=JSON.parse(t);self.postMessage({type:"parseBolt11Invoice",data:r,requestId:i})}catch(e){self.postMessage({type:"error",error:`Failed to parse invoice: ${e.message}`,requestId:i})}}else self.postMessage({type:"error",error:"Unknown message type",requestId:i})}catch(e){console.error("ERROR",e),self.postMessage({type:"error",error:e,requestId:i})}};
1
+ let e;globalThis.__vitest_browser_runner__={wrapDynamicImport:e=>e()};let s=null,r=null;console.log("Worker - init"),self.onmessage=async t=>{const{type:a,payload:i,requestId:n}=t.data;try{if("init"===a){const t=(await import("@fedimint/fedimint-client-wasm-bundler")).RpcHandler,a=await navigator.storage.getDirectory(),o=i?.filename||"fedimint.db";r=o;const l=await a.getFileHandle(o,{create:!0});s=await l.createSyncAccessHandle(),e=new t(s),self.postMessage({type:"initialized",data:{filename:o},request_id:n})}else if("set_mnemonic"===a||"generate_mnemonic"===a||"get_mnemonic"===a||"join_federation"===a||"open_client"===a||"close_client"===a||"client_rpc"===a||"cancel_rpc"===a||"parse_invite_code"===a||"parse_bolt11_invoice"===a||"preview_federation"===a){if(self.postMessage({type:"log",level:"info",message:"RPC received",request_type:a,requestId:n,payload:i}),!e)return void self.postMessage({type:"error",error:"rpcHandler not initialized",request_id:n});const s=JSON.stringify({request_id:n,type:a,...i});e.rpc(s,(e=>self.postMessage(JSON.parse(e))))}else"cleanup"===a?(console.log("cleanup message received"),s?.close(),e?.free(),self.postMessage({type:"cleanup",data:{filename:r},request_id:n}),close()):self.postMessage({type:"error",error:"Unknown message type",request_id:n})}catch(e){console.error("ERROR",e),self.postMessage({type:"error",error:e.message,request_id:n})}},self.onerror=e=>{self.postMessage({type:"error",error:e.message})};
2
2
  //# sourceMappingURL=worker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sources":["../src/worker.js"],"sourcesContent":["// Web Worker for fedimint-client-wasm to run in the browser\n\n// HACK: Fixes vitest browser runner\n// TODO: remove once https://github.com/vitest-dev/vitest/pull/6569 lands in a release\nglobalThis.__vitest_browser_runner__ = { wrapDynamicImport: (foo) => foo() }\n\n// dynamically imported Constructor for WasmClient\nlet WasmClient = null\n// client instance\nlet client = null\n\nconst streamCancelMap = new Map()\n\nconst handleFree = (requestId) => {\n streamCancelMap.delete(requestId)\n}\n\nconsole.log('Worker - init')\n\n/**\n * Type definitions for the worker messages\n *\n * @typedef {import('@fedimint/types').TransportMessageType} WorkerMessageType\n * @typedef {{\n * type: WorkerMessageType\n * payload: any\n * requestId: number\n * }} WorkerMessage\n * @param {{data: WorkerMessage}} event\n */\nself.onmessage = async (event) => {\n const { type, payload, requestId } = event.data\n\n try {\n if (type === 'init') {\n WasmClient = (await import('@fedimint/fedimint-client-wasm-bundler'))\n .WasmClient\n self.postMessage({ type: 'initialized', data: {}, requestId })\n } else if (type === 'open') {\n const { clientName } = payload\n client = (await WasmClient.open(clientName)) || null\n self.postMessage({\n type: 'open',\n data: { success: !!client },\n requestId,\n })\n } else if (type === 'join') {\n const { inviteCode, clientName: joinClientName } = payload\n try {\n client = await WasmClient.join_federation(joinClientName, inviteCode)\n self.postMessage({\n type: 'join',\n data: { success: !!client },\n requestId,\n })\n } catch (e) {\n self.postMessage({ type: 'error', error: e.message, requestId })\n }\n } else if (type === 'previewFederation') {\n const { inviteCode } = payload\n try {\n client = await WasmClient.preview_federation(inviteCode)\n const parsed = JSON.parse(client)\n self.postMessage({\n type: 'previewFederation',\n data: {\n success: !!client,\n config: parsed.config,\n federation_id: parsed.federation_id,\n },\n requestId,\n })\n } catch (e) {\n self.postMessage({ type: 'error', error: e.message, requestId })\n }\n } else if (type === 'rpc') {\n const { module, method, body } = payload\n console.log('RPC received', module, method, body)\n if (!client) {\n self.postMessage({\n type: 'error',\n error: 'WasmClient not initialized',\n requestId,\n })\n return\n }\n const rpcHandle = await client.rpc(\n module,\n method,\n JSON.stringify(body),\n (res) => {\n console.log('RPC response', requestId, res)\n const data = JSON.parse(res)\n self.postMessage({ type: 'rpcResponse', requestId, ...data })\n\n if (data.end !== undefined) {\n // Handle stream ending\n const handle = streamCancelMap.get(requestId)\n handle?.free()\n }\n },\n )\n streamCancelMap.set(requestId, rpcHandle)\n } else if (type === 'unsubscribe') {\n const rpcHandle = streamCancelMap.get(requestId)\n if (rpcHandle) {\n rpcHandle.cancel()\n rpcHandle.free()\n streamCancelMap.delete(requestId)\n }\n } else if (type === 'cleanup') {\n console.log('cleanup message received')\n client?.free()\n self.postMessage({\n type: 'cleanup',\n data: {},\n requestId,\n })\n close()\n } else if (type === 'parseInviteCode') {\n const { inviteCode } = payload\n try {\n const res = WasmClient.parse_invite_code(inviteCode)\n const parsedRes = JSON.parse(res)\n self.postMessage({\n type: 'parseInviteCode',\n data: parsedRes,\n requestId,\n })\n } catch (error) {\n self.postMessage({\n type: 'error',\n error: `Failed to parse invite code: ${error.message}`,\n requestId,\n })\n }\n } else if (type === 'parseBolt11Invoice') {\n const { invoiceStr } = payload\n try {\n const res = WasmClient.parse_bolt11_invoice(invoiceStr)\n const parsedRes = JSON.parse(res)\n self.postMessage({\n type: 'parseBolt11Invoice',\n data: parsedRes,\n requestId,\n })\n } catch (error) {\n self.postMessage({\n type: 'error',\n error: `Failed to parse invoice: ${error.message}`,\n requestId,\n })\n }\n } else {\n self.postMessage({\n type: 'error',\n error: 'Unknown message type',\n requestId,\n })\n }\n } catch (e) {\n console.error('ERROR', e)\n self.postMessage({ type: 'error', error: e, requestId })\n }\n}\n\n// self.postMessage({ type: 'init', data: {} })\n"],"names":["globalThis","__vitest_browser_runner__","wrapDynamicImport","foo","WasmClient","client","streamCancelMap","Map","console","log","self","onmessage","async","event","type","payload","requestId","data","import","postMessage","clientName","open","success","inviteCode","joinClientName","join_federation","e","error","message","preview_federation","parsed","JSON","parse","config","federation_id","module","method","body","rpcHandle","rpc","stringify","res","undefined","end","handle","get","free","set","cancel","delete","close","parse_invite_code","parsedRes","invoiceStr","parse_bolt11_invoice"],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","sources":["../src/worker.js"],"sourcesContent":["// Web Worker for fedimint-client-wasm to run in the browser\n\n// HACK: Fixes vitest browser runner\n// TODO: remove once https://github.com/vitest-dev/vitest/pull/6569 lands in a release\nglobalThis.__vitest_browser_runner__ = { wrapDynamicImport: (foo) => foo() }\n\n// dynamically imported rpcHandler\n/** @type {import('@fedimint/fedimint-client-wasm-bundler').RpcHandler} */\nlet rpcHandler\nlet dbSyncHandle = null\nlet dbFilename = null\n\nconsole.log('Worker - init')\n\n/**\n * Type definitions for the worker messages\n *\n * @typedef {import('@fedimint/types').TransportMessageType} WorkerMessageType\n * @typedef {{\n * type: WorkerMessageType\n * payload: any\n * requestId: number\n * }} WorkerMessage\n * @param {{data: WorkerMessage}} event\n */\nself.onmessage = async (event) => {\n const { type, payload, requestId } = event.data\n\n try {\n if (type === 'init') {\n const RpcHandler = (\n await import('@fedimint/fedimint-client-wasm-bundler')\n ).RpcHandler\n\n const root = await navigator.storage.getDirectory()\n // Allows to pass in a filename for testing\n const filename = payload?.filename || 'fedimint.db'\n dbFilename = filename\n const dbFileHandle = await root.getFileHandle(filename, {\n create: true,\n })\n dbSyncHandle = await dbFileHandle.createSyncAccessHandle()\n rpcHandler = new RpcHandler(dbSyncHandle)\n self.postMessage({\n type: 'initialized',\n data: { filename },\n request_id: requestId,\n })\n } else if (\n type === 'set_mnemonic' ||\n type === 'generate_mnemonic' ||\n type === 'get_mnemonic' ||\n type === 'join_federation' ||\n type === 'open_client' ||\n type === 'close_client' ||\n type === 'client_rpc' ||\n type === 'cancel_rpc' ||\n type === 'parse_invite_code' ||\n type === 'parse_bolt11_invoice' ||\n type === 'preview_federation'\n ) {\n self.postMessage({\n type: 'log',\n level: 'info',\n message: `RPC received`,\n request_type: type,\n requestId,\n payload,\n })\n if (!rpcHandler) {\n self.postMessage({\n type: 'error',\n error: 'rpcHandler not initialized',\n request_id: requestId,\n })\n return\n }\n const rpcRequest = JSON.stringify({\n request_id: requestId,\n type,\n ...payload,\n })\n rpcHandler.rpc(rpcRequest, (response) =>\n self.postMessage(JSON.parse(response)),\n )\n } else if (type === 'cleanup') {\n console.log('cleanup message received')\n dbSyncHandle?.close()\n rpcHandler?.free()\n self.postMessage({\n type: 'cleanup',\n data: { filename: dbFilename },\n request_id: requestId,\n })\n close()\n } else {\n self.postMessage({\n type: 'error',\n error: 'Unknown message type',\n request_id: requestId,\n })\n }\n } catch (e) {\n console.error('ERROR', e)\n self.postMessage({ type: 'error', error: e.message, request_id: requestId })\n }\n}\n\nself.onerror = (e) => {\n self.postMessage({ type: 'error', error: e.message })\n}\n"],"names":["rpcHandler","globalThis","__vitest_browser_runner__","wrapDynamicImport","foo","dbSyncHandle","dbFilename","console","log","self","onmessage","async","event","type","payload","requestId","data","RpcHandler","import","root","navigator","storage","getDirectory","filename","dbFileHandle","getFileHandle","create","createSyncAccessHandle","postMessage","request_id","level","message","request_type","error","rpcRequest","JSON","stringify","rpc","response","parse","close","free","e","onerror"],"mappings":"AAQA,IAAIA,EAJJC,WAAWC,0BAA4B,CAAEC,kBAAoBC,GAAQA,KAKrE,IAAIC,EAAe,KACfC,EAAa,KAEjBC,QAAQC,IAAI,iBAaZC,KAAKC,UAAYC,MAAOC,IACtB,MAAMC,KAAEA,EAAIC,QAAEA,EAAOC,UAAEA,GAAcH,EAAMI,KAE3C,IACE,GAAa,SAATH,EAAiB,CACnB,MAAMI,SACEC,OAAO,2CACbD,WAEIE,QAAaC,UAAUC,QAAQC,eAE/BC,EAAWT,GAASS,UAAY,cACtCjB,EAAaiB,EACb,MAAMC,QAAqBL,EAAKM,cAAcF,EAAU,CACtDG,QAAQ,IAEVrB,QAAqBmB,EAAaG,yBAClC3B,EAAa,IAAIiB,EAAWZ,GAC5BI,KAAKmB,YAAY,CACff,KAAM,cACNG,KAAM,CAAEO,YACRM,WAAYd,GAEhB,MAAO,GACI,iBAATF,GACS,sBAATA,GACS,iBAATA,GACS,oBAATA,GACS,gBAATA,GACS,iBAATA,GACS,eAATA,GACS,eAATA,GACS,sBAATA,GACS,yBAATA,GACS,uBAATA,EACA,CASA,GARAJ,KAAKmB,YAAY,CACff,KAAM,MACNiB,MAAO,OACPC,QAAS,eACTC,aAAcnB,EACdE,YACAD,aAEGd,EAMH,YALAS,KAAKmB,YAAY,CACff,KAAM,QACNoB,MAAO,6BACPJ,WAAYd,IAIhB,MAAMmB,EAAaC,KAAKC,UAAU,CAChCP,WAAYd,EACZF,UACGC,IAELd,EAAWqC,IAAIH,GAAaI,GAC1B7B,KAAKmB,YAAYO,KAAKI,MAAMD,KAEhC,KAAoB,YAATzB,GACTN,QAAQC,IAAI,4BACZH,GAAcmC,QACdxC,GAAYyC,OACZhC,KAAKmB,YAAY,CACff,KAAM,UACNG,KAAM,CAAEO,SAAUjB,GAClBuB,WAAYd,IAEdyB,SAEA/B,KAAKmB,YAAY,CACff,KAAM,QACNoB,MAAO,uBACPJ,WAAYd,GAGlB,CAAE,MAAO2B,GACPnC,QAAQ0B,MAAM,QAASS,GACvBjC,KAAKmB,YAAY,CAAEf,KAAM,QAASoB,MAAOS,EAAEX,QAASF,WAAYd,GAClE,GAGFN,KAAKkC,QAAWD,IACdjC,KAAKmB,YAAY,CAAEf,KAAM,QAASoB,MAAOS,EAAEX,SAAS"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fedimint/transport-web",
3
3
  "description": "Web worker transport for the Fedimint client",
4
- "version": "0.1.0",
4
+ "version": "0.1.2",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/fedimint/fedimint-web-sdk.git",
@@ -18,21 +18,21 @@
18
18
  "./dist/worker.js"
19
19
  ],
20
20
  "dependencies": {
21
- "@fedimint/fedimint-client-wasm-bundler": "0.1.0",
22
- "@fedimint/types": "0.0.2"
21
+ "@fedimint/fedimint-client-wasm-bundler": "0.1.1",
22
+ "@fedimint/types": "0.0.3"
23
23
  },
24
24
  "peerDependencies": {
25
- "@fedimint/core": "0.1.1"
25
+ "@fedimint/core": "0.1.3"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@rollup/plugin-terser": "^0.4.4",
29
29
  "@rollup/plugin-typescript": "^11.1.6",
30
- "@types/node": "^20.17.49",
31
- "rollup": "^4.41.0",
32
- "rollup-plugin-dts": "^6.2.1",
30
+ "@types/node": "^22.5.5",
31
+ "rollup": "^4.52.4",
32
+ "rollup-plugin-dts": "^6.2.3",
33
33
  "rollup-plugin-typescript2": "^0.36.0",
34
34
  "tslib": "^2.8.1",
35
- "typescript": "^5.8.3"
35
+ "typescript": "^5.9.3"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "rollup --config",
@@ -1,19 +1,13 @@
1
- import type {
2
- Transport,
3
- TransportErrorHandler,
4
- TransportLogger,
5
- TransportMessageHandler,
6
- TransportRequest,
7
- } from '@fedimint/types'
1
+ import type { TransportLogger, TransportRequest } from '@fedimint/types'
2
+ import { Transport } from '@fedimint/types'
8
3
 
9
- export class WasmWorkerTransport implements Transport {
10
- private messageHandler: TransportMessageHandler = () => {}
11
- private errorHandler: TransportErrorHandler = () => {}
4
+ export class WasmWorkerTransport extends Transport {
12
5
  private readonly worker: Worker
13
6
 
14
7
  logger: TransportLogger = console
15
8
 
16
9
  constructor() {
10
+ super()
17
11
  this.worker = new Worker(new URL('./worker.js', import.meta.url), {
18
12
  type: 'module',
19
13
  })
@@ -28,12 +22,4 @@ export class WasmWorkerTransport implements Transport {
28
22
  postMessage(message: TransportRequest) {
29
23
  this.worker.postMessage(message)
30
24
  }
31
-
32
- setMessageHandler(handler: TransportMessageHandler) {
33
- this.messageHandler = handler
34
- }
35
-
36
- setErrorHandler(handler: TransportErrorHandler) {
37
- this.errorHandler = handler
38
- }
39
25
  }
package/src/worker.js CHANGED
@@ -4,16 +4,11 @@
4
4
  // TODO: remove once https://github.com/vitest-dev/vitest/pull/6569 lands in a release
5
5
  globalThis.__vitest_browser_runner__ = { wrapDynamicImport: (foo) => foo() }
6
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
- }
7
+ // dynamically imported rpcHandler
8
+ /** @type {import('@fedimint/fedimint-client-wasm-bundler').RpcHandler} */
9
+ let rpcHandler
10
+ let dbSyncHandle = null
11
+ let dbFilename = null
17
12
 
18
13
  console.log('Worker - init')
19
14
 
@@ -33,135 +28,84 @@ self.onmessage = async (event) => {
33
28
 
34
29
  try {
35
30
  if (type === 'init') {
36
- WasmClient = (await import('@fedimint/fedimint-client-wasm-bundler'))
37
- .WasmClient
38
- self.postMessage({ type: 'initialized', data: {}, requestId })
39
- } else if (type === 'open') {
40
- const { clientName } = payload
41
- client = (await WasmClient.open(clientName)) || null
31
+ const RpcHandler = (
32
+ await import('@fedimint/fedimint-client-wasm-bundler')
33
+ ).RpcHandler
34
+
35
+ const root = await navigator.storage.getDirectory()
36
+ // Allows to pass in a filename for testing
37
+ const filename = payload?.filename || 'fedimint.db'
38
+ dbFilename = filename
39
+ const dbFileHandle = await root.getFileHandle(filename, {
40
+ create: true,
41
+ })
42
+ dbSyncHandle = await dbFileHandle.createSyncAccessHandle()
43
+ rpcHandler = new RpcHandler(dbSyncHandle)
44
+ self.postMessage({
45
+ type: 'initialized',
46
+ data: { filename },
47
+ request_id: requestId,
48
+ })
49
+ } else if (
50
+ type === 'set_mnemonic' ||
51
+ type === 'generate_mnemonic' ||
52
+ type === 'get_mnemonic' ||
53
+ type === 'join_federation' ||
54
+ type === 'open_client' ||
55
+ type === 'close_client' ||
56
+ type === 'client_rpc' ||
57
+ type === 'cancel_rpc' ||
58
+ type === 'parse_invite_code' ||
59
+ type === 'parse_bolt11_invoice' ||
60
+ type === 'preview_federation'
61
+ ) {
42
62
  self.postMessage({
43
- type: 'open',
44
- data: { success: !!client },
63
+ type: 'log',
64
+ level: 'info',
65
+ message: `RPC received`,
66
+ request_type: type,
45
67
  requestId,
68
+ payload,
46
69
  })
47
- } else if (type === 'join') {
48
- const { inviteCode, clientName: joinClientName } = payload
49
- try {
50
- client = await WasmClient.join_federation(joinClientName, inviteCode)
51
- self.postMessage({
52
- type: 'join',
53
- data: { success: !!client },
54
- requestId,
55
- })
56
- } catch (e) {
57
- self.postMessage({ type: 'error', error: e.message, requestId })
58
- }
59
- } else if (type === 'previewFederation') {
60
- const { inviteCode } = payload
61
- try {
62
- client = await WasmClient.preview_federation(inviteCode)
63
- const parsed = JSON.parse(client)
64
- self.postMessage({
65
- type: 'previewFederation',
66
- data: {
67
- success: !!client,
68
- config: parsed.config,
69
- federation_id: parsed.federation_id,
70
- },
71
- requestId,
72
- })
73
- } catch (e) {
74
- self.postMessage({ type: 'error', error: e.message, requestId })
75
- }
76
- } else if (type === 'rpc') {
77
- const { module, method, body } = payload
78
- console.log('RPC received', module, method, body)
79
- if (!client) {
70
+ if (!rpcHandler) {
80
71
  self.postMessage({
81
72
  type: 'error',
82
- error: 'WasmClient not initialized',
83
- requestId,
73
+ error: 'rpcHandler not initialized',
74
+ request_id: requestId,
84
75
  })
85
76
  return
86
77
  }
87
- const rpcHandle = await client.rpc(
88
- module,
89
- method,
90
- JSON.stringify(body),
91
- (res) => {
92
- console.log('RPC response', requestId, res)
93
- const data = JSON.parse(res)
94
- self.postMessage({ type: 'rpcResponse', requestId, ...data })
95
-
96
- if (data.end !== undefined) {
97
- // Handle stream ending
98
- const handle = streamCancelMap.get(requestId)
99
- handle?.free()
100
- }
101
- },
78
+ const rpcRequest = JSON.stringify({
79
+ request_id: requestId,
80
+ type,
81
+ ...payload,
82
+ })
83
+ rpcHandler.rpc(rpcRequest, (response) =>
84
+ self.postMessage(JSON.parse(response)),
102
85
  )
103
- streamCancelMap.set(requestId, rpcHandle)
104
- } else if (type === 'unsubscribe') {
105
- const rpcHandle = streamCancelMap.get(requestId)
106
- if (rpcHandle) {
107
- rpcHandle.cancel()
108
- rpcHandle.free()
109
- streamCancelMap.delete(requestId)
110
- }
111
86
  } else if (type === 'cleanup') {
112
87
  console.log('cleanup message received')
113
- client?.free()
88
+ dbSyncHandle?.close()
89
+ rpcHandler?.free()
114
90
  self.postMessage({
115
91
  type: 'cleanup',
116
- data: {},
117
- requestId,
92
+ data: { filename: dbFilename },
93
+ request_id: requestId,
118
94
  })
119
95
  close()
120
- } else if (type === 'parseInviteCode') {
121
- const { inviteCode } = payload
122
- try {
123
- const res = WasmClient.parse_invite_code(inviteCode)
124
- const parsedRes = JSON.parse(res)
125
- self.postMessage({
126
- type: 'parseInviteCode',
127
- data: parsedRes,
128
- requestId,
129
- })
130
- } catch (error) {
131
- self.postMessage({
132
- type: 'error',
133
- error: `Failed to parse invite code: ${error.message}`,
134
- requestId,
135
- })
136
- }
137
- } else if (type === 'parseBolt11Invoice') {
138
- const { invoiceStr } = payload
139
- try {
140
- const res = WasmClient.parse_bolt11_invoice(invoiceStr)
141
- const parsedRes = JSON.parse(res)
142
- self.postMessage({
143
- type: 'parseBolt11Invoice',
144
- data: parsedRes,
145
- requestId,
146
- })
147
- } catch (error) {
148
- self.postMessage({
149
- type: 'error',
150
- error: `Failed to parse invoice: ${error.message}`,
151
- requestId,
152
- })
153
- }
154
96
  } else {
155
97
  self.postMessage({
156
98
  type: 'error',
157
99
  error: 'Unknown message type',
158
- requestId,
100
+ request_id: requestId,
159
101
  })
160
102
  }
161
103
  } catch (e) {
162
104
  console.error('ERROR', e)
163
- self.postMessage({ type: 'error', error: e, requestId })
105
+ self.postMessage({ type: 'error', error: e.message, request_id: requestId })
164
106
  }
165
107
  }
166
108
 
167
- // self.postMessage({ type: 'init', data: {} })
109
+ self.onerror = (e) => {
110
+ self.postMessage({ type: 'error', error: e.message })
111
+ }