@1sat/react 0.0.7 → 0.0.9

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,56 +1,21 @@
1
1
  import type { ReactNode } from 'react';
2
2
  export interface ConnectButtonProps {
3
- /** Custom class name for the button */
4
3
  className?: string;
5
- /** Custom styles for the button */
6
4
  style?: React.CSSProperties;
7
- /** Text to show when disconnected */
8
5
  connectLabel?: ReactNode;
9
- /** Text to show when connecting */
10
6
  connectingLabel?: ReactNode;
11
- /** Text to show when connected (receives address) */
12
- connectedLabel?: ReactNode | ((address: string) => ReactNode);
13
- /** Called after successful connection */
7
+ connectedLabel?: ReactNode | ((identityKey: string) => ReactNode);
14
8
  onConnect?: () => void;
15
- /** Called after disconnection */
16
9
  onDisconnect?: () => void;
17
- /** Called on error */
18
10
  onError?: (error: Error) => void;
19
- /** Whether to disconnect on click when connected */
20
11
  disconnectOnClick?: boolean;
21
- /** Custom render function for full control */
22
12
  children?: (props: {
23
13
  isConnected: boolean;
24
14
  isConnecting: boolean;
25
- address: string | null;
15
+ identityKey: string | null;
26
16
  connect: () => Promise<void>;
27
- disconnect: () => Promise<void>;
17
+ disconnect: () => void;
28
18
  }) => ReactNode;
29
19
  }
30
- /**
31
- * Ready-to-use connect button component
32
- *
33
- * @example
34
- * ```tsx
35
- * // Basic usage
36
- * <ConnectButton />
37
- *
38
- * // With custom labels
39
- * <ConnectButton
40
- * connectLabel="Connect 1Sat"
41
- * connectingLabel="Connecting..."
42
- * connectedLabel={(addr) => `Connected: ${addr}`}
43
- * />
44
- *
45
- * // With custom render
46
- * <ConnectButton>
47
- * {({ isConnected, connect, disconnect }) => (
48
- * <button onClick={isConnected ? disconnect : connect}>
49
- * {isConnected ? 'Disconnect' : 'Connect'}
50
- * </button>
51
- * )}
52
- * </ConnectButton>
53
- * ```
54
- */
55
20
  export declare function ConnectButton({ className, style, connectLabel, connectingLabel, connectedLabel, onConnect, onDisconnect, onError, disconnectOnClick, children, }: ConnectButtonProps): import("react/jsx-runtime").JSX.Element;
56
21
  //# sourceMappingURL=ConnectButton.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectButton.d.ts","sourceRoot":"","sources":["../src/ConnectButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,MAAM,WAAW,kBAAkB;IAClC,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IAC3B,qCAAqC;IACrC,YAAY,CAAC,EAAE,SAAS,CAAA;IACxB,mCAAmC;IACnC,eAAe,CAAC,EAAE,SAAS,CAAA;IAC3B,qDAAqD;IACrD,cAAc,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,CAAC,CAAA;IAC7D,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,sBAAsB;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAClB,WAAW,EAAE,OAAO,CAAA;QACpB,YAAY,EAAE,OAAO,CAAA;QACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5B,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAC/B,KAAK,SAAS,CAAA;CACf;AAUD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAAC,EAC7B,SAAS,EACT,KAAK,EACL,YAA+B,EAC/B,eAAiC,EACjC,cAAc,EACd,SAAS,EACT,YAAY,EACZ,OAAO,EACP,iBAAwB,EACxB,QAAQ,GACR,EAAE,kBAAkB,2CA0EpB"}
