@prb/effect-evm-safe 1.1.1 → 2.0.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
@@ -8,6 +8,21 @@ The format is based on [Common Changelog](https://common-changelog.org/).
8
8
  [1.0.1]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%401.0.1
9
9
  [1.1.0]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%401.1.0
10
10
  [1.1.1]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%401.1.1
11
+ [2.0.0]: https://github.com/PaulRBerg/prb-effect/releases/tag/%40prb%2Feffect-evm-safe%402.0.0
12
+
13
+ ## [2.0.0] - 2026-02-17
14
+
15
+ ### Changed
16
+
17
+ - Rename `txHash` to `onchainHash` in `SafeAppsService.getTx` return type
18
+ - Rename `hash` to `onchainHash` in `SafeMultisigWaitResult` success variant
19
+ - Include `safeTxHash` in all `SafeMultisigWaitResult` variants
20
+ - Return `SafeMultisigTxInfo` type from `getTx` with confirmation metadata
21
+
22
+ ### Added
23
+
24
+ - Add `SafeMultisigTxInfo` type with `confirmations` and `confirmationsRequired` fields
25
+ - Add `getSafeMultisigTxUrl` utility to build Safe web UI transaction URLs
11
26
 
12
27
  ## [1.1.1] - 2026-02-10
13
28
 
@@ -7,5 +7,6 @@ export { type SafeAppsServiceConfig, SafeAppsServiceLive } from "./live.js";
7
7
  export { SafeAppsService, type SafeAppsServiceShape } from "./service.js";
8
8
  export * from "./simulation/index.js";
9
9
  export { getSafeMultisigTxStatus, type SafeMultisigTxStatus, type SafeMultisigWaitOptions, type SafeMultisigWaitResult, waitForSafeMultisigTx, } from "./tx-lifecycle.js";
10
- export type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeMultisigInfo, SafeMultisigTx, SafeMultisigTxResult, SafeMultisigTxSubmission, SafeWaitPolicy, SignTypedDataResult, } from "./types.js";
10
+ export { type GetSafeMultisigTxUrlParams, getSafeMultisigTxUrl } from "./tx-url.js";
11
+ export type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeMultisigInfo, SafeMultisigTx, SafeMultisigTxInfo, SafeMultisigTxResult, SafeMultisigTxSubmission, SafeWaitPolicy, SignTypedDataResult, } from "./types.js";
11
12
  //# 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,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,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"}
@@ -6,4 +6,5 @@ export { SafeAppsServiceLive } from "./live.js";
6
6
  export { SafeAppsService } from "./service.js";
7
7
  export * from "./simulation/index.js";
8
8
  export { getSafeMultisigTxStatus, waitForSafeMultisigTx, } from "./tx-lifecycle.js";
9
+ export { getSafeMultisigTxUrl } from "./tx-url.js";
9
10
  //# 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","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"]}
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 +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,mDA4V/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;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"}
package/dist/safe/live.js CHANGED
@@ -101,9 +101,17 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
101
101
  safeTxHash,
102
102
  }));
103
103
  const txHash = tx.txHash ? yield* validateHash(tx.txHash, "getTx") : null;
104
+ const executionInfo = tx.detailedExecutionInfo;
105
+ const hasMultisigExecutionInfo = executionInfo !== undefined &&
106
+ executionInfo !== null &&
107
+ executionInfo.type === "MULTISIG";
104
108
  return {
109
+ confirmations: hasMultisigExecutionInfo ? executionInfo.confirmations.length : null,
110
+ confirmationsRequired: hasMultisigExecutionInfo
111
+ ? executionInfo.confirmationsRequired
112
+ : null,
113
+ onchainHash: txHash ? Option.some(txHash) : Option.none(),
105
114
  status: tx.txStatus ?? "AWAITING_CONFIRMATIONS",
106
- txHash: txHash ? Option.some(txHash) : Option.none(),
107
115
  };
108
116
  });
