@welshare/react 0.0.1-alpha.1

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 (42) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +124 -0
  3. package/dist/esm/components/connect-button.d.ts +6 -0
  4. package/dist/esm/components/connect-button.d.ts.map +1 -0
  5. package/dist/esm/components/connect-button.js +58 -0
  6. package/dist/esm/hooks/use-welshare.d.ts +10 -0
  7. package/dist/esm/hooks/use-welshare.d.ts.map +1 -0
  8. package/dist/esm/hooks/use-welshare.js +111 -0
  9. package/dist/esm/index.d.ts +7 -0
  10. package/dist/esm/index.d.ts.map +1 -0
  11. package/dist/esm/index.js +10 -0
  12. package/dist/esm/package.json +3 -0
  13. package/dist/esm/types.d.ts +32 -0
  14. package/dist/esm/types.d.ts.map +1 -0
  15. package/dist/esm/types.js +1 -0
  16. package/dist/node_modules/@welshare/react/.gitignore +6 -0
  17. package/dist/node_modules/@welshare/react/.npmignore +34 -0
  18. package/dist/node_modules/@welshare/react/.tshy/build.json +8 -0
  19. package/dist/node_modules/@welshare/react/.tshy/esm.json +16 -0
  20. package/dist/node_modules/@welshare/react/LICENSE +7 -0
  21. package/dist/node_modules/@welshare/react/README.md +124 -0
  22. package/dist/node_modules/@welshare/react/dist/esm/components/connect-button.d.ts +6 -0
  23. package/dist/node_modules/@welshare/react/dist/esm/components/connect-button.d.ts.map +1 -0
  24. package/dist/node_modules/@welshare/react/dist/esm/components/connect-button.js +58 -0
  25. package/dist/node_modules/@welshare/react/dist/esm/hooks/use-welshare.d.ts +10 -0
  26. package/dist/node_modules/@welshare/react/dist/esm/hooks/use-welshare.d.ts.map +1 -0
  27. package/dist/node_modules/@welshare/react/dist/esm/hooks/use-welshare.js +111 -0
  28. package/dist/node_modules/@welshare/react/dist/esm/index.d.ts +7 -0
  29. package/dist/node_modules/@welshare/react/dist/esm/index.d.ts.map +1 -0
  30. package/dist/node_modules/@welshare/react/dist/esm/index.js +10 -0
  31. package/dist/node_modules/@welshare/react/dist/esm/package.json +3 -0
  32. package/dist/node_modules/@welshare/react/dist/esm/types.d.ts +32 -0
  33. package/dist/node_modules/@welshare/react/dist/esm/types.d.ts.map +1 -0
  34. package/dist/node_modules/@welshare/react/dist/esm/types.js +1 -0
  35. package/dist/node_modules/@welshare/react/eslint.config.mjs +4 -0
  36. package/dist/node_modules/@welshare/react/package.json +88 -0
  37. package/dist/node_modules/@welshare/react/src/components/connect-button.tsx +99 -0
  38. package/dist/node_modules/@welshare/react/src/hooks/use-welshare.ts +148 -0
  39. package/dist/node_modules/@welshare/react/src/index.ts +13 -0
  40. package/dist/node_modules/@welshare/react/src/types.ts +37 -0
  41. package/dist/node_modules/@welshare/react/tsconfig.json +21 -0
  42. package/package.json +87 -0
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright © 2025 Welshare Health UG (haftungsbeschränkt) 2025
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # @welshare/react
2
+
3
+ ### Disclaimer, notes on maturity
4
+
5
+ This library is in Alpha / demo state at this moment. We're using it to review the security aspects while data is in transfer and in rest. There's absolutely no guarantee or warrant that at this point any data is safe. All data can be lost at any time - even though we're using resources that puts decentralization and resilience values to the front. Be **very** careful if you're integrating this into user facing code. Welshare Health wallets are controlled by cryptographic material which _can_ be stored in non custodial / MPC environments (Privy). While that's considered very safe, we can't guarantee at this point that we've already got each aspect of inter application communication or key derivation features right, so don't connect wallets that store significant value with the welshare wallet yet.
6
+
7
+ ## Purpose
8
+
9
+ This is a React library that helps integrating with Welshare's sovereign data sharing platform. This package provides React hooks and components to connect applications with Welshare's wallet for secure data submission.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @welshare/react
15
+ # or
16
+ yarn add @welshare/react
17
+ # or
18
+ pnpm add @welshare/react
19
+ ```
20
+
21
+ ## Peer Dependencies
22
+
23
+ This package requires React 19+ as a peer dependency.
24
+
25
+ ## Prerequisites
26
+
27
+ You need to register an app identifier using the Welshare Wallet frontend first: https://wallet.welshare.app/application. We're referring to this as `your-application-id` from here on.
28
+
29
+ If you want to submit questionnaire data, your application must first register a new questionnaire definition. You can also reuse an existing questionnaire id to let users contribute responses to another app's questionaire, but that's not highly encouraged at this point.
30
+
31
+ ## Data Submissions
32
+
33
+ At the moment there are only two supported submission types: Fhir compatible QuestionnaireResponses and our custom "Reflex" app submissions. Both types are identified by schema uids that are accessible on the `Schemas` export.
34
+
35
+ ```
36
+ export const Schemas = {
37
+ QuestionnaireResponse: "b14b538f-7de3-4767-ad77-464d755d78bd"
38
+ };
39
+ ```
40
+
41
+ To submit questionnaires using custom frontends, you'll use the `useWelshare` hook to open a wallet dialog that lets your application talk to the user's connected wallets (using derived storage keys). All communication with the Welshare infrastructure happens inside that browser window.
42
+
43
+ ## Code Sample
44
+
45
+ ```tsx
46
+ import { ConnectWelshareButton, Schemas, useWelshare } from "@welshare/react";
47
+
48
+ export function QuestionnaireForm() {
49
+ const { isConnected, openWallet, submitData } = useWelshare({
50
+ applicationId: <your-application-id>,
51
+ environment: "development", //optional, at the moment the environment is always development
52
+ callbacks: {
53
+ onUploaded: (payload) => console.log('Data uploaded:', payload),
54
+ onError: (error) => console.error('Error:', error),
55
+ onSessionReady: (storageKey) => console.log('Session ready:', storageKey),
56
+ }
57
+ });
58
+
59
+ const handleSubmit = () => {
60
+ //response is a QuestionnaireResponse compatible object
61
+ submitData(Schemas.QuestionnaireResponse, response);
62
+ };
63
+
64
+ // using the `ConnectWelshareButton` is not mandatory. Use your own buttons if you feel like it.
65
+ return (
66
+ <div>
67
+ {!isConnected ? (
68
+ <ConnectWelshareButton openWallet={openWallet}>
69
+ Connect to Welshare
70
+ </ConnectWelshareButton>
71
+ ) : (
72
+ <form>
73
+ {/* ... some form that collects your response data ... */}
74
+ <button onClick={() => handleSubmit(response)} disabled={isSubmitting}>
75
+ {isSubmitting ? 'Submitting...' : 'Submit Data'}
76
+ </button>
77
+ </form>
78
+ )}
79
+ </div>
80
+ );
81
+ }
82
+ ```
83
+
84
+ ## API
85
+
86
+ ### supported callbacks
87
+
88
+ those are configured in the `useWelshare` options parameter and called back during interactions with the wallet dialog
89
+
90
+ ```tsx
91
+ callbacks: {
92
+ onUploaded?: (payload: SubmissionPayload<unknown>) => void;
93
+ onError?: (error: string) => void;
94
+ onSessionReady?: (sessionPubKey: string) => void;
95
+ onDialogClosing?: () => void;
96
+ onDialogReady?: () => void;
97
+ }
98
+ ```
99
+
100
+ ## Security Notes
101
+
102
+ No part of this application deals with a "blockchain" directly (Nillion nodes are validated by a custom chain but that's not a fact relevant for end users' security in this scope).
103
+
104
+ The EVM addresses that control a user profile are (supposedly) never leaked to a third party.
105
+
106
+ The key derivation mechanism that creates new storage keys that users use to sign messages is not guaranteed to be 100% sound. At this moment it's used as a cryptographic authenticator, but the derivation mechanism will change in the future, rendering already existing keys obsolete. We're not guaranteeing that your key material stays trivially derivable.
107
+
108
+ Data is stored on [nilDB (by Nillion)](https://docs.nillion.com/build/private-storage/quickstart), a system that can enforces access control, encryption at rest and storage redundancy. While technically possible, the current library does not MPC-encrypt any information. The data is sent to nilDB by a _user client_ that's controlled by the user's own key material. Welshare only delegates NUCs (access rights) to the users. Right now the welshare builder _can_ read any data users upload. This concept will eventually change - welshare's goal is to only make user originated information available inside trusted execution environments.
109
+
110
+ ## Development
111
+
112
+ This package is built using:
113
+
114
+ - TypeScript
115
+ - Tshy for build management
116
+ - Vitest for testing
117
+
118
+ ## License
119
+
120
+ MIT. See the [LICENSE](LICENSE) file for details.
121
+
122
+ ## Contact
123
+
124
+ Get in touch on Telegram. Check https://welshare.health
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export declare const ConnectWelshareButton: (props: {
3
+ openWallet: () => void;
4
+ children?: React.ReactNode;
5
+ }) => import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=connect-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-button.d.ts","sourceRoot":"","sources":["../../../src/components/connect-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAO,MAAM,qBAAqB,UAAW;IAC3C,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,4CAgFA,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export const ConnectWelshareButton = (props) => {
3
+ // Self-contained styles that won't conflict with external applications
4
+ const buttonStyles = {
5
+ // Reset any inherited styles
6
+ all: 'unset',
7
+ boxSizing: 'border-box',
8
+ // Layout
9
+ display: 'inline-flex',
10
+ alignItems: 'center',
11
+ justifyContent: 'center',
12
+ width: '100%',
13
+ minHeight: '44px',
14
+ padding: '12px 24px',
15
+ // Typography
16
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
17
+ fontSize: '16px',
18
+ fontWeight: '600',
19
+ lineHeight: '1.5',
20
+ textAlign: 'center',
21
+ textDecoration: 'none',
22
+ whiteSpace: 'nowrap',
23
+ // Visual styling
24
+ backgroundColor: '#0198ff',
25
+ background: 'linear-gradient(135deg, #0198ff 0%, #16ffef 100%)',
26
+ color: '#ffffff',
27
+ border: 'none',
28
+ borderRadius: '8px',
29
+ cursor: 'pointer',
30
+ transition: 'all 0.2s ease-in-out',
31
+ // Accessibility
32
+ userSelect: 'none',
33
+ WebkitUserSelect: 'none',
34
+ MozUserSelect: 'none',
35
+ // Focus states
36
+ outline: 'none',
37
+ };
38
+ // Handle hover and focus states since inline styles don't support pseudo-selectors
39
+ const handleMouseEnter = (e) => {
40
+ e.currentTarget.style.transform = 'translateY(-1px)';
41
+ e.currentTarget.style.boxShadow = '0 4px 12px rgba(1, 152, 255, 0.3)';
42
+ };
43
+ const handleMouseLeave = (e) => {
44
+ e.currentTarget.style.transform = 'translateY(0)';
45
+ e.currentTarget.style.boxShadow = '0 2px 6px rgba(1, 152, 255, 0.2)';
46
+ };
47
+ const handleMouseDown = (e) => {
48
+ e.currentTarget.style.transform = 'translateY(0)';
49
+ e.currentTarget.style.boxShadow = '0 2px 6px rgba(1, 152, 255, 0.2)';
50
+ };
51
+ const handleFocus = (e) => {
52
+ e.currentTarget.style.boxShadow = '0 0 0 3px rgba(1, 152, 255, 0.3)';
53
+ };
54
+ const handleBlur = (e) => {
55
+ e.currentTarget.style.boxShadow = '0 2px 6px rgba(1, 152, 255, 0.2)';
56
+ };
57
+ return (_jsx("button", { onClick: props.openWallet, style: buttonStyles, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onFocus: handleFocus, onBlur: handleBlur, type: "button", children: props.children || "Connect Welshare Profile" }));
58
+ };
@@ -0,0 +1,10 @@
1
+ import { SubmissionPayload, SubmissionSchemaId, WelshareConnectionOptions } from "@/types.js";
2
+ export declare const useWelshare: (props: WelshareConnectionOptions) => {
3
+ isConnected: boolean;
4
+ storageKey: string | undefined;
5
+ openWallet: () => void;
6
+ isDialogOpen: boolean;
7
+ submitData: <T>(schemaId: SubmissionSchemaId, submission: SubmissionPayload<T>) => void;
8
+ isSubmitting: boolean;
9
+ };
10
+ //# sourceMappingURL=use-welshare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-welshare.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-welshare.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,WAAW,UAAW,yBAAyB;;;;;iBAkFtC,CAAC,YACT,kBAAkB,cAChB,iBAAiB,CAAC,CAAC,CAAC;;CAuDnC,CAAC"}
@@ -0,0 +1,111 @@
1
+ import { useEffect, useState } from "react";
2
+ export const useWelshare = (props) => {
3
+ const [storageKey, setStorageKey] = useState();
4
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
5
+ const [dialogWindow, setDialogWindow] = useState(null);
6
+ const [messageIdCounter, setMessageIdCounter] = useState(0);
7
+ const [isSubmitting, setIsSubmitting] = useState(false);
8
+ const options = {
9
+ environment: "development",
10
+ apiBaseUrl: "https://wallet.welshare.health",
11
+ ...props,
12
+ };
13
+ const WELSHARE_WALLET_URL = `${options.apiBaseUrl}/wallet-external`;
14
+ useEffect(() => {
15
+ const handleMessage = (event) => {
16
+ // Verify origin for security
17
+ if (event.origin !== new URL(WELSHARE_WALLET_URL).origin) {
18
+ return;
19
+ }
20
+ const message = event.data;
21
+ let errorMessage = "";
22
+ switch (message.type) {
23
+ case "ERROR":
24
+ errorMessage = message.payload.error || "An unknown error occurred";
25
+ console.error("Welshare Wallet sent an error:", errorMessage);
26
+ setIsSubmitting(false);
27
+ options.callbacks.onError?.(errorMessage);
28
+ break;
29
+ case "DIALOG_READY":
30
+ setIsDialogOpen(true);
31
+ console.debug("Welshare Wallet Dialog is ready");
32
+ break;
33
+ case "SESSION_READY":
34
+ if (!message.payload.sessionPublicKey) {
35
+ errorMessage = "No session public key found";
36
+ console.error("Welshare Wallet sent a session without a key:", message.payload);
37
+ setStorageKey(undefined);
38
+ options.callbacks.onError?.(errorMessage);
39
+ break;
40
+ }
41
+ console.debug("Welshare Profile Session ready", message.payload);
42
+ setStorageKey(message.payload.sessionPublicKey);
43
+ options.callbacks.onSessionReady?.(message.payload.sessionPublicKey);
44
+ break;
45
+ case "DIALOG_CLOSING":
46
+ console.debug("Welshare Wallet Dialog is closing");
47
+ setStorageKey(undefined);
48
+ setIsDialogOpen(false);
49
+ options.callbacks.onDialogClosing?.();
50
+ break;
51
+ case "DATA_UPLOADED":
52
+ console.debug("data uploaded", message.payload);
53
+ setIsSubmitting(false);
54
+ options.callbacks.onUploaded?.(message.payload);
55
+ break;
56
+ default:
57
+ console.log("Received unexpected message from Welshare Wallet:", message);
58
+ }
59
+ };
60
+ window.addEventListener("message", handleMessage);
61
+ return () => {
62
+ window.removeEventListener("message", handleMessage);
63
+ };
64
+ }, [WELSHARE_WALLET_URL, options.callbacks]);
65
+ /**
66
+ * @param schemaType a welshare schema type uid
67
+ * @param submission your submission that validates against the schema type
68
+ */
69
+ const submitData = (schemaId, submission) => {
70
+ if (!dialogWindow) {
71
+ throw new Error("Dialog window not open");
72
+ }
73
+ const submissionPayload = {
74
+ applicationId: options.applicationId,
75
+ schemaId,
76
+ timestamp: new Date(),
77
+ submission,
78
+ };
79
+ //todo: before submitting data, consider verifying it locally here;
80
+ // 1. request the actual schema using a welshare api
81
+ // 2. create a json schema validator
82
+ // 3. run payload against that validator
83
+ // 4. submit
84
+ const message = {
85
+ type: "SUBMIT_DATA",
86
+ payload: submissionPayload,
87
+ id: String(messageIdCounter),
88
+ };
89
+ dialogWindow.postMessage(message, WELSHARE_WALLET_URL);
90
+ setIsSubmitting(true);
91
+ setMessageIdCounter((prev) => prev + 1);
92
+ };
93
+ const openWallet = () => {
94
+ const width = 800;
95
+ const height = 600;
96
+ const left = window.screenX + (window.outerWidth - width) / 2;
97
+ const top = window.screenY + (window.outerHeight - height) / 2;
98
+ const newWindow = window.open(WELSHARE_WALLET_URL, "Welshare Wallet", `width=${width},height=${height},left=${left},top=${top}`);
99
+ if (newWindow) {
100
+ setDialogWindow(newWindow);
101
+ }
102
+ };
103
+ return {
104
+ isConnected: !!storageKey,
105
+ storageKey,
106
+ openWallet,
107
+ isDialogOpen,
108
+ submitData,
109
+ isSubmitting,
110
+ };
111
+ };
@@ -0,0 +1,7 @@
1
+ export { ConnectWelshareButton } from "./components/connect-button.js";
2
+ export { useWelshare } from "./hooks/use-welshare.js";
3
+ export declare const Schemas: {
4
+ QuestionnaireResponse: string;
5
+ ReflexSubmission: string;
6
+ };
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAEvE,OAAO,EACL,WAAW,EACZ,MAAM,yBAAyB,CAAC;AAGjC,eAAO,MAAM,OAAO;;;CAGnB,CAAC"}
@@ -0,0 +1,10 @@
1
+ //todo: this is not tree shaken and leaks nillion dependencies transitively. Consider pulling it up
2
+ //import { QuestionnaireResponseSchema, ReflexSubmissionSchema } from "@welshare/sdk";
3
+ export { ConnectWelshareButton } from "./components/connect-button.js";
4
+ // ---- hooks ----
5
+ export { useWelshare } from "./hooks/use-welshare.js";
6
+ //todo: import them from the SDK or a dedicated SDK constants export
7
+ export const Schemas = {
8
+ QuestionnaireResponse: "b14b538f-7de3-4767-ad77-464d755d78bd", //QuestionnaireResponseSchema.schemaUid,
9
+ ReflexSubmission: "f5cf2d8a-1f78-4f21-b4bd-082e983b830c" //ReflexSubmissionSchema.schemaUid,
10
+ };
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,32 @@
1
+ export interface DialogMessage {
2
+ type: string;
3
+ payload?: any;
4
+ id?: string;
5
+ }
6
+ export type WelshareEnvironment = "development" | "production";
7
+ /**
8
+ * a welshare schema type uid
9
+ */
10
+ export type SubmissionSchemaId = string;
11
+ export interface SubmissionPayload<T> {
12
+ applicationId: string;
13
+ timestamp: Date;
14
+ schemaId: SubmissionSchemaId;
15
+ submission: T;
16
+ }
17
+ export interface DataSubmissionDialogMessage extends DialogMessage {
18
+ payload: SubmissionPayload<unknown>;
19
+ }
20
+ export interface WelshareConnectionOptions {
21
+ applicationId: string;
22
+ apiBaseUrl?: string;
23
+ environment?: WelshareEnvironment;
24
+ callbacks: {
25
+ onUploaded?: (payload: SubmissionPayload<unknown>) => void;
26
+ onError?: (error: string) => void;
27
+ onSessionReady?: (sessionPubKey: string) => void;
28
+ onDialogClosing?: () => void;
29
+ onDialogReady?: () => void;
30
+ };
31
+ }
32
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,YAAY,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAA;AAEvC,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC;CACf;AAED,MAAM,WAAW,2BAA4B,SAAQ,aAAa;IAChE,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IAEtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,SAAS,EAAE;QACT,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAClC,cAAc,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;QACjD,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;KAC5B,CAAC;CACH"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ .tshy-build
2
+ dist/
3
+ node_modules/
4
+ *.tsbuildinfo
5
+ coverage/
6
+ .vitest/
@@ -0,0 +1,34 @@
1
+ # Source files
2
+ src/
3
+ tsconfig.json
4
+ tsconfig.lint.json
5
+ tshy.config.ts
6
+ vitest.config.ts
7
+
8
+ # Development files
9
+ .github/
10
+ .vscode/
11
+ *.log
12
+ *.tsbuildinfo
13
+
14
+ # Test files
15
+ __tests__/
16
+ *.test.*
17
+ *.spec.*
18
+
19
+ # Build artifacts
20
+ .tshy-build/
21
+ coverage/
22
+ .vitest/
23
+
24
+ # Development dependencies
25
+ node_modules/
26
+
27
+ # IDE files
28
+ .idea/
29
+ *.swp
30
+ *.swo
31
+
32
+ # OS files
33
+ .DS_Store
34
+ Thumbs.db
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "../src",
5
+ "module": "nodenext",
6
+ "moduleResolution": "nodenext"
7
+ }
8
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "./build.json",
3
+ "include": [
4
+ "../src/**/*.ts",
5
+ "../src/**/*.mts",
6
+ "../src/**/*.tsx",
7
+ "../src/**/*.json"
8
+ ],
9
+ "exclude": [
10
+ "../src/**/__tests__/**",
11
+ "../src/package.json"
12
+ ],
13
+ "compilerOptions": {
14
+ "outDir": "../.tshy-build/esm"
15
+ }
16
+ }
@@ -0,0 +1,7 @@
1
+ Copyright © 2025 Welshare Health UG (haftungsbeschränkt) 2025
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,124 @@
1
+ # @welshare/react
2
+
3
+ ### Disclaimer, notes on maturity
4
+
5
+ This library is in Alpha / demo state at this moment. We're using it to review the security aspects while data is in transfer and in rest. There's absolutely no guarantee or warrant that at this point any data is safe. All data can be lost at any time - even though we're using resources that puts decentralization and resilience values to the front. Be **very** careful if you're integrating this into user facing code. Welshare Health wallets are controlled by cryptographic material which _can_ be stored in non custodial / MPC environments (Privy). While that's considered very safe, we can't guarantee at this point that we've already got each aspect of inter application communication or key derivation features right, so don't connect wallets that store significant value with the welshare wallet yet.
6
+
7
+ ## Purpose
8
+
9
+ This is a React library that helps integrating with Welshare's sovereign data sharing platform. This package provides React hooks and components to connect applications with Welshare's wallet for secure data submission.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @welshare/react
15
+ # or
16
+ yarn add @welshare/react
17
+ # or
18
+ pnpm add @welshare/react
19
+ ```
20
+
21
+ ## Peer Dependencies
22
+
23
+ This package requires React 19+ as a peer dependency.
24
+
25
+ ## Prerequisites
26
+
27
+ You need to register an app identifier using the Welshare Wallet frontend first: https://wallet.welshare.app/application. We're referring to this as `your-application-id` from here on.
28
+
29
+ If you want to submit questionnaire data, your application must first register a new questionnaire definition. You can also reuse an existing questionnaire id to let users contribute responses to another app's questionaire, but that's not highly encouraged at this point.
30
+
31
+ ## Data Submissions
32
+
33
+ At the moment there are only two supported submission types: Fhir compatible QuestionnaireResponses and our custom "Reflex" app submissions. Both types are identified by schema uids that are accessible on the `Schemas` export.
34
+
35
+ ```
36
+ export const Schemas = {
37
+ QuestionnaireResponse: "b14b538f-7de3-4767-ad77-464d755d78bd"
38
+ };
39
+ ```
40
+
41
+ To submit questionnaires using custom frontends, you'll use the `useWelshare` hook to open a wallet dialog that lets your application talk to the user's connected wallets (using derived storage keys). All communication with the Welshare infrastructure happens inside that browser window.
42
+
43
+ ## Code Sample
44
+
45
+ ```tsx
46
+ import { ConnectWelshareButton, Schemas, useWelshare } from "@welshare/react";
47
+
48
+ export function QuestionnaireForm() {
49
+ const { isConnected, openWallet, submitData } = useWelshare({
50
+ applicationId: <your-application-id>,
51
+ environment: "development", //optional, at the moment the environment is always development
52
+ callbacks: {
53
+ onUploaded: (payload) => console.log('Data uploaded:', payload),
54
+ onError: (error) => console.error('Error:', error),
55
+ onSessionReady: (storageKey) => console.log('Session ready:', storageKey),
56
+ }
57
+ });
58
+
59
+ const handleSubmit = () => {
60
+ //response is a QuestionnaireResponse compatible object
61
+ submitData(Schemas.QuestionnaireResponse, response);
62
+ };
63
+
64
+ // using the `ConnectWelshareButton` is not mandatory. Use your own buttons if you feel like it.
65
+ return (
66
+ <div>
67
+ {!isConnected ? (
68
+ <ConnectWelshareButton openWallet={openWallet}>
69
+ Connect to Welshare
70
+ </ConnectWelshareButton>
71
+ ) : (
72
+ <form>
73
+ {/* ... some form that collects your response data ... */}
74
+ <button onClick={() => handleSubmit(response)} disabled={isSubmitting}>
75
+ {isSubmitting ? 'Submitting...' : 'Submit Data'}
76
+ </button>
77
+ </form>
78
+ )}
79
+ </div>
80
+ );
81
+ }
82
+ ```
83
+
84
+ ## API
85
+
86
+ ### supported callbacks
87
+
88
+ those are configured in the `useWelshare` options parameter and called back during interactions with the wallet dialog
89
+
90
+ ```tsx
91
+ callbacks: {
92
+ onUploaded?: (payload: SubmissionPayload<unknown>) => void;
93
+ onError?: (error: string) => void;
94
+ onSessionReady?: (sessionPubKey: string) => void;
95
+ onDialogClosing?: () => void;
96
+ onDialogReady?: () => void;
97
+ }
98
+ ```
99
+
100
+ ## Security Notes
101
+
102
+ No part of this application deals with a "blockchain" directly (Nillion nodes are validated by a custom chain but that's not a fact relevant for end users' security in this scope).
103
+
104
+ The EVM addresses that control a user profile are (supposedly) never leaked to a third party.
105
+
106
+ The key derivation mechanism that creates new storage keys that users use to sign messages is not guaranteed to be 100% sound. At this moment it's used as a cryptographic authenticator, but the derivation mechanism will change in the future, rendering already existing keys obsolete. We're not guaranteeing that your key material stays trivially derivable.
107
+
108
+ Data is stored on [nilDB (by Nillion)](https://docs.nillion.com/build/private-storage/quickstart), a system that can enforces access control, encryption at rest and storage redundancy. While technically possible, the current library does not MPC-encrypt any information. The data is sent to nilDB by a _user client_ that's controlled by the user's own key material. Welshare only delegates NUCs (access rights) to the users. Right now the welshare builder _can_ read any data users upload. This concept will eventually change - welshare's goal is to only make user originated information available inside trusted execution environments.
109
+
110
+ ## Development
111
+
112
+ This package is built using:
113
+
114
+ - TypeScript
115
+ - Tshy for build management
116
+ - Vitest for testing
117
+
118
+ ## License
119
+
120
+ MIT. See the [LICENSE](LICENSE) file for details.
121
+
122
+ ## Contact
123
+
124
+ Get in touch on Telegram. Check https://welshare.health
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export declare const ConnectWelshareButton: (props: {
3
+ openWallet: () => void;
4
+ children?: React.ReactNode;
5
+ }) => import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=connect-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect-button.d.ts","sourceRoot":"","sources":["../../../src/components/connect-button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAO,MAAM,qBAAqB,UAAW;IAC3C,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,4CAgFA,CAAC"}