@prb/effect-evm 1.0.0-beta.4 → 1.0.0-beta.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 (54) hide show
  1. package/DOCS.md +13 -0
  2. package/README.md +1 -0
  3. package/dist/react-hooks/index.d.ts +4 -4
  4. package/dist/react-hooks/index.d.ts.map +1 -1
  5. package/dist/react-hooks/index.js +4 -4
  6. package/dist/react-hooks/index.js.map +1 -1
  7. package/dist/react-hooks/safe-app-origins.d.ts +8 -0
  8. package/dist/react-hooks/safe-app-origins.d.ts.map +1 -0
  9. package/dist/react-hooks/{safe-origins.js → safe-app-origins.js} +29 -29
  10. package/dist/react-hooks/safe-app-origins.js.map +1 -0
  11. package/dist/react-hooks/use-is-host-safe-app.d.ts +2 -0
  12. package/dist/react-hooks/use-is-host-safe-app.d.ts.map +1 -0
  13. package/dist/react-hooks/use-is-host-safe-app.js +16 -0
  14. package/dist/react-hooks/use-is-host-safe-app.js.map +1 -0
  15. package/dist/react-hooks/use-is-safe-app-context.d.ts +2 -0
  16. package/dist/react-hooks/use-is-safe-app-context.d.ts.map +1 -0
  17. package/dist/react-hooks/{use-safe-context.js → use-is-safe-app-context.js} +2 -2
  18. package/dist/react-hooks/use-is-safe-app-context.js.map +1 -0
  19. package/dist/react-hooks/use-is-safe-multisig-wallet.d.ts +2 -0
  20. package/dist/react-hooks/use-is-safe-multisig-wallet.d.ts.map +1 -0
  21. package/dist/react-hooks/use-is-safe-multisig-wallet.js +24 -0
  22. package/dist/react-hooks/use-is-safe-multisig-wallet.js.map +1 -0
  23. package/dist/safe/index.d.ts +1 -1
  24. package/dist/safe/index.d.ts.map +1 -1
  25. package/dist/safe/index.js.map +1 -1
  26. package/dist/safe/live.d.ts.map +1 -1
  27. package/dist/safe/live.js +14 -14
  28. package/dist/safe/live.js.map +1 -1
  29. package/dist/safe/service.d.ts +4 -4
  30. package/dist/safe/service.d.ts.map +1 -1
  31. package/dist/safe/service.js.map +1 -1
  32. package/dist/safe/service.test.integration.js +10 -12
  33. package/dist/safe/service.test.integration.js.map +1 -1
  34. package/dist/safe/types.d.ts +14 -14
  35. package/dist/safe/types.d.ts.map +1 -1
  36. package/dist/safe/types.js.map +1 -1
  37. package/dist/telemetry/tracer.d.ts +2 -2
  38. package/dist/telemetry/tracer.js +2 -2
  39. package/dist/telemetry/tracer.js.map +1 -1
  40. package/package.json +1 -1
  41. package/dist/react-hooks/safe-origins.d.ts +0 -8
  42. package/dist/react-hooks/safe-origins.d.ts.map +0 -1
  43. package/dist/react-hooks/safe-origins.js.map +0 -1
  44. package/dist/react-hooks/use-is-host-safe-multisig.d.ts +0 -2
  45. package/dist/react-hooks/use-is-host-safe-multisig.d.ts.map +0 -1
  46. package/dist/react-hooks/use-is-host-safe-multisig.js +0 -16
  47. package/dist/react-hooks/use-is-host-safe-multisig.js.map +0 -1
  48. package/dist/react-hooks/use-is-wallet-safe-multisig.d.ts +0 -2
  49. package/dist/react-hooks/use-is-wallet-safe-multisig.d.ts.map +0 -1
  50. package/dist/react-hooks/use-is-wallet-safe-multisig.js +0 -24
  51. package/dist/react-hooks/use-is-wallet-safe-multisig.js.map +0 -1
  52. package/dist/react-hooks/use-safe-context.d.ts +0 -2
  53. package/dist/react-hooks/use-safe-context.d.ts.map +0 -1
  54. package/dist/react-hooks/use-safe-context.js.map +0 -1
package/DOCS.md CHANGED
@@ -229,6 +229,19 @@ function App() {
229
229
  }
230
230
  ```
231
231
 
232
+ ### Safe App vs Safe multisig
233
+
234
+ Use Safe App hooks to detect the host iframe context, and Safe multisig hooks to detect the connected wallet.
235
+
236
+ - Safe App context (SDK): `useIsSafeAppContext`
237
+ - Safe App host (SDK + origin): `useIsHostSafeApp`
238
+ - Safe multisig wallet (SDK + connector + host): `useIsSafeMultisigWallet`
239
+
240
+ Safe App origin utilities let you control the allowed host list:
241
+
242
+ - `DEFAULT_SAFE_APP_ORIGINS`
243
+ - `getSafeAppOrigins`, `setSafeAppOrigins`, `extendSafeAppOrigins`, `subscribeSafeAppOrigins`
244
+
232
245
  ### Primitive hooks
233
246
 
234
247
  Low-level hooks for running Effects and Streams in React:
package/README.md CHANGED
@@ -60,6 +60,7 @@ Effect.runPromise(program.pipe(Effect.provide(EvmLayer)));
60
60
  - **Subscriptions** — `SubscriptionService` (blocks/logs/pending tx)
61
61
  - **EIP-7702** — Delegation and atomic batching for EOAs
62
62
  - **React hooks** — `effect-evm/react-hooks` (primitives + convenience hooks)
63
+ - **Safe App + Safe multisig** — `useIsSafeAppContext`, `useIsHostSafeApp`, `useIsSafeMultisigWallet`
63
64
  - **Wagmi integration** — `effect-evm/wagmi` (build layers from wagmi config)
64
65
  - **Browser persistence** — `browser` namespace (localStorage-backed stores)
65
66
  - **Testing** — `effect-evm/testing-kit` (mocks + `makeEffectEvmTestLayer`)
@@ -4,8 +4,8 @@ export type { EffectEvmLayerProviderProps, EffectEvmProviderProps, } from "../in
4
4
  export { EffectEvmLayerProvider, EffectEvmProvider, EffectEvmProviderSync, useEffectEvmLayer, useEffectEvmRuntime, } from "../integrations/react-hooks/provider.js";
5
5
  export type { WalletProviderRefActions } from "../integrations/react-hooks/wallet-provider-ref.js";
6
6
  export { useWalletProviderRef } from "../integrations/react-hooks/wallet-provider-ref.js";
7
- export { DEFAULT_SAFE_ORIGINS, extendSafeOrigins, getSafeOrigins, setSafeOrigins, } from "./safe-origins.js";
8
- export { useIsHostSafeMultisig } from "./use-is-host-safe-multisig.js";
9
- export { useIsWalletSafeMultisig } from "./use-is-wallet-safe-multisig.js";
10
- export { useSafeContext } from "./use-safe-context.js";
7
+ export { DEFAULT_SAFE_APP_ORIGINS, extendSafeAppOrigins, getSafeAppOrigins, setSafeAppOrigins, } from "./safe-app-origins.js";
8
+ export { useIsHostSafeApp } from "./use-is-host-safe-app.js";
9
+ export { useIsSafeAppContext } from "./use-is-safe-app-context.js";
10
+ export { useIsSafeMultisigWallet } from "./use-is-safe-multisig-wallet.js";
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react-hooks/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,eAAe,GAChB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,SAAS,EACT,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,8CAA8C,CAAC;AACtD,YAAY,EACV,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,4CAA4C,CAAC;AACpD,YAAY,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,MAAM,uDAAuD,CAAC;AAC7F,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react-hooks/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,eAAe,GAChB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,SAAS,EACT,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,8CAA8C,CAAC;AACtD,YAAY,EACV,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,4CAA4C,CAAC;AACpD,YAAY,EAAE,wBAAwB,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,MAAM,uDAAuD,CAAC;AAC7F,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC"}
@@ -2,8 +2,8 @@
2
2
  export { useEffectMemo, useEffectMemoFactory, useEffectOnce, useForkEffect, useStream, useStreamEffect, useStreamValue, useSubscriptionRef, useSubscriptionRefValue, } from "../integrations/react-hooks/primitives.js";
3
3
  export { EffectEvmLayerProvider, EffectEvmProvider, EffectEvmProviderSync, useEffectEvmLayer, useEffectEvmRuntime, } from "../integrations/react-hooks/provider.js";
4
4
  export { useWalletProviderRef } from "../integrations/react-hooks/wallet-provider-ref.js";
5
- export { DEFAULT_SAFE_ORIGINS, extendSafeOrigins, getSafeOrigins, setSafeOrigins, } from "./safe-origins.js";
6
- export { useIsHostSafeMultisig } from "./use-is-host-safe-multisig.js";
7
- export { useIsWalletSafeMultisig } from "./use-is-wallet-safe-multisig.js";
8
- export { useSafeContext } from "./use-safe-context.js";
5
+ export { DEFAULT_SAFE_APP_ORIGINS, extendSafeAppOrigins, getSafeAppOrigins, setSafeAppOrigins, } from "./safe-app-origins.js";
6
+ export { useIsHostSafeApp } from "./use-is-host-safe-app.js";
7
+ export { useIsSafeAppContext } from "./use-is-safe-app-context.js";
8
+ export { useIsSafeMultisigWallet } from "./use-is-safe-multisig-wallet.js";
9
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react-hooks/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAOb,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,SAAS,EACT,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,8CAA8C,CAAC;AAKtD,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uDAAuD,CAAC;AAC7F,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["\"use client\";\n\nexport type {\n EffectMemoOptions,\n StreamState,\n UseEffectResult,\n} from \"@/src/integrations/react-hooks/primitives.js\";\nexport {\n useEffectMemo,\n useEffectMemoFactory,\n useEffectOnce,\n useForkEffect,\n useStream,\n useStreamEffect,\n useStreamValue,\n useSubscriptionRef,\n useSubscriptionRefValue,\n} from \"@/src/integrations/react-hooks/primitives.js\";\nexport type {\n EffectEvmLayerProviderProps,\n EffectEvmProviderProps,\n} from \"@/src/integrations/react-hooks/provider.js\";\nexport {\n EffectEvmLayerProvider,\n EffectEvmProvider,\n EffectEvmProviderSync,\n useEffectEvmLayer,\n useEffectEvmRuntime,\n} from \"@/src/integrations/react-hooks/provider.js\";\nexport type { WalletProviderRefActions } from \"@/src/integrations/react-hooks/wallet-provider-ref.js\";\nexport { useWalletProviderRef } from \"@/src/integrations/react-hooks/wallet-provider-ref.js\";\nexport {\n DEFAULT_SAFE_ORIGINS,\n extendSafeOrigins,\n getSafeOrigins,\n setSafeOrigins,\n} from \"./safe-origins.js\";\nexport { useIsHostSafeMultisig } from \"./use-is-host-safe-multisig.js\";\nexport { useIsWalletSafeMultisig } from \"./use-is-wallet-safe-multisig.js\";\nexport { useSafeContext } from \"./use-safe-context.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react-hooks/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAOb,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,SAAS,EACT,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,8CAA8C,CAAC;AAKtD,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uDAAuD,CAAC;AAC7F,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC","sourcesContent":["\"use client\";\n\nexport type {\n EffectMemoOptions,\n StreamState,\n UseEffectResult,\n} from \"@/src/integrations/react-hooks/primitives.js\";\nexport {\n useEffectMemo,\n useEffectMemoFactory,\n useEffectOnce,\n useForkEffect,\n useStream,\n useStreamEffect,\n useStreamValue,\n useSubscriptionRef,\n useSubscriptionRefValue,\n} from \"@/src/integrations/react-hooks/primitives.js\";\nexport type {\n EffectEvmLayerProviderProps,\n EffectEvmProviderProps,\n} from \"@/src/integrations/react-hooks/provider.js\";\nexport {\n EffectEvmLayerProvider,\n EffectEvmProvider,\n EffectEvmProviderSync,\n useEffectEvmLayer,\n useEffectEvmRuntime,\n} from \"@/src/integrations/react-hooks/provider.js\";\nexport type { WalletProviderRefActions } from \"@/src/integrations/react-hooks/wallet-provider-ref.js\";\nexport { useWalletProviderRef } from \"@/src/integrations/react-hooks/wallet-provider-ref.js\";\nexport {\n DEFAULT_SAFE_APP_ORIGINS,\n extendSafeAppOrigins,\n getSafeAppOrigins,\n setSafeAppOrigins,\n} from \"./safe-app-origins.js\";\nexport { useIsHostSafeApp } from \"./use-is-host-safe-app.js\";\nexport { useIsSafeAppContext } from \"./use-is-safe-app-context.js\";\nexport { useIsSafeMultisigWallet } from \"./use-is-safe-multisig-wallet.js\";\n"]}
@@ -0,0 +1,8 @@
1
+ export declare const DEFAULT_SAFE_APP_ORIGINS: readonly ["https://app.safe.global", "https://gnosis-safe.io", "https://safe.global", "https://safe.berachain.com", "https://safe.chiliz.com", "https://safe.lightlink.io", "https://safe.optimism.io"];
2
+ export declare function setSafeAppOrigins(origins: readonly string[]): void;
3
+ export declare function extendSafeAppOrigins(origins: readonly string[]): void;
4
+ export declare function getSafeAppOrigins(): readonly string[];
5
+ export declare function subscribeSafeAppOrigins(listener: () => void): () => void;
6
+ export declare function isValidSafeAppOrigin(): boolean;
7
+ export declare function isHostEmbedded(): boolean;
8
+ //# sourceMappingURL=safe-app-origins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-app-origins.d.ts","sourceRoot":"","sources":["../../src/react-hooks/safe-app-origins.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,wBAAwB,yMAU3B,CAAC;AASX,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,QAE3D;AAGD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,QAE9D;AAGD,wBAAgB,iBAAiB,IAAI,SAAS,MAAM,EAAE,CAErD;AAGD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAKxE;AAGD,wBAAgB,oBAAoB,IAAI,OAAO,CAM9C;AAGD,wBAAgB,cAAc,IAAI,OAAO,CAExC"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- export const DEFAULT_SAFE_ORIGINS = [
2
+ export const DEFAULT_SAFE_APP_ORIGINS = [
3
3
  "https://app.safe.global",
4
4
  "https://gnosis-safe.io",
5
5
  "https://safe.global",
@@ -9,31 +9,31 @@ export const DEFAULT_SAFE_ORIGINS = [
9
9
  "https://safe.optimism.io",
10
10
  ];
11
11
  const ORIGIN_PROTOCOL_PATTERN = /^[a-z]+:\/\//i;
12
- let safeOrigins = normalizeOrigins(DEFAULT_SAFE_ORIGINS);
13
- let safeOriginSet = new Set(safeOrigins);
14
- const safeOriginListeners = new Set();
15
- let safeOriginsConfigured = false;
16
- export function setSafeOrigins(origins) {
17
- configureSafeOrigins(normalizeOrigins(origins));
12
+ let safeAppOrigins = normalizeOrigins(DEFAULT_SAFE_APP_ORIGINS);
13
+ let safeAppOriginSet = new Set(safeAppOrigins);
14
+ const safeAppOriginListeners = new Set();
15
+ let safeAppOriginsConfigured = false;
16
+ export function setSafeAppOrigins(origins) {
17
+ configureSafeAppOrigins(normalizeOrigins(origins));
18
18
  }
19
- export function extendSafeOrigins(origins) {
20
- configureSafeOrigins(normalizeOrigins([...safeOrigins, ...origins]));
19
+ export function extendSafeAppOrigins(origins) {
20
+ configureSafeAppOrigins(normalizeOrigins([...safeAppOrigins, ...origins]));
21
21
  }
22
- export function getSafeOrigins() {
23
- return [...safeOrigins];
22
+ export function getSafeAppOrigins() {
23
+ return [...safeAppOrigins];
24
24
  }
25
- export function subscribeSafeOrigins(listener) {
26
- safeOriginListeners.add(listener);
25
+ export function subscribeSafeAppOrigins(listener) {
26
+ safeAppOriginListeners.add(listener);
27
27
  return () => {
28
- safeOriginListeners.delete(listener);
28
+ safeAppOriginListeners.delete(listener);
29
29
  };
30
30
  }
31
- export function isValidSafeOrigin() {
31
+ export function isValidSafeAppOrigin() {
32
32
  const origin = getAncestorOrigin();
33
33
  if (!origin) {
34
34
  return false;
35
35
  }
36
- return safeOriginSet.has(origin);
36
+ return safeAppOriginSet.has(origin);
37
37
  }
38
38
  export function isHostEmbedded() {
39
39
  return typeof window !== "undefined" && window.parent !== window;
@@ -60,23 +60,23 @@ function getAncestorOrigin() {
60
60
  return null;
61
61
  }
62
62
  }
63
- function updateSafeOrigins(nextOrigins) {
64
- if (areSameOrigins(safeOrigins, nextOrigins)) {
63
+ function updateSafeAppOrigins(nextOrigins) {
64
+ if (areSameOrigins(safeAppOrigins, nextOrigins)) {
65
65
  return;
66
66
  }
67
- safeOrigins = nextOrigins;
68
- safeOriginSet = new Set(safeOrigins);
69
- notifySafeOriginListeners();
67
+ safeAppOrigins = nextOrigins;
68
+ safeAppOriginSet = new Set(safeAppOrigins);
69
+ notifySafeAppOriginListeners();
70
70
  }
71
- function configureSafeOrigins(nextOrigins) {
72
- if (safeOriginsConfigured) {
73
- throw new Error("Safe origins already configured.");
71
+ function configureSafeAppOrigins(nextOrigins) {
72
+ if (safeAppOriginsConfigured) {
73
+ throw new Error("Safe App origins already configured.");
74
74
  }
75
- safeOriginsConfigured = true;
76
- updateSafeOrigins(nextOrigins);
75
+ safeAppOriginsConfigured = true;
76
+ updateSafeAppOrigins(nextOrigins);
77
77
  }
78
- function notifySafeOriginListeners() {
79
- for (const listener of safeOriginListeners) {
78
+ function notifySafeAppOriginListeners() {
79
+ for (const listener of safeAppOriginListeners) {
80
80
  listener();
81
81
  }
82
82
  }
@@ -121,4 +121,4 @@ function areSameOrigins(left, right) {
121
121
  }
122
122
  return true;
123
123
  }
124
- //# sourceMappingURL=safe-origins.js.map
124
+ //# sourceMappingURL=safe-app-origins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-app-origins.js","sourceRoot":"","sources":["../../src/react-hooks/safe-app-origins.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * Known Safe App domains for iframe origin validation.\n * Includes the main Safe App and chain-specific Safe deployments.\n */\nexport const DEFAULT_SAFE_APP_ORIGINS = [\n // Main Safe domains\n \"https://app.safe.global\",\n \"https://gnosis-safe.io\",\n \"https://safe.global\",\n // Chain-specific Safe deployments\n \"https://safe.berachain.com\",\n \"https://safe.chiliz.com\",\n \"https://safe.lightlink.io\",\n \"https://safe.optimism.io\",\n] as const;\n\nconst ORIGIN_PROTOCOL_PATTERN = /^[a-z]+:\\/\\//i;\nlet safeAppOrigins = normalizeOrigins(DEFAULT_SAFE_APP_ORIGINS);\nlet safeAppOriginSet = new Set(safeAppOrigins);\nconst safeAppOriginListeners = new Set<() => void>();\nlet safeAppOriginsConfigured = false;\n\n/** Replace the Safe App origins list (one-time configuration). */\nexport function setSafeAppOrigins(origins: readonly string[]) {\n configureSafeAppOrigins(normalizeOrigins(origins));\n}\n\n/** Extend the Safe App origins list (one-time configuration). */\nexport function extendSafeAppOrigins(origins: readonly string[]) {\n configureSafeAppOrigins(normalizeOrigins([...safeAppOrigins, ...origins]));\n}\n\n/** Read the currently configured Safe App origins list. */\nexport function getSafeAppOrigins(): readonly string[] {\n return [...safeAppOrigins];\n}\n\n/** Subscribe to Safe App origin changes. */\nexport function subscribeSafeAppOrigins(listener: () => void): () => void {\n safeAppOriginListeners.add(listener);\n return () => {\n safeAppOriginListeners.delete(listener);\n };\n}\n\n/** Check if the parent browsing context origin is a Safe App domain. */\nexport function isValidSafeAppOrigin(): boolean {\n const origin = getAncestorOrigin();\n if (!origin) {\n return false;\n }\n return safeAppOriginSet.has(origin);\n}\n\n/** Check whether the app is running inside an iframe. */\nexport function isHostEmbedded(): boolean {\n return typeof window !== \"undefined\" && window.parent !== window;\n}\n\n/**\n * Get the origin of the parent browsing context.\n * Returns null if it cannot be determined due to cross-origin restrictions.\n */\nfunction getAncestorOrigin(): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return window.parent.location.origin;\n } catch {\n if (window.location.ancestorOrigins?.length) {\n return window.location.ancestorOrigins[0];\n }\n\n if (document.referrer) {\n try {\n return new URL(document.referrer).origin;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n}\n\nfunction updateSafeAppOrigins(nextOrigins: string[]) {\n if (areSameOrigins(safeAppOrigins, nextOrigins)) {\n return;\n }\n\n safeAppOrigins = nextOrigins;\n safeAppOriginSet = new Set(safeAppOrigins);\n notifySafeAppOriginListeners();\n}\n\nfunction configureSafeAppOrigins(nextOrigins: string[]) {\n if (safeAppOriginsConfigured) {\n throw new Error(\"Safe App origins already configured.\");\n }\n\n safeAppOriginsConfigured = true;\n updateSafeAppOrigins(nextOrigins);\n}\n\nfunction notifySafeAppOriginListeners() {\n for (const listener of safeAppOriginListeners) {\n listener();\n }\n}\n\nfunction normalizeOrigins(origins: readonly string[]): string[] {\n const normalized: string[] = [];\n const seen = new Set<string>();\n\n for (const origin of origins) {\n const normalizedOrigin = normalizeOrigin(origin);\n if (!normalizedOrigin || seen.has(normalizedOrigin)) {\n continue;\n }\n seen.add(normalizedOrigin);\n normalized.push(normalizedOrigin);\n }\n\n return normalized;\n}\n\nfunction normalizeOrigin(origin: string): string | null {\n const trimmed = origin.trim();\n if (!trimmed) {\n return null;\n }\n\n const candidate = ORIGIN_PROTOCOL_PATTERN.test(trimmed) ? trimmed : `https://${trimmed}`;\n\n try {\n const url = new URL(candidate);\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n return null;\n }\n return url.origin;\n } catch {\n return null;\n }\n}\n\nfunction areSameOrigins(left: readonly string[], right: readonly string[]): boolean {\n if (left.length !== right.length) {\n return false;\n }\n\n for (let index = 0; index < left.length; index += 1) {\n if (left[index] !== right[index]) {\n return false;\n }\n }\n\n return true;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function useIsHostSafeApp(): boolean;
2
+ //# sourceMappingURL=use-is-host-safe-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-is-host-safe-app.d.ts","sourceRoot":"","sources":["../../src/react-hooks/use-is-host-safe-app.ts"],"names":[],"mappings":"AAsBA,wBAAgB,gBAAgB,IAAI,OAAO,CAS1C"}
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { useSyncExternalStore } from "react";
3
+ import { isHostEmbedded, isValidSafeAppOrigin, subscribeSafeAppOrigins, } from "./safe-app-origins.js";
4
+ import { useIsSafeAppContext } from "./use-is-safe-app-context.js";
5
+ export function useIsHostSafeApp() {
6
+ const isSafeContext = useIsSafeAppContext();
7
+ const isSafeHost = useSyncExternalStore(subscribeSafeAppOrigins, getSafeHostSnapshot, getServerSnapshot);
8
+ return isSafeContext || isSafeHost;
9
+ }
10
+ function getSafeHostSnapshot() {
11
+ return isHostEmbedded() && isValidSafeAppOrigin();
12
+ }
13
+ function getServerSnapshot() {
14
+ return false;
15
+ }
16
+ //# sourceMappingURL=use-is-host-safe-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-is-host-safe-app.js","sourceRoot":"","sources":["../../src/react-hooks/use-is-host-safe-app.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAcnE,MAAM,UAAU,gBAAgB;IAC9B,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,oBAAoB,CACrC,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,CAClB,CAAC;IAEF,OAAO,aAAa,IAAI,UAAU,CAAC;AACrC,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO,cAAc,EAAE,IAAI,oBAAoB,EAAE,CAAC;AACpD,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\nimport {\n isHostEmbedded,\n isValidSafeAppOrigin,\n subscribeSafeAppOrigins,\n} from \"./safe-app-origins.js\";\nimport { useIsSafeAppContext } from \"./use-is-safe-app-context.js\";\n\n/**\n * Detect if the app is running within a Safe App context.\n *\n * This hook returns `true` when either:\n * - Safe Apps SDK confirms the Safe context (async, most reliable), or\n * - The app is embedded in a Safe App-origin iframe (sync check).\n *\n * Notes:\n * - This answers “is the host Safe App?” and will return true even without a wallet.\n * - For full wallet detection heuristics, use `useIsSafeMultisigWallet`.\n * - For SDK-only checks, use `useIsSafeAppContext`.\n */\nexport function useIsHostSafeApp(): boolean {\n const isSafeContext = useIsSafeAppContext();\n const isSafeHost = useSyncExternalStore(\n subscribeSafeAppOrigins,\n getSafeHostSnapshot,\n getServerSnapshot\n );\n\n return isSafeContext || isSafeHost;\n}\n\nfunction getSafeHostSnapshot(): boolean {\n return isHostEmbedded() && isValidSafeAppOrigin();\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function useIsSafeAppContext(): boolean;
2
+ //# sourceMappingURL=use-is-safe-app-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-is-safe-app-context.d.ts","sourceRoot":"","sources":["../../src/react-hooks/use-is-safe-app-context.ts"],"names":[],"mappings":"AAuCA,wBAAgB,mBAAmB,IAAI,OAAO,CA6C7C"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { useEffect, useState } from "react";
3
3
  const SAFE_SDK_TIMEOUT = 3000;
