@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.
- package/DOCS.md +13 -0
- package/README.md +1 -0
- package/dist/react-hooks/index.d.ts +4 -4
- package/dist/react-hooks/index.d.ts.map +1 -1
- package/dist/react-hooks/index.js +4 -4
- package/dist/react-hooks/index.js.map +1 -1
- package/dist/react-hooks/safe-app-origins.d.ts +8 -0
- package/dist/react-hooks/safe-app-origins.d.ts.map +1 -0
- package/dist/react-hooks/{safe-origins.js → safe-app-origins.js} +29 -29
- package/dist/react-hooks/safe-app-origins.js.map +1 -0
- package/dist/react-hooks/use-is-host-safe-app.d.ts +2 -0
- package/dist/react-hooks/use-is-host-safe-app.d.ts.map +1 -0
- package/dist/react-hooks/use-is-host-safe-app.js +16 -0
- package/dist/react-hooks/use-is-host-safe-app.js.map +1 -0
- package/dist/react-hooks/use-is-safe-app-context.d.ts +2 -0
- package/dist/react-hooks/use-is-safe-app-context.d.ts.map +1 -0
- package/dist/react-hooks/{use-safe-context.js → use-is-safe-app-context.js} +2 -2
- package/dist/react-hooks/use-is-safe-app-context.js.map +1 -0
- package/dist/react-hooks/use-is-safe-multisig-wallet.d.ts +2 -0
- package/dist/react-hooks/use-is-safe-multisig-wallet.d.ts.map +1 -0
- package/dist/react-hooks/use-is-safe-multisig-wallet.js +24 -0
- package/dist/react-hooks/use-is-safe-multisig-wallet.js.map +1 -0
- package/dist/safe/index.d.ts +1 -1
- package/dist/safe/index.d.ts.map +1 -1
- package/dist/safe/index.js.map +1 -1
- package/dist/safe/live.d.ts.map +1 -1
- package/dist/safe/live.js +14 -14
- package/dist/safe/live.js.map +1 -1
- package/dist/safe/service.d.ts +4 -4
- package/dist/safe/service.d.ts.map +1 -1
- package/dist/safe/service.js.map +1 -1
- package/dist/safe/service.test.integration.js +10 -12
- package/dist/safe/service.test.integration.js.map +1 -1
- package/dist/safe/types.d.ts +14 -14
- package/dist/safe/types.d.ts.map +1 -1
- package/dist/safe/types.js.map +1 -1
- package/dist/telemetry/tracer.d.ts +2 -2
- package/dist/telemetry/tracer.js +2 -2
- package/dist/telemetry/tracer.js.map +1 -1
- package/package.json +1 -1
- package/dist/react-hooks/safe-origins.d.ts +0 -8
- package/dist/react-hooks/safe-origins.d.ts.map +0 -1
- package/dist/react-hooks/safe-origins.js.map +0 -1
- package/dist/react-hooks/use-is-host-safe-multisig.d.ts +0 -2
- package/dist/react-hooks/use-is-host-safe-multisig.d.ts.map +0 -1
- package/dist/react-hooks/use-is-host-safe-multisig.js +0 -16
- package/dist/react-hooks/use-is-host-safe-multisig.js.map +0 -1
- package/dist/react-hooks/use-is-wallet-safe-multisig.d.ts +0 -2
- package/dist/react-hooks/use-is-wallet-safe-multisig.d.ts.map +0 -1
- package/dist/react-hooks/use-is-wallet-safe-multisig.js +0 -24
- package/dist/react-hooks/use-is-wallet-safe-multisig.js.map +0 -1
- package/dist/react-hooks/use-safe-context.d.ts +0 -2
- package/dist/react-hooks/use-safe-context.d.ts.map +0 -1
- 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 {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
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,
|
|
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 {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
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,
|
|
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
|
|
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
|
|
13
|
-
let
|
|
14
|
-
const
|
|
15
|
-
let
|
|
16
|
-
export function
|
|
17
|
-
|
|
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
|
|
20
|
-
|
|
19
|
+
export function extendSafeAppOrigins(origins) {
|
|
20
|
+
configureSafeAppOrigins(normalizeOrigins([...safeAppOrigins, ...origins]));
|
|
21
21
|
}
|
|
22
|
-
export function
|
|
23
|
-
return [...
|
|
22
|
+
export function getSafeAppOrigins() {
|
|
23
|
+
return [...safeAppOrigins];
|
|
24
24
|
}
|
|
25
|
-
export function
|
|
26
|
-
|
|
25
|
+
export function subscribeSafeAppOrigins(listener) {
|
|
26
|
+
safeAppOriginListeners.add(listener);
|
|
27
27
|
return () => {
|
|
28
|
-
|
|
28
|
+
safeAppOriginListeners.delete(listener);
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
-
export function
|
|
31
|
+
export function isValidSafeAppOrigin() {
|
|
32
32
|
const origin = getAncestorOrigin();
|
|
33
33
|
if (!origin) {
|
|
34
34
|
return false;
|
|
35
35
|
}
|
|
36
|
-
return
|
|
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
|
|
64
|
-
if (areSameOrigins(
|
|
63
|
+
function updateSafeAppOrigins(nextOrigins) {
|
|
64
|
+
if (areSameOrigins(safeAppOrigins, nextOrigins)) {
|
|
65
65
|
return;
|
|
66
66
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
safeAppOrigins = nextOrigins;
|
|
68
|
+
safeAppOriginSet = new Set(safeAppOrigins);
|
|
69
|
+
notifySafeAppOriginListeners();
|
|
70
70
|
}
|
|
71
|
-
function
|
|
72
|
-
if (
|
|
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
|
-
|
|
76
|
-
|
|
75
|
+
safeAppOriginsConfigured = true;
|
|
76
|
+
updateSafeAppOrigins(nextOrigins);
|
|
77
77
|
}
|
|
78
|
-
function
|
|
79
|
-
for (const listener of
|
|
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 @@
|
|
|
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 @@
|
|
|
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
|
|
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 @@
|
|
|
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"]}
|
package/dist/safe/index.d.ts
CHANGED
|
@@ -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,
|
|
7
|
+
export type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeInfo, SafeMultisigTx, SafeTxResult, SafeTxSubmission, SafeWaitPolicy, SignTypedDataResult, } from "./types.js";
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/safe/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/safe/index.js.map
CHANGED
|
@@ -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
|
|
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"]}
|
package/dist/safe/live.d.ts.map
CHANGED
|
@@ -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,
|
|
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
|
|
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
|
|
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, "
|
|
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
|
|
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
|
|
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
|
|
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, "
|
|
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
|
|
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*
|
|
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
|
|
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
|
|
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
|
-
|
|
243
|
+
getTx,
|
|
244
244
|
pollOffchainSignature,
|
|
245
|
-
|
|
245
|
+
sendTxs,
|
|
246
246
|
signTypedData,
|
|
247
|
-
|
|
247
|
+
waitForTxReceipt,
|
|
248
248
|
});
|
|
249
249
|
}));
|
|
250
250
|
//# sourceMappingURL=live.js.map
|
package/dist/safe/live.js.map
CHANGED
|
@@ -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":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,wBAAwB,EACxB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQ/C,MAAM,eAAe,GAAG,CACtB,KAAa,EACb,OAAe,EAC4B,EAAE,CAC7C,SAAS,CAAC,KAAK,CAAC;IACd,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;IACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CACT,IAAI,iBAAiB,CAAC;QACpB,OAAO,EAAE,+BAA+B,OAAO,KAAK,KAAK,EAAE;QAC3D,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,EAAE;KACf,CAAC,CACH,CAAC;AAKR,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,OAAe,EAA0C,EAAE,CAC9F,MAAM,CAAC,KAAK,CAAC;IACX,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;IACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CACT,IAAI,iBAAiB,CAAC;QACpB,OAAO,EAAE,4BAA4B,OAAO,KAAK,KAAK,EAAE;QACxD,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,EAAE;KACf,CAAC,CACH,CAAC;AAKR,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,OAAe,EAAyC,EAAE,CAC5F,KAAK,CAAC,KAAK,CAAC;IACV,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;IACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CACT,IAAI,iBAAiB,CAAC;QACpB,OAAO,EAAE,2BAA2B,OAAO,KAAK,KAAK,EAAE;QACvD,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,EAAE;KACf,CAAC,CACH,CAAC;AAER,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAA8B,EAAE,EAAE,CACpE,KAAK,CAAC,MAAM,CACV,eAAe,EACf,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAElB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,IAAI,wBAAwB,CAAC;YAC3B,OAAO,EAAE,oEAAoE;SAC9E,CAAC,CACH,CAAC;IACJ,CAAC;IAGD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAGvC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAkB,IAAI,CAAC,CAAC;IAGvD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;IAInC,MAAM,OAAO,GAAG,GAAG,EAAE,CACnB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;YACpC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,wBAAwB,CAAC;gBAC3B,KAAK;gBACL,OAAO,EAAE,kCAAkC;aAC5C,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE;SAC9B,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,IAAI,CAC1E,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CACzC,MAAM,CAAC,IAAI,CAAC,IAAI,wBAAwB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAC5E,CACF,CAAC;QAEF,MAAM,QAAQ,GAAa;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW;SACZ,CAAC;QAEF,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAClC,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpD,MAAM,OAAO,GAAG,CAAC,GAA8B,EAAE,MAA+B,EAAE,EAAE,CAClF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAElB,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,EAAE,EAAE,EAAE,CAAC,EAAE;YACT,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG;SACnC,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;YACtC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,qBAAqB,CAAC;gBACxB,KAAK;gBACL,OAAO,EAAE,8BAA8B;aACxC,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;SACjD,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,IAAI,CACvE,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CACzC,MAAM,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CACzE,CACF,CAAC;QAEF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QAE9B,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU;SACX,CAAC;IACJ,CAAC,CAAC;SACC,IAAI,CACH,MAAM,CAAC,QAAQ,CAAC,0BAA0B,EAAE,CAAC,KAAK,EAAE,EAAE,CACpD,MAAM,CAAC,IAAI,CACT,IAAI,qBAAqB,CAAC;QACxB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,6CAA6C;KACvD,CAAC,CACH,CACF,CACF;SACA,IAAI,CACH,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE;QACvC,UAAU,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;KACpC,CAAC,CACH,CAAC;IAEN,MAAM,KAAK,GAAG,CAAC,UAAgB,EAAE,EAAE,CACjC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;YAClC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,iBAAiB,CAAC;gBACpB,KAAK;gBACL,OAAO,EAAE,4BAA4B,UAAU,EAAE;gBACjD,SAAS,EAAE,IAAI;gBACf,UAAU;aACX,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC;SAC/C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAE1E,OAAO;YACL,MAAM,EAAE,EAAE,CAAC,QAAQ,IAAI,wBAAwB;YAC/C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAQ;SAC3D,CAAC;IACJ,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE;QACrC,UAAU,EAAE,EAAE,UAAU,EAAE;KAC3B,CAAC,CACH,CAAC;IAEJ,MAAM,gBAAgB,GAAG,CACvB,UAAgB,EAChB,SAII,EAAE,EACN,EAAE,CACF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QAC9B,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,kBAAkB,CAAC;QAC/D,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,IAAI,sBAAsB,CAAC;QAI3E,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC7C,IAAI,UAAU,GAAG,wBAAwB,CAAC;YAC1C,IAAI,KAAK,GAAgB,IAAI,CAAC;YAE9B,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBACrC,OAAO,KAAK,KAAK,IAAI,EAAE,CAAC;oBACtB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;oBACpC,UAAU,GAAG,EAAE,CAAC,MAAM,CAAC;oBAEvB,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;wBAC7B,KAAK,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC1B,CAAC;yBAAM,CAAC;wBAEN,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;oBACrD,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,CACpB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,EACjD,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE,CACvC,MAAM,CAAC,IAAI,CACT,IAAI,2BAA2B,CAAC;gBAC9B,UAAU;gBACV,OAAO,EAAE,WAAW,UAAU,wBAAwB,gBAAgB,oBAAoB,UAAU,GAAG;gBACvG,UAAU;gBACV,OAAO,EAAE,gBAAgB;aAC1B,CAAC,CACH,CACF,CACF,CAAC;YAEF,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,IAAI,2BAA2B,CAAC;oBAC9B,UAAU;oBACV,OAAO,EAAE,WAAW,UAAU,8BAA8B;oBAC5D,UAAU;oBACV,OAAO,EAAE,gBAAgB;iBAC1B,CAAC,CACH,CAAC;YACJ,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QAGH,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,SAAS;aAC7B,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC;aAC/D,IAAI,CACH,MAAM,CAAC,QAAQ,CAAC,0BAA0B,EAAE,CAAC,KAAK,EAAE,EAAE,CACpD,MAAM,CAAC,IAAI,CACT,IAAI,iBAAiB,CAAC;YACpB,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,6BAA6B,KAAK,CAAC,OAAO,EAAE;YACrD,SAAS,EAAE,KAAK;YAChB,UAAU;SACX,CAAC,CACH,CACF,CACF,CAAC;QAEJ,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW;YACX,OAAO;YACP,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU;SACX,CAAC;IACJ,CAAC,CAAC;SACC,IAAI,CACH,MAAM,CAAC,QAAQ,CAAC,0BAA0B,EAAE,CAAC,KAAK,EAAE,EAAE,CACpD,MAAM,CAAC,IAAI,CACT,IAAI,iBAAiB,CAAC;QACpB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,6CAA6C;QACtD,SAAS,EAAE,IAAI;QACf,UAAU;KACX,CAAC,CACH,CACF,CACF;SACA,IAAI,CACH,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,iBAAiB,EAAE;QAC3C,UAAU,EAAE,EAAE,UAAU,EAAE;KAC3B,CAAC,CACH,CAAC;IAEN,MAAM,aAAa,GAAG,CAAC,SAA0B,EAAE,EAAE,CACnD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;YACtC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,kBAAkB,CAAC;gBACrB,KAAK;gBACL,OAAO,EAAE,oCAAoC;aAC9C,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CACR,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,SAA2D,CAAC;SACxF,CAAC,CAAC;QAGH,IAAI,aAAa,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YAClD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,IAAI,CAC9E,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CACzC,MAAM,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CACtE,CACF,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,UAAmB,EAAE,WAAW,EAAE,CAAC;QACpD,CAAC;QAGD,MAAM,aAAa,GAAG,MAAgC,CAAC;QACvD,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,IAAI,CACpF,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CACzC,MAAM,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CACtE,CACF,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,SAAkB,EAAE,UAAU,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAE3D,MAAM,oBAAoB,GAAG,CAAC,WAAgB,EAAE,EAAE,CAChD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;YACnC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,iBAAiB,CAAC;gBACpB,KAAK;gBACL,OAAO,EAAE,yCAAyC,WAAW,EAAE;gBAC/D,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,WAAW;aACxB,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC;SACtD,CAAC,CAAC;QAGH,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACvC,OAAO,MAAM,CAAC,IAAI,EAAO,CAAC;QAC5B,CAAC;QAED,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;QACrE,OAAO,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,qBAAqB,EAAE;QAC/C,UAAU,EAAE,EAAE,WAAW,EAAE;KAC5B,CAAC,CACH,CAAC;IAEJ,MAAM,qBAAqB,GAAG,CAC5B,WAAgB,EAChB,SAAsD,EAAE,EACxD,EAAE,CACF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,4BAA4B,CAAC;QACzE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,sBAAsB,CAAC;QAIzD,IAAI,KAAK,GAAe,IAAI,CAAC;QAE7B,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACrC,OAAO,KAAK,KAAK,IAAI,EAAE,CAAC;gBACtB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;gBACrD,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvB,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;gBACpB,CAAC;qBAAM,CAAC;oBAEN,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,CACpB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EACxC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE,CACvC,MAAM,CAAC,IAAI,CACT,IAAI,6BAA6B,CAAC;YAChC,OAAO,EAAE,2BAA2B,WAAW,yBAAyB,OAAO,IAAI;YACnF,WAAW;YACX,OAAO;SACR,CAAC,CACH,CACF,CACF,CAAC;QAEF,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,IAAI,6BAA6B,CAAC;gBAChC,OAAO,EAAE,2BAA2B,WAAW,+BAA+B;gBAC9E,WAAW;gBACX,OAAO;aACR,CAAC,CACH,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,sBAAsB,EAAE;QAChD,UAAU,EAAE,EAAE,WAAW,EAAE;KAC5B,CAAC,CACH,CAAC;IAEJ,MAAM,qBAAqB,GAAG,GAAG,EAAE,CACjC,MAAM,CAAC,UAAU,CAAC;QAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,iBAAiB,CAAC;YACpB,KAAK;YACL,OAAO,EAAE,yCAAyC;SACnD,CAAC;QACJ,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;KAChE,CAAC;SACC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;SACnB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAE3D,OAAO,eAAe,CAAC,EAAE,CAAC;QACxB,qBAAqB;QACrB,OAAO;QACP,oBAAoB;QACpB,KAAK;QACL,qBAAqB;QACrB,OAAO;QACP,aAAa;QACb,gBAAgB;KACjB,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC","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"]}
|
package/dist/safe/service.d.ts
CHANGED
|
@@ -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,
|
|
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
|
|
9
|
+
readonly sendTxs: (txs: readonly SafeMultisigTx[], params?: {
|
|
10
10
|
safeTxGas?: number;
|
|
11
11
|
}) => Effect.Effect<SafeTxSubmission, SafeTxSubmissionError>;
|
|
12
|
-
readonly
|
|
12
|
+
readonly getTx: (safeTxHash: Hash) => Effect.Effect<{
|
|
13
13
|
txHash: Option.Option<Hash>;
|
|
14
14
|
status: string;
|
|
15
15
|
}, SafeTxLookupError>;
|
|
16
|
-
readonly
|
|
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,
|
|
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"}
|
package/dist/safe/service.js.map
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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("
|
|
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.
|
|
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("
|
|
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.
|
|
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.
|
|
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("
|
|
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.
|
|
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":"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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 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"]}
|
package/dist/safe/types.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
17
|
+
chainId: number;
|
|
18
18
|
onchainHash: Hash;
|
|
19
19
|
receipt: TransactionReceipt;
|
|
20
20
|
safeAddress: Address;
|
|
21
|
-
|
|
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
|
-
|
|
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
|
package/dist/safe/types.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/safe/types.js.map
CHANGED
|
@@ -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
|
|
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.
|
|
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.
|
|
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";
|
package/dist/telemetry/tracer.js
CHANGED
|
@@ -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.
|
|
66
|
+
SAFE_GET_TX: "ew3.safe.getTx",
|
|
67
67
|
SAFE_POLL_OFFCHAIN_SIG: "ew3.safe.pollOffchainSignature",
|
|
68
|
-
SAFE_SEND_TXS: "ew3.safe.
|
|
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":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC,MAAM,CAAC,MAAM,QAAQ,GACnB,CAAC,IAAY,EAAE,UAAoC,EAAE,EAAE,CACvD,CAAU,MAA8B,EAA0B,EAAE,CAClE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;AAKlD,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,aAAa,EAAE,mBAAmB;IAClC,mBAAmB,EAAE,wBAAwB;IAC7C,WAAW,EAAE,iBAAiB;IAC9B,iBAAiB,EAAE,sBAAsB;IACzC,uBAAuB,EAAE,2BAA2B;IACpD,aAAa,EAAE,mBAAmB;IAClC,mBAAmB,EAAE,wBAAwB;IAC7C,SAAS,EAAE,eAAe;IAC1B,iBAAiB,EAAE,qBAAqB;IACxC,gBAAgB,EAAE,qBAAqB;IACvC,eAAe,EAAE,oBAAoB;IACrC,mBAAmB,EAAE,wBAAwB;IAC7C,UAAU,EAAE,gBAAgB;IAC5B,WAAW,EAAE,iBAAiB;IAC9B,qBAAqB,EAAE,0BAA0B;IACjD,aAAa,EAAE,mBAAmB;IAClC,iBAAiB,EAAE,uBAAuB;IAC1C,cAAc,EAAE,oBAAoB;IACpC,yBAAyB,EAAE,6BAA6B;IACxD,oBAAoB,EAAE,wBAAwB;IAC9C,qBAAqB,EAAE,yBAAyB;IAChD,sBAAsB,EAAE,2BAA2B;IACnD,eAAe,EAAE,qBAAqB;IACtC,aAAa,EAAE,mBAAmB;IAClC,eAAe,EAAE,oBAAoB;IACrC,cAAc,EAAE,mBAAmB;IACnC,YAAY,EAAE,iBAAiB;IAC/B,gBAAgB,EAAE,qBAAqB;IACvC,YAAY,EAAE,iBAAiB;IAC/B,cAAc,EAAE,oBAAoB;IACpC,iBAAiB,EAAE,sBAAsB;IACzC,qBAAqB,EAAE,0BAA0B;IACjD,mBAAmB,EAAE,wBAAwB;IAC7C,0BAA0B,EAAE,6BAA6B;IACzD,WAAW,EAAE,iBAAiB;IAC9B,eAAe,EAAE,oBAAoB;IACrC,yBAAyB,EAAE,6BAA6B;IACxD,2BAA2B,EAAE,8BAA8B;IAC3D,aAAa,EAAE,mBAAmB;IAClC,gBAAgB,EAAE,qBAAqB;IACvC,mBAAmB,EAAE,wBAAwB;IAC7C,oBAAoB,EAAE,yBAAyB;IAC/C,cAAc,EAAE,oBAAoB;IACpC,WAAW,EAAE,iBAAiB;IAC9B,iBAAiB,EAAE,sBAAsB;IACzC,gBAAgB,EAAE,qBAAqB;IACvC,qBAAqB,EAAE,yBAAyB;IAChD,gBAAgB,EAAE,oBAAoB;IACtC,wBAAwB,EAAE,2BAA2B;IACrD,oBAAoB,EAAE,yBAAyB;IAC/C,SAAS,EAAE,wBAAwB;IACnC,aAAa,EAAE,mBAAmB;IAClC,yBAAyB,EAAE,6BAA6B;IACxD,cAAc,EAAE,mBAAmB;IACnC,cAAc,EAAE,mBAAmB;IACnC,uBAAuB,EAAE,2BAA2B;IACpD,aAAa,EAAE,mBAAmB;IAClC,aAAa,EAAE,mBAAmB;IAClC,UAAU,EAAE,gBAAgB;IAC5B,oBAAoB,EAAE,gCAAgC;IAGtD,aAAa,EAAE,kBAAkB;IACjC,qBAAqB,EAAE,+BAA+B;IACtD,WAAW,EAAE,
|
|
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
|
@@ -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":"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","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 +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 +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 +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"]}
|