@prb/effect-evm-safe 2.0.2 → 3.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/react-hooks/index.d.ts +1 -0
  3. package/dist/react-hooks/index.d.ts.map +1 -1
  4. package/dist/react-hooks/index.js +1 -0
  5. package/dist/react-hooks/index.js.map +1 -1
  6. package/dist/react-hooks/use-wallet-execution.d.ts +14 -0
  7. package/dist/react-hooks/use-wallet-execution.d.ts.map +1 -0
  8. package/dist/react-hooks/use-wallet-execution.js +110 -0
  9. package/dist/react-hooks/use-wallet-execution.js.map +1 -0
  10. package/dist/safe/allowance.d.ts +22 -2
  11. package/dist/safe/allowance.d.ts.map +1 -1
  12. package/dist/safe/allowance.js +20 -1
  13. package/dist/safe/allowance.js.map +1 -1
  14. package/dist/safe/errors.d.ts +2 -0
  15. package/dist/safe/errors.d.ts.map +1 -1
  16. package/dist/safe/errors.js +11 -0
  17. package/dist/safe/errors.js.map +1 -1
  18. package/dist/safe/index.d.ts +4 -2
  19. package/dist/safe/index.d.ts.map +1 -1
  20. package/dist/safe/index.js +3 -1
  21. package/dist/safe/index.js.map +1 -1
  22. package/dist/safe/live.d.ts.map +1 -1
  23. package/dist/safe/live.js +7 -37
  24. package/dist/safe/live.js.map +1 -1
  25. package/dist/safe/pipeline-adapter.d.ts +6 -0
  26. package/dist/safe/pipeline-adapter.d.ts.map +1 -0
  27. package/dist/safe/pipeline-adapter.js +165 -0
  28. package/dist/safe/pipeline-adapter.js.map +1 -0
  29. package/dist/safe/tx-lifecycle.d.ts +1 -1
  30. package/dist/safe/tx-lifecycle.d.ts.map +1 -1
  31. package/dist/safe/tx-lifecycle.js +1 -0
  32. package/dist/safe/tx-lifecycle.js.map +1 -1
  33. package/dist/safe/write-and-track.d.ts +72 -0
  34. package/dist/safe/write-and-track.d.ts.map +1 -0
  35. package/dist/safe/write-and-track.js +116 -0
  36. package/dist/safe/write-and-track.js.map +1 -0
  37. package/package.json +2 -2
