@prb/effect-evm-safe 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/react-hooks/index.d.ts +1 -0
  3. package/dist/react-hooks/index.d.ts.map +1 -1
  4. package/dist/react-hooks/index.js +1 -0
  5. package/dist/react-hooks/index.js.map +1 -1
  6. package/dist/react-hooks/use-wallet-execution.d.ts +14 -0
  7. package/dist/react-hooks/use-wallet-execution.d.ts.map +1 -0
  8. package/dist/react-hooks/use-wallet-execution.js +110 -0
  9. package/dist/react-hooks/use-wallet-execution.js.map +1 -0
  10. package/dist/safe/allowance.d.ts +22 -2
  11. package/dist/safe/allowance.d.ts.map +1 -1
  12. package/dist/safe/allowance.js +20 -1
  13. package/dist/safe/allowance.js.map +1 -1
  14. package/dist/safe/errors.d.ts +2 -0
  15. package/dist/safe/errors.d.ts.map +1 -1
  16. package/dist/safe/errors.js +11 -0
  17. package/dist/safe/errors.js.map +1 -1
  18. package/dist/safe/index.d.ts +4 -2
  19. package/dist/safe/index.d.ts.map +1 -1
  20. package/dist/safe/index.js +3 -1
  21. package/dist/safe/index.js.map +1 -1
  22. package/dist/safe/live.d.ts.map +1 -1
  23. package/dist/safe/live.js +7 -37
  24. package/dist/safe/live.js.map +1 -1
  25. package/dist/safe/pipeline-adapter.d.ts +6 -0
  26. package/dist/safe/pipeline-adapter.d.ts.map +1 -0
  27. package/dist/safe/pipeline-adapter.js +143 -0
  28. package/dist/safe/pipeline-adapter.js.map +1 -0
  29. package/dist/safe/tx-lifecycle.d.ts +1 -1
  30. package/dist/safe/tx-lifecycle.d.ts.map +1 -1
  31. package/dist/safe/tx-lifecycle.js +1 -0
  32. package/dist/safe/tx-lifecycle.js.map +1 -1
  33. package/dist/safe/write-and-track.d.ts +72 -0
  34. package/dist/safe/write-and-track.d.ts.map +1 -0
  35. package/dist/safe/write-and-track.js +116 -0
  36. package/dist/safe/write-and-track.js.map +1 -0
  37. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -11,6 +11,23 @@ The format is based on [Common Changelog](https://common-changelog.org/).
11
11
  [2.0.0]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%402.0.0
12
12
  [2.0.1]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%402.0.1
13
13
  [2.0.2]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%402.0.2
14
+ [2.1.0]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%402.1.0
15
+
16
+ ## [2.1.0] - 2026-02-18
17
+
18
+ ### Changed
19
+
20
+ - Add optional `multiSendStrategy: "fallback-required-approval"` to `safeMultisigAllowAndWrite` for chains without
21
+ MultiSend
22
+ - Normalize Safe lookup failures via shared `toSafeMultisigTxLookupError` constructor
23
+
24
+ ### Added
25
+
26
+ - Add `safeWriteAndTrack` with lifecycle callbacks and streamed Safe state transitions
27
+ - Add `SafeWriteExecutionAdapterLive` to bridge Safe execution into `@prb/effect-evm` `ContractPipeline`
28
+ - Add `useWalletExecution` hook for Safe-versus-EOA routing across context, connector, origin, and owners probe
29
+ - Add `cancelled` status support to `SafeMultisigTxStatus`
30
+ - Export `SafeMultisigAllowAndWriteResult` and Safe write-and-track types from `safe` module
14
31
 
15
32
  ## [2.0.2] - 2026-02-18
16
33
 
@@ -2,4 +2,5 @@ export { DEFAULT_SAFE_APP_ORIGINS, extendSafeAppOrigins, getSafeAppOrigins, setS
2
2
  export { useIsHostSafeApp } from "./use-is-host-safe-app.js";
3
3
  export { useIsSafeAppContext } from "./use-is-safe-app-context.js";
4
4
  export { useIsSafeMultisigWallet } from "./use-is-safe-multisig-wallet.js";
5
+ export { useWalletExecution, type WalletExecution, type WalletExecutionDetectionSource, type WalletExecutionHost, type WalletExecutionOptions, type WalletExecutionType, } from "./use-wallet-execution.js";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react-hooks/index.ts"],"names":[],"mappings":"AAEA,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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react-hooks/index.ts"],"names":[],"mappings":"AAEA,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;AAC3E,OAAO,EACL,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,8BAA8B,EACnC,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,GACzB,MAAM,2BAA2B,CAAC"}
@@ -3,4 +3,5 @@ export { DEFAULT_SAFE_APP_ORIGINS, extendSafeAppOrigins, getSafeAppOrigins, setS
3
3
  export { useIsHostSafeApp } from "./use-is-host-safe-app.js";
4
4
  export { useIsSafeAppContext } from "./use-is-safe-app-context.js";
5
5
  export { useIsSafeMultisigWallet } from "./use-is-safe-multisig-wallet.js";
6
+ export { useWalletExecution, } from "./use-wallet-execution.js";
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react-hooks/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,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 {\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"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react-hooks/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,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;AAC3E,OAAO,EACL,kBAAkB,GAMnB,MAAM,2BAA2B,CAAC","sourcesContent":["\"use client\";\n\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\";\nexport {\n useWalletExecution,\n type WalletExecution,\n type WalletExecutionDetectionSource,\n type WalletExecutionHost,\n type WalletExecutionOptions,\n type WalletExecutionType,\n} from \"./use-wallet-execution.js\";\n"]}
@@ -0,0 +1,14 @@
1
+ export type WalletExecutionDetectionSource = "safe-context" | "safe-connector" | "safe-origin" | "owners-probe" | "none";
2
+ export type WalletExecutionHost = "safe" | "browser";
3
+ export type WalletExecutionType = "safe-multisig" | "eoa" | "unknown";
4
+ export type WalletExecution = {
5
+ readonly detectionSource: WalletExecutionDetectionSource;
6
+ readonly host: WalletExecutionHost;
7
+ readonly isSafeMultisig: boolean;
8
+ readonly walletType: WalletExecutionType;
9
+ };
10
+ export type WalletExecutionOptions = {
11
+ readonly enableOwnersProbe?: boolean;
12
+ };
13
+ export declare function useWalletExecution(options?: WalletExecutionOptions): WalletExecution;
14
+ //# sourceMappingURL=use-wallet-execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-wallet-execution.d.ts","sourceRoot":"","sources":["../../src/react-hooks/use-wallet-execution.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,8BAA8B,GACtC,cAAc,GACd,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,MAAM,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,SAAS,CAAC;AAErD,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG,KAAK,GAAG,SAAS,CAAC;AAEtE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,eAAe,EAAE,8BAA8B,CAAC;IACzD,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC,CAAC;AAKF,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,CAyGxF"}
@@ -0,0 +1,110 @@
1
+ "use client";
2
+ import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
3
+ import { useAccount, usePublicClient } from "wagmi";
4
+ import { isHostEmbedded, isValidSafeAppOrigin, subscribeSafeAppOrigins, } from "./safe-app-origins.js";
5
+ import { useIsSafeAppContext } from "./use-is-safe-app-context.js";
6
+ const safeOwnersAbi = [
7
+ {
8
+ inputs: [],
9
+ name: "getOwners",
10
+ outputs: [{ name: "", type: "address[]" }],
11
+ stateMutability: "view",
12
+ type: "function",
13
+ },
14
+ ];
15
+ export function useWalletExecution(options = {}) {
16
+ const { address, connector, isConnected } = useAccount();
17
+ const publicClient = usePublicClient();
18
+ const isSafeContext = useIsSafeAppContext();
19
+ const isSafeOrigin = useSyncExternalStore(subscribeSafeAppOrigins, getSafeHostSnapshot, getServerSnapshot);
20
+ const enableOwnersProbe = options.enableOwnersProbe ?? true;
21
+ const [ownersProbeDetectedSafe, setOwnersProbeDetectedSafe] = useState(false);
22
+ const isSafeConnector = isConnected && connector?.id === "safe";
23
+ useEffect(() => {
24
+ if (!enableOwnersProbe ||
25
+ !address ||
26
+ !isConnected ||
27
+ !publicClient ||
28
+ isSafeContext ||
29
+ isSafeConnector ||
30
+ isSafeOrigin) {
31
+ setOwnersProbeDetectedSafe(false);
32
+ return;
33
+ }
34
+ let cancelled = false;
35
+ void publicClient
36
+ .readContract({
37
+ abi: safeOwnersAbi,
38
+ address,
39
+ functionName: "getOwners",
40
+ })
41
+ .then((owners) => {
42
+ if (!cancelled) {
43
+ setOwnersProbeDetectedSafe(Array.isArray(owners) && owners.length > 0);
44
+ }
45
+ })
46
+ .catch(() => {
47
+ if (!cancelled) {
48
+ setOwnersProbeDetectedSafe(false);
49
+ }
50
+ });
51
+ return () => {
52
+ cancelled = true;
53
+ };
54
+ }, [
55
+ address,
56
+ enableOwnersProbe,
57
+ isConnected,
58
+ isSafeConnector,
59
+ isSafeContext,
60
+ isSafeOrigin,
61
+ publicClient,
62
+ ]);
63
+ return useMemo(() => {
64
+ if (isSafeContext) {
65
+ return {
66
+ detectionSource: "safe-context",
67
+ host: "safe",
68
+ isSafeMultisig: true,
69
+ walletType: "safe-multisig",
70
+ };
71
+ }
72
+ if (isSafeConnector) {
73
+ return {
74
+ detectionSource: "safe-connector",
75
+ host: "safe",
76
+ isSafeMultisig: true,
77
+ walletType: "safe-multisig",
78
+ };
79
+ }
80
+ if (isSafeOrigin) {
81
+ return {
82
+ detectionSource: "safe-origin",
83
+ host: "safe",
84
+ isSafeMultisig: true,
85
+ walletType: "safe-multisig",
86
+ };
87
+ }
88
+ if (ownersProbeDetectedSafe) {
89
+ return {
90
+ detectionSource: "owners-probe",
91
+ host: "browser",
92
+ isSafeMultisig: true,
93
+ walletType: "safe-multisig",
94
+ };
95
+ }
96
+ return {
97
+ detectionSource: "none",
98
+ host: "browser",
99
+ isSafeMultisig: false,
100
+ walletType: isConnected ? "eoa" : "unknown",
101
+ };
102
+ }, [isConnected, isSafeConnector, isSafeContext, isSafeOrigin, ownersProbeDetectedSafe]);
103
+ }
104
+ function getSafeHostSnapshot() {
105
+ return isHostEmbedded() && isValidSafeAppOrigin();
106
+ }
107
+ function getServerSnapshot() {
108
+ return false;
109
+ }
110
+ //# sourceMappingURL=use-wallet-execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-wallet-execution.js","sourceRoot":"","sources":["../../src/react-hooks/use-wallet-execution.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState, useSyncExternalStore } from \"react\";\nimport type { PublicClient } from \"viem\";\nimport { useAccount, usePublicClient } 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\nconst safeOwnersAbi = [\n {\n inputs: [],\n name: \"getOwners\",\n outputs: [{ name: \"\", type: \"address[]\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const;\n\nexport type WalletExecutionDetectionSource =\n | \"safe-context\"\n | \"safe-connector\"\n | \"safe-origin\"\n | \"owners-probe\"\n | \"none\";\n\nexport type WalletExecutionHost = \"safe\" | \"browser\";\n\nexport type WalletExecutionType = \"safe-multisig\" | \"eoa\" | \"unknown\";\n\nexport type WalletExecution = {\n readonly detectionSource: WalletExecutionDetectionSource;\n readonly host: WalletExecutionHost;\n readonly isSafeMultisig: boolean;\n readonly walletType: WalletExecutionType;\n};\n\nexport type WalletExecutionOptions = {\n readonly enableOwnersProbe?: boolean;\n};\n\n/**\n * Unified wallet execution detection for Safe vs EOA routing.\n */\nexport function useWalletExecution(options: WalletExecutionOptions = {}): WalletExecution {\n const { address, connector, isConnected } = useAccount();\n const publicClient = usePublicClient() as PublicClient | undefined;\n const isSafeContext = useIsSafeAppContext();\n const isSafeOrigin = useSyncExternalStore(\n subscribeSafeAppOrigins,\n getSafeHostSnapshot,\n getServerSnapshot\n );\n\n const enableOwnersProbe = options.enableOwnersProbe ?? true;\n const [ownersProbeDetectedSafe, setOwnersProbeDetectedSafe] = useState(false);\n\n const isSafeConnector = isConnected && connector?.id === \"safe\";\n\n useEffect(() => {\n if (\n !enableOwnersProbe ||\n !address ||\n !isConnected ||\n !publicClient ||\n isSafeContext ||\n isSafeConnector ||\n isSafeOrigin\n ) {\n setOwnersProbeDetectedSafe(false);\n return;\n }\n\n let cancelled = false;\n\n void publicClient\n .readContract({\n abi: safeOwnersAbi,\n address,\n functionName: \"getOwners\",\n })\n .then((owners) => {\n if (!cancelled) {\n setOwnersProbeDetectedSafe(Array.isArray(owners) && owners.length > 0);\n }\n })\n .catch(() => {\n if (!cancelled) {\n setOwnersProbeDetectedSafe(false);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [\n address,\n enableOwnersProbe,\n isConnected,\n isSafeConnector,\n isSafeContext,\n isSafeOrigin,\n publicClient,\n ]);\n\n return useMemo(() => {\n if (isSafeContext) {\n return {\n detectionSource: \"safe-context\",\n host: \"safe\",\n isSafeMultisig: true,\n walletType: \"safe-multisig\",\n } satisfies WalletExecution;\n }\n\n if (isSafeConnector) {\n return {\n detectionSource: \"safe-connector\",\n host: \"safe\",\n isSafeMultisig: true,\n walletType: \"safe-multisig\",\n } satisfies WalletExecution;\n }\n\n if (isSafeOrigin) {\n return {\n detectionSource: \"safe-origin\",\n host: \"safe\",\n isSafeMultisig: true,\n walletType: \"safe-multisig\",\n } satisfies WalletExecution;\n }\n\n if (ownersProbeDetectedSafe) {\n return {\n detectionSource: \"owners-probe\",\n host: \"browser\",\n isSafeMultisig: true,\n walletType: \"safe-multisig\",\n } satisfies WalletExecution;\n }\n\n return {\n detectionSource: \"none\",\n host: \"browser\",\n isSafeMultisig: false,\n walletType: isConnected ? \"eoa\" : \"unknown\",\n } satisfies WalletExecution;\n }, [isConnected, isSafeConnector, isSafeContext, isSafeOrigin, ownersProbeDetectedSafe]);\n}\n\nfunction getSafeHostSnapshot(): boolean {\n return isHostEmbedded() && isValidSafeAppOrigin();\n}\n\nfunction getServerSnapshot(): boolean {\n return false;\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { Effect } from "effect";
2
- import type { Address } from "viem";
2
+ import type { Address, Hash } from "viem";
3
+ import { SafeMultiSendUnavailableError } from "./errors.js";
3
4
  import type { SafeMultisigTx } from "./types.js";
4
5
  export type SafeMultisigAllowAndWriteParams = {
5
6
  readonly mainTransaction: SafeMultisigTx;
@@ -9,6 +10,15 @@ export type SafeMultisigAllowAndWriteParams = {
9
10
  readonly chainId: number;
10
11
  };
11
12
  readonly amount: bigint;
13
+ readonly multiSendStrategy?: "require" | "fallback-required-approval";
14
+ };
15
+ export type SafeMultisigAllowAndWriteResult = {
16
+ readonly _tag: "batched";
17
+ readonly safeTxHash: Hash;
18
+ } | {
19
+ readonly _tag: "fallback-required-approval";
20
+ readonly approveSafeTxHash: Hash;
21
+ readonly mainSafeTxHash: Hash;
12
22
  };
13
23
  export type SafeMultisigApproveTxParams = {
14
24
  readonly amount: bigint;
@@ -16,5 +26,15 @@ export type SafeMultisigApproveTxParams = {
16
26
  readonly tokenAddress: Address;
17
27
  };
18
28
  export declare function buildSafeApproveTx(params: SafeMultisigApproveTxParams): SafeMultisigTx;
19
- export declare const safeMultisigAllowAndWrite: (params: SafeMultisigAllowAndWriteParams) => Effect.Effect<`0x${string}`, import("./errors.js").SafeMultisigTxSubmissionError | import("./errors.js").SafeMultiSendUnavailableError, import("./service.js").SafeAppsService>;
29
+ export declare const safeMultisigAllowAndWrite: (params: SafeMultisigAllowAndWriteParams) => Effect.Effect<{
30
+ _tag: "batched";
31
+ safeTxHash: `0x${string}`;
32
+ approveSafeTxHash?: undefined;
33
+ mainSafeTxHash?: undefined;
34
+ } | {
35
+ _tag: "fallback-required-approval";
36
+ approveSafeTxHash: `0x${string}`;
37
+ mainSafeTxHash: `0x${string}`;
38
+ safeTxHash?: undefined;
39
+ }, import("./errors.js").SafeMultisigTxSubmissionError | SafeMultiSendUnavailableError, import("./service.js").SafeAppsService>;
20
40
  //# sourceMappingURL=allowance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"allowance.d.ts","sourceRoot":"","sources":["../../src/safe/allowance.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAOjD,MAAM,MAAM,+BAA+B,GAAG;IAE5C,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC;IAEzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAGF,MAAM,MAAM,2BAA2B,GAAG;IAExC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC,CAAC;AASF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,2BAA2B,GAAG,cAAc,CAUtF;AAgBD,eAAO,MAAM,yBAAyB,8NAapC,CAAC"}
1
+ {"version":3,"file":"allowance.d.ts","sourceRoot":"","sources":["../../src/safe/allowance.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAOjD,MAAM,MAAM,+BAA+B,GAAG;IAE5C,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC;IAEzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAMxB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,4BAA4B,CAAC;CACvE,CAAC;AAEF,MAAM,MAAM,+BAA+B,GACvC;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC;CAC/B,CAAC;AAGN,MAAM,MAAM,2BAA2B,GAAG;IAExC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC,CAAC;AASF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,2BAA2B,GAAG,cAAc,CAUtF;AAgBD,eAAO,MAAM,yBAAyB;;;;;;;;;;+HAuCpC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { Effect } from "effect";
2
2
  import { encodeFunctionData, erc20Abi } from "viem";
3
3
  import { safeMultisigBatchWrite } from "./batch.js";
4
+ import { SafeMultiSendUnavailableError } from "./errors.js";
4
5
  export function buildSafeApproveTx(params) {
5
6
  const { amount, spender, tokenAddress } = params;
6
7
  const data = encodeFunctionData({
@@ -12,11 +13,29 @@ export function buildSafeApproveTx(params) {
12
13
  }
13
14
  export const safeMultisigAllowAndWrite = Effect.fn("safeMultisigAllowAndWrite")(function* (params) {
14
15
  const { amount, mainTransaction, spender, token } = params;
16
+ const strategy = params.multiSendStrategy ?? "require";
15
17
  const approveTx = buildSafeApproveTx({
16
18
  amount,
17
19
  spender,
18
20
  tokenAddress: token.address,
19
21
  });
20
- return yield* safeMultisigBatchWrite([approveTx, mainTransaction], token.chainId);
22
+ const batched = yield* safeMultisigBatchWrite([approveTx, mainTransaction], token.chainId).pipe(Effect.either);
23
+ if (batched._tag === "Right") {
24
+ return {
25
+ _tag: "batched",
26
+ safeTxHash: batched.right,
27
+ };
28
+ }
29
+ const error = batched.left;
30
+ if (!(error instanceof SafeMultiSendUnavailableError) || strategy === "require") {
31
+ return yield* Effect.fail(error);
32
+ }
33
+ const approveSafeTxHash = yield* safeMultisigBatchWrite([approveTx], token.chainId);
34
+ const mainSafeTxHash = yield* safeMultisigBatchWrite([mainTransaction], token.chainId);
35
+ return {
36
+ _tag: "fallback-required-approval",
37
+ approveSafeTxHash,
38
+ mainSafeTxHash,
39
+ };
21
40
  });
22
41
  //# sourceMappingURL=allowance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"allowance.js","sourceRoot":"","sources":["../../src/safe/allowance.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAuCpD,MAAM,UAAU,kBAAkB,CAAC,MAAmC;IACpE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEjD,MAAM,IAAI,GAAG,kBAAkB,CAAC;QAC9B,GAAG,EAAE,QAAQ;QACb,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,SAAS;KACxB,CAAC,CAAC;IAEH,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AAC/C,CAAC;AAgBD,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,QAAQ,CAAC,EACvF,MAAuC;IAEvC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAE3D,MAAM,SAAS,GAAG,kBAAkB,CAAC;QACnC,MAAM;QACN,OAAO;QACP,YAAY,EAAE,KAAK,CAAC,OAAO;KAC5B,CAAC,CAAC;IAGH,OAAO,KAAK,CAAC,CAAC,sBAAsB,CAAC,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;AACpF,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Safe multisig allowance batching.\n *\n * Prepends an ERC-20 approve() tx to a main tx and submits both as a\n * single atomic Safe batch. Every dApp doing token operations through\n * Safe needs this \"approve + action\" pattern.\n *\n * @module safe/allowance\n */\n\nimport { Effect } from \"effect\";\nimport type { Address } from \"viem\";\nimport { encodeFunctionData, erc20Abi } from \"viem\";\nimport { safeMultisigBatchWrite } from \"./batch.js\";\nimport type { SafeMultisigTx } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Parameters for Safe multisig allowance batching. */\nexport type SafeMultisigAllowAndWriteParams = {\n /** Main transaction to execute after approval. */\n readonly mainTransaction: SafeMultisigTx;\n /** Spender contract that needs the allowance. */\n readonly spender: Address;\n /** Token to approve. */\n readonly token: {\n readonly address: Address;\n readonly chainId: number;\n };\n /** Approval amount (e.g. MaxUint256 or a computed amount). */\n readonly amount: bigint;\n};\n\n/** Parameters for building a standalone ERC-20 approve tx. */\nexport type SafeMultisigApproveTxParams = {\n /** Approval amount. */\n readonly amount: bigint;\n /** Spender contract that needs the allowance. */\n readonly spender: Address;\n /** Token contract address. */\n readonly tokenAddress: Address;\n};\n\n// ---------------------------------------------------------------------------\n// buildSafeApproveTx\n// ---------------------------------------------------------------------------\n\n/**\n * Encode an ERC-20 `approve(spender, amount)` call as a Safe transaction.\n */\nexport function buildSafeApproveTx(params: SafeMultisigApproveTxParams): SafeMultisigTx {\n const { amount, spender, tokenAddress } = params;\n\n const data = encodeFunctionData({\n abi: erc20Abi,\n args: [spender, amount],\n functionName: \"approve\",\n });\n\n return { data, to: tokenAddress, value: 0n };\n}\n\n// ---------------------------------------------------------------------------\n// safeMultisigAllowAndWrite\n// ---------------------------------------------------------------------------\n\n/**\n * Batch an ERC-20 approve tx with a main tx as a single Safe proposal.\n *\n * Approve is placed first so the allowance is set before the main contract\n * interaction. Both execute atomically — Safe users sign once.\n *\n * On chains where MultiSend is not deployed, fails with\n * `SafeMultiSendUnavailableError`. Callers should catch that tag and fall\n * back to sequential approve → action flow.\n */\nexport const safeMultisigAllowAndWrite = Effect.fn(\"safeMultisigAllowAndWrite\")(function* (\n params: SafeMultisigAllowAndWriteParams\n) {\n const { amount, mainTransaction, spender, token } = params;\n\n const approveTx = buildSafeApproveTx({\n amount,\n spender,\n tokenAddress: token.address,\n });\n\n // Approve first, then main transaction\n return yield* safeMultisigBatchWrite([approveTx, mainTransaction], token.chainId);\n});\n"]}
1
+ {"version":3,"file":"allowance.js","sourceRoot":"","sources":["../../src/safe/allowance.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAwD5D,MAAM,UAAU,kBAAkB,CAAC,MAAmC;IACpE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEjD,MAAM,IAAI,GAAG,kBAAkB,CAAC;QAC9B,GAAG,EAAE,QAAQ;QACb,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,SAAS;KACxB,CAAC,CAAC;IAEH,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AAC/C,CAAC;AAgBD,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,QAAQ,CAAC,EACvF,MAAuC;IAEvC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,IAAI,SAAS,CAAC;IAEvD,MAAM,SAAS,GAAG,kBAAkB,CAAC;QACnC,MAAM;QACN,OAAO;QACP,YAAY,EAAE,KAAK,CAAC,OAAO;KAC5B,CAAC,CAAC;IAGH,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,sBAAsB,CAAC,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAC7F,MAAM,CAAC,MAAM,CACd,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO;YACL,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,OAAO,CAAC,KAAK;SACgB,CAAC;IAC9C,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAE3B,IAAI,CAAC,CAAC,KAAK,YAAY,6BAA6B,CAAC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAChF,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAGD,MAAM,iBAAiB,GAAG,KAAK,CAAC,CAAC,sBAAsB,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACpF,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,sBAAsB,CAAC,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAEvF,OAAO;QACL,IAAI,EAAE,4BAA4B;QAClC,iBAAiB;QACjB,cAAc;KAC2B,CAAC;AAC9C,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Safe multisig allowance batching.\n *\n * Prepends an ERC-20 approve() tx to a main tx and submits both as a\n * single atomic Safe batch. Every dApp doing token operations through\n * Safe needs this \"approve + action\" pattern.\n *\n * @module safe/allowance\n */\n\nimport { Effect } from \"effect\";\nimport type { Address, Hash } from \"viem\";\nimport { encodeFunctionData, erc20Abi } from \"viem\";\nimport { safeMultisigBatchWrite } from \"./batch.js\";\nimport { SafeMultiSendUnavailableError } from \"./errors.js\";\nimport type { SafeMultisigTx } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Parameters for Safe multisig allowance batching. */\nexport type SafeMultisigAllowAndWriteParams = {\n /** Main transaction to execute after approval. */\n readonly mainTransaction: SafeMultisigTx;\n /** Spender contract that needs the allowance. */\n readonly spender: Address;\n /** Token to approve. */\n readonly token: {\n readonly address: Address;\n readonly chainId: number;\n };\n /** Approval amount (e.g. MaxUint256 or a computed amount). */\n readonly amount: bigint;\n /**\n * MultiSend behavior:\n * - \"require\": fail if MultiSend is unavailable\n * - \"fallback-required-approval\": submit separate Safe proposals for approve and main tx\n */\n readonly multiSendStrategy?: \"require\" | \"fallback-required-approval\";\n};\n\nexport type SafeMultisigAllowAndWriteResult =\n | {\n readonly _tag: \"batched\";\n readonly safeTxHash: Hash;\n }\n | {\n readonly _tag: \"fallback-required-approval\";\n readonly approveSafeTxHash: Hash;\n readonly mainSafeTxHash: Hash;\n };\n\n/** Parameters for building a standalone ERC-20 approve tx. */\nexport type SafeMultisigApproveTxParams = {\n /** Approval amount. */\n readonly amount: bigint;\n /** Spender contract that needs the allowance. */\n readonly spender: Address;\n /** Token contract address. */\n readonly tokenAddress: Address;\n};\n\n// ---------------------------------------------------------------------------\n// buildSafeApproveTx\n// ---------------------------------------------------------------------------\n\n/**\n * Encode an ERC-20 `approve(spender, amount)` call as a Safe transaction.\n */\nexport function buildSafeApproveTx(params: SafeMultisigApproveTxParams): SafeMultisigTx {\n const { amount, spender, tokenAddress } = params;\n\n const data = encodeFunctionData({\n abi: erc20Abi,\n args: [spender, amount],\n functionName: \"approve\",\n });\n\n return { data, to: tokenAddress, value: 0n };\n}\n\n// ---------------------------------------------------------------------------\n// safeMultisigAllowAndWrite\n// ---------------------------------------------------------------------------\n\n/**\n * Batch an ERC-20 approve tx with a main tx as a single Safe proposal.\n *\n * Approve is placed first so the allowance is set before the main contract\n * interaction. Both execute atomically — Safe users sign once.\n *\n * On chains where MultiSend is not deployed, fails with\n * `SafeMultiSendUnavailableError`. Callers should catch that tag and fall\n * back to sequential approve → action flow.\n */\nexport const safeMultisigAllowAndWrite = Effect.fn(\"safeMultisigAllowAndWrite\")(function* (\n params: SafeMultisigAllowAndWriteParams\n) {\n const { amount, mainTransaction, spender, token } = params;\n const strategy = params.multiSendStrategy ?? \"require\";\n\n const approveTx = buildSafeApproveTx({\n amount,\n spender,\n tokenAddress: token.address,\n });\n\n // Approve first, then main transaction\n const batched = yield* safeMultisigBatchWrite([approveTx, mainTransaction], token.chainId).pipe(\n Effect.either\n );\n\n if (batched._tag === \"Right\") {\n return {\n _tag: \"batched\",\n safeTxHash: batched.right,\n } satisfies SafeMultisigAllowAndWriteResult;\n }\n\n const error = batched.left;\n\n if (!(error instanceof SafeMultiSendUnavailableError) || strategy === \"require\") {\n return yield* Effect.fail(error);\n }\n\n // Fallback for chains without MultiSend: submit two standalone Safe tx proposals.\n const approveSafeTxHash = yield* safeMultisigBatchWrite([approveTx], token.chainId);\n const mainSafeTxHash = yield* safeMultisigBatchWrite([mainTransaction], token.chainId);\n\n return {\n _tag: \"fallback-required-approval\",\n approveSafeTxHash,\n mainSafeTxHash,\n } satisfies SafeMultisigAllowAndWriteResult;\n});\n"]}
@@ -1,4 +1,5 @@
1
1
  import { Schema } from "effect";
2
+ import type { Hash, Hex } from "viem";
2
3
  declare const SafeAppsSdkUnavailableError_base: Schema.TaggedErrorClass<SafeAppsSdkUnavailableError, "SafeAppsSdkUnavailableError", {
3
4
  readonly _tag: Schema.tag<"SafeAppsSdkUnavailableError">;
4
5
  } & {
@@ -85,6 +86,7 @@ declare const SafeMultiSendUnavailableError_base: Schema.TaggedErrorClass<SafeMu
85
86
  export declare class SafeMultiSendUnavailableError extends SafeMultiSendUnavailableError_base {
86
87
  }
87
88
  export declare function getSafeErrorMessage(error: unknown): string | undefined;
89
+ export declare function toSafeMultisigTxLookupError(safeTxHash: Hash | Hex, cause: unknown, retryable?: boolean): SafeMultisigTxLookupError;
88
90
  export declare function isMultiSendUnavailableError(error: unknown): boolean;
89
91
  export {};
90
92
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/safe/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;;;;;;;AAGhC,qBAAa,2BAA4B,SAAQ,gCAGhD;CAAG;;;;;;AAEJ,qBAAa,wBAAyB,SAAQ,6BAG7C;CAAG;;;;;;;AAGJ,qBAAa,gCAAiC,SAAQ,qCAGrD;CAAG;;;;;;;AAEJ,qBAAa,yBAA0B,SAAQ,8BAG9C;CAAG;;;;;;;AAEJ,qBAAa,6BAA8B,SAAQ,kCAGlD;CAAG;;;;;;;;;AAEJ,qBAAa,yBAA0B,SAAQ,8BAQ9C;CAAG;;;;;;;;;AAEJ,qBAAa,mCAAoC,SAAQ,wCAQxD;CAAG;;;;;;;AAGJ,qBAAa,kBAAmB,SAAQ,uBAGvC;CAAG;;;;;;;;AAEJ,qBAAa,6BAA8B,SAAQ,kCAOlD;CAAG;;;;;;;;AAIJ,qBAAa,6BAA8B,SAAQ,kCAOlD;CAAG;AA0GJ,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAEtE;AAMD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEnE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/safe/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;;;;;;;AAGtC,qBAAa,2BAA4B,SAAQ,gCAGhD;CAAG;;;;;;AAEJ,qBAAa,wBAAyB,SAAQ,6BAG7C;CAAG;;;;;;;AAGJ,qBAAa,gCAAiC,SAAQ,qCAGrD;CAAG;;;;;;;AAEJ,qBAAa,yBAA0B,SAAQ,8BAG9C;CAAG;;;;;;;AAEJ,qBAAa,6BAA8B,SAAQ,kCAGlD;CAAG;;;;;;;;;AAEJ,qBAAa,yBAA0B,SAAQ,8BAQ9C;CAAG;;;;;;;;;AAEJ,qBAAa,mCAAoC,SAAQ,wCAQxD;CAAG;;;;;;;AAGJ,qBAAa,kBAAmB,SAAQ,uBAGvC;CAAG;;;;;;;;AAEJ,qBAAa,6BAA8B,SAAQ,kCAOlD;CAAG;;;;;;;;AAIJ,qBAAa,6BAA8B,SAAQ,kCAOlD;CAAG;AA0GJ,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAEtE;AAKD,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,IAAI,GAAG,GAAG,EACtB,KAAK,EAAE,OAAO,EACd,SAAS,UAAO,GACf,yBAAyB,CAU3B;AAMD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEnE"}
@@ -109,6 +109,17 @@ function getSafeErrorMessageInternal(error, depth) {
109
109
  export function getSafeErrorMessage(error) {
110
110
  return getSafeErrorMessageInternal(error, 0);
111
111
  }
112
+ export function toSafeMultisigTxLookupError(safeTxHash, cause, retryable = true) {
113
+ const detail = getSafeErrorMessage(cause);
114
+ return new SafeMultisigTxLookupError({
115
+ cause,
116
+ message: detail
117
+ ? `Failed to lookup Safe tx ${safeTxHash}: ${detail}`
118
+ : `Failed to lookup Safe tx ${safeTxHash}`,
119
+ retryable,
120
+ safeTxHash,
121
+ });
122
+ }
112
123
  export function isMultiSendUnavailableError(error) {
113
124
  return checkMultiSendError(error, 0);
114
125
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/safe/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import { Schema } from \"effect\";\n\n// SDK availability errors\nexport class SafeAppsSdkUnavailableError extends Schema.TaggedError<SafeAppsSdkUnavailableError>()(\n \"SafeAppsSdkUnavailableError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class NotInSafeAppContextError extends Schema.TaggedError<NotInSafeAppContextError>()(\n \"NotInSafeAppContextError\",\n { message: Schema.String }\n) {}\n\n// Safe operation errors\nexport class SafeMultisigInfoUnavailableError extends Schema.TaggedError<SafeMultisigInfoUnavailableError>()(\n \"SafeMultisigInfoUnavailableError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class SafeMultisigSettingsError extends Schema.TaggedError<SafeMultisigSettingsError>()(\n \"SafeMultisigSettingsError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class SafeMultisigTxSubmissionError extends Schema.TaggedError<SafeMultisigTxSubmissionError>()(\n \"SafeMultisigTxSubmissionError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class SafeMultisigTxLookupError extends Schema.TaggedError<SafeMultisigTxLookupError>()(\n \"SafeMultisigTxLookupError\",\n {\n cause: Schema.optional(Schema.Unknown),\n message: Schema.String,\n retryable: Schema.Boolean,\n safeTxHash: Schema.String,\n }\n) {}\n\nexport class SafeMultisigTxExecutionTimeoutError extends Schema.TaggedError<SafeMultisigTxExecutionTimeoutError>()(\n \"SafeMultisigTxExecutionTimeoutError\",\n {\n lastStatus: Schema.optional(Schema.String),\n message: Schema.String,\n safeTxHash: Schema.String,\n timeout: Schema.Number,\n }\n) {}\n\n// Signing errors\nexport class SignTypedDataError extends Schema.TaggedError<SignTypedDataError>()(\n \"SignTypedDataError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class OffchainSignatureTimeoutError extends Schema.TaggedError<OffchainSignatureTimeoutError>()(\n \"OffchainSignatureTimeoutError\",\n {\n message: Schema.String,\n messageHash: Schema.String,\n timeout: Schema.Number,\n }\n) {}\n\n// MultiSend errors\n\nexport class SafeMultiSendUnavailableError extends Schema.TaggedError<SafeMultiSendUnavailableError>()(\n \"SafeMultiSendUnavailableError\",\n {\n cause: Schema.optional(Schema.Unknown),\n chainId: Schema.optional(Schema.Number),\n message: Schema.String,\n }\n) {}\n\n// MultiSend error detection\n\nconst MULTISEND_ERROR_PATTERN = /MultiSend contract not deployed|MultiSend call failed/i;\nconst MAX_ERROR_DEPTH = 10;\nconst USER_REJECTION_CODE = 4001;\nconst MAX_ERROR_MESSAGE_DEPTH = 10;\n\ntype ErrorMessageShape = {\n readonly cause?: unknown;\n readonly code?: unknown;\n readonly error?: unknown;\n readonly errors?: unknown;\n readonly message?: unknown;\n readonly shortMessage?: unknown;\n};\n\nfunction toNonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction isUserRejectionCode(code: unknown): boolean {\n return code === USER_REJECTION_CODE || code === `${USER_REJECTION_CODE}`;\n}\n\nfunction getSafeErrorMessageInternal(error: unknown, depth: number): string | undefined {\n if (!error || depth >= MAX_ERROR_MESSAGE_DEPTH) {\n return undefined;\n }\n\n if (typeof error === \"string\") {\n return toNonEmptyString(error);\n }\n\n if (error instanceof Error) {\n if (isUserRejectionCode((error as { code?: unknown }).code)) {\n return \"User rejected the request\";\n }\n\n const shortMessage = toNonEmptyString((error as { shortMessage?: unknown }).shortMessage);\n if (shortMessage) {\n return shortMessage;\n }\n\n const message = toNonEmptyString(error.message);\n if (message) {\n return message;\n }\n\n return getSafeErrorMessageInternal((error as { cause?: unknown }).cause, depth + 1);\n }\n\n if (typeof error !== \"object\") {\n return undefined;\n }\n\n const typedError = error as ErrorMessageShape;\n\n if (isUserRejectionCode(typedError.code)) {\n return \"User rejected the request\";\n }\n\n const shortMessage = toNonEmptyString(typedError.shortMessage);\n if (shortMessage) {\n return shortMessage;\n }\n\n const message = toNonEmptyString(typedError.message);\n if (message) {\n return message;\n }\n\n const causeMessage = getSafeErrorMessageInternal(typedError.cause, depth + 1);\n if (causeMessage) {\n return causeMessage;\n }\n\n const nestedErrorMessage = getSafeErrorMessageInternal(typedError.error, depth + 1);\n if (nestedErrorMessage) {\n return nestedErrorMessage;\n }\n\n if (!Array.isArray(typedError.errors)) {\n return undefined;\n }\n\n for (const nestedError of typedError.errors) {\n const nestedMessage = getSafeErrorMessageInternal(nestedError, depth + 1);\n if (nestedMessage) {\n return nestedMessage;\n }\n }\n\n return undefined;\n}\n\n/**\n * Best-effort extraction of a human-readable Safe SDK error message.\n * Preserves nested `cause` / `error` chains and handles EIP-1193 user rejection codes.\n */\nexport function getSafeErrorMessage(error: unknown): string | undefined {\n return getSafeErrorMessageInternal(error, 0);\n}\n\n/**\n * Check if an error is caused by MultiSend contract unavailability.\n * Recursively checks error messages and causes for MultiSend-related strings.\n */\nexport function isMultiSendUnavailableError(error: unknown): boolean {\n return checkMultiSendError(error, 0);\n}\n\nfunction checkMultiSendError(error: unknown, depth: number): boolean {\n if (depth >= MAX_ERROR_DEPTH) {\n return false;\n }\n\n if (typeof error === \"string\") {\n return MULTISEND_ERROR_PATTERN.test(error);\n }\n\n if (typeof error === \"object\" && error !== null) {\n const { message, cause } = error as { message?: unknown; cause?: unknown };\n\n if (typeof message === \"string\" && MULTISEND_ERROR_PATTERN.test(message)) {\n return true;\n }\n\n if (cause) {\n return checkMultiSendError(cause, depth + 1);\n }\n }\n\n return false;\n}\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/safe/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import { Schema } from \"effect\";\nimport type { Hash, Hex } from \"viem\";\n\n// SDK availability errors\nexport class SafeAppsSdkUnavailableError extends Schema.TaggedError<SafeAppsSdkUnavailableError>()(\n \"SafeAppsSdkUnavailableError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class NotInSafeAppContextError extends Schema.TaggedError<NotInSafeAppContextError>()(\n \"NotInSafeAppContextError\",\n { message: Schema.String }\n) {}\n\n// Safe operation errors\nexport class SafeMultisigInfoUnavailableError extends Schema.TaggedError<SafeMultisigInfoUnavailableError>()(\n \"SafeMultisigInfoUnavailableError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class SafeMultisigSettingsError extends Schema.TaggedError<SafeMultisigSettingsError>()(\n \"SafeMultisigSettingsError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class SafeMultisigTxSubmissionError extends Schema.TaggedError<SafeMultisigTxSubmissionError>()(\n \"SafeMultisigTxSubmissionError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class SafeMultisigTxLookupError extends Schema.TaggedError<SafeMultisigTxLookupError>()(\n \"SafeMultisigTxLookupError\",\n {\n cause: Schema.optional(Schema.Unknown),\n message: Schema.String,\n retryable: Schema.Boolean,\n safeTxHash: Schema.String,\n }\n) {}\n\nexport class SafeMultisigTxExecutionTimeoutError extends Schema.TaggedError<SafeMultisigTxExecutionTimeoutError>()(\n \"SafeMultisigTxExecutionTimeoutError\",\n {\n lastStatus: Schema.optional(Schema.String),\n message: Schema.String,\n safeTxHash: Schema.String,\n timeout: Schema.Number,\n }\n) {}\n\n// Signing errors\nexport class SignTypedDataError extends Schema.TaggedError<SignTypedDataError>()(\n \"SignTypedDataError\",\n { cause: Schema.optional(Schema.Unknown), message: Schema.String }\n) {}\n\nexport class OffchainSignatureTimeoutError extends Schema.TaggedError<OffchainSignatureTimeoutError>()(\n \"OffchainSignatureTimeoutError\",\n {\n message: Schema.String,\n messageHash: Schema.String,\n timeout: Schema.Number,\n }\n) {}\n\n// MultiSend errors\n\nexport class SafeMultiSendUnavailableError extends Schema.TaggedError<SafeMultiSendUnavailableError>()(\n \"SafeMultiSendUnavailableError\",\n {\n cause: Schema.optional(Schema.Unknown),\n chainId: Schema.optional(Schema.Number),\n message: Schema.String,\n }\n) {}\n\n// MultiSend error detection\n\nconst MULTISEND_ERROR_PATTERN = /MultiSend contract not deployed|MultiSend call failed/i;\nconst MAX_ERROR_DEPTH = 10;\nconst USER_REJECTION_CODE = 4001;\nconst MAX_ERROR_MESSAGE_DEPTH = 10;\n\ntype ErrorMessageShape = {\n readonly cause?: unknown;\n readonly code?: unknown;\n readonly error?: unknown;\n readonly errors?: unknown;\n readonly message?: unknown;\n readonly shortMessage?: unknown;\n};\n\nfunction toNonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const normalized = value.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction isUserRejectionCode(code: unknown): boolean {\n return code === USER_REJECTION_CODE || code === `${USER_REJECTION_CODE}`;\n}\n\nfunction getSafeErrorMessageInternal(error: unknown, depth: number): string | undefined {\n if (!error || depth >= MAX_ERROR_MESSAGE_DEPTH) {\n return undefined;\n }\n\n if (typeof error === \"string\") {\n return toNonEmptyString(error);\n }\n\n if (error instanceof Error) {\n if (isUserRejectionCode((error as { code?: unknown }).code)) {\n return \"User rejected the request\";\n }\n\n const shortMessage = toNonEmptyString((error as { shortMessage?: unknown }).shortMessage);\n if (shortMessage) {\n return shortMessage;\n }\n\n const message = toNonEmptyString(error.message);\n if (message) {\n return message;\n }\n\n return getSafeErrorMessageInternal((error as { cause?: unknown }).cause, depth + 1);\n }\n\n if (typeof error !== \"object\") {\n return undefined;\n }\n\n const typedError = error as ErrorMessageShape;\n\n if (isUserRejectionCode(typedError.code)) {\n return \"User rejected the request\";\n }\n\n const shortMessage = toNonEmptyString(typedError.shortMessage);\n if (shortMessage) {\n return shortMessage;\n }\n\n const message = toNonEmptyString(typedError.message);\n if (message) {\n return message;\n }\n\n const causeMessage = getSafeErrorMessageInternal(typedError.cause, depth + 1);\n if (causeMessage) {\n return causeMessage;\n }\n\n const nestedErrorMessage = getSafeErrorMessageInternal(typedError.error, depth + 1);\n if (nestedErrorMessage) {\n return nestedErrorMessage;\n }\n\n if (!Array.isArray(typedError.errors)) {\n return undefined;\n }\n\n for (const nestedError of typedError.errors) {\n const nestedMessage = getSafeErrorMessageInternal(nestedError, depth + 1);\n if (nestedMessage) {\n return nestedMessage;\n }\n }\n\n return undefined;\n}\n\n/**\n * Best-effort extraction of a human-readable Safe SDK error message.\n * Preserves nested `cause` / `error` chains and handles EIP-1193 user rejection codes.\n */\nexport function getSafeErrorMessage(error: unknown): string | undefined {\n return getSafeErrorMessageInternal(error, 0);\n}\n\n/**\n * Canonical constructor for Safe tx lookup errors.\n */\nexport function toSafeMultisigTxLookupError(\n safeTxHash: Hash | Hex,\n cause: unknown,\n retryable = true\n): SafeMultisigTxLookupError {\n const detail = getSafeErrorMessage(cause);\n return new SafeMultisigTxLookupError({\n cause,\n message: detail\n ? `Failed to lookup Safe tx ${safeTxHash}: ${detail}`\n : `Failed to lookup Safe tx ${safeTxHash}`,\n retryable,\n safeTxHash,\n });\n}\n\n/**\n * Check if an error is caused by MultiSend contract unavailability.\n * Recursively checks error messages and causes for MultiSend-related strings.\n */\nexport function isMultiSendUnavailableError(error: unknown): boolean {\n return checkMultiSendError(error, 0);\n}\n\nfunction checkMultiSendError(error: unknown, depth: number): boolean {\n if (depth >= MAX_ERROR_DEPTH) {\n return false;\n }\n\n if (typeof error === \"string\") {\n return MULTISEND_ERROR_PATTERN.test(error);\n }\n\n if (typeof error === \"object\" && error !== null) {\n const { message, cause } = error as { message?: unknown; cause?: unknown };\n\n if (typeof message === \"string\" && MULTISEND_ERROR_PATTERN.test(message)) {\n return true;\n }\n\n if (cause) {\n return checkMultiSendError(cause, depth + 1);\n }\n }\n\n return false;\n}\n"]}
@@ -1,12 +1,14 @@
1
- export { buildSafeApproveTx, type SafeMultisigAllowAndWriteParams, type SafeMultisigApproveTxParams, safeMultisigAllowAndWrite, } from "./allowance.js";
1
+ export { buildSafeApproveTx, type SafeMultisigAllowAndWriteParams, type SafeMultisigAllowAndWriteResult, type SafeMultisigApproveTxParams, safeMultisigAllowAndWrite, } from "./allowance.js";
2
2
  export { safeMultisigBatchWrite } from "./batch.js";
3
3
  export type { SafeDetectionParams, SafeDetectionResult } from "./detection.js";
4
4
  export { isSafeMultisig, SafeMultisigDetectionError } from "./detection.js";
5
- export { isMultiSendUnavailableError, NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeAppsSdkUnavailableError, SafeMultiSendUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, } from "./errors.js";
5
+ export { isMultiSendUnavailableError, NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeAppsSdkUnavailableError, SafeMultiSendUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, toSafeMultisigTxLookupError, } from "./errors.js";
6
6
  export { type SafeAppsServiceConfig, SafeAppsServiceLive } from "./live.js";
7
+ export { SafeWriteExecutionAdapterLive } from "./pipeline-adapter.js";
7
8
  export { SafeAppsService, type SafeAppsServiceShape } from "./service.js";
8
9
  export * from "./simulation/index.js";
9
10
  export { getSafeMultisigTxStatus, type SafeMultisigTxStatus, type SafeMultisigWaitOptions, type SafeMultisigWaitResult, waitForSafeMultisigTx, } from "./tx-lifecycle.js";
10
11
  export { type GetSafeMultisigTxUrlParams, getSafeMultisigTxUrl } from "./tx-url.js";
11
12
  export type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeMultisigInfo, SafeMultisigTx, SafeMultisigTxInfo, SafeMultisigTxResult, SafeMultisigTxSubmission, SafeWaitPolicy, SignTypedDataResult, } from "./types.js";
13
+ export { type SafeWriteAndTrackError, type SafeWriteAndTrackParams, type SafeWriteAndTrackResult, type SafeWriteAndTrackState, safeWriteAndTrack, } from "./write-and-track.js";
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,KAAK,+BAA+B,EACpC,KAAK,2BAA2B,EAChC,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,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,OAAO,EACL,uBAAuB,EACvB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,KAAK,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEpF,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,KAAK,+BAA+B,EACpC,KAAK,+BAA+B,EACpC,KAAK,2BAA2B,EAChC,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,KAAK,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE1E,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EACL,uBAAuB,EACvB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,KAAK,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEpF,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,iBAAiB,GAClB,MAAM,sBAAsB,CAAC"}
@@ -1,10 +1,12 @@
1
1
  export { buildSafeApproveTx, safeMultisigAllowAndWrite, } from "./allowance.js";
2
2
  export { safeMultisigBatchWrite } from "./batch.js";
3
3
  export { isSafeMultisig, SafeMultisigDetectionError } from "./detection.js";
4
- export { isMultiSendUnavailableError, NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeAppsSdkUnavailableError, SafeMultiSendUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, } from "./errors.js";
4
+ export { isMultiSendUnavailableError, NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeAppsSdkUnavailableError, SafeMultiSendUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, toSafeMultisigTxLookupError, } from "./errors.js";
5
5
  export { SafeAppsServiceLive } from "./live.js";
6
+ export { SafeWriteExecutionAdapterLive } from "./pipeline-adapter.js";
6
7
  export { SafeAppsService } from "./service.js";
7
8
  export * from "./simulation/index.js";
8
9
  export { getSafeMultisigTxStatus, waitForSafeMultisigTx, } from "./tx-lifecycle.js";
9
10
  export { getSafeMultisigTxUrl } from "./tx-url.js";
11
+ export { safeWriteAndTrack, } from "./write-and-track.js";
10
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAGlB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAA8B,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,eAAe,EAA6B,MAAM,cAAc,CAAC;AAE1E,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EACL,uBAAuB,EAIvB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAmC,oBAAoB,EAAE,MAAM,aAAa,CAAC","sourcesContent":["// Allowance batching (approve + action as one Safe proposal)\nexport {\n buildSafeApproveTx,\n type SafeMultisigAllowAndWriteParams,\n type SafeMultisigApproveTxParams,\n safeMultisigAllowAndWrite,\n} from \"./allowance.js\";\n// Batch write (atomic multi-call via MultiSend)\nexport { safeMultisigBatchWrite } from \"./batch.js\";\n// Detection\nexport type { SafeDetectionParams, SafeDetectionResult } from \"./detection.js\";\nexport { isSafeMultisig, SafeMultisigDetectionError } from \"./detection.js\";\n// Errors\nexport {\n isMultiSendUnavailableError,\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeAppsSdkUnavailableError,\n SafeMultiSendUnavailableError,\n SafeMultisigInfoUnavailableError,\n SafeMultisigSettingsError,\n SafeMultisigTxExecutionTimeoutError,\n SafeMultisigTxLookupError,\n SafeMultisigTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\n// Service and layer\nexport { type SafeAppsServiceConfig, SafeAppsServiceLive } from \"./live.js\";\nexport { SafeAppsService, type SafeAppsServiceShape } from \"./service.js\";\n// Simulation\nexport * from \"./simulation/index.js\";\n// Transaction lifecycle (polling, status checks)\nexport {\n getSafeMultisigTxStatus,\n type SafeMultisigTxStatus,\n type SafeMultisigWaitOptions,\n type SafeMultisigWaitResult,\n waitForSafeMultisigTx,\n} from \"./tx-lifecycle.js\";\n// Safe URL helpers\nexport { type GetSafeMultisigTxUrlParams, getSafeMultisigTxUrl } from \"./tx-url.js\";\n// Types\nexport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeMultisigInfo,\n SafeMultisigTx,\n SafeMultisigTxInfo,\n SafeMultisigTxResult,\n SafeMultisigTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAIlB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,EAClB,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AAErB,OAAO,EAA8B,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,eAAe,EAA6B,MAAM,cAAc,CAAC;AAE1E,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EACL,uBAAuB,EAIvB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAmC,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAcpF,OAAO,EAKL,iBAAiB,GAClB,MAAM,sBAAsB,CAAC","sourcesContent":["// Allowance batching (approve + action as one Safe proposal)\nexport {\n buildSafeApproveTx,\n type SafeMultisigAllowAndWriteParams,\n type SafeMultisigAllowAndWriteResult,\n type SafeMultisigApproveTxParams,\n safeMultisigAllowAndWrite,\n} from \"./allowance.js\";\n// Batch write (atomic multi-call via MultiSend)\nexport { safeMultisigBatchWrite } from \"./batch.js\";\n// Detection\nexport type { SafeDetectionParams, SafeDetectionResult } from \"./detection.js\";\nexport { isSafeMultisig, SafeMultisigDetectionError } from \"./detection.js\";\n// Errors\nexport {\n isMultiSendUnavailableError,\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeAppsSdkUnavailableError,\n SafeMultiSendUnavailableError,\n SafeMultisigInfoUnavailableError,\n SafeMultisigSettingsError,\n SafeMultisigTxExecutionTimeoutError,\n SafeMultisigTxLookupError,\n SafeMultisigTxSubmissionError,\n SignTypedDataError,\n toSafeMultisigTxLookupError,\n} from \"./errors.js\";\n// Service and layer\nexport { type SafeAppsServiceConfig, SafeAppsServiceLive } from \"./live.js\";\nexport { SafeWriteExecutionAdapterLive } from \"./pipeline-adapter.js\";\nexport { SafeAppsService, type SafeAppsServiceShape } from \"./service.js\";\n// Simulation\nexport * from \"./simulation/index.js\";\n// Transaction lifecycle (polling, status checks)\nexport {\n getSafeMultisigTxStatus,\n type SafeMultisigTxStatus,\n type SafeMultisigWaitOptions,\n type SafeMultisigWaitResult,\n waitForSafeMultisigTx,\n} from \"./tx-lifecycle.js\";\n// Safe URL helpers\nexport { type GetSafeMultisigTxUrlParams, getSafeMultisigTxUrl } from \"./tx-url.js\";\n// Types\nexport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeMultisigInfo,\n SafeMultisigTx,\n SafeMultisigTxInfo,\n SafeMultisigTxResult,\n SafeMultisigTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\nexport {\n type SafeWriteAndTrackError,\n type SafeWriteAndTrackParams,\n type SafeWriteAndTrackResult,\n type SafeWriteAndTrackState,\n safeWriteAndTrack,\n} from \"./write-and-track.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAU,KAAK,EAAe,MAAM,QAAQ,CAAC;AASpD,OAAO,KAAK,EAAuB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAe3E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AA4CtD,eAAO,MAAM,mBAAmB,GAAI,SAAS,qBAAqB,mDAqW/D,CAAC"}
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAU,KAAK,EAAe,MAAM,QAAQ,CAAC;AASpD,OAAO,KAAK,EAAuB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAgB3E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AA4CtD,eAAO,MAAM,mBAAmB,GAAI,SAAS,qBAAqB,mDA+T/D,CAAC"}
package/dist/safe/live.js CHANGED
@@ -3,7 +3,7 @@ import { Effect, Layer, Option, Ref } from "effect";
3
3
  import { isAddress, isHash, isHex } from "viem";
4
4
  import { SAFE_EXECUTION_TIMEOUT, SAFE_POLL_INTERVAL, SAFE_SIGNATURE_POLL_INTERVAL, SAFE_SIGNATURE_TIMEOUT, } from "#src/constants/index.js";
5
5
  import { loadSafeSdk } from "./adapter.js";
6
- import { getSafeErrorMessage, NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, } from "./errors.js";
6
+ import { getSafeErrorMessage, NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, toSafeMultisigTxLookupError, } from "./errors.js";
7
7
  import { pollUntil } from "./internal/poll.js";
8
8
  import { SafeAppsService } from "./service.js";
9
9
  const makeValidator = (predicate, label) => (value, context) => predicate(value)
@@ -87,19 +87,9 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
87
87
  });
88
88
  const getTx = Effect.fn("SafeAppsService.getTx")(function* (safeTxHash) {
89
89
  const tx = yield* withSdk(getSdk, (s) => Effect.tryPromise({
90
- catch: (cause) => new SafeMultisigTxLookupError({
91
- cause,
92
- message: `Failed to lookup Safe tx ${safeTxHash}`,
93
- retryable: true,
94
- safeTxHash,
95
- }),
90
+ catch: (cause) => toSafeMultisigTxLookupError(safeTxHash, cause, true),
96
91
  try: () => s.txs.getBySafeTxHash(safeTxHash),
97
- }), (e) => new SafeMultisigTxLookupError({
98
- cause: e,
99
- message: e.message,
100
- retryable: false,
101
- safeTxHash,
102
- }));
92
+ }), (e) => toSafeMultisigTxLookupError(safeTxHash, e, false));
103
93
  const txHash = tx.txHash ? yield* validateHash(tx.txHash, "getTx") : null;
104
94
  const executionInfo = tx.detailedExecutionInfo;
105
95
  const hasMultisigExecutionInfo = executionInfo !== undefined &&
@@ -115,12 +105,7 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
115
105
  };
116
106
  });
117
107
  const waitForTxReceipt = Effect.fn("SafeAppsService.waitForTxReceipt")(function* (safeTxHash, policy = {}) {
118
- const info = yield* getInfo().pipe(Effect.catchTag("SafeMultisigInfoUnavailableError", (error) => Effect.fail(new SafeMultisigTxLookupError({
119
- cause: error,
120
- message: "Failed to get Safe info for receipt waiting",
121
- retryable: true,
122
- safeTxHash,
123
- }))));
108
+ const info = yield* getInfo().pipe(Effect.catchTag("SafeMultisigInfoUnavailableError", (error) => Effect.fail(toSafeMultisigTxLookupError(safeTxHash, error, true))));
124
109
  const pollInterval = policy.pollInterval ?? SAFE_POLL_INTERVAL;
125
110
  const executionTimeout = policy.executionTimeout ?? SAFE_EXECUTION_TIMEOUT;
126
111
  let lastStatus = "AWAITING_CONFIRMATIONS";
@@ -136,12 +121,7 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
136
121
  }));
137
122
  const receipt = yield* txManager
138
123
  .waitForReceipt(info.chainId, onchainHash, policy.receiptPolicy)
139
- .pipe(Effect.catchTag("TxReplacedError", (error) => Effect.fail(new SafeMultisigTxLookupError({
140
- cause: error,
141
- message: `Transaction was replaced: ${error.message}`,
142
- retryable: false,
143
- safeTxHash,
144
- }))));
124
+ .pipe(Effect.catchTag("TxReplacedError", (error) => Effect.fail(toSafeMultisigTxLookupError(safeTxHash, error, false))));
145
125
  return {
146
126
  chainId: info.chainId,
147
127
  onchainHash,
@@ -164,19 +144,9 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
164
144
  });
165
145
  const getOffchainSignature = Effect.fn("SafeAppsService.getOffchainSignature")(function* (messageHash) {
166
146
  const sig = yield* withSdk(getSdk, (s) => Effect.tryPromise({
167
- catch: (cause) => new SafeMultisigTxLookupError({
168
- cause,
169
- message: `Failed to get off-chain signature for ${messageHash}`,
170
- retryable: true,
171
- safeTxHash: messageHash,
172
- }),
147
+ catch: (cause) => toSafeMultisigTxLookupError(messageHash, cause, true),
173
148
  try: () => s.safe.getOffChainSignature(messageHash),
174
- }), (e) => new SafeMultisigTxLookupError({
175
- cause: e,
176
- message: e.message,
177
- retryable: false,
178
- safeTxHash: messageHash,
179
- }));
149
+ }), (e) => toSafeMultisigTxLookupError(messageHash, e, false));
180
150
  if (!sig || sig === "" || sig === "0x") {
181
151
  return Option.none();
182
152
  }