1
+ {"version":3,"file":"ConnectButton.d.ts","sourceRoot":"","sources":["../src/ConnectButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,MAAM,WAAW,kBAAkB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IAC3B,YAAY,CAAC,EAAE,SAAS,CAAA;IACxB,eAAe,CAAC,EAAE,SAAS,CAAA;IAC3B,cAAc,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,WAAW,EAAE,MAAM,KAAK,SAAS,CAAC,CAAA;IACjE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;QAClB,WAAW,EAAE,OAAO,CAAA;QACpB,YAAY,EAAE,OAAO,CAAA;QACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5B,UAAU,EAAE,MAAM,IAAI,CAAA;KACtB,KAAK,SAAS,CAAA;CACf;AAOD,wBAAgB,aAAa,CAAC,EAC7B,SAAS,EACT,KAAK,EACL,YAA+B,EAC/B,eAAiC,EACjC,cAAc,EACd,SAAS,EACT,YAAY,EACZ,OAAO,EACP,iBAAwB,EACxB,QAAQ,GACR,EAAE,kBAAkB,2CA0EpB"}
@@ -0,0 +1,25 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface SigmaCallbackProps {
3
+ /** Where to redirect after successful auth (default: '/') */
4
+ redirectTo?: string;
5
+ /** Server-side route that exchanges code for tokens (default: /api/auth/sigma/callback) */
6
+ serverCallbackUrl?: string;
7
+ /** Custom loading content */
8
+ loadingContent?: ReactNode;
9
+ /** Custom error render */
10
+ renderError?: (error: string, goBack: () => void) => ReactNode;
11
+ }
12
+ /**
13
+ * Generic Sigma OAuth callback page component.
14
+ *
15
+ * Place this as the default export of your callback route page:
16
+ * ```tsx
17
+ * // app/auth/sigma/callback/page.tsx
18
+ * import { SigmaCallback } from '@1sat/react'
19
+ * export default function Page() {
20
+ * return <SigmaCallback redirectTo="/dashboard" />
21
+ * }
22
+ * ```
23
+ */
24
+ export declare function SigmaCallback({ redirectTo, serverCallbackUrl, loadingContent, renderError, }: SigmaCallbackProps): import("react/jsx-runtime").JSX.Element;
25
+ //# sourceMappingURL=SigmaCallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SigmaCallback.d.ts","sourceRoot":"","sources":["../src/SigmaCallback.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAA;AAI3D,MAAM,WAAW,kBAAkB;IAClC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,6BAA6B;IAC7B,cAAc,CAAC,EAAE,SAAS,CAAA;IAC1B,0BAA0B;IAC1B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,KAAK,SAAS,CAAA;CAC9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC7B,UAAgB,EAChB,iBAA8C,EAC9C,cAAc,EACd,WAAW,GACX,EAAE,kBAAkB,2CAoGpB"}
@@ -0,0 +1,19 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface WalletSelectorProviderInfo {
3
+ type: string;
4
+ name: string;
5
+ icon?: string;
6
+ detected: boolean;
7
+ isConnecting: boolean;
8
+ connect: () => Promise<void>;
9
+ }
10
+ export interface WalletSelectorRenderProps {
11
+ providers: WalletSelectorProviderInfo[];
12
+ error: Error | null;
13
+ }
14
+ export interface WalletSelectorProps {
15
+ onClose?: () => void;
16
+ children: (props: WalletSelectorRenderProps) => ReactNode;
17
+ }
18
+ export declare function WalletSelector({ onClose, children }: WalletSelectorProps): import("react/jsx-runtime").JSX.Element;
19
+ //# sourceMappingURL=WalletSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WalletSelector.d.ts","sourceRoot":"","sources":["../src/WalletSelector.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,OAAO,CAAA;AAG7D,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACzC,SAAS,EAAE,0BAA0B,EAAE,CAAA;IACvC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,SAAS,CAAA;CACzD;AAED,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CA6BxE"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from '@1sat/connect';
2
- export { OneSatProvider, useOneSatContext, type OneSatContextValue, type OneSatProviderProps, } from './context';
3
- export { useBalance, useOrdinals, useTokens, useUtxos, useSignTransaction, useSignMessage, useInscribe, useSendOrdinals, useTransferToken, useCreateListing, usePurchaseListing, useCancelListing, } from './hooks';
2
+ export { WalletProvider, useWallet, type WalletContextValue, type WalletProviderProps, type WalletStatus, } from './wallet-context';
3
+ export { SigmaCallback, type SigmaCallbackProps } from './SigmaCallback';
4
4
  export { ConnectButton, type ConnectButtonProps } from './ConnectButton';
5
+ export { WalletSelector, type WalletSelectorProps, type WalletSelectorProviderInfo, type WalletSelectorRenderProps, } from './WalletSelector';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAA;AAG7B,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACxB,MAAM,WAAW,CAAA;AAGlB,OAAO,EACN,UAAU,EACV,WAAW,EACX,SAAS,EACT,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,GAChB,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAA;AAG7B,OAAO,EACN,cAAc,EACd,SAAS,EACT,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,YAAY,GACjB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAGxE,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,EACN,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,GAC9B,MAAM,kBAAkB,CAAA"}
package/dist/index.js CHANGED
@@ -3,9 +3,11 @@
3
3
  // src/index.ts
4
4
  export * from "@1sat/connect";
5
5
 
6
- // src/context.tsx
6
+ // src/wallet-context.tsx
7
7
  import {
8
- createOneSat
8
+ connectWallet,
9
+ getAvailableProviders,
10
+ reconnectSigma
9
11
  } from "@1sat/connect";
10
12
  import {
11
13
  createContext,
@@ -13,326 +15,286 @@ import {
13
15
  useContext,
14
16
  useEffect,
15
17
  useMemo,
18
+ useRef,
16
19
  useState
17
20
  } from "react";
18
21
  import { jsx } from "react/jsx-runtime";
19
- "use client";
20
- var OneSatContext = createContext(null);
21
- function OneSatProvider({
22
- appName,
23
- popupUrl,
24
- timeout,
25
- network,
22
+ var STORAGE_KEY = "onesat_wallet_provider";
23
+ function loadStored() {
24
+ if (typeof window === "undefined")
25
+ return null;
26
+ try {
27
+ const raw = localStorage.getItem(STORAGE_KEY);
28
+ if (!raw)
29
+ return null;
30
+ return JSON.parse(raw);
31
+ } catch {
32
+ return null;
33
+ }
34
+ }
35
+ function saveStored(providerType, identityKey) {
36
+ if (typeof window === "undefined")
37
+ return;
38
+ localStorage.setItem(STORAGE_KEY, JSON.stringify({ providerType, identityKey }));
39
+ }
40
+ function clearStored() {
41
+ if (typeof window === "undefined")
42
+ return;
43
+ localStorage.removeItem(STORAGE_KEY);
44
+ }
45
+ var WalletContext = createContext(null);
46
+ function WalletProvider({
47
+ autoDetect = true,
48
+ providers,
26
49
  children
27
50
  }) {
28
- const [provider, setProvider] = useState(null);
29
- const [isConnected, setIsConnected] = useState(false);
30
- const [isConnecting, setIsConnecting] = useState(false);
31
- const [paymentAddress, setPaymentAddress] = useState(null);
32
- const [ordinalAddress, setOrdinalAddress] = useState(null);
33
- const [identityPubKey, setIdentityPubKey] = useState(null);
51
+ const [wallet, setWallet] = useState(null);
52
+ const [status, setStatus] = useState("disconnected");
53
+ const [identityKey, setIdentityKey] = useState(null);
54
+ const [providerType, setProviderType] = useState(null);
34
55
  const [error, setError] = useState(null);
35
- useEffect(() => {
36
- if (typeof window === "undefined")
37
- return;
38
- const p = createOneSat({ appName, popupUrl, timeout, network });
39
- setProvider(p);
40
- if (p.isConnected()) {
41
- const addresses = p.getAddresses();
42
- if (addresses) {
43
- setIsConnected(true);
44
- setPaymentAddress(addresses.paymentAddress);
45
- setOrdinalAddress(addresses.ordinalAddress);
46
- setIdentityPubKey(p.getIdentityPubKey());
56
+ const disconnectRef = useRef(null);
57
+ const availableProviders = useMemo(() => getAvailableProviders({ providers }), [providers]);
58
+ const applyResult = useCallback((result) => {
59
+ setWallet(result.wallet);
60
+ setIdentityKey(result.identityKey);
61
+ setProviderType(result.provider);
62
+ setStatus("connected");
63
+ setError(null);
64
+ disconnectRef.current = result.disconnect;
65
+ saveStored(result.provider, result.identityKey);
66
+ }, []);
67
+ const disconnect = useCallback(() => {
68
+ disconnectRef.current?.();
69
+ disconnectRef.current = null;
70
+ setWallet(null);
71
+ setIdentityKey(null);
72
+ setProviderType(null);
73
+ setStatus("disconnected");
74
+ setError(null);
75
+ clearStored();
76
+ }, []);
77
+ const connect = useCallback(async (selectedType) => {
78
+ setError(null);
79
+ if (selectedType) {
80
+ const provider = availableProviders.find((p) => p.type === selectedType);
81
+ if (!provider) {
82
+ setError(new Error(`Unknown provider: ${selectedType}`));
83
+ return;
47
84
  }
85
+ setStatus("connecting");
86
+ try {
87
+ applyResult(await provider.connect());
88
+ } catch (e) {
89
+ setError(e instanceof Error ? e : new Error(String(e)));
90
+ setStatus("selecting");
91
+ }
92
+ return;
48
93
  }
49
- const handleConnect = (result) => {
50
- setIsConnected(true);
51
- setPaymentAddress(result.paymentAddress);
52
- setOrdinalAddress(result.ordinalAddress);
53
- setIdentityPubKey(result.identityPubKey);
54
- };
55
- const handleDisconnect = () => {
56
- setIsConnected(false);
57
- setPaymentAddress(null);
58
- setOrdinalAddress(null);
59
- setIdentityPubKey(null);
60
- };
61
- p.on("connect", handleConnect);
62
- p.on("disconnect", handleDisconnect);
63
- return () => {
64
- p.off("connect", handleConnect);
65
- p.off("disconnect", handleDisconnect);
66
- };
67
- }, [appName, popupUrl, timeout, network]);
68
- const connect = useCallback(async () => {
69
- if (!provider) {
70
- throw new Error("Provider not initialized");
94
+ setStatus("detecting");
95
+ const result = await connectWallet({
96
+ autoDetect: true,
97
+ providers
98
+ });
99
+ if (result) {
100
+ applyResult(result);
101
+ } else {
102
+ setStatus("selecting");
71
103
  }
72
- setIsConnecting(true);
73
- setError(null);
74
- try {
75
- const result = await provider.connect();
76
- return result;
77
- } catch (e) {
78
- const err = e instanceof Error ? e : new Error(String(e));
79
- setError(err);
80
- throw err;
81
- } finally {
82
- setIsConnecting(false);
104
+ }, [availableProviders, providers, applyResult]);
105
+ const mountRef = useRef({
106
+ autoDetect,
107
+ providers,
108
+ availableProviders,
109
+ connect,
110
+ applyResult
111
+ });
112
+ mountRef.current = {
113
+ autoDetect,
114
+ providers,
115
+ availableProviders,
116
+ connect,
117
+ applyResult
118
+ };
119
+ useEffect(() => {
120
+ const {
121
+ autoDetect: auto,
122
+ providers: providerConfigs,
123
+ availableProviders: available,
124
+ connect: doConnect,
125
+ applyResult: apply
126
+ } = mountRef.current;
127
+ const stored = loadStored();
128
+ if (stored) {
129
+ setStatus("connecting");
130
+ if (stored.providerType === "sigma" && stored.bapId) {
131
+ const sigmaConfig = providerConfigs?.find((p) => p.type === "sigma" && ("clientId" in p));
132
+ if (sigmaConfig) {
133
+ reconnectSigma(sigmaConfig, stored.bapId).then(apply).catch(() => {
134
+ clearStored();
135
+ if (auto)
136
+ doConnect();
137
+ else
138
+ setStatus("selecting");
139
+ });
140
+ return;
141
+ }
142
+ }
143
+ const provider = available.find((p) => p.type === stored.providerType);
144
+ if (provider) {
145
+ provider.connect().then(apply).catch(() => {
146
+ clearStored();
147
+ if (auto)
148
+ doConnect();
149
+ else
150
+ setStatus("selecting");
151
+ });
152
+ return;
153
+ }
83
154
  }
84
- }, [provider]);
85
- const disconnect = useCallback(async () => {
86
- if (!provider)
87
- return;
88
- await provider.disconnect();
89
- }, [provider]);
155
+ if (auto) {
156
+ doConnect();
157
+ } else {
158
+ setStatus("selecting");
159
+ }
160
+ }, []);
90
161
  const value = useMemo(() => ({
91
- provider,
92
- isConnected,
93
- isConnecting,
94
- paymentAddress,
95
- ordinalAddress,
96
- identityPubKey,
162
+ wallet,
163
+ status,
164
+ identityKey,
165
+ providerType,
166
+ availableProviders,
97
167
  connect,
98
168
  disconnect,
99
169
  error
100
170
  }), [
101
- provider,
102
- isConnected,
103
- isConnecting,
104
- paymentAddress,
105
- ordinalAddress,
106
- identityPubKey,
171
+ wallet,
172
+ status,
173
+ identityKey,
174
+ providerType,
175
+ availableProviders,
107
176
  connect,
108
177
  disconnect,
109
178
  error
110
179
  ]);
111
- return /* @__PURE__ */ jsx(OneSatContext.Provider, {
180
+ return /* @__PURE__ */ jsx(WalletContext.Provider, {
112
181
  value,
113
182
  children
114
183
  });
115
184
  }
116
- function useOneSatContext() {
117
- const context = useContext(OneSatContext);
118
- if (!context) {
119
- throw new Error("useOneSatContext must be used within an OneSatProvider");
185
+ function useWallet() {
186
+ const ctx = useContext(WalletContext);
187
+ if (!ctx) {
188
+ throw new Error("useWallet must be used within a WalletProvider");
120
189
  }
121
- return context;
190
+ return ctx;
122
191
  }
123
- // src/hooks.ts
124
- import { useCallback as useCallback2, useEffect as useEffect2, useRef, useState as useState2 } from "react";
192
+ // src/SigmaCallback.tsx
193
+ import { completeSigmaOAuth, isSigmaCallback } from "@1sat/connect";
194
+ import { useEffect as useEffect2, useState as useState2 } from "react";
195
+ import { jsx as jsx2, jsxs, Fragment } from "react/jsx-runtime";
125
196
  "use client";
126
- function useProviderAction(actionFn) {
127
- const { provider, isConnected } = useOneSatContext();
128
- const [isLoading, setIsLoading] = useState2(false);
129
- const [error, setError] = useState2(null);
130
- const actionRef = useRef(actionFn);
131
- actionRef.current = actionFn;
132
- const mutate = useCallback2(async (...args) => {
133
- if (!provider || !isConnected)
134
- throw new Error("Wallet not connected");
135
- setIsLoading(true);
136
- setError(null);
137
- try {
138
- return await actionRef.current(provider, ...args);
139
- } catch (e) {
140
- const err = e instanceof Error ? e : new Error(String(e));
141
- setError(err);
142
- throw err;
143
- } finally {
144
- setIsLoading(false);
145
- }
146
- }, [provider, isConnected]);
147
- return { mutate, isLoading, error };
148
- }
149
- function useBalance() {
150
- const { provider, isConnected } = useOneSatContext();
151
- const [balance, setBalance] = useState2(null);
152
- const [isLoading, setIsLoading] = useState2(false);
153
- const [error, setError] = useState2(null);
154
- const refetch = useCallback2(async () => {
155
- if (!provider || !isConnected)
156
- return;
157
- setIsLoading(true);
158
- setError(null);
159
- try {
160
- setBalance(await provider.getBalance());
161
- } catch (e) {
162
- setError(e instanceof Error ? e : new Error(String(e)));
163
- } finally {
164
- setIsLoading(false);
165
- }
166
- }, [provider, isConnected]);
167
- useEffect2(() => {
168
- if (isConnected) {
169
- refetch();
170
- } else {
171
- setBalance(null);
172
- }
173
- }, [isConnected, refetch]);
174
- return {
175
- satoshis: balance?.satoshis ?? 0,
176
- usd: balance?.usd ?? 0,
177
- isLoading,
178
- error,
179
- refetch
180
- };
181
- }
182
- function useOrdinals(limit, offset) {
183
- const { provider, isConnected } = useOneSatContext();
184
- const [ordinals, setOrdinals] = useState2([]);
185
- const [isLoading, setIsLoading] = useState2(false);
186
- const [error, setError] = useState2(null);
187
- const refetch = useCallback2(async () => {
188
- if (!provider || !isConnected)
189
- return;
190
- setIsLoading(true);
191
- setError(null);
192
- try {
193
- const opts = limit !== undefined || offset !== undefined ? { limit, offset } : undefined;
194
- setOrdinals(await provider.getOrdinals(opts));
195
- } catch (e) {
196
- setError(e instanceof Error ? e : new Error(String(e)));
197
- } finally {
198
- setIsLoading(false);
199
- }
200
- }, [provider, isConnected, limit, offset]);
201
- useEffect2(() => {
202
- if (isConnected) {
203
- refetch();
204
- } else {
205
- setOrdinals([]);
206
- }
207
- }, [isConnected, refetch]);
208
- return { ordinals, isLoading, error, refetch };
209
- }
210
- function useTokens(limit, offset) {
211
- const { provider, isConnected } = useOneSatContext();
212
- const [tokens, setTokens] = useState2([]);
213
- const [isLoading, setIsLoading] = useState2(false);
197
+ var STORAGE_KEY2 = "onesat_wallet_provider";
198
+ function SigmaCallback({
199
+ redirectTo = "/",
200
+ serverCallbackUrl = "/api/auth/sigma/callback",
201
+ loadingContent,
202
+ renderError
203
+ }) {
214
204
  const [error, setError] = useState2(null);
215
- const refetch = useCallback2(async () => {
216
- if (!provider || !isConnected)
217
- return;
218
- setIsLoading(true);
219
- setError(null);
220
- try {
221
- const opts = limit !== undefined || offset !== undefined ? { limit, offset } : undefined;
222
- setTokens(await provider.getTokens(opts));
223
- } catch (e) {
224
- setError(e instanceof Error ? e : new Error(String(e)));
225
- } finally {
226
- setIsLoading(false);
227
- }
228
- }, [provider, isConnected, limit, offset]);
229
205
  useEffect2(() => {
230
- if (isConnected) {
231
- refetch();
232
- } else {
233
- setTokens([]);
234
- }
235
- }, [isConnected, refetch]);
236
- return { tokens, isLoading, error, refetch };
237
- }
238
- function useUtxos() {
239
- const { provider, isConnected } = useOneSatContext();
240
- const [utxos, setUtxos] = useState2([]);
241
- const [isLoading, setIsLoading] = useState2(false);
242
- const [error, setError] = useState2(null);
243
- const refetch = useCallback2(async () => {
244
- if (!provider || !isConnected)
206
+ const searchParams = new URLSearchParams(window.location.search);
207
+ if (!isSigmaCallback(searchParams)) {
208
+ setError("Invalid callback — missing or mismatched OAuth parameters.");
245
209
  return;
246
- setIsLoading(true);
247
- setError(null);
248
- try {
249
- setUtxos(await provider.getUtxos());
250
- } catch (e) {
251
- setError(e instanceof Error ? e : new Error(String(e)));
252
- } finally {
253
- setIsLoading(false);
254
210
  }
255
- }, [provider, isConnected]);
256
- useEffect2(() => {
257
- if (isConnected) {
258
- refetch();
259
- } else {
260
- setUtxos([]);
211
+ completeSigmaOAuth(searchParams, serverCallbackUrl).then((result) => {
212
+ localStorage.setItem(STORAGE_KEY2, JSON.stringify({
213
+ providerType: "sigma",
214
+ identityKey: result.pubkey,
215
+ bapId: result.bapId,
216
+ user: result.user,
217
+ accessToken: result.accessToken
218
+ }));
219
+ window.location.href = redirectTo;
220
+ }).catch((err) => {
221
+ console.error("Sigma OAuth callback error:", err);
222
+ setError(err instanceof Error ? err.message : "Authentication failed");
223
+ });
224
+ }, [redirectTo, serverCallbackUrl]);
225
+ if (error) {
226
+ if (renderError) {
227
+ return /* @__PURE__ */ jsx2(Fragment, {
228
+ children: renderError(error, () => {
229
+ window.location.href = "/";
230
+ })
231
+ });
261
232
  }
262
- }, [isConnected, refetch]);
263
- return { utxos, isLoading, error, refetch };
264
- }
265
- function useSignTransaction() {
266
- const {
267
- mutate: signTransaction,
268
- isLoading,
269
- error
270
- } = useProviderAction((p, request) => p.signTransaction(request));
271
- return { signTransaction, isLoading, error };
272
- }
273
- function useSignMessage() {
274
- const {
275
- mutate: signMessage,
276
- isLoading,
277
- error
278
- } = useProviderAction((p, message) => p.signMessage(message));
279
- return { signMessage, isLoading, error };
280
- }
281
- function useInscribe() {
282
- const {
283
- mutate: inscribe,
284
- isLoading,
285
- error
286
- } = useProviderAction((p, request) => p.inscribe(request));
287
- return { inscribe, isLoading, error };
288
- }
289
- function useSendOrdinals() {
290
- const {
291
- mutate: sendOrdinals,
292
- isLoading,
293
- error
294
- } = useProviderAction((p, request) => p.sendOrdinals(request));
295
- return { sendOrdinals, isLoading, error };
296
- }
297
- function useTransferToken() {
298
- const {
299
- mutate: transferToken,
300
- isLoading,
301
- error
302
- } = useProviderAction((p, request) => p.transferToken(request));
303
- return { transferToken, isLoading, error };
304
- }
305
- function useCreateListing() {
306
- const {
307
- mutate: createListing,
308
- isLoading,
309
- error
310
- } = useProviderAction((p, request) => p.createListing(request));
311
- return { createListing, isLoading, error };
312
- }
313
- function usePurchaseListing() {
314
- const {
315
- mutate: purchaseListing,
316
- isLoading,
317
- error
318
- } = useProviderAction((p, request) => p.purchaseListing(request));
319
- return { purchaseListing, isLoading, error };
320
- }
321
- function useCancelListing() {
322
- const {
323
- mutate: cancelListing,
324
- isLoading,
325
- error
326
- } = useProviderAction((p, request) => p.cancelListing(request));
327
- return { cancelListing, isLoading, error };
233
+ return /* @__PURE__ */ jsx2("div", {
234
+ style: {
235
+ display: "flex",
236
+ minHeight: "100vh",
237
+ alignItems: "center",
238
+ justifyContent: "center",
239
+ padding: "1rem"
240
+ },
241
+ children: /* @__PURE__ */ jsxs("div", {
242
+ style: { maxWidth: "28rem", width: "100%" },
243
+ children: [
244
+ /* @__PURE__ */ jsx2("h2", {
245
+ style: {
246
+ fontSize: "1.125rem",
247
+ fontWeight: 600,
248
+ marginBottom: "0.5rem"
249
+ },
250
+ children: "Authentication Error"
251
+ }),
252
+ /* @__PURE__ */ jsx2("p", {
253
+ style: { fontSize: "0.875rem", color: "#666" },
254
+ children: error
255
+ }),
256
+ /* @__PURE__ */ jsx2("button", {
257
+ type: "button",
258
+ onClick: () => {
259
+ window.location.href = "/";
260
+ },
261
+ style: {
262
+ marginTop: "1rem",
263
+ padding: "0.5rem 1rem",
264
+ fontSize: "0.875rem",
265
+ cursor: "pointer"
266
+ },
267
+ children: "Go Back"
268
+ })
269
+ ]
270
+ })
271
+ });
272
+ }
273
+ if (loadingContent) {
274
+ return /* @__PURE__ */ jsx2(Fragment, {
275
+ children: loadingContent
276
+ });
277
+ }
278
+ return /* @__PURE__ */ jsx2("div", {
279
+ style: {
280
+ display: "flex",
281
+ minHeight: "100vh",
282
+ alignItems: "center",
283
+ justifyContent: "center"
284
+ },
285
+ children: /* @__PURE__ */ jsx2("p", {
286
+ style: { color: "#666" },
287
+ children: "Connecting wallet..."
288
+ })
289
+ });
328
290
  }
329
291
  // src/ConnectButton.tsx
330
- import { jsx as jsx2, Fragment } from "react/jsx-runtime";
292
+ import { jsx as jsx3, Fragment as Fragment2 } from "react/jsx-runtime";
331
293
  "use client";
332
- function truncateAddress(address) {
333
- if (address.length <= 12)
334
- return address;
335
- return `${address.slice(0, 6)}...${address.slice(-4)}`;
294
+ function truncateIdentityKey(key) {
295
+ if (key.length <= 12)
296
+ return key;
297
+ return `${key.slice(0, 6)}...${key.slice(-4)}`;
336
298
  }
337
299
  function ConnectButton({
338
300
  className,
@@ -347,41 +309,42 @@ function ConnectButton({
347
309
  children
348
310
  }) {
349
311
  const {
350
- isConnected,
351
- isConnecting,
352
- paymentAddress,
353
- connect: providerConnect,
354
- disconnect: providerDisconnect
355
- } = useOneSatContext();
312
+ status,
313
+ identityKey,
314
+ connect: walletConnect,
315
+ disconnect: walletDisconnect
316
+ } = useWallet();
317
+ const isConnected = status === "connected";
318
+ const isConnecting = status === "detecting" || status === "connecting";
356
319
  const connect = async () => {
357
320
  try {
358
- await providerConnect();
321
+ await walletConnect();
359
322
  onConnect?.();
360
323
  } catch (e) {
361
324
  onError?.(e instanceof Error ? e : new Error(String(e)));
362
325
  }
363
326
  };
364
- const disconnect = async () => {
327
+ const disconnect = () => {
365
328
  try {
366
- await providerDisconnect();
329
+ walletDisconnect();
367
330
  onDisconnect?.();
368
331
  } catch (e) {
369
332
  onError?.(e instanceof Error ? e : new Error(String(e)));
370
333
  }
371
334
  };
372
335
  if (children) {
373
- return /* @__PURE__ */ jsx2(Fragment, {
336
+ return /* @__PURE__ */ jsx3(Fragment2, {
374
337
  children: children({
375
338
  isConnected,
376
339
  isConnecting,
377
- address: paymentAddress,
340
+ identityKey,
378
341
  connect,
379
342
  disconnect
380
343
  })
381
344
  });
382
345
  }
383
346
  if (isConnecting) {
384
- return /* @__PURE__ */ jsx2("button", {
347
+ return /* @__PURE__ */ jsx3("button", {
385
348
  className,
386
349
  style,
387
350
  disabled: true,
@@ -390,8 +353,8 @@ function ConnectButton({
390
353
  });
391
354
  }
392
355
  if (isConnected) {
393
- const label = typeof connectedLabel === "function" ? connectedLabel(paymentAddress ?? "") : connectedLabel ?? truncateAddress(paymentAddress ?? "");
394
- return /* @__PURE__ */ jsx2("button", {
356
+ const label = typeof connectedLabel === "function" ? connectedLabel(identityKey ?? "") : connectedLabel ?? truncateIdentityKey(identityKey ?? "");
357
+ return /* @__PURE__ */ jsx3("button", {
395
358
  className,
396
359
  style,
397
360
  onClick: disconnectOnClick ? disconnect : undefined,
@@ -399,7 +362,7 @@ function ConnectButton({
399
362
  children: label
400
363
  });
401
364
  }
402
- return /* @__PURE__ */ jsx2("button", {
365
+ return /* @__PURE__ */ jsx3("button", {
403
366
  className,
404
367
  style,
405
368
  onClick: connect,
@@ -407,20 +370,38 @@ function ConnectButton({
407
370
  children: connectLabel
408
371
  });
409
372
  }
373
+ // src/WalletSelector.tsx
374
+ import { useCallback as useCallback2, useState as useState3 } from "react";
375
+ import { jsx as jsx4, Fragment as Fragment3 } from "react/jsx-runtime";
376
+ "use client";
377
+ function WalletSelector({ onClose, children }) {
378
+ const { availableProviders, connect, error } = useWallet();
379
+ const [connectingType, setConnectingType] = useState3(null);
380
+ const handleConnect = useCallback2(async (providerType) => {
381
+ setConnectingType(providerType);
382
+ try {
383
+ await connect(providerType);
384
+ onClose?.();
385
+ } finally {
386
+ setConnectingType(null);
387
+ }
388
+ }, [connect, onClose]);
389
+ const providers = availableProviders.map((p) => ({
390
+ type: p.type,
391
+ name: p.name,
392
+ icon: p.icon,
393
+ detected: p.detected,
394
+ isConnecting: connectingType === p.type,
395
+ connect: () => handleConnect(p.type)
396
+ }));
397
+ return /* @__PURE__ */ jsx4(Fragment3, {
398
+ children: children({ providers, error })
399
+ });
400
+ }
410
401
  export {
411
- useUtxos,
412
- useTransferToken,
413
- useTokens,
414
- useSignTransaction,
415
- useSignMessage,
416
- useSendOrdinals,
417
- usePurchaseListing,
418
- useOrdinals,
419
- useOneSatContext,
420
- useInscribe,
421
- useCreateListing,
422
- useCancelListing,
423
- useBalance,
424
- OneSatProvider,
402
+ useWallet,
403
+ WalletSelector,
404
+ WalletProvider,
405
+ SigmaCallback,
425
406
  ConnectButton
426
407
  };
@@ -0,0 +1,22 @@
1
+ import { type AvailableProvider, type WalletProviderConfig } from '@1sat/connect';
2
+ import type { WalletInterface } from '@bsv/sdk';
3
+ import { type ReactNode } from 'react';
4
+ export type WalletStatus = 'disconnected' | 'detecting' | 'selecting' | 'connecting' | 'connected';
5
+ export interface WalletContextValue {
6
+ wallet: WalletInterface | null;
7
+ status: WalletStatus;
8
+ identityKey: string | null;
9
+ providerType: string | null;
10
+ availableProviders: AvailableProvider[];
11
+ connect: (providerType?: string) => Promise<void>;
12
+ disconnect: () => void;
13
+ error: Error | null;
14
+ }
15
+ export interface WalletProviderProps {
16
+ autoDetect?: boolean;
17
+ providers?: WalletProviderConfig[];
18
+ children: ReactNode;
19
+ }
20
+ export declare function WalletProvider({ autoDetect, providers, children, }: WalletProviderProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare function useWallet(): WalletContextValue;
22
+ //# sourceMappingURL=wallet-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-context.d.ts","sourceRoot":"","sources":["../src/wallet-context.tsx"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,iBAAiB,EAGtB,KAAK,oBAAoB,EAIzB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC/C,OAAO,EACN,KAAK,SAAS,EAQd,MAAM,OAAO,CAAA;AAEd,MAAM,MAAM,YAAY,GACrB,cAAc,GACd,WAAW,GACX,WAAW,GACX,YAAY,GACZ,WAAW,CAAA;AAEd,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B,MAAM,EAAE,YAAY,CAAA;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,kBAAkB,EAAE,iBAAiB,EAAE,CAAA;IACvC,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IACnC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,oBAAoB,EAAE,CAAA;IAClC,QAAQ,EAAE,SAAS,CAAA;CACnB;AAyCD,wBAAgB,cAAc,CAAC,EAC9B,UAAiB,EACjB,SAAS,EACT,QAAQ,GACR,EAAE,mBAAmB,2CAsKrB;AAED,wBAAgB,SAAS,IAAI,kBAAkB,CAM9C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/react",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "React hooks and components for 1Sat wallet integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -19,12 +19,14 @@
19
19
  "keywords": ["1sat", "bsv", "ordinals", "wallet", "sdk", "react", "hooks"],
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@1sat/connect": "0.0.9"
22
+ "@1sat/connect": "0.0.11"
23
23
  },
24
24
  "peerDependencies": {
25
+ "@bsv/sdk": "^2.0.0",
25
26
  "react": "^18.0.0 || ^19.0.0"
26
27
  },
27
28
  "devDependencies": {
29
+ "@bsv/sdk": "^2.0.12",
28
30
  "@types/react": "^19.0.0",
29
31
  "react": "^19.0.0",
30
32
  "typescript": "^5.9.3"