@prb/effect-evm-safe 1.0.1 → 1.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.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,19 @@ The format is based on [Common Changelog](https://common-changelog.org/).
6
6
 
7
7
  [1.0.0]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%401.0.0
8
8
  [1.0.1]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%401.0.1
9
+ [1.1.0]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%401.1.0
10
+
11
+ ## [1.1.0] - 2026-02-10
12
+
13
+ ### Added
14
+
15
+ - Add `safeMultisigBatchWrite` for atomic multi-transaction Safe batches via MultiSend
16
+ - Add `safeMultisigAllowAndWrite` for ERC-20 approve + action as a single Safe proposal
17
+ - Add `buildSafeApproveTx` helper to encode ERC-20 approve calls as Safe transactions
18
+ - Add `waitForSafeMultisigTx` to poll Safe transaction lifecycle until terminal state or timeout
19
+ - Add `getSafeMultisigTxStatus` for one-shot Safe transaction status checks
20
+ - Add `SafeMultiSendUnavailableError` for chains without MultiSend contract
21
+ - Add `isMultiSendUnavailableError` detector with depth-limited cause chain traversal
9
22
 
10
23
  ## [1.0.1] - 2026-02-09
11
24
 
@@ -0,0 +1,20 @@
1
+ import { Effect } from "effect";
2
+ import type { Address } from "viem";
3
+ import type { SafeMultisigTx } from "./types.js";
4
+ export type SafeMultisigAllowAndWriteParams = {
5
+ readonly mainTransaction: SafeMultisigTx;
6
+ readonly spender: Address;
7
+ readonly token: {
8
+ readonly address: Address;
9
+ readonly chainId: number;
10
+ };
11
+ readonly amount: bigint;
12
+ };
13
+ export type SafeMultisigApproveTxParams = {
14
+ readonly amount: bigint;
15
+ readonly spender: Address;
16
+ readonly tokenAddress: Address;
17
+ };
18
+ 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>;
20
+ //# sourceMappingURL=allowance.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,22 @@
1
+ import { Effect } from "effect";
2
+ import { encodeFunctionData, erc20Abi } from "viem";
3
+ import { safeMultisigBatchWrite } from "./batch.js";
4
+ export function buildSafeApproveTx(params) {
5
+ const { amount, spender, tokenAddress } = params;
6
+ const data = encodeFunctionData({
7
+ abi: erc20Abi,
8
+ args: [spender, amount],
9
+ functionName: "approve",
10
+ });
11
+ return { data, to: tokenAddress, value: 0n };
12
+ }
13
+ export const safeMultisigAllowAndWrite = Effect.fn("safeMultisigAllowAndWrite")(function* (params) {
14
+ const { amount, mainTransaction, spender, token } = params;
15
+ const approveTx = buildSafeApproveTx({
16
+ amount,
17
+ spender,
18
+ tokenAddress: token.address,
19
+ });
20
+ return yield* safeMultisigBatchWrite([approveTx, mainTransaction], token.chainId);
21
+ });
22
+ //# sourceMappingURL=allowance.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,6 @@
1
+ import { Effect } from "effect";
2
+ import { SafeMultiSendUnavailableError, SafeMultisigTxSubmissionError } from "./errors.js";
3
+ import { SafeAppsService } from "./service.js";
4
+ import type { SafeMultisigTx } from "./types.js";
5
+ export declare const safeMultisigBatchWrite: (transactions: readonly [SafeMultisigTx, ...SafeMultisigTx[]], chainId?: number | undefined) => Effect.Effect<`0x${string}`, SafeMultisigTxSubmissionError | SafeMultiSendUnavailableError, SafeAppsService>;
6
+ //# sourceMappingURL=batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/safe/batch.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAEL,6BAA6B,EAC7B,6BAA6B,EAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAWjD,eAAO,MAAM,sBAAsB,8MAqBjC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { Effect } from "effect";
2
+ import { isMultiSendUnavailableError, SafeMultiSendUnavailableError, SafeMultisigTxSubmissionError, } from "./errors.js";
3
+ import { SafeAppsService } from "./service.js";
4
+ export const safeMultisigBatchWrite = Effect.fn("safeMultisigBatchWrite")(function* (transactions, chainId) {
5
+ const safeApps = yield* SafeAppsService;
6
+ const result = yield* safeApps.sendTxs(transactions).pipe(Effect.mapError((error) => {
7
+ if (isMultiSendUnavailableError(error)) {
8
+ return new SafeMultiSendUnavailableError({
9
+ cause: error,
10
+ chainId,
11
+ message: `MultiSend contract not available on chain ${chainId ?? "unknown"}`,
12
+ });
13
+ }
14
+ return new SafeMultisigTxSubmissionError({
15
+ cause: error,
16
+ message: `Safe batch write failed: ${error.message}`,
17
+ });
18
+ }));
19
+ return result.safeTxHash;
20
+ });
21
+ //# sourceMappingURL=batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/safe/batch.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAY/C,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,EACjF,YAA4D,EAC5D,OAAgB;IAEhB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,IAAI,CACvD,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE;QACxB,IAAI,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,OAAO,IAAI,6BAA6B,CAAC;gBACvC,KAAK,EAAE,KAAK;gBACZ,OAAO;gBACP,OAAO,EAAE,6CAA6C,OAAO,IAAI,SAAS,EAAE;aAC7E,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,6BAA6B,CAAC;YACvC,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,4BAA4B,KAAK,CAAC,OAAO,EAAE;SACrD,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;IACF,OAAO,MAAM,CAAC,UAAU,CAAC;AAC3B,CAAC,CAAC,CAAC","sourcesContent":["/**\n * Safe multisig batch transaction operations.\n *\n * Send multiple transactions as an atomic Safe batch using SafeAppsSDK.\n * Detects MultiSend contract unavailability and surfaces it as a typed error.\n *\n * @module safe/batch\n */\n\nimport { Effect } from \"effect\";\nimport {\n isMultiSendUnavailableError,\n SafeMultiSendUnavailableError,\n SafeMultisigTxSubmissionError,\n} from \"./errors.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { SafeMultisigTx } from \"./types.js\";\n\n/**\n * Send multiple transactions as a single Safe multisig batch.\n *\n * Uses SafeAppsService to atomically execute all transactions via MultiSend.\n * On chains where MultiSend is not deployed, fails with `SafeMultiSendUnavailableError`.\n *\n * @param transactions - Array of transactions to batch\n * @param chainId - Optional chain ID for error context\n */\nexport const safeMultisigBatchWrite = Effect.fn(\"safeMultisigBatchWrite\")(function* (\n transactions: readonly [SafeMultisigTx, ...SafeMultisigTx[]],\n chainId?: number\n) {\n const safeApps = yield* SafeAppsService;\n const result = yield* safeApps.sendTxs(transactions).pipe(\n Effect.mapError((error) => {\n if (isMultiSendUnavailableError(error)) {\n return new SafeMultiSendUnavailableError({\n cause: error,\n chainId,\n message: `MultiSend contract not available on chain ${chainId ?? \"unknown\"}`,\n });\n }\n return new SafeMultisigTxSubmissionError({\n cause: error,\n message: `Safe batch write failed: ${error.message}`,\n });\n })\n );\n return result.safeTxHash;\n});\n"]}
@@ -75,5 +75,15 @@ declare const OffchainSignatureTimeoutError_base: Schema.TaggedErrorClass<Offcha
75
75
  }>;