4
- export function useSafeContext() {
4
+ export function useIsSafeAppContext() {
5
5
  const [isSafe, setIsSafe] = useState(false);
6
6
  useEffect(() => {
7
7
  if (typeof window === "undefined") {
@@ -38,4 +38,4 @@ export function useSafeContext() {
38
38
  }, []);
39
39
  return isSafe;
40
40
  }
41
- //# sourceMappingURL=use-safe-context.js.map
41
+ //# sourceMappingURL=use-is-safe-app-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-is-safe-app-context.js","sourceRoot":"","sources":["../../src/react-hooks/use-is-safe-app-context.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAM5C,MAAM,gBAAgB,GAAG,IAAI,CAAC;AA+B9B,MAAM,UAAU,mBAAmB;IACjC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QAEb,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAC;QAGtB,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACH,CAAC,EAAE,gBAAgB,CAAC,CAAC;QAGrB,MAAM,CAAC,4BAA4B,CAAC;aACjC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE;YACjC,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,EAAE;YACT,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACH,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QAEL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * Timeout for Safe SDK detection in milliseconds.\n * Safe Apps SDK uses postMessage which can hang if not in Safe context.\n */\nconst SAFE_SDK_TIMEOUT = 3000;\n\n/**\n * Detect if the app is running in a Safe App context using the Safe Apps SDK.\n *\n * This hook asynchronously checks with the Safe Apps SDK to determine if\n * we're running inside a Safe App iframe. More reliable than iframe origin\n * detection because:\n * - Uses postMessage (works cross-origin)\n * - Gets definitive answer from Safe\n * - Includes timeout to prevent hangs\n *\n * @returns true if running in Safe App context, false otherwise\n *\n * Notes:\n * - This only verifies the Safe Apps SDK context (async).\n * - For a host-based sync check, use `useIsHostSafeApp`.\n * - For a full wallet detection heuristic, use `useIsSafeMultisigWallet`.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const isSafeContext = useIsSafeAppContext();\n *\n * if (isSafeContext) {\n * return <p>Running in Safe App</p>;\n * }\n * return <p>Regular browser context</p>;\n * }\n * ```\n */\nexport function useIsSafeAppContext(): boolean {\n const [isSafe, setIsSafe] = useState(false);\n\n useEffect(() => {\n // SSR guard\n if (typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n\n // Timeout fallback - resolve to false if SDK doesn't respond\n const timeout = setTimeout(() => {\n if (!cancelled) {\n setIsSafe(false);\n }\n }, SAFE_SDK_TIMEOUT);\n\n // Dynamically import SDK to keep it optional\n import(\"@safe-global/safe-apps-sdk\")\n .then(({ default: SafeAppsSDK }) => {\n const sdk = new SafeAppsSDK();\n return sdk.safe.getInfo();\n })\n .then(() => {\n if (!cancelled) {\n setIsSafe(true);\n }\n })\n .catch(() => {\n if (!cancelled) {\n setIsSafe(false);\n }\n })\n .finally(() => {\n clearTimeout(timeout);\n });\n\n return () => {\n cancelled = true;\n clearTimeout(timeout);\n };\n }, []);\n\n return isSafe;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function useIsSafeMultisigWallet(): boolean;
2
+ //# sourceMappingURL=use-is-safe-multisig-wallet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-is-safe-multisig-wallet.d.ts","sourceRoot":"","sources":["../../src/react-hooks/use-is-safe-multisig-wallet.ts"],"names":[],"mappings":"AA0BA,wBAAgB,uBAAuB,IAAI,OAAO,CAuBjD"}
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { useSyncExternalStore } from "react";
3
+ import { useAccount } from "wagmi";
4
+ import { isHostEmbedded, isValidSafeAppOrigin, subscribeSafeAppOrigins, } from "./safe-app-origins.js";
5
+ import { useIsSafeAppContext } from "./use-is-safe-app-context.js";
6
+ export function useIsSafeMultisigWallet() {
7
+ const { connector, isConnected } = useAccount();
8
+ const isSafeContext = useIsSafeAppContext();
9
+ const isSafeIframe = useSyncExternalStore(subscribeSafeAppOrigins, getSafeIframeSnapshot, getServerSnapshot);
10
+ if (isSafeContext) {
11
+ return true;
12
+ }
13
+ if (isConnected && connector?.id === "safe") {
14
+ return true;
15
+ }
16
+ return isSafeIframe;
17
+ }
18
+ function getSafeIframeSnapshot() {
19
+ return isHostEmbedded() && isValidSafeAppOrigin();
20
+ }
21
+ function getServerSnapshot() {
22
+ return false;
23
+ }
24
+ //# sourceMappingURL=use-is-safe-multisig-wallet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-is-safe-multisig-wallet.js","sourceRoot":"","sources":["../../src/react-hooks/use-is-safe-multisig-wallet.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAiBnE,MAAM,UAAU,uBAAuB;IACrC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,UAAU,EAAE,CAAC;IAChD,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;IAG5C,MAAM,YAAY,GAAG,oBAAoB,CACvC,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,CAClB,CAAC;IAGF,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,IAAI,WAAW,IAAI,SAAS,EAAE,EAAE,KAAK,MAAM,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO,cAAc,EAAE,IAAI,oBAAoB,EAAE,CAAC;AACpD,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\nimport { useAccount } from \"wagmi\";\nimport {\n isHostEmbedded,\n isValidSafeAppOrigin,\n subscribeSafeAppOrigins,\n} from \"./safe-app-origins.js\";\nimport { useIsSafeAppContext } from \"./use-is-safe-app-context.js\";\n\n/**\n * Detect if the connected wallet is a Safe multisig wallet.\n *\n * Detection strategy (in order of reliability):\n * 1. Safe Apps SDK detection via postMessage (most reliable, works cross-origin)\n * 2. Wagmi connector ID check\n * 3. Iframe origin validation (fallback, may fail cross-origin)\n *\n * @returns true if wallet is a Safe multisig\n *\n * Notes:\n * - This is a broader heuristic: SDK context, connector ID, then host origin.\n * - For just SDK context, use `useIsSafeAppContext`.\n * - For a sync host-only check, use `useIsHostSafeApp`.\n */\nexport function useIsSafeMultisigWallet(): boolean {\n const { connector, isConnected } = useAccount();\n const isSafeContext = useIsSafeAppContext();\n\n // Method 3: Iframe origin fallback (may fail cross-origin)\n const isSafeIframe = useSyncExternalStore(\n subscribeSafeAppOrigins,\n getSafeIframeSnapshot,\n getServerSnapshot\n );\n\n // Method 1: Safe Apps SDK (most reliable - uses postMessage)\n if (isSafeContext) {\n return true;\n }\n\n // Method 2: Connected via Safe connector\n if (isConnected && connector?.id === \"safe\") {\n return true;\n }\n\n // Method 3: Fallback\n return isSafeIframe;\n}\n\nfunction getSafeIframeSnapshot(): boolean {\n return isHostEmbedded() && isValidSafeAppOrigin();\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n"]}
@@ -4,5 +4,5 @@ export { NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeInfoUnavai
4
4
  export { type SafeAppsServiceConfig, SafeAppsServiceLive } from "./live.js";
5
5
  export { SafeAppsService, type SafeAppsServiceShape } from "./service.js";
6
6
  export * from "./simulation/index.js";
7
- export type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeInfo, SafeTransaction, SafeTxResult, SafeTxSubmission, SafeWaitPolicy, SignTypedDataResult, } from "./types.js";
7
+ export type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeInfo, SafeMultisigTx, SafeTxResult, SafeTxSubmission, SafeWaitPolicy, SignTypedDataResult, } from "./types.js";
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE/E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE1E,cAAc,uBAAuB,CAAC;AAEtC,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE/E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE1E,cAAc,uBAAuB,CAAC;AAEtC,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAA8B,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,eAAe,EAA6B,MAAM,cAAc,CAAC;AAE1E,cAAc,uBAAuB,CAAC","sourcesContent":["// Service and layer\n\nexport type { SafeDetectionParams, SafeDetectionResult } from \"./detection.js\";\n// Detection\nexport { isSafeMultisig, SafeDetectionError } from \"./detection.js\";\n\n// Errors\nexport {\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeInfoUnavailableError,\n SafeSdkUnavailableError,\n SafeSettingsError,\n SafeTxExecutionTimeoutError,\n SafeTxLookupError,\n SafeTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nexport { type SafeAppsServiceConfig, SafeAppsServiceLive } from \"./live.js\";\nexport { SafeAppsService, type SafeAppsServiceShape } from \"./service.js\";\n// Simulation\nexport * from \"./simulation/index.js\";\n// Types\nexport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeInfo,\n SafeTransaction,\n SafeTxResult,\n SafeTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAA8B,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,eAAe,EAA6B,MAAM,cAAc,CAAC;AAE1E,cAAc,uBAAuB,CAAC","sourcesContent":["// Service and layer\n\nexport type { SafeDetectionParams, SafeDetectionResult } from \"./detection.js\";\n// Detection\nexport { isSafeMultisig, SafeDetectionError } from \"./detection.js\";\n\n// Errors\nexport {\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeInfoUnavailableError,\n SafeSdkUnavailableError,\n SafeSettingsError,\n SafeTxExecutionTimeoutError,\n SafeTxLookupError,\n SafeTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nexport { type SafeAppsServiceConfig, SafeAppsServiceLive } from \"./live.js\";\nexport { SafeAppsService, type SafeAppsServiceShape } from \"./service.js\";\n// Simulation\nexport * from \"./simulation/index.js\";\n// Types\nexport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeInfo,\n SafeMultisigTx,\n SafeTxResult,\n SafeTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,EAAe,MAAM,QAAQ,CAAC;AAU9D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EACL,wBAAwB,EAQzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AA+CtD,eAAO,MAAM,mBAAmB,GAAI,SAAS,qBAAqB,sHAgX/D,CAAC"}
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,EAAe,MAAM,QAAQ,CAAC;AAU9D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EACL,wBAAwB,EAQzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AA+CtD,eAAO,MAAM,mBAAmB,GAAI,SAAS,qBAAqB,sHA6W/D,CAAC"}
package/dist/safe/live.js CHANGED
@@ -56,7 +56,7 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
56
56
  yield* Ref.set(infoRef, safeInfo);
57
57
  return safeInfo;
58
58
  }).pipe(Effect.withSpan(SpanNames.SAFE_GET_INFO));