109
117
  const waitForTxReceipt = Effect.fn("SafeAppsService.waitForTxReceipt")(function* (safeTxHash, policy = {}) {
@@ -119,7 +127,7 @@ export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Eff
119
127
  const onchainHash = yield* pollUntil(Effect.gen(function* () {
120
128
  const tx = yield* getTx(safeTxHash);
121
129
  lastStatus = tx.status;
122
- return tx.txHash;
130
+ return tx.onchainHash;
123
131
  }), { interval: pollInterval, timeout: executionTimeout }, (timeout) => new SafeMultisigTxExecutionTimeoutError({
124
132
  lastStatus,
125
133
  message: `Safe tx ${safeTxHash} not executed within ${timeout}ms (last status: ${lastStatus})`,
@@ -1 +1 @@
1
- {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAS/C,MAAM,aAAa,GACjB,CAAmB,SAAuB,EAAE,KAAa,EAAE,EAAE,CAC7D,CAAC,KAAa,EAAE,OAAe,EAA+C,EAAE,CAC9E,SAAS,CAAC,KAAK,CAAC;IACd,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;IACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CACT,IAAI,yBAAyB,CAAC;QAC5B,OAAO,EAAE,WAAW,KAAK,gBAAgB,OAAO,KAAK,KAAK,EAAE;QAC5D,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,EAAE;KACf,CAAC,CACH,CAAC;AAEV,MAAM,eAAe,GAAG,aAAa,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAC5D,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACnD,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAehD,MAAM,OAAO,GAAG,CACd,MAA+D,EAC/D,EAAqD,EACrD,QAAuC,EAClB,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;AAIhF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAA8B,EAAE,EAAE,CACpE,KAAK,CAAC,MAAM,CACV,eAAe,EACf,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAElB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAA0B,IAAI,CAAC,CAAC;IAG/D,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;IAEnC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAgC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAGnF,MAAM,MAAM,GAA4D,MAAM,CAAC,GAAG,CAChF,QAAQ,CAAC;QACP,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAErC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC,GAAG,CAAC;QACnB,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;QAGD,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,IAAI,wBAAwB,CAAC;gBACzC,OAAO,EAAE,oEAAoE;aAC9E,CAAC,CAAC;YACH,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QAGD,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAChD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAiB,EAAE,GAAG,EAAE,CAAC,CAAC,EACvD,MAAM,CAAC,QAAQ,CAAC,6BAA6B,EAAE,CAAC,KAAK,EAAE,EAAE,CACvD,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,aAAsB,EAAE,KAAK,EAAW,CAAC,CACjE,CACF,CAAC;QAEF,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAEnC,IAAI,UAAU,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACtC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;QAED,OAAO,UAAU,CAAC,GAAG,CAAC;IACxB,CAAC,CACF,CAAC;IAIF,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,QAAQ,CAAC;QAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,OAAO,CACxB,MAAM,EACN,CAAC,CAAC,EAAE,EAAE,CACJ,MAAM,CAAC,UAAU,CAAC;YAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,gCAAgC,CAAC;gBACnC,KAAK;gBACL,OAAO,EAAE,kCAAkC;aAC5C,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE;SAC5B,CAAC,EACJ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,gCAAgC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAC9E,CAAC;QAEF,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,IAAI,CACzE,MAAM,CAAC,QAAQ,CAAC,2BAA2B,EAAE,CAAC,CAAC,EAAE,EAAE,CACjD,MAAM,CAAC,IAAI,CAAC,IAAI,gCAAgC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CACpF,CACF,CAAC;QAEF,MAAM,QAAQ,GAAqB,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;QACzE,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAClC,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,QAAQ,CAAC,EAC5D,GAA8B,EAC9B,MAA+B;QAG/B,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9B,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,EAAE,EAAE,EAAE,CAAC,EAAE;YACT,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG;SACnC,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAC3B,MAAM,EACN,CAAC,CAAC,EAAE,EAAE,CACJ,MAAM,CAAC,UAAU,CAAC;YAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;gBACf,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;gBAC1C,OAAO,IAAI,6BAA6B,CAAC;oBACvC,KAAK;oBACL,OAAO,EAAE,MAAM;wBACb,CAAC,CAAC,iCAAiC,MAAM,EAAE;wBAC3C,CAAC,CAAC,8BAA8B;iBACnC,CAAC,CAAC;YACL,CAAC;YACD,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;SAC/C,CAAC,EACJ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,6BAA6B,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAC3E,CAAC;QAEF,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,IAAI,CACvE,MAAM,CAAC,QAAQ,CAAC,2BAA2B,EAAE,CAAC,CAAC,EAAE,EAAE,CACjD,MAAM,CAAC,IAAI,CAAC,IAAI,6BAA6B,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CACjF,CACF,CAAC;QAEF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAChC,MAAM,CAAC,QAAQ,CAAC,kCAAkC,EAAE,CAAC,KAAK,EAAE,EAAE,CAC5D,MAAM,CAAC,IAAI,CACT,IAAI,6BAA6B,CAAC;YAChC,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,6CAA6C;SACvD,CAAC,CACH,CACF,CACF,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,QAAQ,CAAC,EAAE,UAAgB;QAC1E,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CACvB,MAAM,EACN,CAAC,CAAC,EAAE,EAAE,CACJ,MAAM,CAAC,UAAU,CAAC;YAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,yBAAyB,CAAC;gBAC5B,KAAK;gBACL,OAAO,EAAE,4BAA4B,UAAU,EAAE;gBACjD,SAAS,EAAE,IAAI;gBACf,UAAU;aACX,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC;SAC7C,CAAC,EACJ,CAAC,CAAC,EAAE,EAAE,CACJ,IAAI,yBAAyB,CAAC;YAC5B,KAAK,EAAE,CAAC;YACR,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,SAAS,EAAE,KAAK;YAChB,UAAU;SACX,CAAC,CACL,CAAC;QAEF,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAE1E,OAAO;YACL,MAAM,EAAE,EAAE,CAAC,QAAQ,IAAI,wBAAwB;YAC/C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAQ;SAC3D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,MAAM,CAAC,EAAE,CAAC,kCAAkC,CAAC,CAAC,QAAQ,CAAC,EAC9E,UAAgB,EAChB,SAII,EAAE;QAEN,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAChC,MAAM,CAAC,QAAQ,CAAC,kCAAkC,EAAE,CAAC,KAAK,EAAE,EAAE,CAC5D,MAAM,CAAC,IAAI,CACT,IAAI,yBAAyB,CAAC;YAC5B,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,6CAA6C;YACtD,SAAS,EAAE,IAAI;YACf,UAAU;SACX,CAAC,CACH,CACF,CACF,CAAC;QAEF,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,kBAAkB,CAAC;QAC/D,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,IAAI,sBAAsB,CAAC;QAG3E,IAAI,UAAU,GAAG,wBAAwB,CAAC;QAE1C,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,SAAS,CAClC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACpC,UAAU,GAAG,EAAE,CAAC,MAAM,CAAC;YACvB,OAAO,EAAE,CAAC,MAAM,CAAC;QACnB,CAAC,CAAC,EACF,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,EACrD,CAAC,OAAO,EAAE,EAAE,CACV,IAAI,mCAAmC,CAAC;YACtC,UAAU;YACV,OAAO,EAAE,WAAW,UAAU,wBAAwB,OAAO,oBAAoB,UAAU,GAAG;YAC9F,UAAU;YACV,OAAO;SACR,CAAC,CACL,CAAC;QAGF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,SAAS;aAC7B,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC;aAC/D,IAAI,CACH,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,CAC3C,MAAM,CAAC,IAAI,CACT,IAAI,yBAAyB,CAAC;YAC5B,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,6BAA6B,KAAK,CAAC,OAAO,EAAE;YACrD,SAAS,EAAE,KAAK;YAChB,UAAU;SACX,CAAC,CACH,CACF,CACF,CAAC;QAEJ,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW;YACX,OAAO;YACP,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU;SACX,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,+BAA+B,CAAC,CAAC,QAAQ,CAAC,EACxE,SAA0B;QAE1B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAC3B,MAAM,EACN,CAAC,CAAC,EAAE,EAAE,CACJ,MAAM,CAAC,UAAU,CAAC;YAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC;YAClF,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC;SAC7C,CAAC,EACJ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAChE,CAAC;QAGF,IAAI,aAAa,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC,IAAI,CACpF,MAAM,CAAC,QAAQ,CAAC,2BAA2B,EAAE,CAAC,CAAC,EAAE,EAAE,CACjD,MAAM,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CACtE,CACF,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,UAAmB,EAAE,WAAW,EAAE,CAAC;QACpD,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,IAAI,CAC7E,MAAM,CAAC,QAAQ,CAAC,2BAA2B,EAAE,CAAC,CAAC,EAAE,EAAE,CACjD,MAAM,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CACtE,CACF,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,SAAkB,EAAE,UAAU,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,oBAAoB,GAAG,MAAM,CAAC,EAAE,CAAC,sCAAsC,CAAC,CAAC,QAAQ,CAAC,EACtF,WAAgB;QAEhB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,OAAO,CACxB,MAAM,EACN,CAAC,CAAC,EAAE,EAAE,CACJ,MAAM,CAAC,UAAU,CAAC;YAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,yBAAyB,CAAC;gBAC5B,KAAK;gBACL,OAAO,EAAE,yCAAyC,WAAW,EAAE;gBAC/D,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,WAAW;aACxB,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC;SACpD,CAAC,EACJ,CAAC,CAAC,EAAE,EAAE,CACJ,IAAI,yBAAyB,CAAC;YAC5B,KAAK,EAAE,CAAC;YACR,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,SAAS,EAAE,KAAK;YAChB,UAAU,EAAE,WAAW;SACxB,CAAC,CACL,CAAC;QAGF,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACvC,OAAO,MAAM,CAAC,IAAI,EAAO,CAAC;QAC5B,CAAC;QAED,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;QACrE,OAAO,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,MAAM,qBAAqB,GAAG,MAAM,CAAC,EAAE,CAAC,uCAAuC,CAAC,CAAC,QAAQ,CAAC,EACxF,WAAgB,EAChB,SAAsD,EAAE;QAExD,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,4BAA4B,CAAC;QACzE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,sBAAsB,CAAC;QAEzD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,SAAS,CAChC,oBAAoB,CAAC,WAAW,CAAC,EACjC,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,EACnC,CAAC,OAAO,EAAE,EAAE,CACV,IAAI,6BAA6B,CAAC;YAChC,OAAO,EAAE,2BAA2B,WAAW,yBAAyB,OAAO,IAAI;YACnF,WAAW;YACX,OAAO,EAAE,OAAO;SACjB,CAAC,CACL,CAAC;QAEF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,MAAM,qBAAqB,GAAG,MAAM,CAAC,EAAE,CAAC,uCAAuC,CAAC,CAC9E,QAAQ,CAAC;QACP,KAAK,CAAC,CAAC,OAAO,CACZ,MAAM,EACN,CAAC,CAAC,EAAE,EAAE,CACJ,MAAM,CAAC,UAAU,CAAC;YAChB,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,IAAI,yBAAyB,CAAC;gBAC5B,KAAK;gBACL,OAAO,EAAE,yCAAyC;aACnD,CAAC;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;SAC9D,CAAC,EACJ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,yBAAyB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CACvE,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,OAAO,eAAe,CAAC,EAAE,CAAC;QACxB,qBAAqB;QACrB,OAAO;QACP,oBAAoB;QACpB,KAAK;QACL,qBAAqB;QACrB,OAAO;QACP,aAAa;QACb,gBAAgB;KACjB,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC","sourcesContent":["import { TxManager } from \"@prb/effect-evm/tx\";\nimport { Effect, Layer, Option, Ref } from \"effect\";\nimport type { Hash, Hex } from \"viem\";\nimport { isAddress, isHash, isHex } from \"viem\";\nimport {\n SAFE_EXECUTION_TIMEOUT,\n SAFE_POLL_INTERVAL,\n SAFE_SIGNATURE_POLL_INTERVAL,\n SAFE_SIGNATURE_TIMEOUT,\n} from \"#src/constants/index.js\";\nimport type { SafeAppsSDKInstance, SafeAppsSdkConfig } from \"./adapter.js\";\nimport { loadSafeSdk } from \"./adapter.js\";\nimport type { SafeAppsSdkUnavailableError } from \"./errors.js\";\nimport {\n getSafeErrorMessage,\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeMultisigInfoUnavailableError,\n SafeMultisigSettingsError,\n SafeMultisigTxExecutionTimeoutError,\n SafeMultisigTxLookupError,\n SafeMultisigTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport { pollUntil } from \"./internal/poll.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { EIP712TypedData, SafeMultisigInfo, SafeMultisigTx } from \"./types.js\";\n\nexport type SafeAppsServiceConfig = SafeAppsSdkConfig;\n\n// --- Validation Factory ---\n\ntype Predicate<T extends string> = (value: string) => value is T;\n\nconst makeValidator =\n <T extends string>(predicate: Predicate<T>, label: string) =>\n (value: string, context: string): Effect.Effect<T, SafeMultisigTxLookupError> =>\n predicate(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeMultisigTxLookupError({\n message: `Invalid ${label} from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\nconst validateAddress = makeValidator(isAddress, \"address\");\nconst validateHash = makeValidator(isHash, \"hash\");\nconst validateHex = makeValidator(isHex, \"hex\");\n\n// --- SDK State ---\n\n/** SDK availability error - either SSR environment or SDK load failure */\ntype SdkUnavailableError = NotInSafeAppContextError | SafeAppsSdkUnavailableError;\n\n/** Internal SDK state for lazy loading */\ntype SdkState<T> =\n | { readonly _tag: \"pending\" }\n | { readonly _tag: \"loaded\"; readonly sdk: T }\n | { readonly _tag: \"unavailable\"; readonly error: SdkUnavailableError };\n\n// --- SDK Wrapper Helper ---\n\nconst withSdk = <A, E>(\n getSdk: Effect.Effect<SafeAppsSDKInstance, SdkUnavailableError>,\n fn: (sdk: SafeAppsSDKInstance) => Effect.Effect<A, E>,\n mapError: (e: SdkUnavailableError) => E\n): Effect.Effect<A, E> => Effect.flatMap(Effect.mapError(getSdk, mapError), fn);\n\n// --- Service Implementation ---\n\nexport const SafeAppsServiceLive = (config?: SafeAppsServiceConfig) =>\n Layer.scoped(\n SafeAppsService,\n Effect.gen(function* () {\n // Cache Safe info after first fetch\n const infoRef = yield* Ref.make<SafeMultisigInfo | null>(null);\n\n // Get TxManager for receipt waiting\n const txManager = yield* TxManager;\n\n const sdkRef = yield* Ref.make<SdkState<SafeAppsSDKInstance>>({ _tag: \"pending\" });\n\n /** Get SDK, loading lazily on first call. Fails if not in Safe App context. */\n const getSdk: Effect.Effect<SafeAppsSDKInstance, SdkUnavailableError> = Effect.gen(\n function* () {\n const state = yield* Ref.get(sdkRef);\n\n if (state._tag === \"loaded\") {\n return state.sdk;\n }\n if (state._tag === \"unavailable\") {\n return yield* Effect.fail(state.error);\n }\n\n // First call - check environment and load SDK\n if (typeof window === \"undefined\") {\n const error = new NotInSafeAppContextError({\n message: \"Safe Apps SDK requires a browser environment (window is undefined)\",\n });\n yield* Ref.set(sdkRef, { _tag: \"unavailable\", error });\n return yield* Effect.fail(error);\n }\n\n // Try to load SDK - catch SDK unavailable error and store it\n const loadResult = yield* loadSafeSdk(config).pipe(\n Effect.map((sdk) => ({ _tag: \"loaded\" as const, sdk })),\n Effect.catchTag(\"SafeAppsSdkUnavailableError\", (error) =>\n Effect.succeed({ _tag: \"unavailable\" as const, error } as const)\n )\n );\n\n yield* Ref.set(sdkRef, loadResult);\n\n if (loadResult._tag === \"unavailable\") {\n return yield* Effect.fail(loadResult.error);\n }\n\n return loadResult.sdk;\n }\n );\n\n // --- Service Methods ---\n\n const getInfo = Effect.fn(\"SafeAppsService.getInfo\")(function* () {\n const cached = yield* Ref.get(infoRef);\n if (cached) {\n return cached;\n }\n\n const sdk = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeMultisigInfoUnavailableError({\n cause,\n message: \"Failed to get Safe info from SDK\",\n }),\n try: () => s.safe.getInfo(),\n }),\n (e) => new SafeMultisigInfoUnavailableError({ cause: e, message: e.message })\n );\n\n const safeAddress = yield* validateAddress(sdk.safeAddress, \"getInfo\").pipe(\n Effect.catchTag(\"SafeMultisigTxLookupError\", (e) =>\n Effect.fail(new SafeMultisigInfoUnavailableError({ cause: e, message: e.message }))\n )\n );\n\n const safeInfo: SafeMultisigInfo = { chainId: sdk.chainId, safeAddress };\n yield* Ref.set(infoRef, safeInfo);\n return safeInfo;\n });\n\n const sendTxs = Effect.fn(\"SafeAppsService.sendTxs\")(function* (\n txs: readonly SafeMultisigTx[],\n params?: { safeTxGas?: number }\n ) {\n // Convert bigint values to strings (Safe SDK expects decimal strings)\n const sdkTxs = txs.map((tx) => ({\n data: tx.data,\n to: tx.to,\n value: tx.value?.toString() ?? \"0\",\n }));\n\n const result = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) => {\n const detail = getSafeErrorMessage(cause);\n return new SafeMultisigTxSubmissionError({\n cause,\n message: detail\n ? `Failed to submit txs to Safe: ${detail}`\n : \"Failed to submit txs to Safe\",\n });\n },\n try: () => s.txs.send({ params, txs: sdkTxs }),\n }),\n (e) => new SafeMultisigTxSubmissionError({ cause: e, message: e.message })\n );\n\n const safeTxHash = yield* validateHash(result.safeTxHash, \"sendTxs\").pipe(\n Effect.catchTag(\"SafeMultisigTxLookupError\", (e) =>\n Effect.fail(new SafeMultisigTxSubmissionError({ cause: e, message: e.message }))\n )\n );\n\n const info = yield* getInfo().pipe(\n Effect.catchTag(\"SafeMultisigInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeMultisigTxSubmissionError({\n cause: error,\n message: \"Failed to get Safe info after tx submission\",\n })\n )\n )\n );\n\n return { chainId: info.chainId, safeAddress: info.safeAddress, safeTxHash };\n });\n\n const getTx = Effect.fn(\"SafeAppsService.getTx\")(function* (safeTxHash: Hash) {\n const tx = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeMultisigTxLookupError({\n cause,\n message: `Failed to lookup Safe tx ${safeTxHash}`,\n retryable: true,\n safeTxHash,\n }),\n try: () => s.txs.getBySafeTxHash(safeTxHash),\n }),\n (e) =>\n new SafeMultisigTxLookupError({\n cause: e,\n message: e.message,\n retryable: false,\n safeTxHash,\n })\n );\n\n const txHash = tx.txHash ? yield* validateHash(tx.txHash, \"getTx\") : null;\n\n return {\n status: tx.txStatus ?? \"AWAITING_CONFIRMATIONS\",\n txHash: txHash ? Option.some(txHash) : Option.none<Hash>(),\n };\n });\n\n const waitForTxReceipt = Effect.fn(\"SafeAppsService.waitForTxReceipt\")(function* (\n safeTxHash: Hash,\n policy: {\n pollInterval?: number;\n executionTimeout?: number;\n receiptPolicy?: { receiptTimeout?: number; pollingInterval?: number };\n } = {}\n ) {\n const info = yield* getInfo().pipe(\n Effect.catchTag(\"SafeMultisigInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeMultisigTxLookupError({\n cause: error,\n message: \"Failed to get Safe info for receipt waiting\",\n retryable: true,\n safeTxHash,\n })\n )\n )\n );\n\n const pollInterval = policy.pollInterval ?? SAFE_POLL_INTERVAL;\n const executionTimeout = policy.executionTimeout ?? SAFE_EXECUTION_TIMEOUT;\n\n // Track last status for timeout error message\n let lastStatus = \"AWAITING_CONFIRMATIONS\";\n\n const onchainHash = yield* pollUntil(\n Effect.gen(function* () {\n const tx = yield* getTx(safeTxHash);\n lastStatus = tx.status;\n return tx.txHash;\n }),\n { interval: pollInterval, timeout: executionTimeout },\n (timeout) =>\n new SafeMultisigTxExecutionTimeoutError({\n lastStatus,\n message: `Safe tx ${safeTxHash} not executed within ${timeout}ms (last status: ${lastStatus})`,\n safeTxHash,\n timeout,\n })\n );\n\n // Delegate to TxManager for on-chain receipt\n const receipt = yield* txManager\n .waitForReceipt(info.chainId, onchainHash, policy.receiptPolicy)\n .pipe(\n Effect.catchTag(\"TxReplacedError\", (error) =>\n Effect.fail(\n new SafeMultisigTxLookupError({\n cause: error,\n message: `Transaction was replaced: ${error.message}`,\n retryable: false,\n safeTxHash,\n })\n )\n )\n );\n\n return {\n chainId: info.chainId,\n onchainHash,\n receipt,\n safeAddress: info.safeAddress,\n safeTxHash,\n };\n });\n\n const signTypedData = Effect.fn(\"SafeAppsService.signTypedData\")(function* (\n typedData: EIP712TypedData\n ) {\n const result = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SignTypedDataError({ cause, message: \"Failed to sign typed data via Safe\" }),\n try: () => s.txs.signTypedMessage(typedData),\n }),\n (e) => new SignTypedDataError({ cause: e, message: e.message })\n );\n\n // SDK returns { safeTxHash } for on-chain or { messageHash } for off-chain\n if (\"messageHash\" in result) {\n const messageHash = yield* validateHex(result.messageHash ?? \"\", \"signTypedData\").pipe(\n Effect.catchTag(\"SafeMultisigTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Offchain\" as const, messageHash };\n }\n\n const safeTxHash = yield* validateHash(result.safeTxHash, \"signTypedData\").pipe(\n Effect.catchTag(\"SafeMultisigTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Onchain\" as const, safeTxHash };\n });\n\n const getOffchainSignature = Effect.fn(\"SafeAppsService.getOffchainSignature\")(function* (\n messageHash: Hex\n ) {\n const sig = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeMultisigTxLookupError({\n cause,\n message: `Failed to get off-chain signature for ${messageHash}`,\n retryable: true,\n safeTxHash: messageHash,\n }),\n try: () => s.safe.getOffChainSignature(messageHash),\n }),\n (e) =>\n new SafeMultisigTxLookupError({\n cause: e,\n message: e.message,\n retryable: false,\n safeTxHash: messageHash,\n })\n );\n\n // Empty string or \"0x\" means signature not yet available\n if (!sig || sig === \"\" || sig === \"0x\") {\n return Option.none<Hex>();\n }\n\n const validatedSig = yield* validateHex(sig, \"getOffchainSignature\");\n return Option.some(validatedSig);\n });\n\n const pollOffchainSignature = Effect.fn(\"SafeAppsService.pollOffchainSignature\")(function* (\n messageHash: Hex,\n policy: { pollInterval?: number; timeout?: number } = {}\n ) {\n const pollInterval = policy.pollInterval ?? SAFE_SIGNATURE_POLL_INTERVAL;\n const timeout = policy.timeout ?? SAFE_SIGNATURE_TIMEOUT;\n\n const signature = yield* pollUntil(\n getOffchainSignature(messageHash),\n { interval: pollInterval, timeout },\n (elapsed) =>\n new OffchainSignatureTimeoutError({\n message: `Off-chain signature for ${messageHash} not available within ${elapsed}ms`,\n messageHash,\n timeout: elapsed,\n })\n );\n\n return { messageHash, signature };\n });\n\n const enableOffchainSigning = Effect.fn(\"SafeAppsService.enableOffchainSigning\")(\n function* () {\n yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeMultisigSettingsError({\n cause,\n message: \"Failed to enable off-chain signing mode\",\n }),\n try: () => s.eth.setSafeSettings([{ offChainSigning: true }]),\n }),\n (e) => new SafeMultisigSettingsError({ cause: e, message: e.message })\n );\n }\n );\n\n return SafeAppsService.of({\n enableOffchainSigning,\n getInfo,\n getOffchainSignature,\n getTx,\n pollOffchainSignature,\n sendTxs,\n signTypedData,\n waitForTxReceipt,\n });\n })\n );\n"]}
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"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","sourcesContent":["import { TxManager } from \"@prb/effect-evm/tx\";\nimport { Effect, Layer, Option, Ref } from \"effect\";\nimport type { Hash, Hex } from \"viem\";\nimport { isAddress, isHash, isHex } from \"viem\";\nimport {\n SAFE_EXECUTION_TIMEOUT,\n SAFE_POLL_INTERVAL,\n SAFE_SIGNATURE_POLL_INTERVAL,\n SAFE_SIGNATURE_TIMEOUT,\n} from \"#src/constants/index.js\";\nimport type { SafeAppsSDKInstance, SafeAppsSdkConfig } from \"./adapter.js\";\nimport { loadSafeSdk } from \"./adapter.js\";\nimport type { SafeAppsSdkUnavailableError } from \"./errors.js\";\nimport {\n getSafeErrorMessage,\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeMultisigInfoUnavailableError,\n SafeMultisigSettingsError,\n SafeMultisigTxExecutionTimeoutError,\n SafeMultisigTxLookupError,\n SafeMultisigTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport { pollUntil } from \"./internal/poll.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { EIP712TypedData, SafeMultisigInfo, SafeMultisigTx } from \"./types.js\";\n\nexport type SafeAppsServiceConfig = SafeAppsSdkConfig;\n\n// --- Validation Factory ---\n\ntype Predicate<T extends string> = (value: string) => value is T;\n\nconst makeValidator =\n <T extends string>(predicate: Predicate<T>, label: string) =>\n (value: string, context: string): Effect.Effect<T, SafeMultisigTxLookupError> =>\n predicate(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeMultisigTxLookupError({\n message: `Invalid ${label} from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\nconst validateAddress = makeValidator(isAddress, \"address\");\nconst validateHash = makeValidator(isHash, \"hash\");\nconst validateHex = makeValidator(isHex, \"hex\");\n\n// --- SDK State ---\n\n/** SDK availability error - either SSR environment or SDK load failure */\ntype SdkUnavailableError = NotInSafeAppContextError | SafeAppsSdkUnavailableError;\n\n/** Internal SDK state for lazy loading */\ntype SdkState<T> =\n | { readonly _tag: \"pending\" }\n | { readonly _tag: \"loaded\"; readonly sdk: T }\n | { readonly _tag: \"unavailable\"; readonly error: SdkUnavailableError };\n\n// --- SDK Wrapper Helper ---\n\nconst withSdk = <A, E>(\n getSdk: Effect.Effect<SafeAppsSDKInstance, SdkUnavailableError>,\n fn: (sdk: SafeAppsSDKInstance) => Effect.Effect<A, E>,\n mapError: (e: SdkUnavailableError) => E\n): Effect.Effect<A, E> => Effect.flatMap(Effect.mapError(getSdk, mapError), fn);\n\n// --- Service Implementation ---\n\nexport const SafeAppsServiceLive = (config?: SafeAppsServiceConfig) =>\n Layer.scoped(\n SafeAppsService,\n Effect.gen(function* () {\n // Cache Safe info after first fetch\n const infoRef = yield* Ref.make<SafeMultisigInfo | null>(null);\n\n // Get TxManager for receipt waiting\n const txManager = yield* TxManager;\n\n const sdkRef = yield* Ref.make<SdkState<SafeAppsSDKInstance>>({ _tag: \"pending\" });\n\n /** Get SDK, loading lazily on first call. Fails if not in Safe App context. */\n const getSdk: Effect.Effect<SafeAppsSDKInstance, SdkUnavailableError> = Effect.gen(\n function* () {\n const state = yield* Ref.get(sdkRef);\n\n if (state._tag === \"loaded\") {\n return state.sdk;\n }\n if (state._tag === \"unavailable\") {\n return yield* Effect.fail(state.error);\n }\n\n // First call - check environment and load SDK\n if (typeof window === \"undefined\") {\n const error = new NotInSafeAppContextError({\n message: \"Safe Apps SDK requires a browser environment (window is undefined)\",\n });\n yield* Ref.set(sdkRef, { _tag: \"unavailable\", error });\n return yield* Effect.fail(error);\n }\n\n // Try to load SDK - catch SDK unavailable error and store it\n const loadResult = yield* loadSafeSdk(config).pipe(\n Effect.map((sdk) => ({ _tag: \"loaded\" as const, sdk })),\n Effect.catchTag(\"SafeAppsSdkUnavailableError\", (error) =>\n Effect.succeed({ _tag: \"unavailable\" as const, error } as const)\n )\n );\n\n yield* Ref.set(sdkRef, loadResult);\n\n if (loadResult._tag === \"unavailable\") {\n return yield* Effect.fail(loadResult.error);\n }\n\n return loadResult.sdk;\n }\n );\n\n // --- Service Methods ---\n\n const getInfo = Effect.fn(\"SafeAppsService.getInfo\")(function* () {\n const cached = yield* Ref.get(infoRef);\n if (cached) {\n return cached;\n }\n\n const sdk = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeMultisigInfoUnavailableError({\n cause,\n message: \"Failed to get Safe info from SDK\",\n }),\n try: () => s.safe.getInfo(),\n }),\n (e) => new SafeMultisigInfoUnavailableError({ cause: e, message: e.message })\n );\n\n const safeAddress = yield* validateAddress(sdk.safeAddress, \"getInfo\").pipe(\n Effect.catchTag(\"SafeMultisigTxLookupError\", (e) =>\n Effect.fail(new SafeMultisigInfoUnavailableError({ cause: e, message: e.message }))\n )\n );\n\n const safeInfo: SafeMultisigInfo = { chainId: sdk.chainId, safeAddress };\n yield* Ref.set(infoRef, safeInfo);\n return safeInfo;\n });\n\n const sendTxs = Effect.fn(\"SafeAppsService.sendTxs\")(function* (\n txs: readonly SafeMultisigTx[],\n params?: { safeTxGas?: number }\n ) {\n // Convert bigint values to strings (Safe SDK expects decimal strings)\n const sdkTxs = txs.map((tx) => ({\n data: tx.data,\n to: tx.to,\n value: tx.value?.toString() ?? \"0\",\n }));\n\n const result = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) => {\n const detail = getSafeErrorMessage(cause);\n return new SafeMultisigTxSubmissionError({\n cause,\n message: detail\n ? `Failed to submit txs to Safe: ${detail}`\n : \"Failed to submit txs to Safe\",\n });\n },\n try: () => s.txs.send({ params, txs: sdkTxs }),\n }),\n (e) => new SafeMultisigTxSubmissionError({ cause: e, message: e.message })\n );\n\n const safeTxHash = yield* validateHash(result.safeTxHash, \"sendTxs\").pipe(\n Effect.catchTag(\"SafeMultisigTxLookupError\", (e) =>\n Effect.fail(new SafeMultisigTxSubmissionError({ cause: e, message: e.message }))\n )\n );\n\n const info = yield* getInfo().pipe(\n Effect.catchTag(\"SafeMultisigInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeMultisigTxSubmissionError({\n cause: error,\n message: \"Failed to get Safe info after tx submission\",\n })\n )\n )\n );\n\n return { chainId: info.chainId, safeAddress: info.safeAddress, safeTxHash };\n });\n\n const getTx = Effect.fn(\"SafeAppsService.getTx\")(function* (safeTxHash: Hash) {\n const tx = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeMultisigTxLookupError({\n cause,\n message: `Failed to lookup Safe tx ${safeTxHash}`,\n retryable: true,\n safeTxHash,\n }),\n try: () => s.txs.getBySafeTxHash(safeTxHash),\n }),\n (e) =>\n new SafeMultisigTxLookupError({\n cause: e,\n message: e.message,\n retryable: false,\n safeTxHash,\n })\n );\n\n const txHash = tx.txHash ? yield* validateHash(tx.txHash, \"getTx\") : null;\n const executionInfo = tx.detailedExecutionInfo;\n const hasMultisigExecutionInfo =\n executionInfo !== undefined &&\n executionInfo !== null &&\n executionInfo.type === \"MULTISIG\";\n\n return {\n confirmations: hasMultisigExecutionInfo ? executionInfo.confirmations.length : null,\n confirmationsRequired: hasMultisigExecutionInfo\n ? executionInfo.confirmationsRequired\n : null,\n onchainHash: txHash ? Option.some(txHash) : Option.none<Hash>(),\n status: tx.txStatus ?? \"AWAITING_CONFIRMATIONS\",\n };\n });\n\n const waitForTxReceipt = Effect.fn(\"SafeAppsService.waitForTxReceipt\")(function* (\n safeTxHash: Hash,\n policy: {\n pollInterval?: number;\n executionTimeout?: number;\n receiptPolicy?: { receiptTimeout?: number; pollingInterval?: number };\n } = {}\n ) {\n const info = yield* getInfo().pipe(\n Effect.catchTag(\"SafeMultisigInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeMultisigTxLookupError({\n cause: error,\n message: \"Failed to get Safe info for receipt waiting\",\n retryable: true,\n safeTxHash,\n })\n )\n )\n );\n\n const pollInterval = policy.pollInterval ?? SAFE_POLL_INTERVAL;\n const executionTimeout = policy.executionTimeout ?? SAFE_EXECUTION_TIMEOUT;\n\n // Track last status for timeout error message\n let lastStatus = \"AWAITING_CONFIRMATIONS\";\n\n const onchainHash = yield* pollUntil(\n Effect.gen(function* () {\n const tx = yield* getTx(safeTxHash);\n lastStatus = tx.status;\n return tx.onchainHash;\n }),\n { interval: pollInterval, timeout: executionTimeout },\n (timeout) =>\n new SafeMultisigTxExecutionTimeoutError({\n lastStatus,\n message: `Safe tx ${safeTxHash} not executed within ${timeout}ms (last status: ${lastStatus})`,\n safeTxHash,\n timeout,\n })\n );\n\n // Delegate to TxManager for on-chain receipt\n const receipt = yield* txManager\n .waitForReceipt(info.chainId, onchainHash, policy.receiptPolicy)\n .pipe(\n Effect.catchTag(\"TxReplacedError\", (error) =>\n Effect.fail(\n new SafeMultisigTxLookupError({\n cause: error,\n message: `Transaction was replaced: ${error.message}`,\n retryable: false,\n safeTxHash,\n })\n )\n )\n );\n\n return {\n chainId: info.chainId,\n onchainHash,\n receipt,\n safeAddress: info.safeAddress,\n safeTxHash,\n };\n });\n\n const signTypedData = Effect.fn(\"SafeAppsService.signTypedData\")(function* (\n typedData: EIP712TypedData\n ) {\n const result = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SignTypedDataError({ cause, message: \"Failed to sign typed data via Safe\" }),\n try: () => s.txs.signTypedMessage(typedData),\n }),\n (e) => new SignTypedDataError({ cause: e, message: e.message })\n );\n\n // SDK returns { safeTxHash } for on-chain or { messageHash } for off-chain\n if (\"messageHash\" in result) {\n const messageHash = yield* validateHex(result.messageHash ?? \"\", \"signTypedData\").pipe(\n Effect.catchTag(\"SafeMultisigTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Offchain\" as const, messageHash };\n }\n\n const safeTxHash = yield* validateHash(result.safeTxHash, \"signTypedData\").pipe(\n Effect.catchTag(\"SafeMultisigTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Onchain\" as const, safeTxHash };\n });\n\n const getOffchainSignature = Effect.fn(\"SafeAppsService.getOffchainSignature\")(function* (\n messageHash: Hex\n ) {\n const sig = yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeMultisigTxLookupError({\n cause,\n message: `Failed to get off-chain signature for ${messageHash}`,\n retryable: true,\n safeTxHash: messageHash,\n }),\n try: () => s.safe.getOffChainSignature(messageHash),\n }),\n (e) =>\n new SafeMultisigTxLookupError({\n cause: e,\n message: e.message,\n retryable: false,\n safeTxHash: messageHash,\n })\n );\n\n // Empty string or \"0x\" means signature not yet available\n if (!sig || sig === \"\" || sig === \"0x\") {\n return Option.none<Hex>();\n }\n\n const validatedSig = yield* validateHex(sig, \"getOffchainSignature\");\n return Option.some(validatedSig);\n });\n\n const pollOffchainSignature = Effect.fn(\"SafeAppsService.pollOffchainSignature\")(function* (\n messageHash: Hex,\n policy: { pollInterval?: number; timeout?: number } = {}\n ) {\n const pollInterval = policy.pollInterval ?? SAFE_SIGNATURE_POLL_INTERVAL;\n const timeout = policy.timeout ?? SAFE_SIGNATURE_TIMEOUT;\n\n const signature = yield* pollUntil(\n getOffchainSignature(messageHash),\n { interval: pollInterval, timeout },\n (elapsed) =>\n new OffchainSignatureTimeoutError({\n message: `Off-chain signature for ${messageHash} not available within ${elapsed}ms`,\n messageHash,\n timeout: elapsed,\n })\n );\n\n return { messageHash, signature };\n });\n\n const enableOffchainSigning = Effect.fn(\"SafeAppsService.enableOffchainSigning\")(\n function* () {\n yield* withSdk(\n getSdk,\n (s) =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeMultisigSettingsError({\n cause,\n message: \"Failed to enable off-chain signing mode\",\n }),\n try: () => s.eth.setSafeSettings([{ offChainSigning: true }]),\n }),\n (e) => new SafeMultisigSettingsError({ cause: e, message: e.message })\n );\n }\n );\n\n return SafeAppsService.of({\n enableOffchainSigning,\n getInfo,\n getOffchainSignature,\n getTx,\n pollOffchainSignature,\n sendTxs,\n signTypedData,\n waitForTxReceipt,\n });\n })\n );\n"]}
@@ -3,16 +3,13 @@ import type { Effect, Option } from "effect";
3
3
  import { Context } from "effect";
4
4
  import type { Hash, Hex } from "viem";
5
5
  import type { OffchainSignatureTimeoutError, SafeMultisigInfoUnavailableError, SafeMultisigSettingsError, SafeMultisigTxExecutionTimeoutError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError, SignTypedDataError } from "./errors.js";
6
- import type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeMultisigInfo, SafeMultisigTx, SafeMultisigTxResult, SafeMultisigTxSubmission, SafeWaitPolicy, SignTypedDataResult } from "./types.js";
6
+ import type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeMultisigInfo, SafeMultisigTx, SafeMultisigTxInfo, SafeMultisigTxResult, SafeMultisigTxSubmission, SafeWaitPolicy, SignTypedDataResult } from "./types.js";
7
7
  export type SafeAppsServiceShape = {
8
8
  readonly getInfo: () => Effect.Effect<SafeMultisigInfo, SafeMultisigInfoUnavailableError>;
9
9
  readonly sendTxs: (txs: readonly SafeMultisigTx[], params?: {
10
10
  safeTxGas?: number;
11
11
  }) => Effect.Effect<SafeMultisigTxSubmission, SafeMultisigTxSubmissionError>;
12
- readonly getTx: (safeTxHash: Hash) => Effect.Effect<{
13
- txHash: Option.Option<Hash>;
14
- status: string;
15
- }, SafeMultisigTxLookupError>;
12
+ readonly getTx: (safeTxHash: Hash) => Effect.Effect<SafeMultisigTxInfo, SafeMultisigTxLookupError>;
16
13
  readonly waitForTxReceipt: (safeTxHash: Hash, policy?: SafeWaitPolicy) => Effect.Effect<SafeMultisigTxResult, SafeMultisigTxExecutionTimeoutError | SafeMultisigTxLookupError | TxFailedError | ReceiptTimeoutError | ClientNotFoundError>;
17
14
  readonly signTypedData: (typedData: EIP712TypedData) => Effect.Effect<SignTypedDataResult, SignTypedDataError>;
18
15
  readonly getOffchainSignature: (messageHash: Hex) => Effect.Effect<Option.Option<Hex>, SafeMultisigTxLookupError>;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACd,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,KAAK,EACV,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IAEjC,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,gCAAgC,CAAC,CAAC;IAG1F,QAAQ,CAAC,OAAO,EAAE,CAChB,GAAG,EAAE,SAAS,cAAc,EAAE,EAC9B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,MAAM,CAAC,MAAM,CAAC,wBAAwB,EAAE,6BAA6B,CAAC,CAAC;IAG5E,QAAQ,CAAC,KAAK,EAAE,CACd,UAAU,EAAE,IAAI,KACb,MAAM,CAAC,MAAM,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,yBAAyB,CAAC,CAAC;IAG/F,QAAQ,CAAC,gBAAgB,EAAE,CACzB,UAAU,EAAE,IAAI,EAChB,MAAM,CAAC,EAAE,cAAc,KACpB,MAAM,CAAC,MAAM,CAChB,oBAAoB,EAClB,mCAAmC,GACnC,yBAAyB,GACzB,aAAa,GACb,mBAAmB,GACnB,mBAAmB,CACtB,CAAC;IAGF,QAAQ,CAAC,aAAa,EAAE,CACtB,SAAS,EAAE,eAAe,KACvB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;IAG5D,QAAQ,CAAC,oBAAoB,EAAE,CAC7B,WAAW,EAAE,GAAG,KACb,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,yBAAyB,CAAC,CAAC;IAGlE,QAAQ,CAAC,qBAAqB,EAAE,CAC9B,WAAW,EAAE,GAAG,EAChB,MAAM,CAAC,EAAE,uBAAuB,KAC7B,MAAM,CAAC,MAAM,CAChB,uBAAuB,EACvB,6BAA6B,GAAG,yBAAyB,CAC1D,CAAC;IAGF,QAAQ,CAAC,qBAAqB,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;CACtF,CAAC;;AAEF,qBAAa,eAAgB,SAAQ,oBAGlC;CAAG"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACd,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,KAAK,EACV,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,yBAAyB,EACzB,6BAA6B,EAC7B,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IAEjC,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,gCAAgC,CAAC,CAAC;IAG1F,QAAQ,CAAC,OAAO,EAAE,CAChB,GAAG,EAAE,SAAS,cAAc,EAAE,EAC9B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,MAAM,CAAC,MAAM,CAAC,wBAAwB,EAAE,6BAA6B,CAAC,CAAC;IAG5E,QAAQ,CAAC,KAAK,EAAE,CACd,UAAU,EAAE,IAAI,KACb,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,yBAAyB,CAAC,CAAC;IAGlE,QAAQ,CAAC,gBAAgB,EAAE,CACzB,UAAU,EAAE,IAAI,EAChB,MAAM,CAAC,EAAE,cAAc,KACpB,MAAM,CAAC,MAAM,CAChB,oBAAoB,EAClB,mCAAmC,GACnC,yBAAyB,GACzB,aAAa,GACb,mBAAmB,GACnB,mBAAmB,CACtB,CAAC;IAGF,QAAQ,CAAC,aAAa,EAAE,CACtB,SAAS,EAAE,eAAe,KACvB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;IAG5D,QAAQ,CAAC,oBAAoB,EAAE,CAC7B,WAAW,EAAE,GAAG,KACb,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,yBAAyB,CAAC,CAAC;IAGlE,QAAQ,CAAC,qBAAqB,EAAE,CAC9B,WAAW,EAAE,GAAG,EAChB,MAAM,CAAC,EAAE,uBAAuB,KAC7B,MAAM,CAAC,MAAM,CAChB,uBAAuB,EACvB,6BAA6B,GAAG,yBAAyB,CAC1D,CAAC;IAGF,QAAQ,CAAC,qBAAqB,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;CACtF,CAAC;;AAEF,qBAAa,eAAgB,SAAQ,oBAGlC;CAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AA0EjC,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAG7D;CAAG","sourcesContent":["import type {\n ClientNotFoundError,\n ReceiptTimeoutError,\n TxFailedError,\n} from \"@prb/effect-evm/core/errors\";\nimport type { Effect, Option } from \"effect\";\nimport { Context } from \"effect\";\nimport type { Hash, Hex } from \"viem\";\nimport type {\n OffchainSignatureTimeoutError,\n SafeMultisigInfoUnavailableError,\n SafeMultisigSettingsError,\n SafeMultisigTxExecutionTimeoutError,\n SafeMultisigTxLookupError,\n SafeMultisigTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeMultisigInfo,\n SafeMultisigTx,\n SafeMultisigTxResult,\n SafeMultisigTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\n\nexport type SafeAppsServiceShape = {\n /** Get Safe info (cached after first call) */\n readonly getInfo: () => Effect.Effect<SafeMultisigInfo, SafeMultisigInfoUnavailableError>;\n\n /** Send txs to Safe for execution */\n readonly sendTxs: (\n txs: readonly SafeMultisigTx[],\n params?: { safeTxGas?: number }\n ) => Effect.Effect<SafeMultisigTxSubmission, SafeMultisigTxSubmissionError>;\n\n /** Get Safe tx details by safeTxHash */\n readonly getTx: (\n safeTxHash: Hash\n ) => Effect.Effect<{ txHash: Option.Option<Hash>; status: string }, SafeMultisigTxLookupError>;\n\n /** Wait for Safe tx to execute and return receipt */\n readonly waitForTxReceipt: (\n safeTxHash: Hash,\n policy?: SafeWaitPolicy\n ) => Effect.Effect<\n SafeMultisigTxResult,\n | SafeMultisigTxExecutionTimeoutError\n | SafeMultisigTxLookupError\n | TxFailedError\n | ReceiptTimeoutError\n | ClientNotFoundError\n >;\n\n /** Sign typed data (returns discriminated union based on Safe settings) */\n readonly signTypedData: (\n typedData: EIP712TypedData\n ) => Effect.Effect<SignTypedDataResult, SignTypedDataError>;\n\n /** Get off-chain signature (returns Option.none if not yet available) */\n readonly getOffchainSignature: (\n messageHash: Hex\n ) => Effect.Effect<Option.Option<Hex>, SafeMultisigTxLookupError>;\n\n /** Poll for off-chain signature until available or timeout */\n readonly pollOffchainSignature: (\n messageHash: Hex,\n policy?: OffchainSignaturePolicy\n ) => Effect.Effect<\n OffchainSignatureResult,\n OffchainSignatureTimeoutError | SafeMultisigTxLookupError\n >;\n\n /** Enable off-chain signing mode */\n readonly enableOffchainSigning: () => Effect.Effect<void, SafeMultisigSettingsError>;\n};\n\nexport class SafeAppsService extends Context.Tag(\"ew3/SafeApps\")<\n SafeAppsService,\n SafeAppsServiceShape\n>() {}\n"]}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AA2EjC,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAG7D;CAAG","sourcesContent":["import type {\n ClientNotFoundError,\n ReceiptTimeoutError,\n TxFailedError,\n} from \"@prb/effect-evm/core/errors\";\nimport type { Effect, Option } from \"effect\";\nimport { Context } from \"effect\";\nimport type { Hash, Hex } from \"viem\";\nimport type {\n OffchainSignatureTimeoutError,\n SafeMultisigInfoUnavailableError,\n SafeMultisigSettingsError,\n SafeMultisigTxExecutionTimeoutError,\n SafeMultisigTxLookupError,\n SafeMultisigTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport 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\nexport type SafeAppsServiceShape = {\n /** Get Safe info (cached after first call) */\n readonly getInfo: () => Effect.Effect<SafeMultisigInfo, SafeMultisigInfoUnavailableError>;\n\n /** Send txs to Safe for execution */\n readonly sendTxs: (\n txs: readonly SafeMultisigTx[],\n params?: { safeTxGas?: number }\n ) => Effect.Effect<SafeMultisigTxSubmission, SafeMultisigTxSubmissionError>;\n\n /** Get Safe tx details by safeTxHash (status, onchain hash, confirmations metadata) */\n readonly getTx: (\n safeTxHash: Hash\n ) => Effect.Effect<SafeMultisigTxInfo, SafeMultisigTxLookupError>;\n\n /** Wait for Safe tx to execute and return receipt */\n readonly waitForTxReceipt: (\n safeTxHash: Hash,\n policy?: SafeWaitPolicy\n ) => Effect.Effect<\n SafeMultisigTxResult,\n | SafeMultisigTxExecutionTimeoutError\n | SafeMultisigTxLookupError\n | TxFailedError\n | ReceiptTimeoutError\n | ClientNotFoundError\n >;\n\n /** Sign typed data (returns discriminated union based on Safe settings) */\n readonly signTypedData: (\n typedData: EIP712TypedData\n ) => Effect.Effect<SignTypedDataResult, SignTypedDataError>;\n\n /** Get off-chain signature (returns Option.none if not yet available) */\n readonly getOffchainSignature: (\n messageHash: Hex\n ) => Effect.Effect<Option.Option<Hex>, SafeMultisigTxLookupError>;\n\n /** Poll for off-chain signature until available or timeout */\n readonly pollOffchainSignature: (\n messageHash: Hex,\n policy?: OffchainSignaturePolicy\n ) => Effect.Effect<\n OffchainSignatureResult,\n OffchainSignatureTimeoutError | SafeMultisigTxLookupError\n >;\n\n /** Enable off-chain signing mode */\n readonly enableOffchainSigning: () => Effect.Effect<void, SafeMultisigSettingsError>;\n};\n\nexport class SafeAppsService extends Context.Tag(\"ew3/SafeApps\")<\n SafeAppsService,\n SafeAppsServiceShape\n>() {}\n"]}