76
76
  export declare class OffchainSignatureTimeoutError extends OffchainSignatureTimeoutError_base {
77
77
  }
78
+ declare const SafeMultiSendUnavailableError_base: Schema.TaggedErrorClass<SafeMultiSendUnavailableError, "SafeMultiSendUnavailableError", {
79
+ readonly _tag: Schema.tag<"SafeMultiSendUnavailableError">;
80
+ } & {
81
+ cause: Schema.optional<typeof Schema.Unknown>;
82
+ chainId: Schema.optional<typeof Schema.Number>;
83
+ message: typeof Schema.String;
84
+ }>;
85
+ export declare class SafeMultiSendUnavailableError extends SafeMultiSendUnavailableError_base {
86
+ }
87
+ export declare function isMultiSendUnavailableError(error: unknown): boolean;
78
88
  export {};
79
89
  //# 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"}
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;AAWJ,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEnE"}
@@ -31,4 +31,33 @@ export class OffchainSignatureTimeoutError extends Schema.TaggedError()("Offchai
31
31
  timeout: Schema.Number,
32
32
  }) {
33
33
  }
34
+ export class SafeMultiSendUnavailableError extends Schema.TaggedError()("SafeMultiSendUnavailableError", {
35
+ cause: Schema.optional(Schema.Unknown),
36
+ chainId: Schema.optional(Schema.Number),
37
+ message: Schema.String,
38
+ }) {
39
+ }
40
+ const MULTISEND_ERROR_PATTERN = /MultiSend contract not deployed|MultiSend call failed/i;
41
+ const MAX_ERROR_DEPTH = 10;
42
+ export function isMultiSendUnavailableError(error) {
43
+ return checkMultiSendError(error, 0);
44
+ }
45
+ function checkMultiSendError(error, depth) {
46
+ if (depth >= MAX_ERROR_DEPTH) {
47
+ return false;
48
+ }
49
+ if (typeof error === "string") {
50
+ return MULTISEND_ERROR_PATTERN.test(error);
51
+ }
52
+ if (typeof error === "object" && error !== null) {
53
+ const { message, cause } = error;
54
+ if (typeof message === "string" && MULTISEND_ERROR_PATTERN.test(message)) {
55
+ return true;
56
+ }
57
+ if (cause) {
58
+ return checkMultiSendError(cause, depth + 1);
59
+ }
60
+ }
61
+ return false;
62
+ }
34
63
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/safe/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,MAAM,OAAO,2BAA4B,SAAQ,MAAM,CAAC,WAAW,EAA+B,CAChG,6BAA6B,EAC7B,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CACnE;CAAG;AAEJ,MAAM,OAAO,wBAAyB,SAAQ,MAAM,CAAC,WAAW,EAA4B,CAC1F,0BAA0B,EAC1B,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAC3B;CAAG;AAGJ,MAAM,OAAO,gCAAiC,SAAQ,MAAM,CAAC,WAAW,EAAoC,CAC1G,kCAAkC,EAClC,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CACnE;CAAG;AAEJ,MAAM,OAAO,yBAA0B,SAAQ,MAAM,CAAC,WAAW,EAA6B,CAC5F,2BAA2B,EAC3B,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CACnE;CAAG;AAEJ,MAAM,OAAO,6BAA8B,SAAQ,MAAM,CAAC,WAAW,EAAiC,CACpG,+BAA+B,EAC/B,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CACnE;CAAG;AAEJ,MAAM,OAAO,yBAA0B,SAAQ,MAAM,CAAC,WAAW,EAA6B,CAC5F,2BAA2B,EAC3B;IACE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,SAAS,EAAE,MAAM,CAAC,OAAO;IACzB,UAAU,EAAE,MAAM,CAAC,MAAM;CAC1B,CACF;CAAG;AAEJ,MAAM,OAAO,mCAAoC,SAAQ,MAAM,CAAC,WAAW,EAAuC,CAChH,qCAAqC,EACrC;IACE,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CACF;CAAG;AAGJ,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAC9E,oBAAoB,EACpB,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CACnE;CAAG;AAEJ,MAAM,OAAO,6BAA8B,SAAQ,MAAM,CAAC,WAAW,EAAiC,CACpG,+BAA+B,EAC/B;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,WAAW,EAAE,MAAM,CAAC,MAAM;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CACF;CAAG","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"]}
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;\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,8 +1,11 @@
1
+ export { buildSafeApproveTx, type SafeMultisigAllowAndWriteParams, type SafeMultisigApproveTxParams, safeMultisigAllowAndWrite, } from "./allowance.js";
2
+ export { safeMultisigBatchWrite } from "./batch.js";
1
3
  export type { SafeDetectionParams, SafeDetectionResult } from "./detection.js";