@@ -1 +1 @@
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"]}
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 toSafeMultisigTxLookupError,\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) => toSafeMultisigTxLookupError(safeTxHash, cause, true),\n try: () => s.txs.getBySafeTxHash(safeTxHash),\n }),\n (e) => toSafeMultisigTxLookupError(safeTxHash, e, false)\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(toSafeMultisigTxLookupError(safeTxHash, error, true))\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(toSafeMultisigTxLookupError(safeTxHash, error, false))\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) => toSafeMultisigTxLookupError(messageHash, cause, true),\n try: () => s.safe.getOffChainSignature(messageHash),\n }),\n (e) => toSafeMultisigTxLookupError(messageHash, e, false)\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"]}
@@ -0,0 +1,6 @@
1
+ import { WriteExecutionAdapter } from "@prb/effect-evm/contract/pipeline";
2
+ import { TxManager } from "@prb/effect-evm/tx";
3
+ import { Layer } from "effect";
4
+ import { SafeAppsService } from "./service.js";
5
+ export declare const SafeWriteExecutionAdapterLive: Layer.Layer<WriteExecutionAdapter, never, SafeAppsService | TxManager>;
6
+ //# sourceMappingURL=pipeline-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-adapter.d.ts","sourceRoot":"","sources":["../../src/safe/pipeline-adapter.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,OAAO,EAAkB,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAU,KAAK,EAA2B,MAAM,QAAQ,CAAC;AAGhE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAwE/C,eAAO,MAAM,6BAA6B,wEAiJzC,CAAC"}
@@ -0,0 +1,165 @@
1
+ import { WriteExecutionAdapter } from "@prb/effect-evm/contract/pipeline";
2
+ import { TxFailedError } from "@prb/effect-evm/core/errors";
3
+ import { initialTxState, TxManager } from "@prb/effect-evm/tx";
4
+ import { Effect, Layer, Stream, SubscriptionRef } from "effect";
5
+ import { encodeFunctionData } from "viem";
6
+ import { SafeAppsService } from "./service.js";
7
+ import { safeWriteAndTrack } from "./write-and-track.js";
8
+ function toFailedState(hash, message) {
9
+ return {
10
+ error: new TxFailedError({
11
+ hash,
12
+ message,
13
+ }),
14
+ phase: "receipt",
15
+ status: "failed",
16
+ };
17
+ }
18
+ function mapSafeStateToTxState(state) {
19
+ switch (state.status) {
20
+ case "submitting":
21
+ return { status: "signing" };
22
+ case "awaiting_confirmations":
23
+ case "awaiting_execution":
24
+ case "pending":
25
+ return {
26
+ confirmations: state.confirmations ?? 0,
27
+ hash: state.safeTxHash,
28
+ status: "pending",
29
+ };
30
+ case "queued":
31
+ return {
32
+ details: {
33
+ confirmations: state.confirmations,
34
+ confirmationsRequired: state.confirmationsRequired,
35
+ lastStatus: state.lastStatus,
36
+ },
37
+ reason: "awaiting-safe-confirmations",
38
+ reference: state.safeTxHash,
39
+ status: "queued",
40
+ };
41
+ case "success":
42
+ return {
43
+ hash: state.onchainHash,
44
+ receipt: state.receipt,
45
+ status: "mined",
46
+ };
47
+ case "cancelled":
48
+ return {
49
+ reason: "safe-cancelled",
50
+ reference: state.safeTxHash,
51
+ status: "cancelled",
52
+ };
53
+ case "failed":
54
+ return toFailedState(state.safeTxHash ?? "unknown", state.error ?? "Safe transaction failed");
55
+ }
56
+ }
57
+ function toTxFailedSafeError(error) {
58
+ const hash = typeof error === "object" && error !== null && "safeTxHash" in error
59
+ ? String(error.safeTxHash)
60
+ : "unknown";
61
+ const message = typeof error === "object" && error !== null && "message" in error
62
+ ? String(error.message)
63
+ : "Safe multisig write failed";
64
+ return new TxFailedError({
65
+ cause: error,
66
+ hash,
67
+ message,
68
+ });
69
+ }
70
+ export const SafeWriteExecutionAdapterLive = Layer.effect(WriteExecutionAdapter, Effect.gen(function* () {
71
+ const safeApps = yield* SafeAppsService;
72
+ const txManager = yield* TxManager;
73
+ return WriteExecutionAdapter.of({
74
+ canHandle: (params) => safeApps.getInfo().pipe(Effect.map((info) => (params.chainId == null ? true : info.chainId === params.chainId)), Effect.catchAll(() => Effect.succeed(false))),
75
+ writeAndTrack: (params) => Effect.gen(function* () {
76
+ const encodedData = yield* Effect.try({
77
+ catch: (cause) => new TxFailedError({
78
+ cause,
79
+ hash: "unknown",
80
+ message: "Failed to encode Safe transaction calldata",
81
+ }),
82
+ try: () => encodeFunctionData({
83
+ abi: params.abi,
84
+ args: params.args,
85
+ functionName: params.functionName,
86
+ }),
87
+ }).pipe(Effect.either);
88
+ if (encodedData._tag === "Left") {
89
+ const stateRef = yield* SubscriptionRef.make(toFailedState("unknown", encodedData.left.message));
90
+ return {
91
+ actions: {
92
+ cancel: () => Effect.fail(encodedData.left),
93
+ speedup: () => Effect.fail(encodedData.left),
94
+ },
95
+ stateRef,
96
+ terminal: Effect.fail(encodedData.left),
97
+ };
98
+ }
99
+ const safeTx = {
100
+ data: encodedData.right,
101
+ to: params.address,
102
+ value: params.value ?? 0n,
103
+ };
104
+ const safeExecution = yield* safeWriteAndTrack({
105
+ chainId: params.chainId,
106
+ transactions: [safeTx],
107
+ }).pipe(Effect.provideService(SafeAppsService, safeApps), Effect.provideService(TxManager, txManager));
108
+ const stateRef = yield* SubscriptionRef.make(initialTxState);
109
+ yield* Effect.forkScoped(Stream.runForEach(safeExecution.stateRef.changes, (safeState) => SubscriptionRef.set(stateRef, mapSafeStateToTxState(safeState))));
110
+ const terminal = safeExecution.result.pipe(Effect.mapError(toTxFailedSafeError), Effect.flatMap((safeTerminal) => {
111
+ switch (safeTerminal._tag) {
112
+ case "success":
113
+ return Effect.succeed({
114
+ _tag: "success",
115
+ events: [],
116
+ hash: safeTerminal.onchainHash,
117
+ receipt: safeTerminal.receipt,
118
+ });
119
+ case "queued":
120
+ return Effect.succeed({
121
+ _tag: "queued",
122
+ details: {
123
+ confirmations: safeTerminal.confirmations,
124
+ confirmationsRequired: safeTerminal.confirmationsRequired,
125
+ lastStatus: safeTerminal.lastStatus,
126
+ },
127
+ reason: "awaiting-safe-confirmations",
128
+ reference: safeTerminal.safeTxHash,
129
+ });
130
+ case "cancelled":
131
+ return Effect.succeed({
132
+ _tag: "cancelled",
133
+ reason: "safe-cancelled",
134
+ reference: safeTerminal.safeTxHash,
135
+ });
136
+ case "failed":
137
+ return Effect.fail(new TxFailedError({
138
+ hash: safeTerminal.safeTxHash,
139
+ message: safeTerminal.error,
140
+ }));
141
+ default:
142
+ return Effect.fail(new TxFailedError({
143
+ hash: "unknown",
144
+ message: "Unexpected Safe terminal state",
145
+ }));
146
+ }
147
+ }));
148
+ return {
149
+ actions: {
150
+ cancel: () => Effect.fail(new TxFailedError({
151
+ hash: "unknown",
152
+ message: "Cancel is not supported for Safe multisig execution",
153
+ })),
154
+ speedup: () => Effect.fail(new TxFailedError({
155
+ hash: "unknown",
156
+ message: "Speedup is not supported for Safe multisig execution",
157
+ })),
158
+ },
159
+ stateRef,
160
+ terminal,
161
+ };
162
+ }),
163
+ });
164
+ }));
165
+ //# sourceMappingURL=pipeline-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-adapter.js","sourceRoot":"","sources":["../../src/safe/pipeline-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n WriteAndTrackExecution,\n WriteAndTrackParams,\n WriteAndTrackTerminal,\n} from \"@prb/effect-evm/contract/pipeline\";\nimport { WriteExecutionAdapter } from \"@prb/effect-evm/contract/pipeline\";\nimport { TxFailedError } from \"@prb/effect-evm/core/errors\";\nimport type { TxState } from \"@prb/effect-evm/tx\";\nimport { initialTxState, TxManager } from \"@prb/effect-evm/tx\";\nimport type { ContractFunctionName } from \"@prb/effect-evm/types\";\nimport { Effect, Layer, Stream, SubscriptionRef } from \"effect\";\nimport type { Abi } from \"viem\";\nimport { encodeFunctionData } from \"viem\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { SafeWriteAndTrackState } from \"./write-and-track.js\";\nimport { safeWriteAndTrack } from \"./write-and-track.js\";\n\nfunction toFailedState(hash: string, message: string): TxState {\n return {\n error: new TxFailedError({\n hash,\n message,\n }),\n phase: \"receipt\",\n status: \"failed\",\n };\n}\n\nfunction mapSafeStateToTxState(state: SafeWriteAndTrackState): TxState {\n switch (state.status) {\n case \"submitting\":\n return { status: \"signing\" };\n case \"awaiting_confirmations\":\n case \"awaiting_execution\":\n case \"pending\":\n return {\n confirmations: state.confirmations ?? 0,\n hash: state.safeTxHash,\n status: \"pending\",\n };\n case \"queued\":\n return {\n details: {\n confirmations: state.confirmations,\n confirmationsRequired: state.confirmationsRequired,\n lastStatus: state.lastStatus,\n },\n reason: \"awaiting-safe-confirmations\",\n reference: state.safeTxHash,\n status: \"queued\",\n };\n case \"success\":\n return {\n hash: state.onchainHash,\n receipt: state.receipt,\n status: \"mined\",\n };\n case \"cancelled\":\n return {\n reason: \"safe-cancelled\",\n reference: state.safeTxHash,\n status: \"cancelled\",\n };\n case \"failed\":\n return toFailedState(state.safeTxHash ?? \"unknown\", state.error ?? \"Safe transaction failed\");\n }\n}\n\nfunction toTxFailedSafeError(error: unknown): TxFailedError {\n const hash =\n typeof error === \"object\" && error !== null && \"safeTxHash\" in error\n ? String((error as { safeTxHash: unknown }).safeTxHash)\n : \"unknown\";\n const message =\n typeof error === \"object\" && error !== null && \"message\" in error\n ? String((error as { message: unknown }).message)\n : \"Safe multisig write failed\";\n\n return new TxFailedError({\n cause: error,\n hash,\n message,\n });\n}\n\nexport const SafeWriteExecutionAdapterLive = Layer.effect(\n WriteExecutionAdapter,\n Effect.gen(function* () {\n const safeApps = yield* SafeAppsService;\n const txManager = yield* TxManager;\n\n return WriteExecutionAdapter.of({\n canHandle: (params) =>\n safeApps.getInfo().pipe(\n Effect.map((info) => (params.chainId == null ? true : info.chainId === params.chainId)),\n Effect.catchAll(() => Effect.succeed(false))\n ),\n writeAndTrack: <\n TAbi extends Abi,\n TFunctionName extends ContractFunctionName<TAbi, \"nonpayable\" | \"payable\">,\n >(\n params: WriteAndTrackParams<TAbi, TFunctionName>\n ) =>\n Effect.gen(function* () {\n const encodedData = yield* Effect.try({\n catch: (cause) =>\n new TxFailedError({\n cause,\n hash: \"unknown\",\n message: \"Failed to encode Safe transaction calldata\",\n }),\n try: () =>\n encodeFunctionData({\n abi: params.abi as Abi,\n args: params.args as readonly unknown[] | undefined,\n functionName: params.functionName as string,\n }),\n }).pipe(Effect.either);\n\n if (encodedData._tag === \"Left\") {\n const stateRef = yield* SubscriptionRef.make<TxState>(\n toFailedState(\"unknown\", encodedData.left.message)\n );\n\n return {\n actions: {\n cancel: () => Effect.fail(encodedData.left),\n speedup: () => Effect.fail(encodedData.left),\n },\n stateRef,\n terminal: Effect.fail(encodedData.left),\n } satisfies WriteAndTrackExecution<TAbi>;\n }\n\n const safeTx = {\n data: encodedData.right,\n to: params.address,\n value: params.value ?? 0n,\n };\n\n const safeExecution = yield* safeWriteAndTrack({\n chainId: params.chainId,\n transactions: [safeTx],\n }).pipe(\n Effect.provideService(SafeAppsService, safeApps),\n Effect.provideService(TxManager, txManager)\n );\n\n const stateRef = yield* SubscriptionRef.make<TxState>(initialTxState);\n\n yield* Effect.forkScoped(\n Stream.runForEach(safeExecution.stateRef.changes, (safeState) =>\n SubscriptionRef.set(stateRef, mapSafeStateToTxState(safeState))\n )\n );\n\n const terminal: Effect.Effect<\n WriteAndTrackTerminal<TAbi>,\n TxFailedError\n > = safeExecution.result.pipe(\n Effect.mapError(toTxFailedSafeError),\n Effect.flatMap(\n (safeTerminal): Effect.Effect<WriteAndTrackTerminal<TAbi>, TxFailedError> => {\n switch (safeTerminal._tag) {\n case \"success\":\n return Effect.succeed({\n _tag: \"success\",\n events: [],\n hash: safeTerminal.onchainHash,\n receipt: safeTerminal.receipt,\n } satisfies WriteAndTrackTerminal<TAbi>);\n case \"queued\":\n return Effect.succeed({\n _tag: \"queued\",\n details: {\n confirmations: safeTerminal.confirmations,\n confirmationsRequired: safeTerminal.confirmationsRequired,\n lastStatus: safeTerminal.lastStatus,\n },\n reason: \"awaiting-safe-confirmations\",\n reference: safeTerminal.safeTxHash,\n } satisfies WriteAndTrackTerminal<TAbi>);\n case \"cancelled\":\n return Effect.succeed({\n _tag: \"cancelled\",\n reason: \"safe-cancelled\",\n reference: safeTerminal.safeTxHash,\n } satisfies WriteAndTrackTerminal<TAbi>);\n case \"failed\":\n return Effect.fail(\n new TxFailedError({\n hash: safeTerminal.safeTxHash,\n message: safeTerminal.error,\n })\n );\n default:\n return Effect.fail(\n new TxFailedError({\n hash: \"unknown\",\n message: \"Unexpected Safe terminal state\",\n })\n );\n }\n }\n )\n );\n\n return {\n actions: {\n cancel: () =>\n Effect.fail(\n new TxFailedError({\n hash: \"unknown\",\n message: \"Cancel is not supported for Safe multisig execution\",\n })\n ),\n speedup: () =>\n Effect.fail(\n new TxFailedError({\n hash: \"unknown\",\n message: \"Speedup is not supported for Safe multisig execution\",\n })\n ),\n },\n stateRef,\n terminal,\n } satisfies WriteAndTrackExecution<TAbi>;\n }),\n });\n })\n);\n"]}
@@ -28,7 +28,7 @@ export type SafeMultisigWaitResult = {
28
28
  readonly onchainHash: null;
29
29
  readonly safeTxHash: Hash;
30
30
  };