59
- const sendTransactions = (txs, params) => Effect.gen(function* () {
59
+ const sendTxs = (txs, params) => Effect.gen(function* () {
60
60
  const sdkTxs = txs.map((tx) => ({
61
61
  data: tx.data,
62
62
  to: tx.to,
@@ -65,11 +65,11 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
65
65
  const result = yield* Effect.tryPromise({
66
66
  catch: (cause) => new SafeTxSubmissionError({
67
67
  cause,
68
- message: "Failed to submit transactions to Safe",
68
+ message: "Failed to submit txs to Safe",
69
69
  }),
70
70
  try: () => sdk.txs.send({ params, txs: sdkTxs }),
71
71
  });
72
- const safeTxHash = yield* validateHash(result.safeTxHash, "sendTransactions").pipe(Effect.catchTag("SafeTxLookupError", (e) => Effect.fail(new SafeTxSubmissionError({ cause: e, message: e.message }))));
72
+ const safeTxHash = yield* validateHash(result.safeTxHash, "sendTxs").pipe(Effect.catchTag("SafeTxLookupError", (e) => Effect.fail(new SafeTxSubmissionError({ cause: e, message: e.message }))));
73
73
  const info = yield* getInfo();
74
74
  return {
75
75
  chainId: info.chainId,
@@ -79,22 +79,22 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
79
79
  })
80
80
  .pipe(Effect.catchTag("SafeInfoUnavailableError", (error) => Effect.fail(new SafeTxSubmissionError({
81
81
  cause: error,
82
- message: "Failed to get Safe info after transaction submission",
82
+ message: "Failed to get Safe info after tx submission",
83
83
  }))))
84
84
  .pipe(Effect.withSpan(SpanNames.SAFE_SEND_TXS, {
85
85
  attributes: { txCount: txs.length },
86
86
  }));
87
- const getTransaction = (safeTxHash) => Effect.gen(function* () {
87
+ const getTx = (safeTxHash) => Effect.gen(function* () {
88
88
  const tx = yield* Effect.tryPromise({
89
89
  catch: (cause) => new SafeTxLookupError({
90
90
  cause,
91
- message: `Failed to lookup Safe transaction ${safeTxHash}`,
91
+ message: `Failed to lookup Safe tx ${safeTxHash}`,
92
92
  retryable: true,
93
93
  safeTxHash,
94
94
  }),
95
95
  try: () => sdk.txs.getBySafeTxHash(safeTxHash),
96
96
  });
97
- const txHash = tx.txHash ? yield* validateHash(tx.txHash, "getTransaction") : null;
97
+ const txHash = tx.txHash ? yield* validateHash(tx.txHash, "getTx") : null;
98
98
  return {
99
99
  status: tx.txStatus ?? "AWAITING_CONFIRMATIONS",
100
100
  txHash: txHash ? Option.some(txHash) : Option.none(),
@@ -102,7 +102,7 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
102
102
  }).pipe(Effect.withSpan(SpanNames.SAFE_GET_TX, {
103
103
  attributes: { safeTxHash },
104
104
  }));
105
- const waitForTransactionReceipt = (safeTxHash, policy = {}) => Effect.gen(function* () {
105
+ const waitForTxReceipt = (safeTxHash, policy = {}) => Effect.gen(function* () {
106
106
  const info = yield* getInfo();
107
107
  const pollInterval = policy.pollInterval ?? SAFE_POLL_INTERVAL;
108
108
  const executionTimeout = policy.executionTimeout ?? SAFE_EXECUTION_TIMEOUT;
@@ -111,7 +111,7 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
111
111
  let found = null;
112
112
  const pollEffect = Effect.gen(function* () {
113
113
  while (found === null) {
114
- const tx = yield* getTransaction(safeTxHash);
114
+ const tx = yield* getTx(safeTxHash);
115
115
  lastStatus = tx.status;
116
116
  if (Option.isSome(tx.txHash)) {
117
117
  found = tx.txHash.value;
@@ -123,14 +123,14 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
123
123
  });
124
124
  yield* pollEffect.pipe(Effect.timeout(Duration.millis(executionTimeout)), Effect.catchTag("TimeoutException", () => Effect.fail(new SafeTxExecutionTimeoutError({
125
125
  lastStatus,
126
- message: `Safe transaction ${safeTxHash} not executed within ${executionTimeout}ms (last status: ${lastStatus})`,
126
+ message: `Safe tx ${safeTxHash} not executed within ${executionTimeout}ms (last status: ${lastStatus})`,
127
127
  safeTxHash,
128
128
  timeout: executionTimeout,
129
129
  }))));
130
130
  if (found === null) {
131
131
  return yield* Effect.fail(new SafeTxExecutionTimeoutError({
132
132
  lastStatus,
133
- message: `Safe transaction ${safeTxHash} not executed within timeout`,
133
+ message: `Safe tx ${safeTxHash} not executed within timeout`,
134
134
  safeTxHash,
135
135
  timeout: executionTimeout,
136
136
  }));
@@ -240,11 +240,11 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
240
240
  enableOffchainSigning,
241
241
  getInfo,
242
242
  getOffchainSignature,
243
- getTransaction,
243
+ getTx,
244
244
  pollOffchainSignature,
245
- sendTransactions,
245
+ sendTxs,
246
246
  signTypedData,
247
- waitForTransactionReceipt,
247
+ waitForTxReceipt,
248
248
  });
249
249
  }));
250
250
  //# sourceMappingURL=live.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration, Effect, Layer, Option, Ref } from \"effect\";\nimport type { Address, Hash, Hex } from \"viem\";\nimport { isAddress, isHash, isHex } from \"viem\";\nimport {\n SAFE_EXECUTION_TIMEOUT,\n SAFE_POLL_INTERVAL,\n SAFE_SIGNATURE_POLL_INTERVAL,\n SAFE_SIGNATURE_TIMEOUT,\n} from \"@/src/constants/index.js\";\nimport { SpanNames } from \"@/src/telemetry/index.js\";\nimport { TxManager } from \"@/src/tx/index.js\";\nimport type { SafeAppsSdkConfig } from \"./adapter.js\";\nimport { loadSafeSdk } from \"./adapter.js\";\nimport {\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeInfoUnavailableError,\n SafeSettingsError,\n SafeTxExecutionTimeoutError,\n SafeTxLookupError,\n SafeTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { EIP712TypedData, SafeInfo } from \"./types.js\";\n\nexport type SafeAppsServiceConfig = SafeAppsSdkConfig;\n\n/**\n * Validate that a string is a valid Ethereum address, failing with context if not.\n */\nconst validateAddress = (\n value: string,\n context: string\n): Effect.Effect<Address, SafeTxLookupError> =>\n isAddress(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid address from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\n/**\n * Validate that a string is a valid transaction hash, failing with context if not.\n */\nconst validateHash = (value: string, context: string): Effect.Effect<Hash, SafeTxLookupError> =>\n isHash(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid hash from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\n/**\n * Validate that a string is valid hex, failing with context if not.\n */\nconst validateHex = (value: string, context: string): Effect.Effect<Hex, SafeTxLookupError> =>\n isHex(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid hex from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\nexport const SafeAppsServiceLive = (config?: SafeAppsServiceConfig) =>\n Layer.scoped(\n SafeAppsService,\n Effect.gen(function* () {\n // SSR guard - Safe Apps SDK requires browser environment\n if (typeof window === \"undefined\") {\n return yield* Effect.fail(\n new NotInSafeAppContextError({\n message: \"Safe Apps SDK requires a browser environment (window is undefined)\",\n })\n );\n }\n\n // Load SDK dynamically to keep it optional\n const sdk = yield* loadSafeSdk(config);\n\n // Cache Safe info after first fetch\n const infoRef = yield* Ref.make<SafeInfo | null>(null);\n\n // Get TxManager for receipt waiting\n const txManager = yield* TxManager;\n\n // --- Service method implementations ---\n\n const getInfo = () =>\n Effect.gen(function* () {\n const cached = yield* Ref.get(infoRef);\n if (cached) {\n return cached;\n }\n\n const info = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeInfoUnavailableError({\n cause,\n message: \"Failed to get Safe info from SDK\",\n }),\n try: () => sdk.safe.getInfo(),\n });\n\n const safeAddress = yield* validateAddress(info.safeAddress, \"getInfo\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SafeInfoUnavailableError({ cause: e, message: e.message }))\n )\n );\n\n const safeInfo: SafeInfo = {\n chainId: info.chainId,\n safeAddress,\n };\n\n yield* Ref.set(infoRef, safeInfo);\n return safeInfo;\n }).pipe(Effect.withSpan(SpanNames.SAFE_GET_INFO));\n\n const sendTransactions = (\n txs: readonly { to: Address; data: Hex; value?: bigint }[],\n params?: { safeTxGas?: number }\n ) =>\n Effect.gen(function* () {\n // Convert bigint values to strings (Safe SDK expects decimal strings)\n const sdkTxs = txs.map((tx) => ({\n data: tx.data,\n to: tx.to,\n value: tx.value?.toString() ?? \"0\",\n }));\n\n const result = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxSubmissionError({\n cause,\n message: \"Failed to submit transactions to Safe\",\n }),\n try: () => sdk.txs.send({ params, txs: sdkTxs }),\n });\n\n const safeTxHash = yield* validateHash(result.safeTxHash, \"sendTransactions\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SafeTxSubmissionError({ cause: e, message: e.message }))\n )\n );\n\n const info = yield* getInfo();\n\n return {\n chainId: info.chainId,\n safeAddress: info.safeAddress,\n safeTxHash,\n };\n })\n .pipe(\n Effect.catchTag(\"SafeInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeTxSubmissionError({\n cause: error,\n message: \"Failed to get Safe info after transaction submission\",\n })\n )\n )\n )\n .pipe(\n Effect.withSpan(SpanNames.SAFE_SEND_TXS, {\n attributes: { txCount: txs.length },\n })\n );\n\n const getTransaction = (safeTxHash: Hash) =>\n Effect.gen(function* () {\n const tx = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxLookupError({\n cause,\n message: `Failed to lookup Safe transaction ${safeTxHash}`,\n retryable: true,\n safeTxHash,\n }),\n try: () => sdk.txs.getBySafeTxHash(safeTxHash),\n });\n\n const txHash = tx.txHash ? yield* validateHash(tx.txHash, \"getTransaction\") : null;\n\n return {\n status: tx.txStatus ?? \"AWAITING_CONFIRMATIONS\",\n txHash: txHash ? Option.some(txHash) : Option.none<Hash>(),\n };\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_GET_TX, {\n attributes: { safeTxHash },\n })\n );\n\n const waitForTransactionReceipt = (\n safeTxHash: Hash,\n policy: {\n pollInterval?: number;\n executionTimeout?: number;\n receiptPolicy?: { receiptTimeout?: number; pollingInterval?: number };\n } = {}\n ) =>\n Effect.gen(function* () {\n const info = yield* getInfo();\n const pollInterval = policy.pollInterval ?? SAFE_POLL_INTERVAL;\n const executionTimeout = policy.executionTimeout ?? SAFE_EXECUTION_TIMEOUT;\n\n // Poll Safe gateway until txHash appears\n // Effect.sleep is interruptible, so this loop respects Effect's interruption model\n const onchainHash = yield* Effect.gen(function* () {\n let lastStatus = \"AWAITING_CONFIRMATIONS\";\n let found: Hash | null = null;\n\n const pollEffect = Effect.gen(function* () {\n while (found === null) {\n const tx = yield* getTransaction(safeTxHash);\n lastStatus = tx.status;\n\n if (Option.isSome(tx.txHash)) {\n found = tx.txHash.value;\n } else {\n // Sleep is interruptible - key for Effect's interruption model\n yield* Effect.sleep(Duration.millis(pollInterval));\n }\n }\n });\n\n yield* pollEffect.pipe(\n Effect.timeout(Duration.millis(executionTimeout)),\n Effect.catchTag(\"TimeoutException\", () =>\n Effect.fail(\n new SafeTxExecutionTimeoutError({\n lastStatus,\n message: `Safe transaction ${safeTxHash} not executed within ${executionTimeout}ms (last status: ${lastStatus})`,\n safeTxHash,\n timeout: executionTimeout,\n })\n )\n )\n );\n\n if (found === null) {\n return yield* Effect.fail(\n new SafeTxExecutionTimeoutError({\n lastStatus,\n message: `Safe transaction ${safeTxHash} not executed within timeout`,\n safeTxHash,\n timeout: executionTimeout,\n })\n );\n }\n return found;\n });\n\n // Delegate to TxManager for on-chain receipt\n const receipt = yield* txManager\n .waitForReceipt(info.chainId, onchainHash, policy.receiptPolicy)\n .pipe(\n Effect.catchTag(\"TransactionReplacedError\", (error) =>\n Effect.fail(\n new SafeTxLookupError({\n cause: error,\n message: `Transaction was replaced: ${error.message}`,\n retryable: false,\n safeTxHash,\n })\n )\n )\n );\n\n return {\n chainId: info.chainId,\n onchainHash,\n receipt,\n safeAddress: info.safeAddress,\n safeTxHash,\n };\n })\n .pipe(\n Effect.catchTag(\"SafeInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeTxLookupError({\n cause: error,\n message: \"Failed to get Safe info for receipt waiting\",\n retryable: true,\n safeTxHash,\n })\n )\n )\n )\n .pipe(\n Effect.withSpan(SpanNames.SAFE_WAIT_RECEIPT, {\n attributes: { safeTxHash },\n })\n );\n\n const signTypedData = (typedData: EIP712TypedData) =>\n Effect.gen(function* () {\n const result = yield* Effect.tryPromise({\n catch: (cause) =>\n new SignTypedDataError({\n cause,\n message: \"Failed to sign typed data via Safe\",\n }),\n try: () =>\n sdk.txs.signTypedMessage(typedData as Parameters<typeof sdk.txs.signTypedMessage>[0]),\n });\n\n // SDK returns { safeTxHash } for on-chain or { messageHash } for off-chain\n if (\"messageHash\" in result && result.messageHash) {\n const messageHash = yield* validateHex(result.messageHash, \"signTypedData\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Offchain\" as const, messageHash };\n }\n\n // Type assertion needed because TypeScript can't narrow SignMessageResponse properly\n const onchainResult = result as { safeTxHash: string };\n const safeTxHash = yield* validateHash(onchainResult.safeTxHash, \"signTypedData\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Onchain\" as const, safeTxHash };\n }).pipe(Effect.withSpan(SpanNames.SAFE_SIGN_TYPED_DATA));\n\n const getOffchainSignature = (messageHash: Hex) =>\n Effect.gen(function* () {\n const sig = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxLookupError({\n cause,\n message: `Failed to get off-chain signature for ${messageHash}`,\n retryable: true,\n safeTxHash: messageHash,\n }),\n try: () => sdk.safe.getOffChainSignature(messageHash),\n });\n\n // Empty string or \"0x\" means signature not yet available\n if (!sig || sig === \"\" || sig === \"0x\") {\n return Option.none<Hex>();\n }\n\n const validatedSig = yield* validateHex(sig, \"getOffchainSignature\");\n return Option.some(validatedSig);\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_GET_OFFCHAIN_SIG, {\n attributes: { messageHash },\n })\n );\n\n const pollOffchainSignature = (\n messageHash: Hex,\n policy: { pollInterval?: number; timeout?: number } = {}\n ) =>\n Effect.gen(function* () {\n const pollInterval = policy.pollInterval ?? SAFE_SIGNATURE_POLL_INTERVAL;\n const timeout = policy.timeout ?? SAFE_SIGNATURE_TIMEOUT;\n\n // Poll until we get a signature\n // Effect.sleep is interruptible, so this loop respects Effect's interruption model\n let found: Hex | null = null;\n\n const pollEffect = Effect.gen(function* () {\n while (found === null) {\n const sig = yield* getOffchainSignature(messageHash);\n if (Option.isSome(sig)) {\n found = sig.value;\n } else {\n // Sleep is interruptible - key for Effect's interruption model\n yield* Effect.sleep(Duration.millis(pollInterval));\n }\n }\n });\n\n yield* pollEffect.pipe(\n Effect.timeout(Duration.millis(timeout)),\n Effect.catchTag(\"TimeoutException\", () =>\n Effect.fail(\n new OffchainSignatureTimeoutError({\n message: `Off-chain signature for ${messageHash} not available within ${timeout}ms`,\n messageHash,\n timeout,\n })\n )\n )\n );\n\n if (found === null) {\n return yield* Effect.fail(\n new OffchainSignatureTimeoutError({\n message: `Off-chain signature for ${messageHash} not available within timeout`,\n messageHash,\n timeout,\n })\n );\n }\n\n return { messageHash, signature: found };\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_POLL_OFFCHAIN_SIG, {\n attributes: { messageHash },\n })\n );\n\n const enableOffchainSigning = () =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeSettingsError({\n cause,\n message: \"Failed to enable off-chain signing mode\",\n }),\n try: () => sdk.eth.setSafeSettings([{ offChainSigning: true }]),\n })\n .pipe(Effect.asVoid)\n .pipe(Effect.withSpan(SpanNames.SAFE_ENABLE_OFFCHAIN));\n\n return SafeAppsService.of({\n enableOffchainSigning,\n getInfo,\n getOffchainSignature,\n getTransaction,\n pollOffchainSignature,\n sendTransactions,\n signTypedData,\n waitForTransactionReceipt,\n });\n })\n );\n"]}
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration, Effect, Layer, Option, Ref } from \"effect\";\nimport type { Address, Hash, Hex } from \"viem\";\nimport { isAddress, isHash, isHex } from \"viem\";\nimport {\n SAFE_EXECUTION_TIMEOUT,\n SAFE_POLL_INTERVAL,\n SAFE_SIGNATURE_POLL_INTERVAL,\n SAFE_SIGNATURE_TIMEOUT,\n} from \"@/src/constants/index.js\";\nimport { SpanNames } from \"@/src/telemetry/index.js\";\nimport { TxManager } from \"@/src/tx/index.js\";\nimport type { SafeAppsSdkConfig } from \"./adapter.js\";\nimport { loadSafeSdk } from \"./adapter.js\";\nimport {\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeInfoUnavailableError,\n SafeSettingsError,\n SafeTxExecutionTimeoutError,\n SafeTxLookupError,\n SafeTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { EIP712TypedData, SafeInfo, SafeMultisigTx } from \"./types.js\";\n\nexport type SafeAppsServiceConfig = SafeAppsSdkConfig;\n\n/**\n * Validate that a string is a valid Ethereum address, failing with context if not.\n */\nconst validateAddress = (\n value: string,\n context: string\n): Effect.Effect<Address, SafeTxLookupError> =>\n isAddress(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid address from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\n/**\n * Validate that a string is a valid transaction hash, failing with context if not.\n */\nconst validateHash = (value: string, context: string): Effect.Effect<Hash, SafeTxLookupError> =>\n isHash(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid hash from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\n/**\n * Validate that a string is valid hex, failing with context if not.\n */\nconst validateHex = (value: string, context: string): Effect.Effect<Hex, SafeTxLookupError> =>\n isHex(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid hex from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\nexport const SafeAppsServiceLive = (config?: SafeAppsServiceConfig) =>\n Layer.scoped(\n SafeAppsService,\n Effect.gen(function* () {\n // SSR guard - Safe Apps SDK requires browser environment\n if (typeof window === \"undefined\") {\n return yield* Effect.fail(\n new NotInSafeAppContextError({\n message: \"Safe Apps SDK requires a browser environment (window is undefined)\",\n })\n );\n }\n\n // Load SDK dynamically to keep it optional\n const sdk = yield* loadSafeSdk(config);\n\n // Cache Safe info after first fetch\n const infoRef = yield* Ref.make<SafeInfo | null>(null);\n\n // Get TxManager for receipt waiting\n const txManager = yield* TxManager;\n\n // --- Service method implementations ---\n\n const getInfo = () =>\n Effect.gen(function* () {\n const cached = yield* Ref.get(infoRef);\n if (cached) {\n return cached;\n }\n\n const info = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeInfoUnavailableError({\n cause,\n message: \"Failed to get Safe info from SDK\",\n }),\n try: () => sdk.safe.getInfo(),\n });\n\n const safeAddress = yield* validateAddress(info.safeAddress, \"getInfo\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SafeInfoUnavailableError({ cause: e, message: e.message }))\n )\n );\n\n const safeInfo: SafeInfo = {\n chainId: info.chainId,\n safeAddress,\n };\n\n yield* Ref.set(infoRef, safeInfo);\n return safeInfo;\n }).pipe(Effect.withSpan(SpanNames.SAFE_GET_INFO));\n\n const sendTxs = (txs: readonly SafeMultisigTx[], params?: { safeTxGas?: number }) =>\n Effect.gen(function* () {\n // Convert bigint values to strings (Safe SDK expects decimal strings)\n const sdkTxs = txs.map((tx) => ({\n data: tx.data,\n to: tx.to,\n value: tx.value?.toString() ?? \"0\",\n }));\n\n const result = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxSubmissionError({\n cause,\n message: \"Failed to submit txs to Safe\",\n }),\n try: () => sdk.txs.send({ params, txs: sdkTxs }),\n });\n\n const safeTxHash = yield* validateHash(result.safeTxHash, \"sendTxs\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SafeTxSubmissionError({ cause: e, message: e.message }))\n )\n );\n\n const info = yield* getInfo();\n\n return {\n chainId: info.chainId,\n safeAddress: info.safeAddress,\n safeTxHash,\n };\n })\n .pipe(\n Effect.catchTag(\"SafeInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeTxSubmissionError({\n cause: error,\n message: \"Failed to get Safe info after tx submission\",\n })\n )\n )\n )\n .pipe(\n Effect.withSpan(SpanNames.SAFE_SEND_TXS, {\n attributes: { txCount: txs.length },\n })\n );\n\n const getTx = (safeTxHash: Hash) =>\n Effect.gen(function* () {\n const tx = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxLookupError({\n cause,\n message: `Failed to lookup Safe tx ${safeTxHash}`,\n retryable: true,\n safeTxHash,\n }),\n try: () => sdk.txs.getBySafeTxHash(safeTxHash),\n });\n\n const txHash = tx.txHash ? yield* validateHash(tx.txHash, \"getTx\") : null;\n\n return {\n status: tx.txStatus ?? \"AWAITING_CONFIRMATIONS\",\n txHash: txHash ? Option.some(txHash) : Option.none<Hash>(),\n };\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_GET_TX, {\n attributes: { safeTxHash },\n })\n );\n\n const waitForTxReceipt = (\n safeTxHash: Hash,\n policy: {\n pollInterval?: number;\n executionTimeout?: number;\n receiptPolicy?: { receiptTimeout?: number; pollingInterval?: number };\n } = {}\n ) =>\n Effect.gen(function* () {\n const info = yield* getInfo();\n const pollInterval = policy.pollInterval ?? SAFE_POLL_INTERVAL;\n const executionTimeout = policy.executionTimeout ?? SAFE_EXECUTION_TIMEOUT;\n\n // Poll Safe gateway until txHash appears\n // Effect.sleep is interruptible, so this loop respects Effect's interruption model\n const onchainHash = yield* Effect.gen(function* () {\n let lastStatus = \"AWAITING_CONFIRMATIONS\";\n let found: Hash | null = null;\n\n const pollEffect = Effect.gen(function* () {\n while (found === null) {\n const tx = yield* getTx(safeTxHash);\n lastStatus = tx.status;\n\n if (Option.isSome(tx.txHash)) {\n found = tx.txHash.value;\n } else {\n // Sleep is interruptible - key for Effect's interruption model\n yield* Effect.sleep(Duration.millis(pollInterval));\n }\n }\n });\n\n yield* pollEffect.pipe(\n Effect.timeout(Duration.millis(executionTimeout)),\n Effect.catchTag(\"TimeoutException\", () =>\n Effect.fail(\n new SafeTxExecutionTimeoutError({\n lastStatus,\n message: `Safe tx ${safeTxHash} not executed within ${executionTimeout}ms (last status: ${lastStatus})`,\n safeTxHash,\n timeout: executionTimeout,\n })\n )\n )\n );\n\n if (found === null) {\n return yield* Effect.fail(\n new SafeTxExecutionTimeoutError({\n lastStatus,\n message: `Safe tx ${safeTxHash} not executed within timeout`,\n safeTxHash,\n timeout: executionTimeout,\n })\n );\n }\n return found;\n });\n\n // Delegate to TxManager for on-chain receipt\n const receipt = yield* txManager\n .waitForReceipt(info.chainId, onchainHash, policy.receiptPolicy)\n .pipe(\n Effect.catchTag(\"TransactionReplacedError\", (error) =>\n Effect.fail(\n new SafeTxLookupError({\n cause: error,\n message: `Transaction was replaced: ${error.message}`,\n retryable: false,\n safeTxHash,\n })\n )\n )\n );\n\n return {\n chainId: info.chainId,\n onchainHash,\n receipt,\n safeAddress: info.safeAddress,\n safeTxHash,\n };\n })\n .pipe(\n Effect.catchTag(\"SafeInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeTxLookupError({\n cause: error,\n message: \"Failed to get Safe info for receipt waiting\",\n retryable: true,\n safeTxHash,\n })\n )\n )\n )\n .pipe(\n Effect.withSpan(SpanNames.SAFE_WAIT_RECEIPT, {\n attributes: { safeTxHash },\n })\n );\n\n const signTypedData = (typedData: EIP712TypedData) =>\n Effect.gen(function* () {\n const result = yield* Effect.tryPromise({\n catch: (cause) =>\n new SignTypedDataError({\n cause,\n message: \"Failed to sign typed data via Safe\",\n }),\n try: () =>\n sdk.txs.signTypedMessage(typedData as Parameters<typeof sdk.txs.signTypedMessage>[0]),\n });\n\n // SDK returns { safeTxHash } for on-chain or { messageHash } for off-chain\n if (\"messageHash\" in result && result.messageHash) {\n const messageHash = yield* validateHex(result.messageHash, \"signTypedData\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Offchain\" as const, messageHash };\n }\n\n // Type assertion needed because TypeScript can't narrow SignMessageResponse properly\n const onchainResult = result as { safeTxHash: string };\n const safeTxHash = yield* validateHash(onchainResult.safeTxHash, \"signTypedData\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Onchain\" as const, safeTxHash };\n }).pipe(Effect.withSpan(SpanNames.SAFE_SIGN_TYPED_DATA));\n\n const getOffchainSignature = (messageHash: Hex) =>\n Effect.gen(function* () {\n const sig = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxLookupError({\n cause,\n message: `Failed to get off-chain signature for ${messageHash}`,\n retryable: true,\n safeTxHash: messageHash,\n }),\n try: () => sdk.safe.getOffChainSignature(messageHash),\n });\n\n // Empty string or \"0x\" means signature not yet available\n if (!sig || sig === \"\" || sig === \"0x\") {\n return Option.none<Hex>();\n }\n\n const validatedSig = yield* validateHex(sig, \"getOffchainSignature\");\n return Option.some(validatedSig);\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_GET_OFFCHAIN_SIG, {\n attributes: { messageHash },\n })\n );\n\n const pollOffchainSignature = (\n messageHash: Hex,\n policy: { pollInterval?: number; timeout?: number } = {}\n ) =>\n Effect.gen(function* () {\n const pollInterval = policy.pollInterval ?? SAFE_SIGNATURE_POLL_INTERVAL;\n const timeout = policy.timeout ?? SAFE_SIGNATURE_TIMEOUT;\n\n // Poll until we get a signature\n // Effect.sleep is interruptible, so this loop respects Effect's interruption model\n let found: Hex | null = null;\n\n const pollEffect = Effect.gen(function* () {\n while (found === null) {\n const sig = yield* getOffchainSignature(messageHash);\n if (Option.isSome(sig)) {\n found = sig.value;\n } else {\n // Sleep is interruptible - key for Effect's interruption model\n yield* Effect.sleep(Duration.millis(pollInterval));\n }\n }\n });\n\n yield* pollEffect.pipe(\n Effect.timeout(Duration.millis(timeout)),\n Effect.catchTag(\"TimeoutException\", () =>\n Effect.fail(\n new OffchainSignatureTimeoutError({\n message: `Off-chain signature for ${messageHash} not available within ${timeout}ms`,\n messageHash,\n timeout,\n })\n )\n )\n );\n\n if (found === null) {\n return yield* Effect.fail(\n new OffchainSignatureTimeoutError({\n message: `Off-chain signature for ${messageHash} not available within timeout`,\n messageHash,\n timeout,\n })\n );\n }\n\n return { messageHash, signature: found };\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_POLL_OFFCHAIN_SIG, {\n attributes: { messageHash },\n })\n );\n\n const enableOffchainSigning = () =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeSettingsError({\n cause,\n message: \"Failed to enable off-chain signing mode\",\n }),\n try: () => sdk.eth.setSafeSettings([{ offChainSigning: true }]),\n })\n .pipe(Effect.asVoid)\n .pipe(Effect.withSpan(SpanNames.SAFE_ENABLE_OFFCHAIN));\n\n return SafeAppsService.of({\n enableOffchainSigning,\n getInfo,\n getOffchainSignature,\n getTx,\n pollOffchainSignature,\n sendTxs,\n signTypedData,\n waitForTxReceipt,\n });\n })\n );\n"]}
@@ -3,17 +3,17 @@ import { Context } from "effect";
3
3
  import type { Hash, Hex } from "viem";
4
4
  import type { ClientNotFoundError, ReceiptTimeoutError, TransactionFailedError } from "../core/errors/index.js";
5
5
  import type { OffchainSignatureTimeoutError, SafeInfoUnavailableError, SafeSettingsError, SafeTxExecutionTimeoutError, SafeTxLookupError, SafeTxSubmissionError, SignTypedDataError } from "./errors.js";
6
- import type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeInfo, SafeTransaction, SafeTxResult, SafeTxSubmission, SafeWaitPolicy, SignTypedDataResult } from "./types.js";
6
+ import type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeInfo, SafeMultisigTx, SafeTxResult, SafeTxSubmission, SafeWaitPolicy, SignTypedDataResult } from "./types.js";
7
7
  export type SafeAppsServiceShape = {
8
8
  readonly getInfo: () => Effect.Effect<SafeInfo, SafeInfoUnavailableError>;
9
- readonly sendTransactions: (txs: readonly SafeTransaction[], params?: {
9
+ readonly sendTxs: (txs: readonly SafeMultisigTx[], params?: {
10
10
  safeTxGas?: number;
11
11
  }) => Effect.Effect<SafeTxSubmission, SafeTxSubmissionError>;
12
- readonly getTransaction: (safeTxHash: Hash) => Effect.Effect<{
12
+ readonly getTx: (safeTxHash: Hash) => Effect.Effect<{
13
13
  txHash: Option.Option<Hash>;
14
14
  status: string;
15
15
  }, SafeTxLookupError>;
16
- readonly waitForTransactionReceipt: (safeTxHash: Hash, policy?: SafeWaitPolicy) => Effect.Effect<SafeTxResult, SafeTxExecutionTimeoutError | SafeTxLookupError | TransactionFailedError | ReceiptTimeoutError | ClientNotFoundError>;
16
+ readonly waitForTxReceipt: (safeTxHash: Hash, policy?: SafeWaitPolicy) => Effect.Effect<SafeTxResult, SafeTxExecutionTimeoutError | SafeTxLookupError | TransactionFailedError | ReceiptTimeoutError | ClientNotFoundError>;
17
17
  readonly signTypedData: (typedData: EIP712TypedData) => Effect.Effect<SignTypedDataResult, SignTypedDataError>;
18
18
  readonly getOffchainSignature: (messageHash: Hex) => Effect.Effect<Option.Option<Hex>, SafeTxLookupError>;
19
19
  readonly pollOffchainSignature: (messageHash: Hex, policy?: OffchainSignaturePolicy) => Effect.Effect<OffchainSignatureResult, OffchainSignatureTimeoutError | SafeTxLookupError>;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,6BAA6B,EAC7B,wBAAwB,EACxB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IAEjC,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;IAG1E,QAAQ,CAAC,gBAAgB,EAAE,CACzB,GAAG,EAAE,SAAS,eAAe,EAAE,EAC/B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;IAG5D,QAAQ,CAAC,cAAc,EAAE,CACvB,UAAU,EAAE,IAAI,KACb,MAAM,CAAC,MAAM,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,iBAAiB,CAAC,CAAC;IAGvF,QAAQ,CAAC,yBAAyB,EAAE,CAClC,UAAU,EAAE,IAAI,EAChB,MAAM,CAAC,EAAE,cAAc,KACpB,MAAM,CAAC,MAAM,CAChB,YAAY,EACV,2BAA2B,GAC3B,iBAAiB,GACjB,sBAAsB,GACtB,mBAAmB,GACnB,mBAAmB,CACtB,CAAC;IAGF,QAAQ,CAAC,aAAa,EAAE,CACtB,SAAS,EAAE,eAAe,KACvB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;IAG5D,QAAQ,CAAC,oBAAoB,EAAE,CAC7B,WAAW,EAAE,GAAG,KACb,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAG1D,QAAQ,CAAC,qBAAqB,EAAE,CAC9B,WAAW,EAAE,GAAG,EAChB,MAAM,CAAC,EAAE,uBAAuB,KAC7B,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,6BAA6B,GAAG,iBAAiB,CAAC,CAAC;IAG/F,QAAQ,CAAC,qBAAqB,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;CAC9E,CAAC;;AAEF,qBAAa,eAAgB,SAAQ,oBAGlC;CAAG"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,6BAA6B,EAC7B,wBAAwB,EACxB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IAEjC,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;IAG1E,QAAQ,CAAC,OAAO,EAAE,CAChB,GAAG,EAAE,SAAS,cAAc,EAAE,EAC9B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;IAG5D,QAAQ,CAAC,KAAK,EAAE,CACd,UAAU,EAAE,IAAI,KACb,MAAM,CAAC,MAAM,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,iBAAiB,CAAC,CAAC;IAGvF,QAAQ,CAAC,gBAAgB,EAAE,CACzB,UAAU,EAAE,IAAI,EAChB,MAAM,CAAC,EAAE,cAAc,KACpB,MAAM,CAAC,MAAM,CAChB,YAAY,EACV,2BAA2B,GAC3B,iBAAiB,GACjB,sBAAsB,GACtB,mBAAmB,GACnB,mBAAmB,CACtB,CAAC;IAGF,QAAQ,CAAC,aAAa,EAAE,CACtB,SAAS,EAAE,eAAe,KACvB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;IAG5D,QAAQ,CAAC,oBAAoB,EAAE,CAC7B,WAAW,EAAE,GAAG,KACb,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAG1D,QAAQ,CAAC,qBAAqB,EAAE,CAC9B,WAAW,EAAE,GAAG,EAChB,MAAM,CAAC,EAAE,uBAAuB,KAC7B,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,6BAA6B,GAAG,iBAAiB,CAAC,CAAC;IAG/F,QAAQ,CAAC,qBAAqB,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;CAC9E,CAAC;;AAEF,qBAAa,eAAgB,SAAQ,oBAGlC;CAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AA4EjC,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAG7D;CAAG","sourcesContent":["import type { Effect, Option } from \"effect\";\nimport { Context } from \"effect\";\nimport type { Hash, Hex } from \"viem\";\nimport type {\n ClientNotFoundError,\n ReceiptTimeoutError,\n TransactionFailedError,\n} from \"@/src/core/errors/index.js\";\nimport type {\n OffchainSignatureTimeoutError,\n SafeInfoUnavailableError,\n SafeSettingsError,\n SafeTxExecutionTimeoutError,\n SafeTxLookupError,\n SafeTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeInfo,\n SafeTransaction,\n SafeTxResult,\n SafeTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\n\nexport type SafeAppsServiceShape = {\n /** Get Safe info (cached after first call) */\n readonly getInfo: () => Effect.Effect<SafeInfo, SafeInfoUnavailableError>;\n\n /** Send transactions to Safe for execution */\n readonly sendTransactions: (\n txs: readonly SafeTransaction[],\n params?: { safeTxGas?: number }\n ) => Effect.Effect<SafeTxSubmission, SafeTxSubmissionError>;\n\n /** Get Safe transaction details by safeTxHash */\n readonly getTransaction: (\n safeTxHash: Hash\n ) => Effect.Effect<{ txHash: Option.Option<Hash>; status: string }, SafeTxLookupError>;\n\n /** Wait for Safe tx to execute and return receipt */\n readonly waitForTransactionReceipt: (\n safeTxHash: Hash,\n policy?: SafeWaitPolicy\n ) => Effect.Effect<\n SafeTxResult,\n | SafeTxExecutionTimeoutError\n | SafeTxLookupError\n | TransactionFailedError\n | ReceiptTimeoutError\n | ClientNotFoundError\n >;\n\n /** Sign typed data (returns discriminated union based on Safe settings) */\n readonly signTypedData: (\n typedData: EIP712TypedData\n ) => Effect.Effect<SignTypedDataResult, SignTypedDataError>;\n\n /** Get off-chain signature (returns Option.none if not yet available) */\n readonly getOffchainSignature: (\n messageHash: Hex\n ) => Effect.Effect<Option.Option<Hex>, SafeTxLookupError>;\n\n /** Poll for off-chain signature until available or timeout */\n readonly pollOffchainSignature: (\n messageHash: Hex,\n policy?: OffchainSignaturePolicy\n ) => Effect.Effect<OffchainSignatureResult, OffchainSignatureTimeoutError | SafeTxLookupError>;\n\n /** Enable off-chain signing mode */\n readonly enableOffchainSigning: () => Effect.Effect<void, SafeSettingsError>;\n};\n\nexport class SafeAppsService extends Context.Tag(\"ew3/SafeApps\")<\n SafeAppsService,\n SafeAppsServiceShape\n>() {}\n"]}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AA4EjC,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAG7D;CAAG","sourcesContent":["import type { Effect, Option } from \"effect\";\nimport { Context } from \"effect\";\nimport type { Hash, Hex } from \"viem\";\nimport type {\n ClientNotFoundError,\n ReceiptTimeoutError,\n TransactionFailedError,\n} from \"@/src/core/errors/index.js\";\nimport type {\n OffchainSignatureTimeoutError,\n SafeInfoUnavailableError,\n SafeSettingsError,\n SafeTxExecutionTimeoutError,\n SafeTxLookupError,\n SafeTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeInfo,\n SafeMultisigTx,\n SafeTxResult,\n SafeTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\n\nexport type SafeAppsServiceShape = {\n /** Get Safe info (cached after first call) */\n readonly getInfo: () => Effect.Effect<SafeInfo, SafeInfoUnavailableError>;\n\n /** Send txs to Safe for execution */\n readonly sendTxs: (\n txs: readonly SafeMultisigTx[],\n params?: { safeTxGas?: number }\n ) => Effect.Effect<SafeTxSubmission, SafeTxSubmissionError>;\n\n /** Get Safe tx details by safeTxHash */\n readonly getTx: (\n safeTxHash: Hash\n ) => Effect.Effect<{ txHash: Option.Option<Hash>; status: string }, SafeTxLookupError>;\n\n /** Wait for Safe tx to execute and return receipt */\n readonly waitForTxReceipt: (\n safeTxHash: Hash,\n policy?: SafeWaitPolicy\n ) => Effect.Effect<\n SafeTxResult,\n | SafeTxExecutionTimeoutError\n | SafeTxLookupError\n | TransactionFailedError\n | ReceiptTimeoutError\n | ClientNotFoundError\n >;\n\n /** Sign typed data (returns discriminated union based on Safe settings) */\n readonly signTypedData: (\n typedData: EIP712TypedData\n ) => Effect.Effect<SignTypedDataResult, SignTypedDataError>;\n\n /** Get off-chain signature (returns Option.none if not yet available) */\n readonly getOffchainSignature: (\n messageHash: Hex\n ) => Effect.Effect<Option.Option<Hex>, SafeTxLookupError>;\n\n /** Poll for off-chain signature until available or timeout */\n readonly pollOffchainSignature: (\n messageHash: Hex,\n policy?: OffchainSignaturePolicy\n ) => Effect.Effect<OffchainSignatureResult, OffchainSignatureTimeoutError | SafeTxLookupError>;\n\n /** Enable off-chain signing mode */\n readonly enableOffchainSigning: () => Effect.Effect<void, SafeSettingsError>;\n};\n\nexport class SafeAppsService extends Context.Tag(\"ew3/SafeApps\")<\n SafeAppsService,\n SafeAppsServiceShape\n>() {}\n"]}
@@ -32,12 +32,12 @@ const makeMockSafeAppsService = (config) => {
32
32
  enableOffchainSigning: () => Effect.void,
33
33
  getInfo: () => Effect.succeed(config.getInfoResult ?? defaultInfo),
34
34
  getOffchainSignature: () => Effect.succeed(config.offchainSignature ?? Option.none()),
35
- getTransaction: () => Effect.succeed(config.getTxResult ?? {
35
+ getTx: () => Effect.succeed(config.getTxResult ?? {
36
36
  status: "AWAITING_EXECUTION",
37
37
  txHash: Option.some(TEST_TX_HASH),
38
38
  }),
39
39
  pollOffchainSignature: (messageHash) => Effect.succeed({ messageHash, signature: TEST_SIGNATURE }),
40
- sendTransactions: () => Effect.succeed({
40
+ sendTxs: () => Effect.succeed({
41
41
  chainId: TEST_CHAIN_ID,
42
42
  safeAddress: TEST_SAFE_ADDRESS,
43
43
  safeTxHash: config.sendTxResult?.safeTxHash ?? TEST_SAFE_TX_HASH,
@@ -46,7 +46,7 @@ const makeMockSafeAppsService = (config) => {
46
46
  _tag: "Onchain",
47
47
  safeTxHash: TEST_SAFE_TX_HASH,
48
48
  }),
49
- waitForTransactionReceipt: (safeTxHash) => Effect.succeed({
49
+ waitForTxReceipt: (safeTxHash) => Effect.succeed({
50
50
  chainId: TEST_CHAIN_ID,
51
51
  onchainHash: TEST_TX_HASH,
52
52
  receipt: TEST_RECEIPT,
@@ -64,21 +64,19 @@ describe("SafeAppsService", () => {
64
64
  expect(info.chainId).toBe(TEST_CHAIN_ID);
65
65
  }).pipe(Effect.provide(makeMockSafeAppsService({}))));
66
66
  });
67
- describe("sendTransactions", () => {
67
+ describe("sendTxs", () => {
68
68
  it.effect("returns safeTxHash with safeAddress and chainId", () => Effect.gen(function* () {
69
69
  const service = yield* SafeAppsService;
70
- const result = yield* service.sendTransactions([
71
- { data: "0x", to: TEST_ADDRESS, value: 0n },
72
- ]);
70
+ const result = yield* service.sendTxs([{ data: "0x", to: TEST_ADDRESS, value: 0n }]);
73
71
  expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);
74
72
  expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);
75
73
  expect(result.chainId).toBe(TEST_CHAIN_ID);
76
74
  }).pipe(Effect.provide(makeMockSafeAppsService({}))));
77
75
  });
78
- describe("getTransaction", () => {
76
+ describe("getTx", () => {
79
77
  it.effect("returns txHash as Option when executed", () => Effect.gen(function* () {
80
78
  const service = yield* SafeAppsService;
81
- const result = yield* service.getTransaction(TEST_SAFE_TX_HASH);
79
+ const result = yield* service.getTx(TEST_SAFE_TX_HASH);
82
80
  expect(Option.isSome(result.txHash)).toBe(true);
83
81
  if (Option.isSome(result.txHash)) {
84
82
  expect(result.txHash.value).toBe(TEST_TX_HASH);
@@ -86,7 +84,7 @@ describe("SafeAppsService", () => {
86
84
  }).pipe(Effect.provide(makeMockSafeAppsService({}))));
87
85
  it.effect("returns Option.none when not yet executed", () => Effect.gen(function* () {
88
86
  const service = yield* SafeAppsService;
89
- const result = yield* service.getTransaction(TEST_SAFE_TX_HASH);
87
+ const result = yield* service.getTx(TEST_SAFE_TX_HASH);
90
88
  expect(Option.isNone(result.txHash)).toBe(true);
91
89
  expect(result.status).toBe("AWAITING_CONFIRMATIONS");
92
90
  }).pipe(Effect.provide(makeMockSafeAppsService({
@@ -96,10 +94,10 @@ describe("SafeAppsService", () => {
96
94
  },
97
95
  }))));
98
96
  });
99
- describe("waitForTransactionReceipt", () => {
97
+ describe("waitForTxReceipt", () => {
100
98
  it.effect("returns SafeTxResult with receipt", () => Effect.gen(function* () {
101
99
  const service = yield* SafeAppsService;
102
- const result = yield* service.waitForTransactionReceipt(TEST_SAFE_TX_HASH);
100
+ const result = yield* service.waitForTxReceipt(TEST_SAFE_TX_HASH);
103
101
  expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);
104
102
  expect(result.onchainHash).toBe(TEST_TX_HASH);
105
103
  expect(result.receipt.status).toBe("success");
@@ -1 +1 @@
1
- {"version":3,"file":"service.test.integration.js","sourceRoot":"","sources":["../../src/safe/service.test.integration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE/C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAI/C,MAAM,iBAAiB,GAAG,YAAY,CAAC;AACvC,MAAM,iBAAiB,GACrB,oEAA4E,CAAC;AAC/E,MAAM,iBAAiB,GACrB,oEAA2E,CAAC;AAC9E,MAAM,cAAc,GAAG,aAAoB,CAAC;AAE5C,MAAM,YAAY,GAAuB;IACvC,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,IAAI;IACjB,eAAe,EAAE,IAAI;IACrB,iBAAiB,EAAE,UAAU;IAC7B,iBAAiB,EAAE,EAAE;IACrB,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,UAAU;IACnB,IAAI,EAAE,EAAE;IACR,SAAS,EAAE,IAAI;IACf,MAAM,EAAE,SAAS;IACjB,EAAE,EAAE,MAAM;IACV,eAAe,EAAE,YAAY;IAC7B,gBAAgB,EAAE,CAAC;IACnB,IAAI,EAAE,KAAK;CACZ,CAAC;AAGF,MAAM,uBAAuB,GAAG,CAAC,MAQhC,EAAE,EAAE;IACH,MAAM,WAAW,GAAa;QAC5B,OAAO,EAAE,aAAa;QACtB,WAAW,EAAE,iBAAiB;KAC/B,CAAC;IAEF,OAAO,KAAK,CAAC,OAAO,CAClB,eAAe,EACf,eAAe,CAAC,EAAE,CAAC;QACjB,qBAAqB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI;QACxC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,IAAI,WAAW,CAAC;QAClE,oBAAoB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACrF,cAAc,EAAE,GAAG,EAAE,CACnB,MAAM,CAAC,OAAO,CACZ,MAAM,CAAC,WAAW,IAAI;YACpB,MAAM,EAAE,oBAAoB;YAC5B,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;SAClC,CACF;QACH,qBAAqB,EAAE,CAAC,WAAW,EAAE,EAAE,CACrC,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;QAC5D,gBAAgB,EAAE,GAAG,EAAE,CACrB,MAAM,CAAC,OAAO,CAAC;YACb,OAAO,EAAE,aAAa;YACtB,WAAW,EAAE,iBAAiB;YAC9B,UAAU,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,IAAI,iBAAiB;SACjE,CAAC;QACJ,aAAa,EAAE,GAAG,EAAE,CAClB,MAAM,CAAC,OAAO,CACZ,MAAM,CAAC,mBAAmB,IAAI;YAC5B,IAAI,EAAE,SAAkB;YACxB,UAAU,EAAE,iBAAiB;SAC9B,CACF;QACH,yBAAyB,EAAE,CAAC,UAAU,EAAE,EAAE,CACxC,MAAM,CAAC,OAAO,CAAC;YACb,OAAO,EAAE,aAAa;YACtB,WAAW,EAAE,YAAY;YACzB,OAAO,EAAE,YAAY;YACrB,WAAW,EAAE,iBAAiB;YAC9B,UAAU;SACX,CAAC;KACL,CAAC,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,EAAE,CAAC,MAAM,CAAC,4CAA4C,EAAE,GAAG,EAAE,CAC3D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAEtC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CACrD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,MAAM,CAAC,iDAAiD,EAAE,GAAG,EAAE,CAChE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC;gBAC7C,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE;aAC5C,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAClD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACnD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CACrD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,MAAM,CAAC,wCAAwC,EAAE,GAAG,EAAE,CACvD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;YAEhE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjD,CAAC;QACH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CACrD,CAAC;QAEF,EAAE,CAAC,MAAM,CAAC,2CAA2C,EAAE,GAAG,EAAE,CAC1D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;YAEhE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,OAAO,CACZ,uBAAuB,CAAC;YACtB,WAAW,EAAE;gBACX,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;aACtB;SACF,CAAC,CACH,CACF,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACzC,EAAE,CAAC,MAAM,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAClD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,iBAAiB,CAAC,CAAC;YAE3E,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAClD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACnD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CACrD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,MAAM,CAAC,8CAA8C,EAAE,GAAG,EAAE,CAC7D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;gBAC1C,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;gBACpC,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;gBAC1B,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE;aACrD,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACpD,CAAC;QACH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CACrD,CAAC;QAEF,EAAE,CAAC,MAAM,CAAC,gDAAgD,EAAE,GAAG,EAAE,CAC/D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;gBAC1C,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;gBACpC,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;gBAC1B,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE;aACrD,CAAC,CAAC;YAEH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACrC,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC/B,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACrD,CAAC;QACH,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,OAAO,CACZ,uBAAuB,CAAC;YACtB,mBAAmB,EAAE;gBACnB,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,iBAAiB;aAC/B;SACF,CAAC,CACH,CACF,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,MAAM,CAAC,sDAAsD,EAAE,GAAG,EAAE,CACrE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;YAEtE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CACrD,CAAC;QAEF,EAAE,CAAC,MAAM,CAAC,8CAA8C,EAAE,GAAG,EAAE,CAC7D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;YAEtE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,OAAO,CACZ,uBAAuB,CAAC;YACtB,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC;SAC/C,CAAC,CACH,CACF,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,MAAM,CAAC,kCAAkC,EAAE,GAAG,EAAE,CACjD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,CAAC;YAEvE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACnD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CACrD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,MAAM,CAAC,yBAAyB,EAAE,GAAG,EAAE,CACxC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;YACvC,KAAK,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;QAEzC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CACrD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"@effect/vitest\";\nimport { Effect, Layer, Option } from \"effect\";\nimport type { Hash, Hex, TransactionReceipt } from \"viem\";\nimport { MIN_TX_GAS } from \"@/src/constants/index.js\";\nimport { TEST_ADDRESS, TEST_CHAIN_ID, TEST_TX_HASH } from \"@/src/testing-kit/index.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { SafeInfo } from \"./types.js\";\n\n// Test fixtures\nconst TEST_SAFE_ADDRESS = TEST_ADDRESS;\nconst TEST_SAFE_TX_HASH =\n \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\" as Hash;\nconst TEST_MESSAGE_HASH =\n \"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890\" as Hex;\nconst TEST_SIGNATURE = \"0xsignature\" as Hex;\n\nconst TEST_RECEIPT: TransactionReceipt = {\n blockHash: \"0xblock\",\n blockNumber: 123n,\n contractAddress: null,\n cumulativeGasUsed: MIN_TX_GAS,\n effectiveGasPrice: 1n,\n from: \"0xfrom\",\n gasUsed: MIN_TX_GAS,\n logs: [],\n logsBloom: \"0x\",\n status: \"success\",\n to: \"0xto\",\n transactionHash: TEST_TX_HASH,\n transactionIndex: 0,\n type: \"0x2\",\n};\n\n// Mock SafeAppsService for testing without actual SDK\nconst makeMockSafeAppsService = (config: {\n getInfoResult?: SafeInfo;\n sendTxResult?: { safeTxHash: Hash };\n getTxResult?: { txHash: Option.Option<Hash>; status: string };\n signTypedDataResult?:\n | { _tag: \"Offchain\"; messageHash: Hex }\n | { _tag: \"Onchain\"; safeTxHash: Hash };\n offchainSignature?: Option.Option<Hex>;\n}) => {\n const defaultInfo: SafeInfo = {\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n };\n\n return Layer.succeed(\n SafeAppsService,\n SafeAppsService.of({\n enableOffchainSigning: () => Effect.void,\n getInfo: () => Effect.succeed(config.getInfoResult ?? defaultInfo),\n getOffchainSignature: () => Effect.succeed(config.offchainSignature ?? Option.none()),\n getTransaction: () =>\n Effect.succeed(\n config.getTxResult ?? {\n status: \"AWAITING_EXECUTION\",\n txHash: Option.some(TEST_TX_HASH),\n }\n ),\n pollOffchainSignature: (messageHash) =>\n Effect.succeed({ messageHash, signature: TEST_SIGNATURE }),\n sendTransactions: () =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash: config.sendTxResult?.safeTxHash ?? TEST_SAFE_TX_HASH,\n }),\n signTypedData: () =>\n Effect.succeed(\n config.signTypedDataResult ?? {\n _tag: \"Onchain\" as const,\n safeTxHash: TEST_SAFE_TX_HASH,\n }\n ),\n waitForTransactionReceipt: (safeTxHash) =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n onchainHash: TEST_TX_HASH,\n receipt: TEST_RECEIPT,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash,\n }),\n })\n );\n};\n\ndescribe(\"SafeAppsService\", () => {\n describe(\"getInfo\", () => {\n it.effect(\"returns Safe info with address and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const info = yield* service.getInfo();\n\n expect(info.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(info.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"sendTransactions\", () => {\n it.effect(\"returns safeTxHash with safeAddress and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.sendTransactions([\n { data: \"0x\", to: TEST_ADDRESS, value: 0n },\n ]);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"getTransaction\", () => {\n it.effect(\"returns txHash as Option when executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTransaction(TEST_SAFE_TX_HASH);\n\n expect(Option.isSome(result.txHash)).toBe(true);\n if (Option.isSome(result.txHash)) {\n expect(result.txHash.value).toBe(TEST_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.none when not yet executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTransaction(TEST_SAFE_TX_HASH);\n\n expect(Option.isNone(result.txHash)).toBe(true);\n expect(result.status).toBe(\"AWAITING_CONFIRMATIONS\");\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n getTxResult: {\n status: \"AWAITING_CONFIRMATIONS\",\n txHash: Option.none(),\n },\n })\n )\n )\n );\n });\n\n describe(\"waitForTransactionReceipt\", () => {\n it.effect(\"returns SafeTxResult with receipt\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.waitForTransactionReceipt(TEST_SAFE_TX_HASH);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.onchainHash).toBe(TEST_TX_HASH);\n expect(result.receipt.status).toBe(\"success\");\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"signTypedData\", () => {\n it.effect(\"returns Onchain variant for on-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Onchain\");\n if (result._tag === \"Onchain\") {\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Offchain variant for off-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Offchain\");\n if (result._tag === \"Offchain\") {\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n signTypedDataResult: {\n _tag: \"Offchain\",\n messageHash: TEST_MESSAGE_HASH,\n },\n })\n )\n )\n );\n });\n\n describe(\"getOffchainSignature\", () => {\n it.effect(\"returns Option.none when signature not yet available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isNone(result)).toBe(true);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.some when signature available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isSome(result)).toBe(true);\n if (Option.isSome(result)) {\n expect(result.value).toBe(TEST_SIGNATURE);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n offchainSignature: Option.some(TEST_SIGNATURE),\n })\n )\n )\n );\n });\n\n describe(\"pollOffchainSignature\", () => {\n it.effect(\"returns signature when available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.pollOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n expect(result.signature).toBe(TEST_SIGNATURE);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"enableOffchainSigning\", () => {\n it.effect(\"completes without error\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n yield* service.enableOffchainSigning();\n // Success if no error thrown\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n});\n"]}
1
+ {"version":3,"file":"service.test.integration.js","sourceRoot":"","sources":["../../src/safe/service.test.integration.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"@effect/vitest\";\nimport { Effect, Layer, Option } from \"effect\";\nimport type { Hash, Hex, TransactionReceipt } from \"viem\";\nimport { MIN_TX_GAS } from \"@/src/constants/index.js\";\nimport { TEST_ADDRESS, TEST_CHAIN_ID, TEST_TX_HASH } from \"@/src/testing-kit/index.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { SafeInfo } from \"./types.js\";\n\n// Test fixtures\nconst TEST_SAFE_ADDRESS = TEST_ADDRESS;\nconst TEST_SAFE_TX_HASH =\n \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\" as Hash;\nconst TEST_MESSAGE_HASH =\n \"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890\" as Hex;\nconst TEST_SIGNATURE = \"0xsignature\" as Hex;\n\nconst TEST_RECEIPT: TransactionReceipt = {\n blockHash: \"0xblock\",\n blockNumber: 123n,\n contractAddress: null,\n cumulativeGasUsed: MIN_TX_GAS,\n effectiveGasPrice: 1n,\n from: \"0xfrom\",\n gasUsed: MIN_TX_GAS,\n logs: [],\n logsBloom: \"0x\",\n status: \"success\",\n to: \"0xto\",\n transactionHash: TEST_TX_HASH,\n transactionIndex: 0,\n type: \"0x2\",\n};\n\n// Mock SafeAppsService for testing without actual SDK\nconst makeMockSafeAppsService = (config: {\n getInfoResult?: SafeInfo;\n sendTxResult?: { safeTxHash: Hash };\n getTxResult?: { txHash: Option.Option<Hash>; status: string };\n signTypedDataResult?:\n | { _tag: \"Offchain\"; messageHash: Hex }\n | { _tag: \"Onchain\"; safeTxHash: Hash };\n offchainSignature?: Option.Option<Hex>;\n}) => {\n const defaultInfo: SafeInfo = {\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n };\n\n return Layer.succeed(\n SafeAppsService,\n SafeAppsService.of({\n enableOffchainSigning: () => Effect.void,\n getInfo: () => Effect.succeed(config.getInfoResult ?? defaultInfo),\n getOffchainSignature: () => Effect.succeed(config.offchainSignature ?? Option.none()),\n getTx: () =>\n Effect.succeed(\n config.getTxResult ?? {\n status: \"AWAITING_EXECUTION\",\n txHash: Option.some(TEST_TX_HASH),\n }\n ),\n pollOffchainSignature: (messageHash) =>\n Effect.succeed({ messageHash, signature: TEST_SIGNATURE }),\n sendTxs: () =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash: config.sendTxResult?.safeTxHash ?? TEST_SAFE_TX_HASH,\n }),\n signTypedData: () =>\n Effect.succeed(\n config.signTypedDataResult ?? {\n _tag: \"Onchain\" as const,\n safeTxHash: TEST_SAFE_TX_HASH,\n }\n ),\n waitForTxReceipt: (safeTxHash) =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n onchainHash: TEST_TX_HASH,\n receipt: TEST_RECEIPT,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash,\n }),\n })\n );\n};\n\ndescribe(\"SafeAppsService\", () => {\n describe(\"getInfo\", () => {\n it.effect(\"returns Safe info with address and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const info = yield* service.getInfo();\n\n expect(info.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(info.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"sendTxs\", () => {\n it.effect(\"returns safeTxHash with safeAddress and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.sendTxs([{ data: \"0x\", to: TEST_ADDRESS, value: 0n }]);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"getTx\", () => {\n it.effect(\"returns txHash as Option when executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTx(TEST_SAFE_TX_HASH);\n\n expect(Option.isSome(result.txHash)).toBe(true);\n if (Option.isSome(result.txHash)) {\n expect(result.txHash.value).toBe(TEST_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.none when not yet executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTx(TEST_SAFE_TX_HASH);\n\n expect(Option.isNone(result.txHash)).toBe(true);\n expect(result.status).toBe(\"AWAITING_CONFIRMATIONS\");\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n getTxResult: {\n status: \"AWAITING_CONFIRMATIONS\",\n txHash: Option.none(),\n },\n })\n )\n )\n );\n });\n\n describe(\"waitForTxReceipt\", () => {\n it.effect(\"returns SafeTxResult with receipt\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.waitForTxReceipt(TEST_SAFE_TX_HASH);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.onchainHash).toBe(TEST_TX_HASH);\n expect(result.receipt.status).toBe(\"success\");\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"signTypedData\", () => {\n it.effect(\"returns Onchain variant for on-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Onchain\");\n if (result._tag === \"Onchain\") {\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Offchain variant for off-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Offchain\");\n if (result._tag === \"Offchain\") {\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n signTypedDataResult: {\n _tag: \"Offchain\",\n messageHash: TEST_MESSAGE_HASH,\n },\n })\n )\n )\n );\n });\n\n describe(\"getOffchainSignature\", () => {\n it.effect(\"returns Option.none when signature not yet available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isNone(result)).toBe(true);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.some when signature available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isSome(result)).toBe(true);\n if (Option.isSome(result)) {\n expect(result.value).toBe(TEST_SIGNATURE);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n offchainSignature: Option.some(TEST_SIGNATURE),\n })\n )\n )\n );\n });\n\n describe(\"pollOffchainSignature\", () => {\n it.effect(\"returns signature when available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.pollOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n expect(result.signature).toBe(TEST_SIGNATURE);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"enableOffchainSigning\", () => {\n it.effect(\"completes without error\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n yield* service.enableOffchainSigning();\n // Success if no error thrown\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n});\n"]}
@@ -1,24 +1,24 @@
1
1
  import type { Address, Hash, Hex, TransactionReceipt } from "viem";
2
2
  export type SafeInfo = {
3
- safeAddress: Address;
4
3
  chainId: number;
4
+ safeAddress: Address;
5
5
  };
6
- export type SafeTransaction = {
7
- to: Address;
6
+ export type SafeMultisigTx = {
8
7
  data: Hex;
8
+ to: Address;
9
9
  value?: bigint;
10
10
  };
11
11
  export type SafeTxSubmission = {
12
- safeTxHash: Hash;
13
- safeAddress: Address;
14
12
  chainId: number;
13
+ safeAddress: Address;
14
+ safeTxHash: Hash;
15
15
  };
16
16
  export type SafeTxResult = {
17
- safeTxHash: Hash;
17
+ chainId: number;
18
18
  onchainHash: Hash;
19
19
  receipt: TransactionReceipt;
20
20
  safeAddress: Address;
21
- chainId: number;
21
+ safeTxHash: Hash;
22
22
  };
23
23
  export type SignTypedDataResult = {
24
24
  readonly _tag: "Offchain";
@@ -32,11 +32,11 @@ export type OffchainSignatureResult = {
32
32
  signature: Hex;
33
33
  };
34
34
  export type SafeWaitPolicy = {
35
- pollInterval?: number;
36
35
  executionTimeout?: number;
36
+ pollInterval?: number;
37
37
  receiptPolicy?: {
38
- receiptTimeout?: number;
39
38
  pollingInterval?: number;
39
+ receiptTimeout?: number;
40
40
  };
41
41
  };
42
42
  export type OffchainSignaturePolicy = {
@@ -45,17 +45,17 @@ export type OffchainSignaturePolicy = {
45
45
  };
46
46
  export type EIP712TypedData = {
47
47
  domain: {
48
- name?: string;
49
- version?: string;
50
48
  chainId?: number;
51
- verifyingContract?: string;
49
+ name?: string;
52
50
  salt?: string;
51
+ verifyingContract?: string;
52
+ version?: string;
53
53
  };
54
+ message: Record<string, unknown>;
55
+ primaryType?: string;
54
56
  types: Record<string, Array<{
55
57
  name: string;
56
58
  type: string;
57
59
  }>>;
58
- message: Record<string, unknown>;
59
- primaryType?: string;
60
60
  };
61
61
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/safe/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAGnE,MAAM,MAAM,QAAQ,GAAG;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAGF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,IAAI,CAAC;IAClB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAGF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,CAAC;AAG5D,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,GAAG,CAAC;IACjB,SAAS,EAAE,GAAG,CAAC;CAChB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IAE3B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,aAAa,CAAC,EAAE;QACd,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH,CAAC;AAGF,MAAM,MAAM,uBAAuB,GAAG;IAEpC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC7D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/safe/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAGnE,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,IAAI,CAAC;IAClB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,CAAC;AAG5D,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,GAAG,CAAC;IACjB,SAAS,EAAE,GAAG,CAAC;CAChB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IAE3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,aAAa,CAAC,EAAE;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACH,CAAC;AAGF,MAAM,MAAM,uBAAuB,GAAG;IAEpC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CAC9D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/safe/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Address, Hash, Hex, TransactionReceipt } from \"viem\";\n\n/** Safe info returned from SDK */\nexport type SafeInfo = {\n safeAddress: Address;\n chainId: number;\n};\n\n/** Transaction to send via Safe */\nexport type SafeTransaction = {\n to: Address;\n data: Hex;\n value?: bigint; // Converted to string at SDK boundary\n};\n\n/** Result from sendTransactions */\nexport type SafeTxSubmission = {\n safeTxHash: Hash;\n safeAddress: Address;\n chainId: number;\n};\n\n/** Result from waitForTransactionReceipt */\nexport type SafeTxResult = {\n safeTxHash: Hash;\n onchainHash: Hash;\n receipt: TransactionReceipt;\n safeAddress: Address;\n chainId: number;\n};\n\n/** Discriminated union for signTypedData result */\nexport type SignTypedDataResult =\n | { readonly _tag: \"Offchain\"; readonly messageHash: Hex }\n | { readonly _tag: \"Onchain\"; readonly safeTxHash: Hash };\n\n/** Off-chain signature result */\nexport type OffchainSignatureResult = {\n messageHash: Hex;\n signature: Hex;\n};\n\n/** Policy for Safe tx waiting (aligns with TxPolicy from src/tx/policy.ts) */\nexport type SafeWaitPolicy = {\n /** Poll interval for Safe gateway in ms (default: 3000) */\n pollInterval?: number;\n /** Timeout for Safe tx execution in ms (default: 300000 = 5 min) */\n executionTimeout?: number;\n /** Policy passed to TxManager.waitForReceipt */\n receiptPolicy?: {\n receiptTimeout?: number;\n pollingInterval?: number;\n };\n};\n\n/** Policy for off-chain signature polling */\nexport type OffchainSignaturePolicy = {\n /** Poll interval in ms (default: 2000) */\n pollInterval?: number;\n /** Timeout in ms (default: 120000 = 2 min) */\n timeout?: number;\n};\n\n/** EIP-712 typed data structure (local definition to avoid SDK import) */\nexport type EIP712TypedData = {\n domain: {\n name?: string;\n version?: string;\n chainId?: number;\n verifyingContract?: string;\n salt?: string;\n };\n types: Record<string, Array<{ name: string; type: string }>>;\n message: Record<string, unknown>;\n primaryType?: string;\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/safe/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Address, Hash, Hex, TransactionReceipt } from \"viem\";\n\n/** Safe info returned from SDK */\nexport type SafeInfo = {\n chainId: number;\n safeAddress: Address;\n};\n\n/** Tx to send via Safe multisig */\nexport type SafeMultisigTx = {\n data: Hex;\n to: Address;\n value?: bigint; // Converted to string at SDK boundary\n};\n\n/** Result from sendTxs */\nexport type SafeTxSubmission = {\n chainId: number;\n safeAddress: Address;\n safeTxHash: Hash;\n};\n\n/** Result from waitForTxReceipt */\nexport type SafeTxResult = {\n chainId: number;\n onchainHash: Hash;\n receipt: TransactionReceipt;\n safeAddress: Address;\n safeTxHash: Hash;\n};\n\n/** Discriminated union for signTypedData result */\nexport type SignTypedDataResult =\n | { readonly _tag: \"Offchain\"; readonly messageHash: Hex }\n | { readonly _tag: \"Onchain\"; readonly safeTxHash: Hash };\n\n/** Off-chain signature result */\nexport type OffchainSignatureResult = {\n messageHash: Hex;\n signature: Hex;\n};\n\n/** Policy for Safe tx waiting (aligns with TxPolicy from src/tx/policy.ts) */\nexport type SafeWaitPolicy = {\n /** Timeout for Safe tx execution in ms (default: 300000 = 5 min) */\n executionTimeout?: number;\n /** Poll interval for Safe gateway in ms (default: 3000) */\n pollInterval?: number;\n /** Policy passed to TxManager.waitForReceipt */\n receiptPolicy?: {\n pollingInterval?: number;\n receiptTimeout?: number;\n };\n};\n\n/** Policy for off-chain signature polling */\nexport type OffchainSignaturePolicy = {\n /** Poll interval in ms (default: 2000) */\n pollInterval?: number;\n /** Timeout in ms (default: 120000 = 2 min) */\n timeout?: number;\n};\n\n/** EIP-712 typed data structure (local definition to avoid SDK import) */\nexport type EIP712TypedData = {\n domain: {\n chainId?: number;\n name?: string;\n salt?: string;\n verifyingContract?: string;\n version?: string;\n };\n message: Record<string, unknown>;\n primaryType?: string;\n types: Record<string, Array<{ name: string; type: string }>>;\n};\n"]}
@@ -63,9 +63,9 @@ export declare const SpanNames: {
63
63
  readonly SAFE_ENABLE_OFFCHAIN: "ew3.safe.enableOffchainSigning";
64
64
  readonly SAFE_GET_INFO: "ew3.safe.getInfo";
65
65
  readonly SAFE_GET_OFFCHAIN_SIG: "ew3.safe.getOffchainSignature";
66
- readonly SAFE_GET_TX: "ew3.safe.getTransaction";
66
+ readonly SAFE_GET_TX: "ew3.safe.getTx";
67
67
  readonly SAFE_POLL_OFFCHAIN_SIG: "ew3.safe.pollOffchainSignature";
68
- readonly SAFE_SEND_TXS: "ew3.safe.sendTransactions";
68
+ readonly SAFE_SEND_TXS: "ew3.safe.sendTxs";
69
69
  readonly SAFE_SIGN_TYPED_DATA: "ew3.safe.signTypedData";
70
70
  readonly SAFE_WAIT_RECEIPT: "ew3.safe.waitForReceipt";
71
71
  readonly SIGNATURE_HASH_MESSAGE: "ew3.signature.hashMessage";
@@ -63,9 +63,9 @@ export const SpanNames = {
63
63
  SAFE_ENABLE_OFFCHAIN: "ew3.safe.enableOffchainSigning",
64
64
  SAFE_GET_INFO: "ew3.safe.getInfo",
65
65
  SAFE_GET_OFFCHAIN_SIG: "ew3.safe.getOffchainSignature",
66
- SAFE_GET_TX: "ew3.safe.getTransaction",
66
+ SAFE_GET_TX: "ew3.safe.getTx",
67
67
  SAFE_POLL_OFFCHAIN_SIG: "ew3.safe.pollOffchainSignature",
68
- SAFE_SEND_TXS: "ew3.safe.sendTransactions",
68
+ SAFE_SEND_TXS: "ew3.safe.sendTxs",
69
69
  SAFE_SIGN_TYPED_DATA: "ew3.safe.signTypedData",
70
70
  SAFE_WAIT_RECEIPT: "ew3.safe.waitForReceipt",
71
71
  SIGNATURE_HASH_MESSAGE: "ew3.signature.hashMessage",
@@ -1 +1 @@
1
- {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/telemetry/tracer.ts"],"names":[],"mappings":"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","sourcesContent":["import { Effect } from \"effect\";\n\n/**\n * Wrap an effect with a span for tracing\n */\nexport const withSpan =\n (name: string, attributes?: Record<string, unknown>) =>\n <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Effect.withSpan(name, { attributes })(effect);\n\n/**\n * Common span names for RPC operations\n */\nexport const SpanNames = {\n BALANCE_CHECK: \"ew3.balance.check\",\n BALANCE_CHECK_TOKEN: \"ew3.balance.checkToken\",\n BALANCE_GET: \"ew3.balance.get\",\n BALANCE_GET_TOKEN: \"ew3.balance.getToken\",\n BALANCE_GET_TOKEN_BATCH: \"ew3.balance.getTokenBatch\",\n BALANCE_WATCH: \"ew3.balance.watch\",\n BALANCE_WATCH_TOKEN: \"ew3.balance.watchToken\",\n BLOCK_GET: \"ew3.block.get\",\n BLOCK_GET_BY_HASH: \"ew3.block.getByHash\",\n BLOCK_GET_NUMBER: \"ew3.block.getNumber\",\n BLOCK_GET_RANGE: \"ew3.block.getRange\",\n BLOCK_GET_TIMESTAMP: \"ew3.block.getTimestamp\",\n BLOCK_WAIT: \"ew3.block.wait\",\n BLOCK_WATCH: \"ew3.block.watch\",\n CONTRACT_ESTIMATE_GAS: \"ew3.contract.estimateGas\",\n CONTRACT_READ: \"ew3.contract.read\",\n CONTRACT_SIMULATE: \"ew3.contract.simulate\",\n CONTRACT_WRITE: \"ew3.contract.write\",\n CROSS_CHAIN_MULTICALL_ALL: \"ew3.crossChain.multicallAll\",\n CROSS_CHAIN_READ_ALL: \"ew3.crossChain.readAll\",\n CROSS_CHAIN_READ_SAME: \"ew3.crossChain.readSame\",\n DEPLOY_COMPUTE_ADDRESS: \"ew3.deploy.computeAddress\",\n DEPLOY_CONTRACT: \"ew3.deploy.contract\",\n DEPLOY_VERIFY: \"ew3.deploy.verify\",\n ENS_GET_ADDRESS: \"ew3.ens.getAddress\",\n ENS_GET_AVATAR: \"ew3.ens.getAvatar\",\n ENS_GET_NAME: \"ew3.ens.getName\",\n ENS_GET_RESOLVER: \"ew3.ens.getResolver\",\n ENS_GET_TEXT: \"ew3.ens.getText\",\n ERC721_APPROVE: \"ew3.erc721.approve\",\n ERC721_BALANCE_OF: \"ew3.erc721.balanceOf\",\n ERC721_FETCH_METADATA: \"ew3.erc721.fetchMetadata\",\n ERC721_GET_APPROVED: \"ew3.erc721.getApproved\",\n ERC721_IS_APPROVED_FOR_ALL: \"ew3.erc721.isApprovedForAll\",\n ERC721_NAME: \"ew3.erc721.name\",\n ERC721_OWNER_OF: \"ew3.erc721.ownerOf\",\n ERC721_SAFE_TRANSFER_FROM: \"ew3.erc721.safeTransferFrom\",\n ERC721_SET_APPROVAL_FOR_ALL: \"ew3.erc721.setApprovalForAll\",\n ERC721_SYMBOL: \"ew3.erc721.symbol\",\n ERC721_TOKEN_URI: \"ew3.erc721.tokenURI\",\n ERC721_TOTAL_SUPPLY: \"ew3.erc721.totalSupply\",\n ERC721_TRANSFER_FROM: \"ew3.erc721.transferFrom\",\n EVENT_BACKFILL: \"ew3.event.backfill\",\n EVENT_WATCH: \"ew3.event.watch\",\n GAS_ESTIMATE_FEES: \"ew3.gas.estimateFees\",\n GAS_ESTIMATE_GAS: \"ew3.gas.estimateGas\",\n GAS_GET_ALL_ESTIMATES: \"ew3.gas.getAllEstimates\",\n GAS_GET_BASE_FEE: \"ew3.gas.getBaseFee\",\n GAS_GET_MAX_PRIORITY_FEE: \"ew3.gas.getMaxPriorityFee\",\n GAS_SUPPORTS_EIP1559: \"ew3.gas.supportsEip1559\",\n MULTICALL: \"ew3.contract.multicall\",\n NONCE_CONFIRM: \"ew3.nonce.confirm\",\n NONCE_GET_CONFIRMED_COUNT: \"ew3.nonce.getConfirmedCount\",\n NONCE_GET_GAPS: \"ew3.nonce.getGaps\",\n NONCE_GET_NEXT: \"ew3.nonce.getNext\",\n NONCE_GET_PENDING_COUNT: \"ew3.nonce.getPendingCount\",\n NONCE_RELEASE: \"ew3.nonce.release\",\n NONCE_RESERVE: \"ew3.nonce.reserve\",\n NONCE_SYNC: \"ew3.nonce.sync\",\n SAFE_ENABLE_OFFCHAIN: \"ew3.safe.enableOffchainSigning\",\n\n // Safe Apps\n SAFE_GET_INFO: \"ew3.safe.getInfo\",\n SAFE_GET_OFFCHAIN_SIG: \"ew3.safe.getOffchainSignature\",\n SAFE_GET_TX: \"ew3.safe.getTransaction\",\n SAFE_POLL_OFFCHAIN_SIG: \"ew3.safe.pollOffchainSignature\",\n SAFE_SEND_TXS: \"ew3.safe.sendTransactions\",\n SAFE_SIGN_TYPED_DATA: \"ew3.safe.signTypedData\",\n SAFE_WAIT_RECEIPT: \"ew3.safe.waitForReceipt\",\n SIGNATURE_HASH_MESSAGE: \"ew3.signature.hashMessage\",\n SIGNATURE_HASH_TYPED_DATA: \"ew3.signature.hashTypedData\",\n SIGNATURE_JOIN: \"ew3.signature.join\",\n SIGNATURE_RECOVER_ADDRESS: \"ew3.signature.recoverAddress\",\n SIGNATURE_RECOVER_TYPED_DATA_ADDRESS: \"ew3.signature.recoverTypedDataAddress\",\n SIGNATURE_SPLIT: \"ew3.signature.split\",\n SIGNATURE_VERIFY_MESSAGE: \"ew3.signature.verifyMessage\",\n SIGNATURE_VERIFY_TYPED_DATA: \"ew3.signature.verifyTypedData\",\n SIMULATION_SIMULATE: \"ew3.simulation.simulate\",\n SIMULATION_SIMULATE_BUNDLE: \"ew3.simulation.simulateBundle\",\n SUBSCRIPTION_WATCH_BLOCKS: \"ew3.subscription.watchBlocks\",\n SUBSCRIPTION_WATCH_LOGS: \"ew3.subscription.watchLogs\",\n SUBSCRIPTION_WATCH_PENDING_TX: \"ew3.subscription.watchPendingTx\",\n TRANSFER_ESTIMATE: \"ew3.transfer.estimateGas\",\n TRANSFER_SEND: \"ew3.transfer.send\",\n TRANSFER_SEND_AND_WAIT: \"ew3.transfer.sendAndWait\",\n TX_GET_CONFIRMATIONS: \"ew3.tx.getConfirmations\",\n TX_TRACK: \"ew3.tx.track\",\n TX_WAIT: \"ew3.tx.wait\",\n WALLET_CONNECT: \"ew3.wallet.connect\",\n WALLET_SIGN_MESSAGE: \"ew3.wallet.signMessage\",\n WALLET_SIGN_TYPED_DATA: \"ew3.wallet.signTypedData\",\n} as const;\n"]}
1
+ {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/telemetry/tracer.ts"],"names":[],"mappings":"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","sourcesContent":["import { Effect } from \"effect\";\n\n/**\n * Wrap an effect with a span for tracing\n */\nexport const withSpan =\n (name: string, attributes?: Record<string, unknown>) =>\n <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Effect.withSpan(name, { attributes })(effect);\n\n/**\n * Common span names for RPC operations\n */\nexport const SpanNames = {\n BALANCE_CHECK: \"ew3.balance.check\",\n BALANCE_CHECK_TOKEN: \"ew3.balance.checkToken\",\n BALANCE_GET: \"ew3.balance.get\",\n BALANCE_GET_TOKEN: \"ew3.balance.getToken\",\n BALANCE_GET_TOKEN_BATCH: \"ew3.balance.getTokenBatch\",\n BALANCE_WATCH: \"ew3.balance.watch\",\n BALANCE_WATCH_TOKEN: \"ew3.balance.watchToken\",\n BLOCK_GET: \"ew3.block.get\",\n BLOCK_GET_BY_HASH: \"ew3.block.getByHash\",\n BLOCK_GET_NUMBER: \"ew3.block.getNumber\",\n BLOCK_GET_RANGE: \"ew3.block.getRange\",\n BLOCK_GET_TIMESTAMP: \"ew3.block.getTimestamp\",\n BLOCK_WAIT: \"ew3.block.wait\",\n BLOCK_WATCH: \"ew3.block.watch\",\n CONTRACT_ESTIMATE_GAS: \"ew3.contract.estimateGas\",\n CONTRACT_READ: \"ew3.contract.read\",\n CONTRACT_SIMULATE: \"ew3.contract.simulate\",\n CONTRACT_WRITE: \"ew3.contract.write\",\n CROSS_CHAIN_MULTICALL_ALL: \"ew3.crossChain.multicallAll\",\n CROSS_CHAIN_READ_ALL: \"ew3.crossChain.readAll\",\n CROSS_CHAIN_READ_SAME: \"ew3.crossChain.readSame\",\n DEPLOY_COMPUTE_ADDRESS: \"ew3.deploy.computeAddress\",\n DEPLOY_CONTRACT: \"ew3.deploy.contract\",\n DEPLOY_VERIFY: \"ew3.deploy.verify\",\n ENS_GET_ADDRESS: \"ew3.ens.getAddress\",\n ENS_GET_AVATAR: \"ew3.ens.getAvatar\",\n ENS_GET_NAME: \"ew3.ens.getName\",\n ENS_GET_RESOLVER: \"ew3.ens.getResolver\",\n ENS_GET_TEXT: \"ew3.ens.getText\",\n ERC721_APPROVE: \"ew3.erc721.approve\",\n ERC721_BALANCE_OF: \"ew3.erc721.balanceOf\",\n ERC721_FETCH_METADATA: \"ew3.erc721.fetchMetadata\",\n ERC721_GET_APPROVED: \"ew3.erc721.getApproved\",\n ERC721_IS_APPROVED_FOR_ALL: \"ew3.erc721.isApprovedForAll\",\n ERC721_NAME: \"ew3.erc721.name\",\n ERC721_OWNER_OF: \"ew3.erc721.ownerOf\",\n ERC721_SAFE_TRANSFER_FROM: \"ew3.erc721.safeTransferFrom\",\n ERC721_SET_APPROVAL_FOR_ALL: \"ew3.erc721.setApprovalForAll\",\n ERC721_SYMBOL: \"ew3.erc721.symbol\",\n ERC721_TOKEN_URI: \"ew3.erc721.tokenURI\",\n ERC721_TOTAL_SUPPLY: \"ew3.erc721.totalSupply\",\n ERC721_TRANSFER_FROM: \"ew3.erc721.transferFrom\",\n EVENT_BACKFILL: \"ew3.event.backfill\",\n EVENT_WATCH: \"ew3.event.watch\",\n GAS_ESTIMATE_FEES: \"ew3.gas.estimateFees\",\n GAS_ESTIMATE_GAS: \"ew3.gas.estimateGas\",\n GAS_GET_ALL_ESTIMATES: \"ew3.gas.getAllEstimates\",\n GAS_GET_BASE_FEE: \"ew3.gas.getBaseFee\",\n GAS_GET_MAX_PRIORITY_FEE: \"ew3.gas.getMaxPriorityFee\",\n GAS_SUPPORTS_EIP1559: \"ew3.gas.supportsEip1559\",\n MULTICALL: \"ew3.contract.multicall\",\n NONCE_CONFIRM: \"ew3.nonce.confirm\",\n NONCE_GET_CONFIRMED_COUNT: \"ew3.nonce.getConfirmedCount\",\n NONCE_GET_GAPS: \"ew3.nonce.getGaps\",\n NONCE_GET_NEXT: \"ew3.nonce.getNext\",\n NONCE_GET_PENDING_COUNT: \"ew3.nonce.getPendingCount\",\n NONCE_RELEASE: \"ew3.nonce.release\",\n NONCE_RESERVE: \"ew3.nonce.reserve\",\n NONCE_SYNC: \"ew3.nonce.sync\",\n SAFE_ENABLE_OFFCHAIN: \"ew3.safe.enableOffchainSigning\",\n\n // Safe Apps\n SAFE_GET_INFO: \"ew3.safe.getInfo\",\n SAFE_GET_OFFCHAIN_SIG: \"ew3.safe.getOffchainSignature\",\n SAFE_GET_TX: \"ew3.safe.getTx\",\n SAFE_POLL_OFFCHAIN_SIG: \"ew3.safe.pollOffchainSignature\",\n SAFE_SEND_TXS: \"ew3.safe.sendTxs\",\n SAFE_SIGN_TYPED_DATA: \"ew3.safe.signTypedData\",\n SAFE_WAIT_RECEIPT: \"ew3.safe.waitForReceipt\",\n SIGNATURE_HASH_MESSAGE: \"ew3.signature.hashMessage\",\n SIGNATURE_HASH_TYPED_DATA: \"ew3.signature.hashTypedData\",\n SIGNATURE_JOIN: \"ew3.signature.join\",\n SIGNATURE_RECOVER_ADDRESS: \"ew3.signature.recoverAddress\",\n SIGNATURE_RECOVER_TYPED_DATA_ADDRESS: \"ew3.signature.recoverTypedDataAddress\",\n SIGNATURE_SPLIT: \"ew3.signature.split\",\n SIGNATURE_VERIFY_MESSAGE: \"ew3.signature.verifyMessage\",\n SIGNATURE_VERIFY_TYPED_DATA: \"ew3.signature.verifyTypedData\",\n SIMULATION_SIMULATE: \"ew3.simulation.simulate\",\n SIMULATION_SIMULATE_BUNDLE: \"ew3.simulation.simulateBundle\",\n SUBSCRIPTION_WATCH_BLOCKS: \"ew3.subscription.watchBlocks\",\n SUBSCRIPTION_WATCH_LOGS: \"ew3.subscription.watchLogs\",\n SUBSCRIPTION_WATCH_PENDING_TX: \"ew3.subscription.watchPendingTx\",\n TRANSFER_ESTIMATE: \"ew3.transfer.estimateGas\",\n TRANSFER_SEND: \"ew3.transfer.send\",\n TRANSFER_SEND_AND_WAIT: \"ew3.transfer.sendAndWait\",\n TX_GET_CONFIRMATIONS: \"ew3.tx.getConfirmations\",\n TX_TRACK: \"ew3.tx.track\",\n TX_WAIT: \"ew3.tx.wait\",\n WALLET_CONNECT: \"ew3.wallet.connect\",\n WALLET_SIGN_MESSAGE: \"ew3.wallet.signMessage\",\n WALLET_SIGN_TYPED_DATA: \"ew3.wallet.signTypedData\",\n} as const;\n"]}
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "sideEffects": false,
7
7
  "type": "module",
8
8
  "types": "./dist/index.d.ts",
9
- "version": "1.0.0-beta.4",
9
+ "version": "1.0.0-beta.5",
10
10
  "scripts": {
11
11
  "build": "just build",
12
12
  "prepack": "bun install --frozen-lockfile && just build"
@@ -1,8 +0,0 @@
1
- export declare const DEFAULT_SAFE_ORIGINS: readonly ["https://app.safe.global", "https://gnosis-safe.io", "https://safe.global", "https://safe.berachain.com", "https://safe.chiliz.com", "https://safe.lightlink.io", "https://safe.optimism.io"];
2
- export declare function setSafeOrigins(origins: readonly string[]): void;
3
- export declare function extendSafeOrigins(origins: readonly string[]): void;
4
- export declare function getSafeOrigins(): readonly string[];
5
- export declare function subscribeSafeOrigins(listener: () => void): () => void;
6
- export declare function isValidSafeOrigin(): boolean;
7
- export declare function isHostEmbedded(): boolean;
8
- //# sourceMappingURL=safe-origins.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"safe-origins.d.ts","sourceRoot":"","sources":["../../src/react-hooks/safe-origins.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,yMAUvB,CAAC;AASX,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,QAExD;AAGD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,QAE3D;AAGD,wBAAgB,cAAc,IAAI,SAAS,MAAM,EAAE,CAElD;AAGD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAKrE;AAGD,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C;AAGD,wBAAgB,cAAc,IAAI,OAAO,CAExC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"safe-origins.js","sourceRoot":"","sources":["../../src/react-hooks/safe-origins.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAMb,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAElC,yBAAyB;IACzB,wBAAwB;IACxB,qBAAqB;IAErB,4BAA4B;IAC5B,yBAAyB;IACzB,2BAA2B;IAC3B,0BAA0B;CAClB,CAAC;AAEX,MAAM,uBAAuB,GAAG,eAAe,CAAC;AAChD,IAAI,WAAW,GAAG,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;AACzD,IAAI,aAAa,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;AACzC,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAc,CAAC;AAClD,IAAI,qBAAqB,GAAG,KAAK,CAAC;AAGlC,MAAM,UAAU,cAAc,CAAC,OAA0B;IACvD,oBAAoB,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;AAClD,CAAC;AAGD,MAAM,UAAU,iBAAiB,CAAC,OAA0B;IAC1D,oBAAoB,CAAC,gBAAgB,CAAC,CAAC,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC;AAGD,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC;AAC1B,CAAC;AAGD,MAAM,UAAU,oBAAoB,CAAC,QAAoB;IACvD,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,OAAO,GAAG,EAAE;QACV,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC,CAAC;AACJ,CAAC;AAGD,MAAM,UAAU,iBAAiB;IAC/B,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAGD,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC;AACnE,CAAC;AAMD,SAAS,iBAAiB;IACxB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;YAC5C,OAAO,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;YAC3C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,WAAqB;IAC9C,IAAI,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,WAAW,GAAG,WAAW,CAAC;IAC1B,aAAa,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IACrC,yBAAyB,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,oBAAoB,CAAC,WAAqB;IACjD,IAAI,qBAAqB,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,qBAAqB,GAAG,IAAI,CAAC;IAC7B,iBAAiB,CAAC,WAAW,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,yBAAyB;IAChC,KAAK,MAAM,QAAQ,IAAI,mBAAmB,EAAE,CAAC;QAC3C,QAAQ,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,OAA0B;IAClD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,gBAAgB,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QACjD,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC3B,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,eAAe,CAAC,MAAc;IACrC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,OAAO,EAAE,CAAC;IAEzF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/B,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,CAAC,MAAM,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,IAAuB,EAAE,KAAwB;IACvE,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["\"use client\";\n\n/**\n * Known Safe wallet domains for iframe origin validation.\n * Includes the main Safe app and chain-specific Safe deployments.\n */\nexport const DEFAULT_SAFE_ORIGINS = [\n // Main Safe domains\n \"https://app.safe.global\",\n \"https://gnosis-safe.io\",\n \"https://safe.global\",\n // Chain-specific Safe deployments\n \"https://safe.berachain.com\",\n \"https://safe.chiliz.com\",\n \"https://safe.lightlink.io\",\n \"https://safe.optimism.io\",\n] as const;\n\nconst ORIGIN_PROTOCOL_PATTERN = /^[a-z]+:\\/\\//i;\nlet safeOrigins = normalizeOrigins(DEFAULT_SAFE_ORIGINS);\nlet safeOriginSet = new Set(safeOrigins);\nconst safeOriginListeners = new Set<() => void>();\nlet safeOriginsConfigured = false;\n\n/** Replace the Safe origins list (one-time configuration). */\nexport function setSafeOrigins(origins: readonly string[]) {\n configureSafeOrigins(normalizeOrigins(origins));\n}\n\n/** Extend the Safe origins list (one-time configuration). */\nexport function extendSafeOrigins(origins: readonly string[]) {\n configureSafeOrigins(normalizeOrigins([...safeOrigins, ...origins]));\n}\n\n/** Read the currently configured Safe origins list. */\nexport function getSafeOrigins(): readonly string[] {\n return [...safeOrigins];\n}\n\n/** Subscribe to Safe origin changes. */\nexport function subscribeSafeOrigins(listener: () => void): () => void {\n safeOriginListeners.add(listener);\n return () => {\n safeOriginListeners.delete(listener);\n };\n}\n\n/** Check if the parent browsing context origin is a Safe domain. */\nexport function isValidSafeOrigin(): boolean {\n const origin = getAncestorOrigin();\n if (!origin) {\n return false;\n }\n return safeOriginSet.has(origin);\n}\n\n/** Check whether the app is running inside an iframe. */\nexport function isHostEmbedded(): boolean {\n return typeof window !== \"undefined\" && window.parent !== window;\n}\n\n/**\n * Get the origin of the parent browsing context.\n * Returns null if it cannot be determined due to cross-origin restrictions.\n */\nfunction getAncestorOrigin(): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return window.parent.location.origin;\n } catch {\n if (window.location.ancestorOrigins?.length) {\n return window.location.ancestorOrigins[0];\n }\n\n if (document.referrer) {\n try {\n return new URL(document.referrer).origin;\n } catch {\n return null;\n }\n }\n\n return null;\n }\n}\n\nfunction updateSafeOrigins(nextOrigins: string[]) {\n if (areSameOrigins(safeOrigins, nextOrigins)) {\n return;\n }\n\n safeOrigins = nextOrigins;\n safeOriginSet = new Set(safeOrigins);\n notifySafeOriginListeners();\n}\n\nfunction configureSafeOrigins(nextOrigins: string[]) {\n if (safeOriginsConfigured) {\n throw new Error(\"Safe origins already configured.\");\n }\n\n safeOriginsConfigured = true;\n updateSafeOrigins(nextOrigins);\n}\n\nfunction notifySafeOriginListeners() {\n for (const listener of safeOriginListeners) {\n listener();\n }\n}\n\nfunction normalizeOrigins(origins: readonly string[]): string[] {\n const normalized: string[] = [];\n const seen = new Set<string>();\n\n for (const origin of origins) {\n const normalizedOrigin = normalizeOrigin(origin);\n if (!normalizedOrigin || seen.has(normalizedOrigin)) {\n continue;\n }\n seen.add(normalizedOrigin);\n normalized.push(normalizedOrigin);\n }\n\n return normalized;\n}\n\nfunction normalizeOrigin(origin: string): string | null {\n const trimmed = origin.trim();\n if (!trimmed) {\n return null;\n }\n\n const candidate = ORIGIN_PROTOCOL_PATTERN.test(trimmed) ? trimmed : `https://${trimmed}`;\n\n try {\n const url = new URL(candidate);\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n return null;\n }\n return url.origin;\n } catch {\n return null;\n }\n}\n\nfunction areSameOrigins(left: readonly string[], right: readonly string[]): boolean {\n if (left.length !== right.length) {\n return false;\n }\n\n for (let index = 0; index < left.length; index += 1) {\n if (left[index] !== right[index]) {\n return false;\n }\n }\n\n return true;\n}\n"]}
@@ -1,2 +0,0 @@
1
- export declare function useIsHostSafeMultisig(): boolean;
2
- //# sourceMappingURL=use-is-host-safe-multisig.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-is-host-safe-multisig.d.ts","sourceRoot":"","sources":["../../src/react-hooks/use-is-host-safe-multisig.ts"],"names":[],"mappings":"AAkBA,wBAAgB,qBAAqB,IAAI,OAAO,CAS/C"}
@@ -1,16 +0,0 @@
1
- "use client";
2
- import { useSyncExternalStore } from "react";
3
- import { isHostEmbedded, isValidSafeOrigin, subscribeSafeOrigins } from "./safe-origins.js";
4
- import { useSafeContext } from "./use-safe-context.js";
5
- export function useIsHostSafeMultisig() {
6
- const isSafeContext = useSafeContext();
7
- const isSafeHost = useSyncExternalStore(subscribeSafeOrigins, getSafeHostSnapshot, getServerSnapshot);
8
- return isSafeContext || isSafeHost;
9
- }
10
- function getSafeHostSnapshot() {
11
- return isHostEmbedded() && isValidSafeOrigin();
12
- }
13
- function getServerSnapshot() {
14
- return false;
15
- }
16
- //# sourceMappingURL=use-is-host-safe-multisig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-is-host-safe-multisig.js","sourceRoot":"","sources":["../../src/react-hooks/use-is-host-safe-multisig.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAcvD,MAAM,UAAU,qBAAqB;IACnC,MAAM,aAAa,GAAG,cAAc,EAAE,CAAC;IACvC,MAAM,UAAU,GAAG,oBAAoB,CACrC,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,CAClB,CAAC;IAEF,OAAO,aAAa,IAAI,UAAU,CAAC;AACrC,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO,cAAc,EAAE,IAAI,iBAAiB,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\nimport { isHostEmbedded, isValidSafeOrigin, subscribeSafeOrigins } from \"./safe-origins.js\";\nimport { useSafeContext } from \"./use-safe-context.js\";\n\n/**\n * Detect if the app is running within a Safe context.\n *\n * This hook returns `true` when either:\n * - Safe Apps SDK confirms the Safe context (async, most reliable), or\n * - The app is embedded in a Safe-origin iframe (sync check).\n *\n * Notes:\n * - This answers “is the host Safe?” and will return true even without a wallet.\n * - For full wallet detection heuristics, use `useIsWalletSafeMultisig`.\n * - For SDK-only checks, use `useSafeContext`.\n */\nexport function useIsHostSafeMultisig(): boolean {\n const isSafeContext = useSafeContext();\n const isSafeHost = useSyncExternalStore(\n subscribeSafeOrigins,\n getSafeHostSnapshot,\n getServerSnapshot\n );\n\n return isSafeContext || isSafeHost;\n}\n\nfunction getSafeHostSnapshot(): boolean {\n return isHostEmbedded() && isValidSafeOrigin();\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n"]}
@@ -1,2 +0,0 @@
1
- export declare function useIsWalletSafeMultisig(): boolean;
2
- //# sourceMappingURL=use-is-wallet-safe-multisig.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-is-wallet-safe-multisig.d.ts","sourceRoot":"","sources":["../../src/react-hooks/use-is-wallet-safe-multisig.ts"],"names":[],"mappings":"AAsBA,wBAAgB,uBAAuB,IAAI,OAAO,CAuBjD"}
@@ -1,24 +0,0 @@
1
- "use client";
2
- import { useSyncExternalStore } from "react";
3
- import { useAccount } from "wagmi";
4
- import { isHostEmbedded, isValidSafeOrigin, subscribeSafeOrigins } from "./safe-origins.js";
5
- import { useSafeContext } from "./use-safe-context.js";
6
- export function useIsWalletSafeMultisig() {
7
- const { connector, isConnected } = useAccount();
8
- const isSafeContext = useSafeContext();
9
- const isSafeIframe = useSyncExternalStore(subscribeSafeOrigins, getSafeIframeSnapshot, getServerSnapshot);
10
- if (isSafeContext) {
11
- return true;
12
- }
13
- if (isConnected && connector?.id === "safe") {
14
- return true;
15
- }
16
- return isSafeIframe;
17
- }
18
- function getSafeIframeSnapshot() {
19
- return isHostEmbedded() && isValidSafeOrigin();
20
- }
21
- function getServerSnapshot() {
22
- return false;
23
- }
24
- //# sourceMappingURL=use-is-wallet-safe-multisig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-is-wallet-safe-multisig.js","sourceRoot":"","sources":["../../src/react-hooks/use-is-wallet-safe-multisig.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAiBvD,MAAM,UAAU,uBAAuB;IACrC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,UAAU,EAAE,CAAC;IAChD,MAAM,aAAa,GAAG,cAAc,EAAE,CAAC;IAGvC,MAAM,YAAY,GAAG,oBAAoB,CACvC,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,CAClB,CAAC;IAGF,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,IAAI,WAAW,IAAI,SAAS,EAAE,EAAE,KAAK,MAAM,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO,cAAc,EAAE,IAAI,iBAAiB,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["\"use client\";\n\nimport { useSyncExternalStore } from \"react\";\nimport { useAccount } from \"wagmi\";\nimport { isHostEmbedded, isValidSafeOrigin, subscribeSafeOrigins } from \"./safe-origins.js\";\nimport { useSafeContext } from \"./use-safe-context.js\";\n\n/**\n * Detect if the connected wallet is a Safe multisig.\n *\n * Detection strategy (in order of reliability):\n * 1. Safe Apps SDK detection via postMessage (most reliable, works cross-origin)\n * 2. Wagmi connector ID check\n * 3. Iframe origin validation (fallback, may fail cross-origin)\n *\n * @returns true if wallet is a Safe multisig\n *\n * Notes:\n * - This is a broader heuristic: SDK context, connector ID, then host origin.\n * - For just SDK context, use `useSafeContext`.\n * - For a sync host-only check, use `useIsHostSafeMultisig`.\n */\nexport function useIsWalletSafeMultisig(): boolean {\n const { connector, isConnected } = useAccount();\n const isSafeContext = useSafeContext();\n\n // Method 3: Iframe origin fallback (may fail cross-origin)\n const isSafeIframe = useSyncExternalStore(\n subscribeSafeOrigins,\n getSafeIframeSnapshot,\n getServerSnapshot\n );\n\n // Method 1: Safe Apps SDK (most reliable - uses postMessage)\n if (isSafeContext) {\n return true;\n }\n\n // Method 2: Connected via Safe connector\n if (isConnected && connector?.id === \"safe\") {\n return true;\n }\n\n // Method 3: Fallback\n return isSafeIframe;\n}\n\nfunction getSafeIframeSnapshot(): boolean {\n return isHostEmbedded() && isValidSafeOrigin();\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n"]}
@@ -1,2 +0,0 @@
1
- export declare function useSafeContext(): boolean;
2
- //# sourceMappingURL=use-safe-context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-safe-context.d.ts","sourceRoot":"","sources":["../../src/react-hooks/use-safe-context.ts"],"names":[],"mappings":"AAuCA,wBAAgB,cAAc,IAAI,OAAO,CA6CxC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-safe-context.js","sourceRoot":"","sources":["../../src/react-hooks/use-safe-context.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAM5C,MAAM,gBAAgB,GAAG,IAAI,CAAC;AA+B9B,MAAM,UAAU,cAAc;IAC5B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QAEb,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAC;QAGtB,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACH,CAAC,EAAE,gBAAgB,CAAC,CAAC;QAGrB,MAAM,CAAC,4BAA4B,CAAC;aACjC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE;YACjC,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,EAAE;YACT,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACH,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QAEL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * Timeout for Safe SDK detection in milliseconds.\n * Safe Apps SDK uses postMessage which can hang if not in Safe context.\n */\nconst SAFE_SDK_TIMEOUT = 3000;\n\n/**\n * Detect if the app is running in a Safe App context using the Safe Apps SDK.\n *\n * This hook asynchronously checks with the Safe Apps SDK to determine if\n * we're running inside a Safe App iframe. More reliable than iframe origin\n * detection because:\n * - Uses postMessage (works cross-origin)\n * - Gets definitive answer from Safe\n * - Includes timeout to prevent hangs\n *\n * @returns true if running in Safe App context, false otherwise\n *\n * Notes:\n * - This only verifies the Safe Apps SDK context (async).\n * - For a host-based sync check, use `useIsHostSafeMultisig`.\n * - For a full wallet detection heuristic, use `useIsWalletSafeMultisig`.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const isSafeContext = useSafeContext();\n *\n * if (isSafeContext) {\n * return <p>Running in Safe App</p>;\n * }\n * return <p>Regular browser context</p>;\n * }\n * ```\n */\nexport function useSafeContext(): boolean {\n const [isSafe, setIsSafe] = useState(false);\n\n useEffect(() => {\n // SSR guard\n if (typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n\n // Timeout fallback - resolve to false if SDK doesn't respond\n const timeout = setTimeout(() => {\n if (!cancelled) {\n setIsSafe(false);\n }\n }, SAFE_SDK_TIMEOUT);\n\n // Dynamically import SDK to keep it optional\n import(\"@safe-global/safe-apps-sdk\")\n .then(({ default: SafeAppsSDK }) => {\n const sdk = new SafeAppsSDK();\n return sdk.safe.getInfo();\n })\n .then(() => {\n if (!cancelled) {\n setIsSafe(true);\n }\n })\n .catch(() => {\n if (!cancelled) {\n setIsSafe(false);\n }\n })\n .finally(() => {\n clearTimeout(timeout);\n });\n\n return () => {\n cancelled = true;\n clearTimeout(timeout);\n };\n }, []);\n\n return isSafe;\n}\n"]}