2
4
  export { isSafeMultisig, SafeMultisigDetectionError } from "./detection.js";
3
- export { NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeAppsSdkUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, } from "./errors.js";
5
+ export { isMultiSendUnavailableError, NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeAppsSdkUnavailableError, SafeMultiSendUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, } from "./errors.js";
4
6
  export { type SafeAppsServiceConfig, SafeAppsServiceLive } from "./live.js";
5
7
  export { SafeAppsService, type SafeAppsServiceShape } from "./service.js";
6
8
  export * from "./simulation/index.js";
9
+ export { getSafeMultisigTxStatus, type SafeMultisigTxStatus, type SafeMultisigWaitOptions, type SafeMultisigWaitResult, waitForSafeMultisigTx, } from "./tx-lifecycle.js";
7
10
  export type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeMultisigInfo, SafeMultisigTx, SafeMultisigTxResult, SafeMultisigTxSubmission, SafeWaitPolicy, SignTypedDataResult, } from "./types.js";
8
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE/E,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAG5E,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,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,gBAAgB,EAChB,cAAc,EACd,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,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,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
@@ -1,6 +1,9 @@
1
+ export { buildSafeApproveTx, safeMultisigAllowAndWrite, } from "./allowance.js";
2
+ export { safeMultisigBatchWrite } from "./batch.js";
1
3
  export { isSafeMultisig, SafeMultisigDetectionError } from "./detection.js";