31
- export type SafeMultisigTxStatus = "awaiting_confirmations" | "awaiting_execution" | "pending" | "success" | "failed";
31
+ export type SafeMultisigTxStatus = "awaiting_confirmations" | "awaiting_execution" | "pending" | "success" | "cancelled" | "failed";
32
32
  export declare const waitForSafeMultisigTx: (safeTxHash: `0x${string}`, getReceipt: (hash: Hash) => Effect.Effect<TransactionReceipt, SafeMultisigTxLookupError>, options?: SafeMultisigWaitOptions | undefined) => Effect.Effect<SafeMultisigWaitResult, SafeMultisigTxLookupError, SafeAppsService>;
33
33
  export declare const getSafeMultisigTxStatus: (safeTxHash: `0x${string}`) => Effect.Effect<SafeMultisigTxStatus, SafeMultisigTxLookupError, SafeAppsService>;
34
34
  //# sourceMappingURL=tx-lifecycle.d.ts.map
@@ -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;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;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,GACD;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;AAwFb,eAAO,MAAM,qBAAqB,iDAEb,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,yBAAyB,CAAC,qIA2ExF,CAAC;AAaH,eAAO,MAAM,uBAAuB,gHAMlC,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;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,GACD;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,WAAW,GACX,QAAQ,CAAC;AAyFb,eAAO,MAAM,qBAAqB,iDAEb,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,yBAAyB,CAAC,qIA2ExF,CAAC;AAaH,eAAO,MAAM,uBAAuB,gHAMlC,CAAC"}
@@ -12,6 +12,7 @@ function mapStatus(raw) {
12
12
  case "SUCCESS":
13
13
  return "success";
14
14
  case "CANCELLED":
15
+ return "cancelled";
15
16
  case "FAILED":
16
17
  return "failed";
17
18
  default:
@@ -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\";\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 | {\n readonly _tag: \"queued\";\n readonly confirmations: number | null;\n readonly confirmationsRequired: number | null;\n readonly lastStatus: SafeMultisigTxStatus;\n readonly onchainHash: null;\n readonly safeTxHash: Hash;\n }\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\nfunction mapStatus(raw: string | undefined): SafeMultisigTxStatus {\n switch (raw) {\n case \"AWAITING_CONFIRMATIONS\":\n return \"awaiting_confirmations\";\n case \"AWAITING_EXECUTION\":\n return \"awaiting_execution\";\n case \"SUCCESS\":\n return \"success\";\n case \"CANCELLED\":\n case \"FAILED\":\n return \"failed\";\n default:\n return \"pending\";\n }\n}\n\nfunction resolveTerminalWaitResult(\n queued: SafeMultisigTxInfo,\n safeTxHash: Hash,\n getReceipt: (hash: Hash) => Effect.Effect<TransactionReceipt, SafeMultisigTxLookupError>\n): Effect.Effect<Option.Option<SafeMultisigWaitResult>, SafeMultisigTxLookupError> {\n switch (queued.status) {\n case \"CANCELLED\":\n return Effect.succeed(\n Option.some({\n _tag: \"cancelled\" as const,\n onchainHash: null,\n safeTxHash,\n } satisfies SafeMultisigWaitResult)\n );\n case \"FAILED\":\n return Effect.succeed(\n Option.some({\n _tag: \"failed\" as const,\n error: \"Safe transaction failed\",\n onchainHash: null,\n safeTxHash,\n } satisfies SafeMultisigWaitResult)\n );\n case \"SUCCESS\": {\n if (Option.isNone(queued.onchainHash)) {\n return Effect.succeed(\n Option.some({\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 }\n const txHash = queued.onchainHash.value as Hash;\n return getReceipt(txHash).pipe(\n Effect.map((receipt) =>\n Option.some({\n _tag: \"success\" as const,\n onchainHash: txHash,\n receipt,\n safeTxHash,\n } satisfies SafeMultisigWaitResult)\n )\n );\n }\n default:\n return Effect.succeed(Option.none());\n }\n}\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 let lastInfo: SafeMultisigTxInfo | null = null;\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 if (attempt < maxAttempts - 1) {\n yield* Effect.sleep(interval);\n }\n continue;\n }\n\n const queued = queuedResult.value;\n lastInfo = queued;\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 const terminalResult = yield* resolveTerminalWaitResult(queued, safeTxHash, getReceipt);\n if (Option.isSome(terminalResult)) {\n return terminalResult.value;\n }\n\n // Still pending — keep polling\n if (attempt < maxAttempts - 1) {\n yield* Effect.sleep(interval);\n }\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 confirmations: lastInfo?.confirmations ?? null,\n confirmationsRequired: lastInfo?.confirmationsRequired ?? null,\n lastStatus: mapStatus(lastInfo?.status),\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 return mapStatus(queued.status);\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 | {\n readonly _tag: \"queued\";\n readonly confirmations: number | null;\n readonly confirmationsRequired: number | null;\n readonly lastStatus: SafeMultisigTxStatus;\n readonly onchainHash: null;\n readonly safeTxHash: Hash;\n }\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 | \"cancelled\"\n | \"failed\";\n\nfunction mapStatus(raw: string | undefined): SafeMultisigTxStatus {\n switch (raw) {\n case \"AWAITING_CONFIRMATIONS\":\n return \"awaiting_confirmations\";\n case \"AWAITING_EXECUTION\":\n return \"awaiting_execution\";\n case \"SUCCESS\":\n return \"success\";\n case \"CANCELLED\":\n return \"cancelled\";\n case \"FAILED\":\n return \"failed\";\n default:\n return \"pending\";\n }\n}\n\nfunction resolveTerminalWaitResult(\n queued: SafeMultisigTxInfo,\n safeTxHash: Hash,\n getReceipt: (hash: Hash) => Effect.Effect<TransactionReceipt, SafeMultisigTxLookupError>\n): Effect.Effect<Option.Option<SafeMultisigWaitResult>, SafeMultisigTxLookupError> {\n switch (queued.status) {\n case \"CANCELLED\":\n return Effect.succeed(\n Option.some({\n _tag: \"cancelled\" as const,\n onchainHash: null,\n safeTxHash,\n } satisfies SafeMultisigWaitResult)\n );\n case \"FAILED\":\n return Effect.succeed(\n Option.some({\n _tag: \"failed\" as const,\n error: \"Safe transaction failed\",\n onchainHash: null,\n safeTxHash,\n } satisfies SafeMultisigWaitResult)\n );\n case \"SUCCESS\": {\n if (Option.isNone(queued.onchainHash)) {\n return Effect.succeed(\n Option.some({\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 }\n const txHash = queued.onchainHash.value as Hash;\n return getReceipt(txHash).pipe(\n Effect.map((receipt) =>\n Option.some({\n _tag: \"success\" as const,\n onchainHash: txHash,\n receipt,\n safeTxHash,\n } satisfies SafeMultisigWaitResult)\n )\n );\n }\n default:\n return Effect.succeed(Option.none());\n }\n}\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 let lastInfo: SafeMultisigTxInfo | null = null;\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 if (attempt < maxAttempts - 1) {\n yield* Effect.sleep(interval);\n }\n continue;\n }\n\n const queued = queuedResult.value;\n lastInfo = queued;\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 const terminalResult = yield* resolveTerminalWaitResult(queued, safeTxHash, getReceipt);\n if (Option.isSome(terminalResult)) {\n return terminalResult.value;\n }\n\n // Still pending — keep polling\n if (attempt < maxAttempts - 1) {\n yield* Effect.sleep(interval);\n }\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 confirmations: lastInfo?.confirmations ?? null,\n confirmationsRequired: lastInfo?.confirmationsRequired ?? null,\n lastStatus: mapStatus(lastInfo?.status),\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 return mapStatus(queued.status);\n});\n"]}
@@ -0,0 +1,72 @@
1
+ import { TxManager } from "@prb/effect-evm/tx";
2
+ import { Effect, SubscriptionRef } from "effect";
3
+ import type { Hash, TransactionReceipt } from "viem";
4
+ import type { SafeMultiSendUnavailableError, SafeMultisigInfoUnavailableError, SafeMultisigTxLookupError, SafeMultisigTxSubmissionError } from "./errors.js";
5
+ import { SafeAppsService } from "./service.js";
6
+ import type { SafeMultisigTxStatus, SafeMultisigWaitOptions, SafeMultisigWaitResult } from "./tx-lifecycle.js";
7
+ import type { SafeMultisigTx } from "./types.js";
8
+ export type SafeWriteAndTrackState = {
9
+ readonly status: "submitting";
10
+ } | {
11
+ readonly status: "awaiting_confirmations";
12
+ readonly confirmations: number | null;
13
+ readonly confirmationsRequired: number | null;
14
+ readonly safeTxHash: Hash;
15
+ } | {
16
+ readonly status: "awaiting_execution";
17
+ readonly confirmations: number | null;
18
+ readonly confirmationsRequired: number | null;
19
+ readonly safeTxHash: Hash;
20
+ } | {
21
+ readonly status: "pending";
22
+ readonly confirmations: number | null;
23
+ readonly confirmationsRequired: number | null;
24
+ readonly safeTxHash: Hash;
25
+ } | {
26
+ readonly status: "queued";
27
+ readonly confirmations: number | null;
28
+ readonly confirmationsRequired: number | null;
29
+ readonly lastStatus: SafeMultisigTxStatus;
30
+ readonly safeTxHash: Hash;
31
+ } | {
32
+ readonly status: "success";
33
+ readonly onchainHash: Hash;
34
+ readonly receipt: TransactionReceipt;
35
+ readonly safeTxHash: Hash;
36
+ } | {
37
+ readonly status: "cancelled";
38
+ readonly safeTxHash: Hash;
39
+ } | {
40
+ readonly status: "failed";
41
+ readonly error: string;
42
+ readonly safeTxHash?: Hash;
43
+ };
44
+ export type SafeWriteAndTrackError = SafeMultiSendUnavailableError | SafeMultisigInfoUnavailableError | SafeMultisigTxLookupError | SafeMultisigTxSubmissionError;
45
+ export type SafeWriteAndTrackParams = {
46
+ readonly transactions: readonly [SafeMultisigTx, ...SafeMultisigTx[]];
47
+ readonly chainId?: number;
48
+ readonly waitOptions?: SafeMultisigWaitOptions;
49
+ readonly onStateChange?: (state: SafeWriteAndTrackState) => Effect.Effect<void>;
50
+ readonly onSubmitted?: (safeTxHash: Hash) => Effect.Effect<void>;
51
+ readonly onQueued?: (result: Extract<SafeMultisigWaitResult, {
52
+ _tag: "queued";
53
+ }>) => Effect.Effect<void>;
54
+ readonly onSuccess?: (result: Extract<SafeMultisigWaitResult, {
55
+ _tag: "success";
56
+ }>) => Effect.Effect<void>;
57
+ readonly onCancelled?: (result: Extract<SafeMultisigWaitResult, {
58
+ _tag: "cancelled";
59
+ }>) => Effect.Effect<void>;
60
+ readonly onFailed?: (result: Extract<SafeMultisigWaitResult, {
61
+ _tag: "failed";
62
+ }>) => Effect.Effect<void>;
63
+ };
64
+ export type SafeWriteAndTrackResult = {
65
+ readonly stateRef: SubscriptionRef.SubscriptionRef<SafeWriteAndTrackState>;
66
+ readonly result: Effect.Effect<SafeMultisigWaitResult, SafeWriteAndTrackError>;
67
+ };
68
+ export declare const safeWriteAndTrack: (params: SafeWriteAndTrackParams) => Effect.Effect<{
69
+ result: Effect.Effect<SafeMultisigWaitResult, SafeWriteAndTrackError, never>;
70
+ stateRef: SubscriptionRef.SubscriptionRef<SafeWriteAndTrackState>;
71
+ }, never, import("effect/Scope").Scope | SafeAppsService | TxManager>;
72
+ //# sourceMappingURL=write-and-track.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-and-track.d.ts","sourceRoot":"","sources":["../../src/safe/write-and-track.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAY,MAAM,EAAe,eAAe,EAAE,MAAM,QAAQ,CAAC;AACxE,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAErD,OAAO,KAAK,EACV,6BAA6B,EAC7B,gCAAgC,EAChC,yBAAyB,EACzB,6BAA6B,EAC9B,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACjC;IACE,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,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,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;CAAE,GAC3D;IACE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;CAC5B,CAAC;AAEN,MAAM,MAAM,sBAAsB,GAC9B,6BAA6B,GAC7B,gCAAgC,GAChC,yBAAyB,GACzB,6BAA6B,CAAC;AAElC,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,cAAc,EAAE,GAAG,cAAc,EAAE,CAAC,CAAC;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,uBAAuB,CAAC;IAC/C,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChF,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAClB,MAAM,EAAE,OAAO,CAAC,sBAAsB,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,KACxD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,CACnB,MAAM,EAAE,OAAO,CAAC,sBAAsB,EAAE;QAAE,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC,KACzD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,CACrB,MAAM,EAAE,OAAO,CAAC,sBAAsB,EAAE;QAAE,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC,KAC3D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAClB,MAAM,EAAE,OAAO,CAAC,sBAAsB,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,KACxD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,eAAe,CAAC,sBAAsB,CAAC,CAAC;IAC3E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,sBAAsB,EAAE,sBAAsB,CAAC,CAAC;CAChF,CAAC;AAgCF,eAAO,MAAM,iBAAiB;;;qEAuH5B,CAAC"}
@@ -0,0 +1,116 @@
1
+ import { TxManager } from "@prb/effect-evm/tx";
2
+ import { Deferred, Effect, Option, Ref, SubscriptionRef } from "effect";
3
+ import { safeMultisigBatchWrite } from "./batch.js";
4
+ import { toSafeMultisigTxLookupError } from "./errors.js";
5
+ import { SafeAppsService } from "./service.js";
6
+ import { waitForSafeMultisigTx } from "./tx-lifecycle.js";
7
+ function mapStatusState(options) {
8
+ const shared = {
9
+ confirmations: options.confirmations,
10
+ confirmationsRequired: options.confirmationsRequired,
11
+ safeTxHash: options.safeTxHash,
12
+ };
13
+ switch (options.status) {
14
+ case "AWAITING_CONFIRMATIONS":
15
+ return { status: "awaiting_confirmations", ...shared };
16
+ case "AWAITING_EXECUTION":
17
+ return { status: "awaiting_execution", ...shared };
18
+ default:
19
+ return { status: "pending", ...shared };
20
+ }
21
+ }
22
+ function runLifecycle(lifecycle) {
23
+ if (!lifecycle) {
24
+ return Effect.void;
25
+ }
26
+ return lifecycle.pipe(Effect.catchAll(() => Effect.void));
27
+ }
28
+ export const safeWriteAndTrack = Effect.fn("safeWriteAndTrack")(function* (params) {
29
+ const safeApps = yield* SafeAppsService;
30
+ const txManager = yield* TxManager;
31
+ const stateRef = yield* SubscriptionRef.make({
32
+ status: "submitting",
33
+ });
34
+ const safeTxHashRef = yield* Ref.make(null);
35
+ const resultDeferred = yield* Deferred.make();
36
+ const setState = (state) => SubscriptionRef.set(stateRef, state).pipe(Effect.zipRight(runLifecycle(params.onStateChange?.(state))));
37
+ const program = Effect.gen(function* () {
38
+ const resolvedChainId = params.chainId ?? (yield* safeApps.getInfo()).chainId;
39
+ const safeTxHash = yield* safeMultisigBatchWrite(params.transactions, resolvedChainId);
40
+ yield* Ref.set(safeTxHashRef, safeTxHash);
41
+ yield* runLifecycle(params.onSubmitted?.(safeTxHash));
42
+ const initialInfo = yield* safeApps.getTx(safeTxHash).pipe(Effect.option);
43
+ if (Option.isSome(initialInfo)) {
44
+ yield* setState(mapStatusState({
45
+ confirmations: initialInfo.value.confirmations,
46
+ confirmationsRequired: initialInfo.value.confirmationsRequired,
47
+ safeTxHash,
48
+ status: initialInfo.value.status,
49
+ }));
50
+ }
51
+ else {
52
+ yield* setState({
53
+ confirmations: null,
54
+ confirmationsRequired: null,
55
+ safeTxHash,
56
+ status: "pending",
57
+ });
58
+ }
59
+ const waitResult = yield* waitForSafeMultisigTx(safeTxHash, (onchainHash) => txManager
60
+ .waitForReceipt(resolvedChainId, onchainHash)
61
+ .pipe(Effect.mapError((cause) => toSafeMultisigTxLookupError(safeTxHash, cause, false))), params.waitOptions);
62
+ switch (waitResult._tag) {
63
+ case "success":
64
+ yield* setState({
65
+ onchainHash: waitResult.onchainHash,
66
+ receipt: waitResult.receipt,
67
+ safeTxHash: waitResult.safeTxHash,
68
+ status: "success",
69
+ });
70
+ yield* runLifecycle(params.onSuccess?.(waitResult));
71
+ break;
72
+ case "queued":
73
+ yield* setState({
74
+ confirmations: waitResult.confirmations,
75
+ confirmationsRequired: waitResult.confirmationsRequired,
76
+ lastStatus: waitResult.lastStatus,
77
+ safeTxHash: waitResult.safeTxHash,
78
+ status: "queued",
79
+ });
80
+ yield* runLifecycle(params.onQueued?.(waitResult));
81
+ break;
82
+ case "cancelled":
83
+ yield* setState({
84
+ safeTxHash: waitResult.safeTxHash,
85
+ status: "cancelled",
86
+ });
87
+ yield* runLifecycle(params.onCancelled?.(waitResult));
88
+ break;
89
+ case "failed":
90
+ yield* setState({
91
+ error: waitResult.error,
92
+ safeTxHash: waitResult.safeTxHash,
93
+ status: "failed",
94
+ });
95
+ yield* runLifecycle(params.onFailed?.(waitResult));
96
+ break;
97
+ }
98
+ return waitResult;
99
+ }).pipe(Effect.catchAll((error) => Effect.gen(function* () {
100
+ const safeTxHash = yield* Ref.get(safeTxHashRef);
101
+ yield* setState({
102
+ error: error.message,
103
+ safeTxHash: safeTxHash ?? undefined,
104
+ status: "failed",
105
+ });
106
+ return yield* Effect.fail(error);
107
+ })));
108
+ yield* Effect.forkScoped(program.pipe(Effect.either, Effect.flatMap((either) => either._tag === "Right"
109
+ ? Deferred.succeed(resultDeferred, either.right)
110
+ : Deferred.fail(resultDeferred, either.left))));
111
+ return {
112
+ result: Deferred.await(resultDeferred),
113
+ stateRef,
114
+ };
115
+ });
116
+ //# sourceMappingURL=write-and-track.js.map