@@ -33,8 +33,10 @@ const makeMockSafeAppsService = (config) => {
33
33
  getInfo: () => Effect.succeed(config.getInfoResult ?? defaultInfo),
34
34
  getOffchainSignature: () => Effect.succeed(config.offchainSignature ?? Option.none()),
35
35
  getTx: () => Effect.succeed(config.getTxResult ?? {
36
+ confirmations: 1,
37
+ confirmationsRequired: 2,
38
+ onchainHash: Option.some(TEST_TX_HASH),
36
39
  status: "AWAITING_EXECUTION",
37
- txHash: Option.some(TEST_TX_HASH),
38
40
  }),
39
41
  pollOffchainSignature: (messageHash) => Effect.succeed({ messageHash, signature: TEST_SIGNATURE }),
40
42
  sendTxs: () => Effect.succeed({
@@ -77,20 +79,26 @@ describe("SafeAppsService", () => {
77
79
  it.effect("returns txHash as Option when executed", () => Effect.gen(function* () {
78
80
  const service = yield* SafeAppsService;
79
81
  const result = yield* service.getTx(TEST_SAFE_TX_HASH);
80
- expect(Option.isSome(result.txHash)).toBe(true);
81
- if (Option.isSome(result.txHash)) {
82
- expect(result.txHash.value).toBe(TEST_TX_HASH);
82
+ expect(Option.isSome(result.onchainHash)).toBe(true);
83
+ expect(result.confirmations).toBe(1);
84
+ expect(result.confirmationsRequired).toBe(2);
85
+ if (Option.isSome(result.onchainHash)) {
86
+ expect(result.onchainHash.value).toBe(TEST_TX_HASH);
83
87
  }
84
88
  }).pipe(Effect.provide(makeMockSafeAppsService({}))));
85
- it.effect("returns Option.none when not yet executed", () => Effect.gen(function* () {
89
+ it.effect("returns Option.none on onchainHash when not yet executed", () => Effect.gen(function* () {
86
90
  const service = yield* SafeAppsService;
87
91
  const result = yield* service.getTx(TEST_SAFE_TX_HASH);
88
- expect(Option.isNone(result.txHash)).toBe(true);
92
+ expect(Option.isNone(result.onchainHash)).toBe(true);
93
+ expect(result.confirmations).toBe(0);
94
+ expect(result.confirmationsRequired).toBe(3);
89
95
  expect(result.status).toBe("AWAITING_CONFIRMATIONS");
90
96
  }).pipe(Effect.provide(makeMockSafeAppsService({
91
97
  getTxResult: {
98
+ confirmations: 0,
99
+ confirmationsRequired: 3,
100
+ onchainHash: Option.none(),
92
101
  status: "AWAITING_CONFIRMATIONS",
93
- txHash: Option.none(),
94
102
  },
95
103
  }))));
96
104
  });
@@ -1 +1 @@
1
- {"version":3,"file":"service.test.integration.js","sourceRoot":"","sources":["../../src/safe/service.test.integration.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"@effect/vitest\";\nimport { MIN_TX_GAS } from \"@prb/effect-evm/constants\";\nimport { TEST_ADDRESS, TEST_CHAIN_ID, TEST_TX_HASH } from \"@prb/effect-evm/testing-kit\";\nimport { Effect, Layer, Option } from \"effect\";\nimport type { Hash, Hex, TransactionReceipt } from \"viem\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { SafeMultisigInfo } from \"./types.js\";\n\n// Test fixtures\nconst TEST_SAFE_ADDRESS = TEST_ADDRESS;\nconst TEST_SAFE_TX_HASH =\n \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\" as Hash;\nconst TEST_MESSAGE_HASH =\n \"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890\" as Hex;\nconst TEST_SIGNATURE = \"0xsignature\" as Hex;\n\nconst TEST_RECEIPT: TransactionReceipt = {\n blockHash: \"0xblock\",\n blockNumber: 123n,\n contractAddress: null,\n cumulativeGasUsed: MIN_TX_GAS,\n effectiveGasPrice: 1n,\n from: \"0xfrom\",\n gasUsed: MIN_TX_GAS,\n logs: [],\n logsBloom: \"0x\",\n status: \"success\",\n to: \"0xto\",\n transactionHash: TEST_TX_HASH,\n transactionIndex: 0,\n type: \"0x2\",\n};\n\n// Mock SafeAppsService for testing without actual SDK\nconst makeMockSafeAppsService = (config: {\n getInfoResult?: SafeMultisigInfo;\n sendTxResult?: { safeTxHash: Hash };\n getTxResult?: { txHash: Option.Option<Hash>; status: string };\n signTypedDataResult?:\n | { _tag: \"Offchain\"; messageHash: Hex }\n | { _tag: \"Onchain\"; safeTxHash: Hash };\n offchainSignature?: Option.Option<Hex>;\n}) => {\n const defaultInfo: SafeMultisigInfo = {\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n };\n\n return Layer.succeed(\n SafeAppsService,\n SafeAppsService.of({\n enableOffchainSigning: () => Effect.void,\n getInfo: () => Effect.succeed(config.getInfoResult ?? defaultInfo),\n getOffchainSignature: () => Effect.succeed(config.offchainSignature ?? Option.none()),\n getTx: () =>\n Effect.succeed(\n config.getTxResult ?? {\n status: \"AWAITING_EXECUTION\",\n txHash: Option.some(TEST_TX_HASH),\n }\n ),\n pollOffchainSignature: (messageHash) =>\n Effect.succeed({ messageHash, signature: TEST_SIGNATURE }),\n sendTxs: () =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash: config.sendTxResult?.safeTxHash ?? TEST_SAFE_TX_HASH,\n }),\n signTypedData: () =>\n Effect.succeed(\n config.signTypedDataResult ?? {\n _tag: \"Onchain\" as const,\n safeTxHash: TEST_SAFE_TX_HASH,\n }\n ),\n waitForTxReceipt: (safeTxHash) =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n onchainHash: TEST_TX_HASH,\n receipt: TEST_RECEIPT,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash,\n }),\n })\n );\n};\n\ndescribe(\"SafeAppsService\", () => {\n describe(\"getInfo\", () => {\n it.effect(\"returns Safe info with address and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const info = yield* service.getInfo();\n\n expect(info.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(info.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"sendTxs\", () => {\n it.effect(\"returns safeTxHash with safeAddress and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.sendTxs([{ data: \"0x\", to: TEST_ADDRESS, value: 0n }]);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"getTx\", () => {\n it.effect(\"returns txHash as Option when executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTx(TEST_SAFE_TX_HASH);\n\n expect(Option.isSome(result.txHash)).toBe(true);\n if (Option.isSome(result.txHash)) {\n expect(result.txHash.value).toBe(TEST_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.none when not yet executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTx(TEST_SAFE_TX_HASH);\n\n expect(Option.isNone(result.txHash)).toBe(true);\n expect(result.status).toBe(\"AWAITING_CONFIRMATIONS\");\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n getTxResult: {\n status: \"AWAITING_CONFIRMATIONS\",\n txHash: Option.none(),\n },\n })\n )\n )\n );\n });\n\n describe(\"waitForTxReceipt\", () => {\n it.effect(\"returns SafeTxResult with receipt\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.waitForTxReceipt(TEST_SAFE_TX_HASH);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.onchainHash).toBe(TEST_TX_HASH);\n expect(result.receipt.status).toBe(\"success\");\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"signTypedData\", () => {\n it.effect(\"returns Onchain variant for on-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Onchain\");\n if (result._tag === \"Onchain\") {\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Offchain variant for off-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Offchain\");\n if (result._tag === \"Offchain\") {\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n signTypedDataResult: {\n _tag: \"Offchain\",\n messageHash: TEST_MESSAGE_HASH,\n },\n })\n )\n )\n );\n });\n\n describe(\"getOffchainSignature\", () => {\n it.effect(\"returns Option.none when signature not yet available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isNone(result)).toBe(true);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.some when signature available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isSome(result)).toBe(true);\n if (Option.isSome(result)) {\n expect(result.value).toBe(TEST_SIGNATURE);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n offchainSignature: Option.some(TEST_SIGNATURE),\n })\n )\n )\n );\n });\n\n describe(\"pollOffchainSignature\", () => {\n it.effect(\"returns signature when available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.pollOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n expect(result.signature).toBe(TEST_SIGNATURE);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"enableOffchainSigning\", () => {\n it.effect(\"completes without error\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n yield* service.enableOffchainSigning();\n // Success if no error thrown\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n});\n"]}
1
+ {"version":3,"file":"service.test.integration.js","sourceRoot":"","sources":["../../src/safe/service.test.integration.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"@effect/vitest\";\nimport { MIN_TX_GAS } from \"@prb/effect-evm/constants\";\nimport { TEST_ADDRESS, TEST_CHAIN_ID, TEST_TX_HASH } from \"@prb/effect-evm/testing-kit\";\nimport { Effect, Layer, Option } from \"effect\";\nimport type { Hash, Hex, TransactionReceipt } from \"viem\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { SafeMultisigInfo, SafeMultisigTxInfo } from \"./types.js\";\n\n// Test fixtures\nconst TEST_SAFE_ADDRESS = TEST_ADDRESS;\nconst TEST_SAFE_TX_HASH =\n \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\" as Hash;\nconst TEST_MESSAGE_HASH =\n \"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890\" as Hex;\nconst TEST_SIGNATURE = \"0xsignature\" as Hex;\n\nconst TEST_RECEIPT: TransactionReceipt = {\n blockHash: \"0xblock\",\n blockNumber: 123n,\n contractAddress: null,\n cumulativeGasUsed: MIN_TX_GAS,\n effectiveGasPrice: 1n,\n from: \"0xfrom\",\n gasUsed: MIN_TX_GAS,\n logs: [],\n logsBloom: \"0x\",\n status: \"success\",\n to: \"0xto\",\n transactionHash: TEST_TX_HASH,\n transactionIndex: 0,\n type: \"0x2\",\n};\n\n// Mock SafeAppsService for testing without actual SDK\nconst makeMockSafeAppsService = (config: {\n getInfoResult?: SafeMultisigInfo;\n sendTxResult?: { safeTxHash: Hash };\n getTxResult?: SafeMultisigTxInfo;\n signTypedDataResult?:\n | { _tag: \"Offchain\"; messageHash: Hex }\n | { _tag: \"Onchain\"; safeTxHash: Hash };\n offchainSignature?: Option.Option<Hex>;\n}) => {\n const defaultInfo: SafeMultisigInfo = {\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n };\n\n return Layer.succeed(\n SafeAppsService,\n SafeAppsService.of({\n enableOffchainSigning: () => Effect.void,\n getInfo: () => Effect.succeed(config.getInfoResult ?? defaultInfo),\n getOffchainSignature: () => Effect.succeed(config.offchainSignature ?? Option.none()),\n getTx: () =>\n Effect.succeed(\n config.getTxResult ?? {\n confirmations: 1,\n confirmationsRequired: 2,\n onchainHash: Option.some(TEST_TX_HASH),\n status: \"AWAITING_EXECUTION\",\n }\n ),\n pollOffchainSignature: (messageHash) =>\n Effect.succeed({ messageHash, signature: TEST_SIGNATURE }),\n sendTxs: () =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash: config.sendTxResult?.safeTxHash ?? TEST_SAFE_TX_HASH,\n }),\n signTypedData: () =>\n Effect.succeed(\n config.signTypedDataResult ?? {\n _tag: \"Onchain\" as const,\n safeTxHash: TEST_SAFE_TX_HASH,\n }\n ),\n waitForTxReceipt: (safeTxHash) =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n onchainHash: TEST_TX_HASH,\n receipt: TEST_RECEIPT,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash,\n }),\n })\n );\n};\n\ndescribe(\"SafeAppsService\", () => {\n describe(\"getInfo\", () => {\n it.effect(\"returns Safe info with address and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const info = yield* service.getInfo();\n\n expect(info.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(info.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"sendTxs\", () => {\n it.effect(\"returns safeTxHash with safeAddress and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.sendTxs([{ data: \"0x\", to: TEST_ADDRESS, value: 0n }]);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"getTx\", () => {\n it.effect(\"returns txHash as Option when executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTx(TEST_SAFE_TX_HASH);\n\n expect(Option.isSome(result.onchainHash)).toBe(true);\n expect(result.confirmations).toBe(1);\n expect(result.confirmationsRequired).toBe(2);\n if (Option.isSome(result.onchainHash)) {\n expect(result.onchainHash.value).toBe(TEST_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.none on onchainHash when not yet executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTx(TEST_SAFE_TX_HASH);\n\n expect(Option.isNone(result.onchainHash)).toBe(true);\n expect(result.confirmations).toBe(0);\n expect(result.confirmationsRequired).toBe(3);\n expect(result.status).toBe(\"AWAITING_CONFIRMATIONS\");\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n getTxResult: {\n confirmations: 0,\n confirmationsRequired: 3,\n onchainHash: Option.none(),\n status: \"AWAITING_CONFIRMATIONS\",\n },\n })\n )\n )\n );\n });\n\n describe(\"waitForTxReceipt\", () => {\n it.effect(\"returns SafeTxResult with receipt\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.waitForTxReceipt(TEST_SAFE_TX_HASH);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.onchainHash).toBe(TEST_TX_HASH);\n expect(result.receipt.status).toBe(\"success\");\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"signTypedData\", () => {\n it.effect(\"returns Onchain variant for on-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Onchain\");\n if (result._tag === \"Onchain\") {\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Offchain variant for off-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Offchain\");\n if (result._tag === \"Offchain\") {\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n signTypedDataResult: {\n _tag: \"Offchain\",\n messageHash: TEST_MESSAGE_HASH,\n },\n })\n )\n )\n );\n });\n\n describe(\"getOffchainSignature\", () => {\n it.effect(\"returns Option.none when signature not yet available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isNone(result)).toBe(true);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.some when signature available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isSome(result)).toBe(true);\n if (Option.isSome(result)) {\n expect(result.value).toBe(TEST_SIGNATURE);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n offchainSignature: Option.some(TEST_SIGNATURE),\n })\n )\n )\n );\n });\n\n describe(\"pollOffchainSignature\", () => {\n it.effect(\"returns signature when available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.pollOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n expect(result.signature).toBe(TEST_SIGNATURE);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"enableOffchainSigning\", () => {\n it.effect(\"completes without error\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n yield* service.enableOffchainSigning();\n // Success if no error thrown\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n});\n"]}
@@ -8,41 +8,47 @@ export type SafeMultisigWaitOptions = {
8
8
  };
9
9
  export type SafeMultisigWaitResult = {
10
10
  readonly _tag: "success";
11
- readonly hash: Hash;
11
+ readonly onchainHash: Hash;
12
12
  readonly receipt: TransactionReceipt;
13
+ readonly safeTxHash: Hash;
13
14
  } | {
14
15
  readonly _tag: "queued";
16
+ readonly onchainHash: null;
15
17
  readonly safeTxHash: Hash;
16
18
  } | {
17
19
  readonly _tag: "cancelled";
20
+ readonly onchainHash: null;
21
+ readonly safeTxHash: Hash;
18
22
  } | {
19
23
  readonly _tag: "failed";
20
24
  readonly error: string;
25
+ readonly onchainHash: null;
26
+ readonly safeTxHash: Hash;
21
27
  };
22
28
  export type SafeMultisigTxStatus = "awaiting_confirmations" | "awaiting_execution" | "pending" | "success" | "failed";
23
29
  export declare const waitForSafeMultisigTx: (safeTxHash: `0x${string}`, getReceipt: (hash: Hash) => Effect.Effect<TransactionReceipt, SafeMultisigTxLookupError>, options?: SafeMultisigWaitOptions | undefined) => Effect.Effect<{
24
30
  _tag: "cancelled";
31
+ onchainHash: null;
32
+ safeTxHash: `0x${string}`;
25
33
  error?: undefined;
26
- hash?: undefined;
27
34
  receipt?: undefined;
28
- safeTxHash?: undefined;
29
35
  } | {
30
36
  _tag: "failed";
31
37
  error: string;
32
- hash?: undefined;
38
+ onchainHash: null;
39
+ safeTxHash: `0x${string}`;
33
40
  receipt?: undefined;
34
- safeTxHash?: undefined;
35
41
  } | {
36
42
  _tag: "success";
37
- hash: `0x${string}`;
43
+ onchainHash: `0x${string}`;
38
44
  receipt: TransactionReceipt;
45
+ safeTxHash: `0x${string}`;
39
46
  error?: undefined;
40
- safeTxHash?: undefined;
41
47
  } | {
42
48
  _tag: "queued";
49
+ onchainHash: null;
43
50
  safeTxHash: `0x${string}`;
44
51
  error?: undefined;
45
- hash?: undefined;
46
52
  receipt?: undefined;
47
53
  }, SafeMultisigTxLookupError, SafeAppsService>;
48
54
  export declare const getSafeMultisigTxStatus: (safeTxHash: `0x${string}`) => Effect.Effect<"pending" | "success" | "failed" | "awaiting_confirmations" | "awaiting_execution", SafeMultisigTxLookupError, SafeAppsService>;
@@ -1 +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"}
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;AAe/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;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,GAClF;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,GACrF;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,CAAC;AAEN,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;;;;;;;;;;;;;;;;;;;;;;;;8CAmGxF,CAAC;AAaH,eAAO,MAAM,uBAAuB,8KAoBlC,CAAC"}
@@ -22,32 +22,41 @@ export const waitForSafeMultisigTx = Effect.fn("waitForSafeMultisigTx")(function
22
22
  const queued = queuedResult.value;
23
23
  yield* Effect.logDebug("Safe tx poll status").pipe(Effect.annotateLogs({
24
24
  attempt,
25
- hash: Option.isSome(queued.txHash) ? queued.txHash.value : "pending",
25
+ hash: Option.isSome(queued.onchainHash) ? queued.onchainHash.value : "pending",
26
26
  safeTxHash,
27
27
  status: queued.status,
28
28
  }));
29
29
  if (queued.status === "CANCELLED") {
30
- return { _tag: "cancelled" };
30
+ return {
31
+ _tag: "cancelled",
32
+ onchainHash: null,
33
+ safeTxHash,
34
+ };
31
35
  }
32
36
  if (queued.status === "FAILED") {
33
37
  return {
34
38
  _tag: "failed",
35
39
  error: "Safe transaction failed",
40
+ onchainHash: null,
41
+ safeTxHash,
36
42
  };
37
43
  }
38
44
  if (queued.status === "SUCCESS") {
39
- if (Option.isNone(queued.txHash)) {
45
+ if (Option.isNone(queued.onchainHash)) {
40
46
  return {
41
47
  _tag: "failed",
42
48
  error: "Safe transaction succeeded but no on-chain hash available",
49
+ onchainHash: null,
50
+ safeTxHash,
43
51
  };
44
52
  }
45
- const txHash = queued.txHash.value;
53
+ const txHash = queued.onchainHash.value;
46
54
  const receipt = yield* getReceipt(txHash);
47
55
  return {
48
56
  _tag: "success",
49
- hash: txHash,
57
+ onchainHash: txHash,
50
58
  receipt,
59
+ safeTxHash,
51
60
  };
52
61
  }
53
62
  yield* Effect.sleep(interval);
@@ -57,7 +66,11 @@ export const waitForSafeMultisigTx = Effect.fn("waitForSafeMultisigTx")(function
57
66
  maxWaitMs: Duration.toMillis(maxWait),
58
67
  safeTxHash,
59
68
  }));
60
- return { _tag: "queued", safeTxHash };
69
+ return {
70
+ _tag: "queued",
71
+ onchainHash: null,
72
+ safeTxHash,
73
+ };
61
74
  });
62
75
  export const getSafeMultisigTxStatus = Effect.fn("getSafeMultisigTxStatus")(function* (safeTxHash) {
63
76
  const safeApps = yield* SafeAppsService;
@@ -1 +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"]}
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\";\nimport type { SafeMultisigTxInfo } from \"./types.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 | {\n readonly _tag: \"success\";\n readonly onchainHash: Hash;\n readonly receipt: TransactionReceipt;\n readonly safeTxHash: Hash;\n }\n | { readonly _tag: \"queued\"; readonly onchainHash: null; readonly safeTxHash: Hash }\n | { readonly _tag: \"cancelled\"; readonly onchainHash: null; readonly safeTxHash: Hash }\n | {\n readonly _tag: \"failed\";\n readonly error: string;\n readonly onchainHash: null;\n readonly safeTxHash: Hash;\n };\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 this returns a \"queued\" result with `onchainHash: null` and the\n * original `safeTxHash` so callers can persist and resume tracking later.\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<SafeMultisigTxInfo>())\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.onchainHash) ? queued.onchainHash.value : \"pending\",\n safeTxHash,\n status: queued.status,\n })\n );\n\n // --- Terminal states ---\n\n if (queued.status === \"CANCELLED\") {\n return {\n _tag: \"cancelled\" as const,\n onchainHash: null,\n safeTxHash,\n } satisfies SafeMultisigWaitResult;\n }\n\n if (queued.status === \"FAILED\") {\n return {\n _tag: \"failed\" as const,\n error: \"Safe transaction failed\",\n onchainHash: null,\n safeTxHash,\n } satisfies SafeMultisigWaitResult;\n }\n\n if (queued.status === \"SUCCESS\") {\n if (Option.isNone(queued.onchainHash)) {\n return {\n _tag: \"failed\" as const,\n error: \"Safe transaction succeeded but no on-chain hash available\",\n onchainHash: null,\n safeTxHash,\n } satisfies SafeMultisigWaitResult;\n }\n const txHash = queued.onchainHash.value as Hash;\n const receipt = yield* getReceipt(txHash);\n return {\n _tag: \"success\" as const,\n onchainHash: txHash,\n receipt,\n safeTxHash,\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 {\n _tag: \"queued\" as const,\n onchainHash: null,\n safeTxHash,\n } 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"]}
@@ -0,0 +1,9 @@
1
+ import type { Address, Hash } from "viem";
2
+ export type GetSafeMultisigTxUrlParams = {
3
+ safeAddress: Address;
4
+ safeTxHash: Hash;
5
+ safeAppOrigin?: string;
6
+ safe?: string;
7
+ };
8
+ export declare function getSafeMultisigTxUrl(params: GetSafeMultisigTxUrlParams): string;
9
+ //# sourceMappingURL=tx-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx-url.d.ts","sourceRoot":"","sources":["../../src/safe/tx-url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI1C,MAAM,MAAM,0BAA0B,GAAG;IAEvC,WAAW,EAAE,OAAO,CAAC;IAErB,UAAU,EAAE,IAAI,CAAC;IAEjB,aAAa,CAAC,EAAE,MAAM,CAAC;IAKvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAQF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,GAAG,MAAM,CAW/E"}
@@ -0,0 +1,11 @@
1
+ const DEFAULT_SAFE_APP_ORIGIN = "https://app.safe.global";
2
+ export function getSafeMultisigTxUrl(params) {
3
+ const { safeAddress, safeAppOrigin = DEFAULT_SAFE_APP_ORIGIN, safeTxHash, safe } = params;
4
+ const url = new URL("/transactions/tx", safeAppOrigin);
5
+ url.searchParams.set("id", `multisig_${safeAddress}_${safeTxHash}`);
6
+ if (safe) {
7
+ url.searchParams.set("safe", safe);
8
+ }
9
+ return url.toString();
10
+ }
11
+ //# sourceMappingURL=tx-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tx-url.js","sourceRoot":"","sources":["../../src/safe/tx-url.ts"],"names":[],"mappings":"AAEA,MAAM,uBAAuB,GAAG,yBAAyB,CAAC;AAsB1D,MAAM,UAAU,oBAAoB,CAAC,MAAkC;IACrE,MAAM,EAAE,WAAW,EAAE,aAAa,GAAG,uBAAuB,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IAE1F,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IACvD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,WAAW,IAAI,UAAU,EAAE,CAAC,CAAC;IAEpE,IAAI,IAAI,EAAE,CAAC;QACT,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC","sourcesContent":["import type { Address, Hash } from \"viem\";\n\nconst DEFAULT_SAFE_APP_ORIGIN = \"https://app.safe.global\";\n\nexport type GetSafeMultisigTxUrlParams = {\n /** Safe account address */\n safeAddress: Address;\n /** Safe transaction hash (proposal hash) */\n safeTxHash: Hash;\n /** Optional Safe app origin (default: https://app.safe.global) */\n safeAppOrigin?: string;\n /**\n * Optional `safe` query value expected by Safe UI.\n * Example: `eth:0x...` or `sep:0x...`.\n */\n safe?: string;\n};\n\n/**\n * Build a Safe web URL for a Safe transaction details page.\n *\n * This points to Safe's multisig tx route (`/transactions/tx`) and includes the\n * tx identifier derived from `safeAddress` and `safeTxHash`.\n */\nexport function getSafeMultisigTxUrl(params: GetSafeMultisigTxUrlParams): string {\n const { safeAddress, safeAppOrigin = DEFAULT_SAFE_APP_ORIGIN, safeTxHash, safe } = params;\n\n const url = new URL(\"/transactions/tx\", safeAppOrigin);\n url.searchParams.set(\"id\", `multisig_${safeAddress}_${safeTxHash}`);\n\n if (safe) {\n url.searchParams.set(\"safe\", safe);\n }\n\n return url.toString();\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type { Option } from "effect";
1
2
  import type { Address, Hash, Hex, TransactionReceipt } from "viem";
2
3
  export type SafeMultisigInfo = {
3
4
  chainId: number;
@@ -13,6 +14,12 @@ export type SafeMultisigTxSubmission = {
13
14
  safeAddress: Address;
14
15
  safeTxHash: Hash;
15
16
  };
17
+ export type SafeMultisigTxInfo = {
18
+ status: string;
19
+ onchainHash: Option.Option<Hash>;
20
+ confirmations: number | null;
21
+ confirmationsRequired: number | null;
22
+ };
16
23
  export type SafeMultisigTxResult = {
17
24
  chainId: number;
18
25
  onchainHash: Hash;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/safe/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAGnE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,IAAI,CAAC;IAClB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,CAAC;AAG5D,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,GAAG,CAAC;IACjB,SAAS,EAAE,GAAG,CAAC;CAChB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IAE3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,aAAa,CAAC,EAAE;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACH,CAAC;AAGF,MAAM,MAAM,uBAAuB,GAAG;IAEpC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CAC9D,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/safe/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAGnE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,GAAG,CAAC;IACV,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,kBAAkB,GAAG;IAE/B,MAAM,EAAE,MAAM,CAAC;IAEf,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAEjC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC,CAAC;AAGF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,IAAI,CAAC;IAClB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,CAAC;AAG5D,MAAM,MAAM,uBAAuB,GAAG;IACpC,WAAW,EAAE,GAAG,CAAC;IACjB,SAAS,EAAE,GAAG,CAAC;CAChB,CAAC;AAGF,MAAM,MAAM,cAAc,GAAG;IAE3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,aAAa,CAAC,EAAE;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACH,CAAC;AAGF,MAAM,MAAM,uBAAuB,GAAG;IAEpC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CAC9D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/safe/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Address, Hash, Hex, TransactionReceipt } from \"viem\";\n\n/** Safe multisig info returned from SDK */\nexport type SafeMultisigInfo = {\n chainId: number;\n safeAddress: Address;\n};\n\n/** Tx to send via Safe multisig */\nexport type SafeMultisigTx = {\n data: Hex;\n to: Address;\n value?: bigint; // Converted to string at SDK boundary\n};\n\n/** Result from sendTxs */\nexport type SafeMultisigTxSubmission = {\n chainId: number;\n safeAddress: Address;\n safeTxHash: Hash;\n};\n\n/** Result from waitForTxReceipt */\nexport type SafeMultisigTxResult = {\n chainId: number;\n onchainHash: Hash;\n receipt: TransactionReceipt;\n safeAddress: Address;\n safeTxHash: Hash;\n};\n\n/** Discriminated union for signTypedData result */\nexport type SignTypedDataResult =\n | { readonly _tag: \"Offchain\"; readonly messageHash: Hex }\n | { readonly _tag: \"Onchain\"; readonly safeTxHash: Hash };\n\n/** Off-chain signature result */\nexport type OffchainSignatureResult = {\n messageHash: Hex;\n signature: Hex;\n};\n\n/** Policy for Safe tx waiting (aligns with TxPolicy from @prb/effect-evm) */\nexport type SafeWaitPolicy = {\n /** Timeout for Safe tx execution in ms (default: 300000 = 5 min) */\n executionTimeout?: number;\n /** Poll interval for Safe gateway in ms (default: 3000) */\n pollInterval?: number;\n /** Policy passed to TxManager.waitForReceipt */\n receiptPolicy?: {\n pollingInterval?: number;\n receiptTimeout?: number;\n };\n};\n\n/** Policy for off-chain signature polling */\nexport type OffchainSignaturePolicy = {\n /** Poll interval in ms (default: 2000) */\n pollInterval?: number;\n /** Timeout in ms (default: 120000 = 2 min) */\n timeout?: number;\n};\n\n/** EIP-712 typed data structure (local definition to avoid SDK import) */\nexport type EIP712TypedData = {\n domain: {\n chainId?: number;\n name?: string;\n salt?: string;\n verifyingContract?: string;\n version?: string;\n };\n message: Record<string, unknown>;\n primaryType?: string;\n types: Record<string, Array<{ name: string; type: string }>>;\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/safe/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Option } from \"effect\";\nimport type { Address, Hash, Hex, TransactionReceipt } from \"viem\";\n\n/** Safe multisig info returned from SDK */\nexport type SafeMultisigInfo = {\n chainId: number;\n safeAddress: Address;\n};\n\n/** Tx to send via Safe multisig */\nexport type SafeMultisigTx = {\n data: Hex;\n to: Address;\n value?: bigint; // Converted to string at SDK boundary\n};\n\n/** Result from sendTxs */\nexport type SafeMultisigTxSubmission = {\n chainId: number;\n safeAddress: Address;\n safeTxHash: Hash;\n};\n\n/** Safe transaction info returned by `SafeAppsService.getTx`. */\nexport type SafeMultisigTxInfo = {\n /** Current Safe status string (e.g. AWAITING_CONFIRMATIONS, SUCCESS). */\n status: string;\n /** On-chain hash when the Safe tx has executed. */\n onchainHash: Option.Option<Hash>;\n /** Number of collected confirmations, when available. */\n confirmations: number | null;\n /** Number of required confirmations, when available. */\n confirmationsRequired: number | null;\n};\n\n/** Result from waitForTxReceipt */\nexport type SafeMultisigTxResult = {\n chainId: number;\n onchainHash: Hash;\n receipt: TransactionReceipt;\n safeAddress: Address;\n safeTxHash: Hash;\n};\n\n/** Discriminated union for signTypedData result */\nexport type SignTypedDataResult =\n | { readonly _tag: \"Offchain\"; readonly messageHash: Hex }\n | { readonly _tag: \"Onchain\"; readonly safeTxHash: Hash };\n\n/** Off-chain signature result */\nexport type OffchainSignatureResult = {\n messageHash: Hex;\n signature: Hex;\n};\n\n/** Policy for Safe tx waiting (aligns with TxPolicy from @prb/effect-evm) */\nexport type SafeWaitPolicy = {\n /** Timeout for Safe tx execution in ms (default: 300000 = 5 min) */\n executionTimeout?: number;\n /** Poll interval for Safe gateway in ms (default: 3000) */\n pollInterval?: number;\n /** Policy passed to TxManager.waitForReceipt */\n receiptPolicy?: {\n pollingInterval?: number;\n receiptTimeout?: number;\n };\n};\n\n/** Policy for off-chain signature polling */\nexport type OffchainSignaturePolicy = {\n /** Poll interval in ms (default: 2000) */\n pollInterval?: number;\n /** Timeout in ms (default: 120000 = 2 min) */\n timeout?: number;\n};\n\n/** EIP-712 typed data structure (local definition to avoid SDK import) */\nexport type EIP712TypedData = {\n domain: {\n chainId?: number;\n name?: string;\n salt?: string;\n verifyingContract?: string;\n version?: string;\n };\n message: Record<string, unknown>;\n primaryType?: string;\n types: Record<string, Array<{ name: string; type: string }>>;\n};\n"]}
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.1.1",
9
+ "version": "2.0.0",
10
10
  "scripts": {
11
11
  "build": "just build",
12
12
  "prepack": "bun install --frozen-lockfile && just build"