2
- export { NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeAppsSdkUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, } from "./errors.js";
4
+ export { isMultiSendUnavailableError, NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeAppsSdkUnavailableError, SafeMultiSendUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError, } from "./errors.js";
3
5
  export { SafeAppsServiceLive } from "./live.js";
4
6
  export { SafeAppsService } from "./service.js";
5
7
  export * from "./simulation/index.js";
8
+ export { getSafeMultisigTxStatus, waitForSafeMultisigTx, } from "./tx-lifecycle.js";
6
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/safe/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAG5E,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,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, SafeMultisigDetectionError } from \"./detection.js\";\n\n// Errors\nexport {\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeAppsSdkUnavailableError,\n SafeMultisigInfoUnavailableError,\n SafeMultisigSettingsError,\n SafeMultisigTxExecutionTimeoutError,\n SafeMultisigTxLookupError,\n SafeMultisigTxSubmissionError,\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 SafeMultisigInfo,\n SafeMultisigTx,\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,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","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// Types\nexport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeMultisigInfo,\n SafeMultisigTx,\n SafeMultisigTxResult,\n SafeMultisigTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\n"]}
@@ -0,0 +1,49 @@
1
+ import { Duration, Effect } from "effect";
2
+ import type { Hash, TransactionReceipt } from "viem";
3
+ import type { SafeMultisigTxLookupError } from "./errors.js";
4
+ import { SafeAppsService } from "./service.js";
5
+ export type SafeMultisigWaitOptions = {
6
+ readonly interval?: Duration.DurationInput;
7
+ readonly maxWait?: Duration.DurationInput;
8
+ };
9
+ export type SafeMultisigWaitResult = {
10
+ readonly _tag: "success";
11
+ readonly hash: Hash;
12
+ readonly receipt: TransactionReceipt;
13
+ } | {
14
+ readonly _tag: "queued";
15
+ readonly safeTxHash: Hash;
16
+ } | {
17
+ readonly _tag: "cancelled";
18
+ } | {
19
+ readonly _tag: "failed";
20
+ readonly error: string;
21
+ };
22
+ export type SafeMultisigTxStatus = "awaiting_confirmations" | "awaiting_execution" | "pending" | "success" | "failed";
23
+ export declare const waitForSafeMultisigTx: (safeTxHash: `0x${string}`, getReceipt: (hash: Hash) => Effect.Effect<TransactionReceipt, SafeMultisigTxLookupError>, options?: SafeMultisigWaitOptions | undefined) => Effect.Effect<{
24
+ _tag: "cancelled";
25
+ error?: undefined;
26
+ hash?: undefined;
27
+ receipt?: undefined;
28
+ safeTxHash?: undefined;
29
+ } | {
30
+ _tag: "failed";
31
+ error: string;
32
+ hash?: undefined;
33
+ receipt?: undefined;
34
+ safeTxHash?: undefined;
35
+ } | {
36
+ _tag: "success";
37
+ hash: `0x${string}`;
38
+ receipt: TransactionReceipt;
39
+ error?: undefined;
40
+ safeTxHash?: undefined;
41
+ } | {
42
+ _tag: "queued";
43
+ safeTxHash: `0x${string}`;
44
+ error?: undefined;
45
+ hash?: undefined;
46
+ receipt?: undefined;
47
+ }, SafeMultisigTxLookupError, SafeAppsService>;
48
+ export declare const getSafeMultisigTxStatus: (safeTxHash: `0x${string}`) => Effect.Effect<"pending" | "success" | "failed" | "awaiting_confirmations" | "awaiting_execution", SafeMultisigTxLookupError, SafeAppsService>;
49
+ //# sourceMappingURL=tx-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx-lifecycle.d.ts","sourceRoot":"","sources":["../../src/safe/tx-lifecycle.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AACrD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAc/C,MAAM,MAAM,uBAAuB,GAAG;IAEpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC;IAE3C,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GACvF;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,oBAAoB,GAC5B,wBAAwB,GACxB,oBAAoB,GACpB,SAAS,GACT,SAAS,GACT,QAAQ,CAAC;AAqBb,eAAO,MAAM,qBAAqB,iDAEb,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,yBAAyB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;8CAsFxF,CAAC;AAaH,eAAO,MAAM,uBAAuB,8KAoBlC,CAAC"}
@@ -0,0 +1,79 @@
1
+ import { Duration, Effect, Option } from "effect";
2
+ import { SafeAppsService } from "./service.js";
3
+ const DEFAULT_POLL_INTERVAL = Duration.seconds(5);
4
+ const DEFAULT_MAX_WAIT = Duration.minutes(90);
5
+ const MIN_POLL_INTERVAL = Duration.seconds(1);
6
+ export const waitForSafeMultisigTx = Effect.fn("waitForSafeMultisigTx")(function* (safeTxHash, getReceipt, options = {}) {
7
+ const interval = Duration.max(Duration.decode(options.interval ?? DEFAULT_POLL_INTERVAL), MIN_POLL_INTERVAL);
8
+ const maxWait = Duration.decode(options.maxWait ?? DEFAULT_MAX_WAIT);
9
+ const maxAttempts = Math.floor(Duration.toMillis(maxWait) / Duration.toMillis(interval));
10
+ const safeApps = yield* SafeAppsService;
11
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
12
+ const queuedResult = yield* safeApps.getTx(safeTxHash).pipe(Effect.map(Option.some), Effect.catchTag("SafeMultisigTxLookupError", (error) => {
13
+ if (error.retryable) {
14
+ return Effect.logWarning("Retryable error polling Safe tx").pipe(Effect.annotateLogs({ attempt, error: error.message, safeTxHash }), Effect.as(Option.none()));
15
+ }
16
+ return Effect.fail(error);
17
+ }));
18
+ if (Option.isNone(queuedResult)) {
19
+ yield* Effect.sleep(interval);
20
+ continue;
21
+ }
22
+ const queued = queuedResult.value;
23
+ yield* Effect.logDebug("Safe tx poll status").pipe(Effect.annotateLogs({
24
+ attempt,
25
+ hash: Option.isSome(queued.txHash) ? queued.txHash.value : "pending",
26
+ safeTxHash,
27
+ status: queued.status,
28
+ }));
29
+ if (queued.status === "CANCELLED") {
30
+ return { _tag: "cancelled" };
31
+ }
32
+ if (queued.status === "FAILED") {
33
+ return {
34
+ _tag: "failed",
35
+ error: "Safe transaction failed",
36
+ };
37
+ }
38
+ if (queued.status === "SUCCESS") {
39
+ if (Option.isNone(queued.txHash)) {
40
+ return {
41
+ _tag: "failed",
42
+ error: "Safe transaction succeeded but no on-chain hash available",
43
+ };
44
+ }
45
+ const txHash = queued.txHash.value;
46
+ const receipt = yield* getReceipt(txHash);
47
+ return {
48
+ _tag: "success",
49
+ hash: txHash,
50
+ receipt,
51
+ };
52
+ }
53
+ yield* Effect.sleep(interval);
54
+ }
55
+ yield* Effect.logWarning("Safe multisig transaction polling timeout").pipe(Effect.annotateLogs({
56
+ maxAttempts,
57
+ maxWaitMs: Duration.toMillis(maxWait),
58
+ safeTxHash,
59
+ }));
60
+ return { _tag: "queued", safeTxHash };
61
+ });
62
+ export const getSafeMultisigTxStatus = Effect.fn("getSafeMultisigTxStatus")(function* (safeTxHash) {
63
+ const safeApps = yield* SafeAppsService;
64
+ const queued = yield* safeApps.getTx(safeTxHash);
65
+ switch (queued.status) {
66
+ case "AWAITING_CONFIRMATIONS":
67
+ return "awaiting_confirmations";
68
+ case "AWAITING_EXECUTION":
69
+ return "awaiting_execution";
70
+ case "SUCCESS":
71
+ return "success";
72
+ case "CANCELLED":
73
+ case "FAILED":
74
+ return "failed";
75
+ default:
76
+ return "pending";
77
+ }
78
+ });
79
+ //# sourceMappingURL=tx-lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx-lifecycle.js","sourceRoot":"","sources":["../../src/safe/tx-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Safe multisig transaction lifecycle tracking.\n *\n * Polls the Safe API to track transactions from proposal through execution.\n * Fills the gap between sendTxs() (which returns a safeTxHash) and knowing\n * when the transaction lands on-chain.\n *\n * @module safe/tx-lifecycle\n */\n\nimport { Duration, Effect, Option } from \"effect\";\nimport type { Hash, TransactionReceipt } from \"viem\";\nimport type { SafeMultisigTxLookupError } from \"./errors.js\";\nimport { SafeAppsService } from \"./service.js\";\n\n// ---------------------------------------------------------------------------\n// Configuration defaults\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_POLL_INTERVAL = Duration.seconds(5);\nconst DEFAULT_MAX_WAIT = Duration.minutes(90);\nconst MIN_POLL_INTERVAL = Duration.seconds(1);\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type SafeMultisigWaitOptions = {\n /** Polling interval (default: 5 seconds). Clamped to a minimum of 1 second. */\n readonly interval?: Duration.DurationInput;\n /** Maximum wait time (default: 90 minutes) */\n readonly maxWait?: Duration.DurationInput;\n};\n\nexport type SafeMultisigWaitResult =\n | { readonly _tag: \"success\"; readonly hash: Hash; readonly receipt: TransactionReceipt }\n | { readonly _tag: \"queued\"; readonly safeTxHash: Hash }\n | { readonly _tag: \"cancelled\" }\n | { readonly _tag: \"failed\"; readonly error: string };\n\nexport type SafeMultisigTxStatus =\n | \"awaiting_confirmations\"\n | \"awaiting_execution\"\n | \"pending\"\n | \"success\"\n | \"failed\";\n\n// ---------------------------------------------------------------------------\n// waitForSafeMultisigTx\n// ---------------------------------------------------------------------------\n\n/**\n * Poll a Safe multisig transaction until it reaches a terminal state or times out.\n *\n * Unlike `SafeAppsService.waitForTxReceipt` (which assumes execution will happen\n * in the current session), this utility handles the full lifecycle including\n * transactions that stay queued because other signers haven't signed yet.\n *\n * Terminal states: success (on-chain), cancelled, failed.\n * On timeout the safeTxHash is returned as \"queued\" so callers can persist it\n * for later resolution.\n *\n * @param safeTxHash - The Safe transaction hash returned by `sendTxs`\n * @param getReceipt - Caller-provided effect to fetch an on-chain receipt\n * @param options - Optional polling configuration\n */\nexport const waitForSafeMultisigTx = Effect.fn(\"waitForSafeMultisigTx\")(function* (\n safeTxHash: Hash,\n getReceipt: (hash: Hash) => Effect.Effect<TransactionReceipt, SafeMultisigTxLookupError>,\n options: SafeMultisigWaitOptions = {}\n) {\n const interval = Duration.max(\n Duration.decode(options.interval ?? DEFAULT_POLL_INTERVAL),\n MIN_POLL_INTERVAL\n );\n const maxWait = Duration.decode(options.maxWait ?? DEFAULT_MAX_WAIT);\n const maxAttempts = Math.floor(Duration.toMillis(maxWait) / Duration.toMillis(interval));\n\n const safeApps = yield* SafeAppsService;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n // --- Fetch tx status, classifying errors ---\n const queuedResult = yield* safeApps.getTx(safeTxHash).pipe(\n Effect.map(Option.some),\n Effect.catchTag(\"SafeMultisigTxLookupError\", (error) => {\n if (error.retryable) {\n return Effect.logWarning(\"Retryable error polling Safe tx\").pipe(\n Effect.annotateLogs({ attempt, error: error.message, safeTxHash }),\n Effect.as(Option.none<{ txHash: Option.Option<Hash>; status: string }>())\n );\n }\n // Terminal lookup error — stop polling immediately\n return Effect.fail(error);\n })\n );\n\n if (Option.isNone(queuedResult)) {\n yield* Effect.sleep(interval);\n continue;\n }\n\n const queued = queuedResult.value;\n yield* Effect.logDebug(\"Safe tx poll status\").pipe(\n Effect.annotateLogs({\n attempt,\n hash: Option.isSome(queued.txHash) ? queued.txHash.value : \"pending\",\n safeTxHash,\n status: queued.status,\n })\n );\n\n // --- Terminal states ---\n\n if (queued.status === \"CANCELLED\") {\n return { _tag: \"cancelled\" as const } satisfies SafeMultisigWaitResult;\n }\n\n if (queued.status === \"FAILED\") {\n return {\n _tag: \"failed\" as const,\n error: \"Safe transaction failed\",\n } satisfies SafeMultisigWaitResult;\n }\n\n if (queued.status === \"SUCCESS\") {\n if (Option.isNone(queued.txHash)) {\n return {\n _tag: \"failed\" as const,\n error: \"Safe transaction succeeded but no on-chain hash available\",\n } satisfies SafeMultisigWaitResult;\n }\n const txHash = queued.txHash.value as Hash;\n const receipt = yield* getReceipt(txHash);\n return {\n _tag: \"success\" as const,\n hash: txHash,\n receipt,\n } satisfies SafeMultisigWaitResult;\n }\n\n // Still pending — keep polling\n yield* Effect.sleep(interval);\n }\n\n // Timed out without reaching a terminal state\n yield* Effect.logWarning(\"Safe multisig transaction polling timeout\").pipe(\n Effect.annotateLogs({\n maxAttempts,\n maxWaitMs: Duration.toMillis(maxWait),\n safeTxHash,\n })\n );\n\n return { _tag: \"queued\" as const, safeTxHash } satisfies SafeMultisigWaitResult;\n});\n\n// ---------------------------------------------------------------------------\n// getSafeMultisigTxStatus\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch the current lifecycle status of a Safe multisig transaction.\n *\n * Maps the raw Safe API status string to a normalized union. Useful for\n * one-shot status checks (e.g. resuming after page reload) without starting\n * a polling loop.\n */\nexport const getSafeMultisigTxStatus = Effect.fn(\"getSafeMultisigTxStatus\")(function* (\n safeTxHash: Hash\n) {\n const safeApps = yield* SafeAppsService;\n const queued = yield* safeApps.getTx(safeTxHash);\n\n switch (queued.status) {\n case \"AWAITING_CONFIRMATIONS\":\n return \"awaiting_confirmations\";\n case \"AWAITING_EXECUTION\":\n return \"awaiting_execution\";\n case \"SUCCESS\":\n return \"success\";\n // Both map to \"failed\" — use waitForSafeMultisigTx to distinguish cancelled vs failed\n case \"CANCELLED\":\n case \"FAILED\":\n return \"failed\";\n default:\n return \"pending\";\n }\n});\n"]}
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "sideEffects": false,
7
7
  "type": "module",
8
8
  "types": "./dist/index.d.ts",
9
- "version": "1.0.1",
9
+ "version": "1.1.0",
10
10
  "scripts": {
11
11
  "build": "just build",
12
12
  "prepack": "bun install --frozen-lockfile && just build"