@prb/effect-evm 1.0.0-beta.5 → 1.0.0-beta.7
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/dist/constants/index.d.ts +0 -4
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +1 -5
- package/dist/constants/index.js.map +1 -1
- package/dist/contract/pipeline/internal/core.d.ts +2 -2
- package/dist/contract/pipeline/internal/core.d.ts.map +1 -1
- package/dist/contract/pipeline/internal/core.js.map +1 -1
- package/dist/contract/pipeline/internal/receipt.d.ts +2 -2
- package/dist/contract/pipeline/internal/receipt.d.ts.map +1 -1
- package/dist/contract/pipeline/internal/receipt.js +1 -1
- package/dist/contract/pipeline/internal/receipt.js.map +1 -1
- package/dist/contract/pipeline/service.d.ts +3 -3
- package/dist/contract/pipeline/service.d.ts.map +1 -1
- package/dist/contract/pipeline/service.js.map +1 -1
- package/dist/contract/pipeline/types.d.ts +2 -2
- package/dist/contract/pipeline/types.d.ts.map +1 -1
- package/dist/contract/pipeline/types.js.map +1 -1
- package/dist/contract/pipeline/write-and-track.d.ts.map +1 -1
- package/dist/contract/pipeline/write-and-track.js +5 -6
- package/dist/contract/pipeline/write-and-track.js.map +1 -1
- package/dist/contract/pipeline/write-and-wait.d.ts +1 -1
- package/dist/contract/pipeline/write-and-wait.d.ts.map +1 -1
- package/dist/core/errors/transaction.d.ts +7 -7
- package/dist/core/errors/transaction.d.ts.map +1 -1
- package/dist/core/errors/transaction.js +2 -2
- package/dist/core/errors/transaction.js.map +1 -1
- package/dist/core/errors/viem-mapper.d.ts +3 -3
- package/dist/core/errors/viem-mapper.d.ts.map +1 -1
- package/dist/core/errors/viem-mapper.js +3 -3
- package/dist/core/errors/viem-mapper.js.map +1 -1
- package/dist/deploy/service.d.ts +3 -3
- package/dist/deploy/service.d.ts.map +1 -1
- package/dist/deploy/service.js.map +1 -1
- package/dist/eip7702/errors.d.ts +3 -3
- package/dist/eip7702/errors.d.ts.map +1 -1
- package/dist/eip7702/errors.js +1 -1
- package/dist/eip7702/errors.js.map +1 -1
- package/dist/eip7702/service.d.ts +8 -8
- package/dist/eip7702/service.d.ts.map +1 -1
- package/dist/eip7702/service.js +2 -2
- package/dist/eip7702/service.js.map +1 -1
- package/dist/react-hooks/index.d.ts +0 -4
- package/dist/react-hooks/index.d.ts.map +1 -1
- package/dist/react-hooks/index.js +0 -4
- package/dist/react-hooks/index.js.map +1 -1
- package/dist/subscriptions/pending-tx.d.ts +1 -1
- package/dist/subscriptions/pending-tx.d.ts.map +1 -1
- package/dist/subscriptions/pending-tx.js +1 -1
- package/dist/subscriptions/pending-tx.js.map +1 -1
- package/dist/subscriptions/service.d.ts +2 -2
- package/dist/subscriptions/service.d.ts.map +1 -1
- package/dist/subscriptions/service.js +4 -4
- package/dist/subscriptions/service.js.map +1 -1
- package/dist/testing-kit/mock-subscription-service.d.ts +2 -2
- package/dist/testing-kit/mock-subscription-service.d.ts.map +1 -1
- package/dist/testing-kit/mock-subscription-service.js +5 -5
- package/dist/testing-kit/mock-subscription-service.js.map +1 -1
- package/dist/testing-kit/mock-transfer-service.d.ts +3 -3
- package/dist/testing-kit/mock-transfer-service.d.ts.map +1 -1
- package/dist/testing-kit/mock-transfer-service.js.map +1 -1
- package/dist/transfer/service.d.ts +3 -3
- package/dist/transfer/service.d.ts.map +1 -1
- package/dist/transfer/service.js +3 -3
- package/dist/transfer/service.js.map +1 -1
- package/dist/tx/manager.d.ts +3 -2
- package/dist/tx/manager.d.ts.map +1 -1
- package/dist/tx/manager.js +232 -216
- package/dist/tx/manager.js.map +1 -1
- package/dist/tx/manager.test.integration.js +25 -5
- package/dist/tx/manager.test.integration.js.map +1 -1
- package/dist/tx/policy.d.ts +0 -1
- package/dist/tx/policy.d.ts.map +1 -1
- package/dist/tx/policy.js.map +1 -1
- package/dist/tx/replacement.d.ts +3 -3
- package/dist/tx/replacement.d.ts.map +1 -1
- package/dist/tx/replacement.js +3 -3
- package/dist/tx/replacement.js.map +1 -1
- package/dist/tx/tracker.d.ts +6 -6
- package/dist/tx/tracker.d.ts.map +1 -1
- package/dist/tx/tracker.js +9 -9
- package/dist/tx/tracker.js.map +1 -1
- package/dist/types/params.d.ts +1 -1
- package/dist/types/params.d.ts.map +1 -1
- package/dist/types/params.js.map +1 -1
- package/dist/wallet/errors.d.ts +3 -3
- package/dist/wallet/errors.d.ts.map +1 -1
- package/dist/wallet/errors.js +1 -1
- package/dist/wallet/errors.js.map +1 -1
- package/dist/wallet/operations.d.ts +2 -2
- package/dist/wallet/operations.d.ts.map +1 -1
- package/dist/wallet/operations.js +2 -2
- package/dist/wallet/operations.js.map +1 -1
- package/dist/wallet/service.d.ts +2 -2
- package/dist/wallet/service.d.ts.map +1 -1
- package/dist/wallet/service.js.map +1 -1
- package/package.json +1 -6
- package/dist/react-hooks/safe-app-origins.d.ts +0 -8
- package/dist/react-hooks/safe-app-origins.d.ts.map +0 -1
- package/dist/react-hooks/safe-app-origins.js +0 -124
- package/dist/react-hooks/safe-app-origins.js.map +0 -1
- package/dist/react-hooks/use-is-host-safe-app.d.ts +0 -2
- package/dist/react-hooks/use-is-host-safe-app.d.ts.map +0 -1
- package/dist/react-hooks/use-is-host-safe-app.js +0 -16
- package/dist/react-hooks/use-is-host-safe-app.js.map +0 -1
- package/dist/react-hooks/use-is-safe-app-context.d.ts +0 -2
- package/dist/react-hooks/use-is-safe-app-context.d.ts.map +0 -1
- package/dist/react-hooks/use-is-safe-app-context.js +0 -41
- package/dist/react-hooks/use-is-safe-app-context.js.map +0 -1
- package/dist/react-hooks/use-is-safe-multisig-wallet.d.ts +0 -2
- package/dist/react-hooks/use-is-safe-multisig-wallet.d.ts.map +0 -1
- package/dist/react-hooks/use-is-safe-multisig-wallet.js +0 -24
- package/dist/react-hooks/use-is-safe-multisig-wallet.js.map +0 -1
- package/dist/safe/adapter.d.ts +0 -9
- package/dist/safe/adapter.d.ts.map +0 -1
- package/dist/safe/adapter.js +0 -13
- package/dist/safe/adapter.js.map +0 -1
- package/dist/safe/detection.d.ts +0 -26
- package/dist/safe/detection.d.ts.map +0 -1
- package/dist/safe/detection.js +0 -102
- package/dist/safe/detection.js.map +0 -1
- package/dist/safe/detection.test.integration.d.ts +0 -2
- package/dist/safe/detection.test.integration.d.ts.map +0 -1
- package/dist/safe/detection.test.integration.js +0 -92
- package/dist/safe/detection.test.integration.js.map +0 -1
- package/dist/safe/errors.d.ts +0 -79
- package/dist/safe/errors.d.ts.map +0 -1
- package/dist/safe/errors.js +0 -34
- package/dist/safe/errors.js.map +0 -1
- package/dist/safe/index.d.ts +0 -8
- package/dist/safe/index.d.ts.map +0 -1
- package/dist/safe/index.js +0 -6
- package/dist/safe/index.js.map +0 -1
- package/dist/safe/live.d.ts +0 -8
- package/dist/safe/live.d.ts.map +0 -1
- package/dist/safe/live.js +0 -250
- package/dist/safe/live.js.map +0 -1
- package/dist/safe/service.d.ts +0 -26
- package/dist/safe/service.d.ts.map +0 -1
- package/dist/safe/service.js +0 -4
- package/dist/safe/service.js.map +0 -1
- package/dist/safe/service.test.integration.d.ts +0 -2
- package/dist/safe/service.test.integration.d.ts.map +0 -1
- package/dist/safe/service.test.integration.js +0 -171
- package/dist/safe/service.test.integration.js.map +0 -1
- package/dist/safe/simulation/abis.d.ts +0 -73
- package/dist/safe/simulation/abis.d.ts.map +0 -1
- package/dist/safe/simulation/abis.js +0 -61
- package/dist/safe/simulation/abis.js.map +0 -1
- package/dist/safe/simulation/addresses.d.ts +0 -4
- package/dist/safe/simulation/addresses.d.ts.map +0 -1
- package/dist/safe/simulation/addresses.js +0 -54
- package/dist/safe/simulation/addresses.js.map +0 -1
- package/dist/safe/simulation/encoding.d.ts +0 -16
- package/dist/safe/simulation/encoding.d.ts.map +0 -1
- package/dist/safe/simulation/encoding.js +0 -36
- package/dist/safe/simulation/encoding.js.map +0 -1
- package/dist/safe/simulation/errors.d.ts +0 -56
- package/dist/safe/simulation/errors.d.ts.map +0 -1
- package/dist/safe/simulation/errors.js +0 -37
- package/dist/safe/simulation/errors.js.map +0 -1
- package/dist/safe/simulation/index.d.ts +0 -7
- package/dist/safe/simulation/index.d.ts.map +0 -1
- package/dist/safe/simulation/index.js +0 -6
- package/dist/safe/simulation/index.js.map +0 -1
- package/dist/safe/simulation/internal/calldata/calldata.d.ts +0 -5
- package/dist/safe/simulation/internal/calldata/calldata.d.ts.map +0 -1
- package/dist/safe/simulation/internal/calldata/calldata.js +0 -17
- package/dist/safe/simulation/internal/calldata/calldata.js.map +0 -1
- package/dist/safe/simulation/internal/calldata/index.d.ts +0 -2
- package/dist/safe/simulation/internal/calldata/index.d.ts.map +0 -1
- package/dist/safe/simulation/internal/calldata/index.js +0 -2
- package/dist/safe/simulation/internal/calldata/index.js.map +0 -1
- package/dist/safe/simulation/internal/contracts/contracts.d.ts +0 -5
- package/dist/safe/simulation/internal/contracts/contracts.d.ts.map +0 -1
- package/dist/safe/simulation/internal/contracts/contracts.js +0 -25
- package/dist/safe/simulation/internal/contracts/contracts.js.map +0 -1
- package/dist/safe/simulation/internal/contracts/index.d.ts +0 -2
- package/dist/safe/simulation/internal/contracts/index.d.ts.map +0 -1
- package/dist/safe/simulation/internal/contracts/index.js +0 -2
- package/dist/safe/simulation/internal/contracts/index.js.map +0 -1
- package/dist/safe/simulation/internal/evaluation/evaluation.d.ts +0 -6
- package/dist/safe/simulation/internal/evaluation/evaluation.d.ts.map +0 -1
- package/dist/safe/simulation/internal/evaluation/evaluation.js +0 -20
- package/dist/safe/simulation/internal/evaluation/evaluation.js.map +0 -1
- package/dist/safe/simulation/internal/evaluation/index.d.ts +0 -2
- package/dist/safe/simulation/internal/evaluation/index.d.ts.map +0 -1
- package/dist/safe/simulation/internal/evaluation/index.js +0 -2
- package/dist/safe/simulation/internal/evaluation/index.js.map +0 -1
- package/dist/safe/simulation/internal/execution/execution.d.ts +0 -9
- package/dist/safe/simulation/internal/execution/execution.d.ts.map +0 -1
- package/dist/safe/simulation/internal/execution/execution.js +0 -65
- package/dist/safe/simulation/internal/execution/execution.js.map +0 -1
- package/dist/safe/simulation/internal/execution/index.d.ts +0 -2
- package/dist/safe/simulation/internal/execution/index.d.ts.map +0 -1
- package/dist/safe/simulation/internal/execution/index.js +0 -2
- package/dist/safe/simulation/internal/execution/index.js.map +0 -1
- package/dist/safe/simulation/internal/limits/index.d.ts +0 -2
- package/dist/safe/simulation/internal/limits/index.d.ts.map +0 -1
- package/dist/safe/simulation/internal/limits/index.js +0 -2
- package/dist/safe/simulation/internal/limits/index.js.map +0 -1
- package/dist/safe/simulation/internal/limits/limits.d.ts +0 -5
- package/dist/safe/simulation/internal/limits/limits.d.ts.map +0 -1
- package/dist/safe/simulation/internal/limits/limits.js +0 -18
- package/dist/safe/simulation/internal/limits/limits.js.map +0 -1
- package/dist/safe/simulation/internal/types/index.d.ts +0 -2
- package/dist/safe/simulation/internal/types/index.d.ts.map +0 -1
- package/dist/safe/simulation/internal/types/index.js +0 -2
- package/dist/safe/simulation/internal/types/index.js.map +0 -1
- package/dist/safe/simulation/internal/types/types.d.ts +0 -11
- package/dist/safe/simulation/internal/types/types.d.ts.map +0 -1
- package/dist/safe/simulation/internal/types/types.js +0 -2
- package/dist/safe/simulation/internal/types/types.js.map +0 -1
- package/dist/safe/simulation/internal/validation/index.d.ts +0 -2
- package/dist/safe/simulation/internal/validation/index.d.ts.map +0 -1
- package/dist/safe/simulation/internal/validation/index.js +0 -2
- package/dist/safe/simulation/internal/validation/index.js.map +0 -1
- package/dist/safe/simulation/internal/validation/validation.d.ts +0 -5
- package/dist/safe/simulation/internal/validation/validation.d.ts.map +0 -1
- package/dist/safe/simulation/internal/validation/validation.js +0 -27
- package/dist/safe/simulation/internal/validation/validation.js.map +0 -1
- package/dist/safe/simulation/service.d.ts +0 -14
- package/dist/safe/simulation/service.d.ts.map +0 -1
- package/dist/safe/simulation/service.js +0 -25
- package/dist/safe/simulation/service.js.map +0 -1
- package/dist/safe/simulation/types.d.ts +0 -20
- package/dist/safe/simulation/types.d.ts.map +0 -1
- package/dist/safe/simulation/types.js +0 -2
- package/dist/safe/simulation/types.js.map +0 -1
- package/dist/safe/types.d.ts +0 -61
- package/dist/safe/types.d.ts.map +0 -1
- package/dist/safe/types.js +0 -2
- package/dist/safe/types.js.map +0 -1
package/dist/safe/live.js
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
import { Duration, Effect, Layer, Option, Ref } from "effect";
|
|
2
|
-
import { isAddress, isHash, isHex } from "viem";
|
|
3
|
-
import { SAFE_EXECUTION_TIMEOUT, SAFE_POLL_INTERVAL, SAFE_SIGNATURE_POLL_INTERVAL, SAFE_SIGNATURE_TIMEOUT, } from "../constants/index.js";
|
|
4
|
-
import { SpanNames } from "../telemetry/index.js";
|
|
5
|
-
import { TxManager } from "../tx/index.js";
|
|
6
|
-
import { loadSafeSdk } from "./adapter.js";
|
|
7
|
-
import { NotInSafeAppContextError, OffchainSignatureTimeoutError, SafeInfoUnavailableError, SafeSettingsError, SafeTxExecutionTimeoutError, SafeTxLookupError, SafeTxSubmissionError, SignTypedDataError, } from "./errors.js";
|
|
8
|
-
import { SafeAppsService } from "./service.js";
|
|
9
|
-
const validateAddress = (value, context) => isAddress(value)
|
|
10
|
-
? Effect.succeed(value)
|
|
11
|
-
: Effect.fail(new SafeTxLookupError({
|
|
12
|
-
message: `Invalid address from SDK in ${context}: ${value}`,
|
|
13
|
-
retryable: false,
|
|
14
|
-
safeTxHash: "",
|
|
15
|
-
}));
|
|
16
|
-
const validateHash = (value, context) => isHash(value)
|
|
17
|
-
? Effect.succeed(value)
|
|
18
|
-
: Effect.fail(new SafeTxLookupError({
|
|
19
|
-
message: `Invalid hash from SDK in ${context}: ${value}`,
|
|
20
|
-
retryable: false,
|
|
21
|
-
safeTxHash: "",
|
|
22
|
-
}));
|
|
23
|
-
const validateHex = (value, context) => isHex(value)
|
|
24
|
-
? Effect.succeed(value)
|
|
25
|
-
: Effect.fail(new SafeTxLookupError({
|
|
26
|
-
message: `Invalid hex from SDK in ${context}: ${value}`,
|
|
27
|
-
retryable: false,
|
|
28
|
-
safeTxHash: "",
|
|
29
|
-
}));
|
|
30
|
-
export const SafeAppsServiceLive = (config) => Layer.scoped(SafeAppsService, Effect.gen(function* () {
|
|
31
|
-
if (typeof window === "undefined") {
|
|
32
|
-
return yield* Effect.fail(new NotInSafeAppContextError({
|
|
33
|
-
message: "Safe Apps SDK requires a browser environment (window is undefined)",
|
|
34
|
-
}));
|
|
35
|
-
}
|
|
36
|
-
const sdk = yield* loadSafeSdk(config);
|
|
37
|
-
const infoRef = yield* Ref.make(null);
|
|
38
|
-
const txManager = yield* TxManager;
|
|
39
|
-
const getInfo = () => Effect.gen(function* () {
|
|
40
|
-
const cached = yield* Ref.get(infoRef);
|
|
41
|
-
if (cached) {
|
|
42
|
-
return cached;
|
|
43
|
-
}
|
|
44
|
-
const info = yield* Effect.tryPromise({
|
|
45
|
-
catch: (cause) => new SafeInfoUnavailableError({
|
|
46
|
-
cause,
|
|
47
|
-
message: "Failed to get Safe info from SDK",
|
|
48
|
-
}),
|
|
49
|
-
try: () => sdk.safe.getInfo(),
|
|
50
|
-
});
|
|
51
|
-
const safeAddress = yield* validateAddress(info.safeAddress, "getInfo").pipe(Effect.catchTag("SafeTxLookupError", (e) => Effect.fail(new SafeInfoUnavailableError({ cause: e, message: e.message }))));
|
|
52
|
-
const safeInfo = {
|
|
53
|
-
chainId: info.chainId,
|
|
54
|
-
safeAddress,
|
|
55
|
-
};
|
|
56
|
-
yield* Ref.set(infoRef, safeInfo);
|
|
57
|
-
return safeInfo;
|
|
58
|
-
}).pipe(Effect.withSpan(SpanNames.SAFE_GET_INFO));
|
|
59
|
-
const sendTxs = (txs, params) => Effect.gen(function* () {
|
|
60
|
-
const sdkTxs = txs.map((tx) => ({
|
|
61
|
-
data: tx.data,
|
|
62
|
-
to: tx.to,
|
|
63
|
-
value: tx.value?.toString() ?? "0",
|
|
64
|
-
}));
|
|
65
|
-
const result = yield* Effect.tryPromise({
|
|
66
|
-
catch: (cause) => new SafeTxSubmissionError({
|
|
67
|
-
cause,
|
|
68
|
-
message: "Failed to submit txs to Safe",
|
|
69
|
-
}),
|
|
70
|
-
try: () => sdk.txs.send({ params, txs: sdkTxs }),
|
|
71
|
-
});
|
|
72
|
-
const safeTxHash = yield* validateHash(result.safeTxHash, "sendTxs").pipe(Effect.catchTag("SafeTxLookupError", (e) => Effect.fail(new SafeTxSubmissionError({ cause: e, message: e.message }))));
|
|
73
|
-
const info = yield* getInfo();
|
|
74
|
-
return {
|
|
75
|
-
chainId: info.chainId,
|
|
76
|
-
safeAddress: info.safeAddress,
|
|
77
|
-
safeTxHash,
|
|
78
|
-
};
|
|
79
|
-
})
|
|
80
|
-
.pipe(Effect.catchTag("SafeInfoUnavailableError", (error) => Effect.fail(new SafeTxSubmissionError({
|
|
81
|
-
cause: error,
|
|
82
|
-
message: "Failed to get Safe info after tx submission",
|
|
83
|
-
}))))
|
|
84
|
-
.pipe(Effect.withSpan(SpanNames.SAFE_SEND_TXS, {
|
|
85
|
-
attributes: { txCount: txs.length },
|
|
86
|
-
}));
|
|
87
|
-
const getTx = (safeTxHash) => Effect.gen(function* () {
|
|
88
|
-
const tx = yield* Effect.tryPromise({
|
|
89
|
-
catch: (cause) => new SafeTxLookupError({
|
|
90
|
-
cause,
|
|
91
|
-
message: `Failed to lookup Safe tx ${safeTxHash}`,
|
|
92
|
-
retryable: true,
|
|
93
|
-
safeTxHash,
|
|
94
|
-
}),
|
|
95
|
-
try: () => sdk.txs.getBySafeTxHash(safeTxHash),
|
|
96
|
-
});
|
|
97
|
-
const txHash = tx.txHash ? yield* validateHash(tx.txHash, "getTx") : null;
|
|
98
|
-
return {
|
|
99
|
-
status: tx.txStatus ?? "AWAITING_CONFIRMATIONS",
|
|
100
|
-
txHash: txHash ? Option.some(txHash) : Option.none(),
|
|
101
|
-
};
|
|
102
|
-
}).pipe(Effect.withSpan(SpanNames.SAFE_GET_TX, {
|
|
103
|
-
attributes: { safeTxHash },
|
|
104
|
-
}));
|
|
105
|
-
const waitForTxReceipt = (safeTxHash, policy = {}) => Effect.gen(function* () {
|
|
106
|
-
const info = yield* getInfo();
|
|
107
|
-
const pollInterval = policy.pollInterval ?? SAFE_POLL_INTERVAL;
|
|
108
|
-
const executionTimeout = policy.executionTimeout ?? SAFE_EXECUTION_TIMEOUT;
|
|
109
|
-
const onchainHash = yield* Effect.gen(function* () {
|
|
110
|
-
let lastStatus = "AWAITING_CONFIRMATIONS";
|
|
111
|
-
let found = null;
|
|
112
|
-
const pollEffect = Effect.gen(function* () {
|
|
113
|
-
while (found === null) {
|
|
114
|
-
const tx = yield* getTx(safeTxHash);
|
|
115
|
-
lastStatus = tx.status;
|
|
116
|
-
if (Option.isSome(tx.txHash)) {
|
|
117
|
-
found = tx.txHash.value;
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
yield* Effect.sleep(Duration.millis(pollInterval));
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
yield* pollEffect.pipe(Effect.timeout(Duration.millis(executionTimeout)), Effect.catchTag("TimeoutException", () => Effect.fail(new SafeTxExecutionTimeoutError({
|
|
125
|
-
lastStatus,
|
|
126
|
-
message: `Safe tx ${safeTxHash} not executed within ${executionTimeout}ms (last status: ${lastStatus})`,
|
|
127
|
-
safeTxHash,
|
|
128
|
-
timeout: executionTimeout,
|
|
129
|
-
}))));
|
|
130
|
-
if (found === null) {
|
|
131
|
-
return yield* Effect.fail(new SafeTxExecutionTimeoutError({
|
|
132
|
-
lastStatus,
|
|
133
|
-
message: `Safe tx ${safeTxHash} not executed within timeout`,
|
|
134
|
-
safeTxHash,
|
|
135
|
-
timeout: executionTimeout,
|
|
136
|
-
}));
|
|
137
|
-
}
|
|
138
|
-
return found;
|
|
139
|
-
});
|
|
140
|
-
const receipt = yield* txManager
|
|
141
|
-
.waitForReceipt(info.chainId, onchainHash, policy.receiptPolicy)
|
|
142
|
-
.pipe(Effect.catchTag("TransactionReplacedError", (error) => Effect.fail(new SafeTxLookupError({
|
|
143
|
-
cause: error,
|
|
144
|
-
message: `Transaction was replaced: ${error.message}`,
|
|
145
|
-
retryable: false,
|
|
146
|
-
safeTxHash,
|
|
147
|
-
}))));
|
|
148
|
-
return {
|
|
149
|
-
chainId: info.chainId,
|
|
150
|
-
onchainHash,
|
|
151
|
-
receipt,
|
|
152
|
-
safeAddress: info.safeAddress,
|
|
153
|
-
safeTxHash,
|
|
154
|
-
};
|
|
155
|
-
})
|
|
156
|
-
.pipe(Effect.catchTag("SafeInfoUnavailableError", (error) => Effect.fail(new SafeTxLookupError({
|
|
157
|
-
cause: error,
|
|
158
|
-
message: "Failed to get Safe info for receipt waiting",
|
|
159
|
-
retryable: true,
|
|
160
|
-
safeTxHash,
|
|
161
|
-
}))))
|
|
162
|
-
.pipe(Effect.withSpan(SpanNames.SAFE_WAIT_RECEIPT, {
|
|
163
|
-
attributes: { safeTxHash },
|
|
164
|
-
}));
|
|
165
|
-
const signTypedData = (typedData) => Effect.gen(function* () {
|
|
166
|
-
const result = yield* Effect.tryPromise({
|
|
167
|
-
catch: (cause) => new SignTypedDataError({
|
|
168
|
-
cause,
|
|
169
|
-
message: "Failed to sign typed data via Safe",
|
|
170
|
-
}),
|
|
171
|
-
try: () => sdk.txs.signTypedMessage(typedData),
|
|
172
|
-
});
|
|
173
|
-
if ("messageHash" in result && result.messageHash) {
|
|
174
|
-
const messageHash = yield* validateHex(result.messageHash, "signTypedData").pipe(Effect.catchTag("SafeTxLookupError", (e) => Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))));
|
|
175
|
-
return { _tag: "Offchain", messageHash };
|
|
176
|
-
}
|
|
177
|
-
const onchainResult = result;
|
|
178
|
-
const safeTxHash = yield* validateHash(onchainResult.safeTxHash, "signTypedData").pipe(Effect.catchTag("SafeTxLookupError", (e) => Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))));
|
|
179
|
-
return { _tag: "Onchain", safeTxHash };
|
|
180
|
-
}).pipe(Effect.withSpan(SpanNames.SAFE_SIGN_TYPED_DATA));
|
|
181
|
-
const getOffchainSignature = (messageHash) => Effect.gen(function* () {
|
|
182
|
-
const sig = yield* Effect.tryPromise({
|
|
183
|
-
catch: (cause) => new SafeTxLookupError({
|
|
184
|
-
cause,
|
|
185
|
-
message: `Failed to get off-chain signature for ${messageHash}`,
|
|
186
|
-
retryable: true,
|
|
187
|
-
safeTxHash: messageHash,
|
|
188
|
-
}),
|
|
189
|
-
try: () => sdk.safe.getOffChainSignature(messageHash),
|
|
190
|
-
});
|
|
191
|
-
if (!sig || sig === "" || sig === "0x") {
|
|
192
|
-
return Option.none();
|
|
193
|
-
}
|
|
194
|
-
const validatedSig = yield* validateHex(sig, "getOffchainSignature");
|
|
195
|
-
return Option.some(validatedSig);
|
|
196
|
-
}).pipe(Effect.withSpan(SpanNames.SAFE_GET_OFFCHAIN_SIG, {
|
|
197
|
-
attributes: { messageHash },
|
|
198
|
-
}));
|
|
199
|
-
const pollOffchainSignature = (messageHash, policy = {}) => Effect.gen(function* () {
|
|
200
|
-
const pollInterval = policy.pollInterval ?? SAFE_SIGNATURE_POLL_INTERVAL;
|
|
201
|
-
const timeout = policy.timeout ?? SAFE_SIGNATURE_TIMEOUT;
|
|
202
|
-
let found = null;
|
|
203
|
-
const pollEffect = Effect.gen(function* () {
|
|
204
|
-
while (found === null) {
|
|
205
|
-
const sig = yield* getOffchainSignature(messageHash);
|
|
206
|
-
if (Option.isSome(sig)) {
|
|
207
|
-
found = sig.value;
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
yield* Effect.sleep(Duration.millis(pollInterval));
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
yield* pollEffect.pipe(Effect.timeout(Duration.millis(timeout)), Effect.catchTag("TimeoutException", () => Effect.fail(new OffchainSignatureTimeoutError({
|
|
215
|
-
message: `Off-chain signature for ${messageHash} not available within ${timeout}ms`,
|
|
216
|
-
messageHash,
|
|
217
|
-
timeout,
|
|
218
|
-
}))));
|
|
219
|
-
if (found === null) {
|
|
220
|
-
return yield* Effect.fail(new OffchainSignatureTimeoutError({
|
|
221
|
-
message: `Off-chain signature for ${messageHash} not available within timeout`,
|
|
222
|
-
messageHash,
|
|
223
|
-
timeout,
|
|
224
|
-
}));
|
|
225
|
-
}
|
|
226
|
-
return { messageHash, signature: found };
|
|
227
|
-
}).pipe(Effect.withSpan(SpanNames.SAFE_POLL_OFFCHAIN_SIG, {
|
|
228
|
-
attributes: { messageHash },
|
|
229
|
-
}));
|
|
230
|
-
const enableOffchainSigning = () => Effect.tryPromise({
|
|
231
|
-
catch: (cause) => new SafeSettingsError({
|
|
232
|
-
cause,
|
|
233
|
-
message: "Failed to enable off-chain signing mode",
|
|
234
|
-
}),
|
|
235
|
-
try: () => sdk.eth.setSafeSettings([{ offChainSigning: true }]),
|
|
236
|
-
})
|
|
237
|
-
.pipe(Effect.asVoid)
|
|
238
|
-
.pipe(Effect.withSpan(SpanNames.SAFE_ENABLE_OFFCHAIN));
|
|
239
|
-
return SafeAppsService.of({
|
|
240
|
-
enableOffchainSigning,
|
|
241
|
-
getInfo,
|
|
242
|
-
getOffchainSignature,
|
|
243
|
-
getTx,
|
|
244
|
-
pollOffchainSignature,
|
|
245
|
-
sendTxs,
|
|
246
|
-
signTypedData,
|
|
247
|
-
waitForTxReceipt,
|
|
248
|
-
});
|
|
249
|
-
}));
|
|
250
|
-
//# sourceMappingURL=live.js.map
|
package/dist/safe/live.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/safe/live.ts"],"names":[],"mappings":"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","sourcesContent":["import { Duration, Effect, Layer, Option, Ref } from \"effect\";\nimport type { Address, Hash, Hex } from \"viem\";\nimport { isAddress, isHash, isHex } from \"viem\";\nimport {\n SAFE_EXECUTION_TIMEOUT,\n SAFE_POLL_INTERVAL,\n SAFE_SIGNATURE_POLL_INTERVAL,\n SAFE_SIGNATURE_TIMEOUT,\n} from \"@/src/constants/index.js\";\nimport { SpanNames } from \"@/src/telemetry/index.js\";\nimport { TxManager } from \"@/src/tx/index.js\";\nimport type { SafeAppsSdkConfig } from \"./adapter.js\";\nimport { loadSafeSdk } from \"./adapter.js\";\nimport {\n NotInSafeAppContextError,\n OffchainSignatureTimeoutError,\n SafeInfoUnavailableError,\n SafeSettingsError,\n SafeTxExecutionTimeoutError,\n SafeTxLookupError,\n SafeTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { EIP712TypedData, SafeInfo, SafeMultisigTx } from \"./types.js\";\n\nexport type SafeAppsServiceConfig = SafeAppsSdkConfig;\n\n/**\n * Validate that a string is a valid Ethereum address, failing with context if not.\n */\nconst validateAddress = (\n value: string,\n context: string\n): Effect.Effect<Address, SafeTxLookupError> =>\n isAddress(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid address from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\n/**\n * Validate that a string is a valid transaction hash, failing with context if not.\n */\nconst validateHash = (value: string, context: string): Effect.Effect<Hash, SafeTxLookupError> =>\n isHash(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid hash from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\n/**\n * Validate that a string is valid hex, failing with context if not.\n */\nconst validateHex = (value: string, context: string): Effect.Effect<Hex, SafeTxLookupError> =>\n isHex(value)\n ? Effect.succeed(value)\n : Effect.fail(\n new SafeTxLookupError({\n message: `Invalid hex from SDK in ${context}: ${value}`,\n retryable: false,\n safeTxHash: \"\",\n })\n );\n\nexport const SafeAppsServiceLive = (config?: SafeAppsServiceConfig) =>\n Layer.scoped(\n SafeAppsService,\n Effect.gen(function* () {\n // SSR guard - Safe Apps SDK requires browser environment\n if (typeof window === \"undefined\") {\n return yield* Effect.fail(\n new NotInSafeAppContextError({\n message: \"Safe Apps SDK requires a browser environment (window is undefined)\",\n })\n );\n }\n\n // Load SDK dynamically to keep it optional\n const sdk = yield* loadSafeSdk(config);\n\n // Cache Safe info after first fetch\n const infoRef = yield* Ref.make<SafeInfo | null>(null);\n\n // Get TxManager for receipt waiting\n const txManager = yield* TxManager;\n\n // --- Service method implementations ---\n\n const getInfo = () =>\n Effect.gen(function* () {\n const cached = yield* Ref.get(infoRef);\n if (cached) {\n return cached;\n }\n\n const info = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeInfoUnavailableError({\n cause,\n message: \"Failed to get Safe info from SDK\",\n }),\n try: () => sdk.safe.getInfo(),\n });\n\n const safeAddress = yield* validateAddress(info.safeAddress, \"getInfo\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SafeInfoUnavailableError({ cause: e, message: e.message }))\n )\n );\n\n const safeInfo: SafeInfo = {\n chainId: info.chainId,\n safeAddress,\n };\n\n yield* Ref.set(infoRef, safeInfo);\n return safeInfo;\n }).pipe(Effect.withSpan(SpanNames.SAFE_GET_INFO));\n\n const sendTxs = (txs: readonly SafeMultisigTx[], params?: { safeTxGas?: number }) =>\n Effect.gen(function* () {\n // Convert bigint values to strings (Safe SDK expects decimal strings)\n const sdkTxs = txs.map((tx) => ({\n data: tx.data,\n to: tx.to,\n value: tx.value?.toString() ?? \"0\",\n }));\n\n const result = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxSubmissionError({\n cause,\n message: \"Failed to submit txs to Safe\",\n }),\n try: () => sdk.txs.send({ params, txs: sdkTxs }),\n });\n\n const safeTxHash = yield* validateHash(result.safeTxHash, \"sendTxs\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SafeTxSubmissionError({ cause: e, message: e.message }))\n )\n );\n\n const info = yield* getInfo();\n\n return {\n chainId: info.chainId,\n safeAddress: info.safeAddress,\n safeTxHash,\n };\n })\n .pipe(\n Effect.catchTag(\"SafeInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeTxSubmissionError({\n cause: error,\n message: \"Failed to get Safe info after tx submission\",\n })\n )\n )\n )\n .pipe(\n Effect.withSpan(SpanNames.SAFE_SEND_TXS, {\n attributes: { txCount: txs.length },\n })\n );\n\n const getTx = (safeTxHash: Hash) =>\n Effect.gen(function* () {\n const tx = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxLookupError({\n cause,\n message: `Failed to lookup Safe tx ${safeTxHash}`,\n retryable: true,\n safeTxHash,\n }),\n try: () => sdk.txs.getBySafeTxHash(safeTxHash),\n });\n\n const txHash = tx.txHash ? yield* validateHash(tx.txHash, \"getTx\") : null;\n\n return {\n status: tx.txStatus ?? \"AWAITING_CONFIRMATIONS\",\n txHash: txHash ? Option.some(txHash) : Option.none<Hash>(),\n };\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_GET_TX, {\n attributes: { safeTxHash },\n })\n );\n\n const waitForTxReceipt = (\n safeTxHash: Hash,\n policy: {\n pollInterval?: number;\n executionTimeout?: number;\n receiptPolicy?: { receiptTimeout?: number; pollingInterval?: number };\n } = {}\n ) =>\n Effect.gen(function* () {\n const info = yield* getInfo();\n const pollInterval = policy.pollInterval ?? SAFE_POLL_INTERVAL;\n const executionTimeout = policy.executionTimeout ?? SAFE_EXECUTION_TIMEOUT;\n\n // Poll Safe gateway until txHash appears\n // Effect.sleep is interruptible, so this loop respects Effect's interruption model\n const onchainHash = yield* Effect.gen(function* () {\n let lastStatus = \"AWAITING_CONFIRMATIONS\";\n let found: Hash | null = null;\n\n const pollEffect = Effect.gen(function* () {\n while (found === null) {\n const tx = yield* getTx(safeTxHash);\n lastStatus = tx.status;\n\n if (Option.isSome(tx.txHash)) {\n found = tx.txHash.value;\n } else {\n // Sleep is interruptible - key for Effect's interruption model\n yield* Effect.sleep(Duration.millis(pollInterval));\n }\n }\n });\n\n yield* pollEffect.pipe(\n Effect.timeout(Duration.millis(executionTimeout)),\n Effect.catchTag(\"TimeoutException\", () =>\n Effect.fail(\n new SafeTxExecutionTimeoutError({\n lastStatus,\n message: `Safe tx ${safeTxHash} not executed within ${executionTimeout}ms (last status: ${lastStatus})`,\n safeTxHash,\n timeout: executionTimeout,\n })\n )\n )\n );\n\n if (found === null) {\n return yield* Effect.fail(\n new SafeTxExecutionTimeoutError({\n lastStatus,\n message: `Safe tx ${safeTxHash} not executed within timeout`,\n safeTxHash,\n timeout: executionTimeout,\n })\n );\n }\n return found;\n });\n\n // Delegate to TxManager for on-chain receipt\n const receipt = yield* txManager\n .waitForReceipt(info.chainId, onchainHash, policy.receiptPolicy)\n .pipe(\n Effect.catchTag(\"TransactionReplacedError\", (error) =>\n Effect.fail(\n new SafeTxLookupError({\n cause: error,\n message: `Transaction was replaced: ${error.message}`,\n retryable: false,\n safeTxHash,\n })\n )\n )\n );\n\n return {\n chainId: info.chainId,\n onchainHash,\n receipt,\n safeAddress: info.safeAddress,\n safeTxHash,\n };\n })\n .pipe(\n Effect.catchTag(\"SafeInfoUnavailableError\", (error) =>\n Effect.fail(\n new SafeTxLookupError({\n cause: error,\n message: \"Failed to get Safe info for receipt waiting\",\n retryable: true,\n safeTxHash,\n })\n )\n )\n )\n .pipe(\n Effect.withSpan(SpanNames.SAFE_WAIT_RECEIPT, {\n attributes: { safeTxHash },\n })\n );\n\n const signTypedData = (typedData: EIP712TypedData) =>\n Effect.gen(function* () {\n const result = yield* Effect.tryPromise({\n catch: (cause) =>\n new SignTypedDataError({\n cause,\n message: \"Failed to sign typed data via Safe\",\n }),\n try: () =>\n sdk.txs.signTypedMessage(typedData as Parameters<typeof sdk.txs.signTypedMessage>[0]),\n });\n\n // SDK returns { safeTxHash } for on-chain or { messageHash } for off-chain\n if (\"messageHash\" in result && result.messageHash) {\n const messageHash = yield* validateHex(result.messageHash, \"signTypedData\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Offchain\" as const, messageHash };\n }\n\n // Type assertion needed because TypeScript can't narrow SignMessageResponse properly\n const onchainResult = result as { safeTxHash: string };\n const safeTxHash = yield* validateHash(onchainResult.safeTxHash, \"signTypedData\").pipe(\n Effect.catchTag(\"SafeTxLookupError\", (e) =>\n Effect.fail(new SignTypedDataError({ cause: e, message: e.message }))\n )\n );\n return { _tag: \"Onchain\" as const, safeTxHash };\n }).pipe(Effect.withSpan(SpanNames.SAFE_SIGN_TYPED_DATA));\n\n const getOffchainSignature = (messageHash: Hex) =>\n Effect.gen(function* () {\n const sig = yield* Effect.tryPromise({\n catch: (cause) =>\n new SafeTxLookupError({\n cause,\n message: `Failed to get off-chain signature for ${messageHash}`,\n retryable: true,\n safeTxHash: messageHash,\n }),\n try: () => sdk.safe.getOffChainSignature(messageHash),\n });\n\n // Empty string or \"0x\" means signature not yet available\n if (!sig || sig === \"\" || sig === \"0x\") {\n return Option.none<Hex>();\n }\n\n const validatedSig = yield* validateHex(sig, \"getOffchainSignature\");\n return Option.some(validatedSig);\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_GET_OFFCHAIN_SIG, {\n attributes: { messageHash },\n })\n );\n\n const pollOffchainSignature = (\n messageHash: Hex,\n policy: { pollInterval?: number; timeout?: number } = {}\n ) =>\n Effect.gen(function* () {\n const pollInterval = policy.pollInterval ?? SAFE_SIGNATURE_POLL_INTERVAL;\n const timeout = policy.timeout ?? SAFE_SIGNATURE_TIMEOUT;\n\n // Poll until we get a signature\n // Effect.sleep is interruptible, so this loop respects Effect's interruption model\n let found: Hex | null = null;\n\n const pollEffect = Effect.gen(function* () {\n while (found === null) {\n const sig = yield* getOffchainSignature(messageHash);\n if (Option.isSome(sig)) {\n found = sig.value;\n } else {\n // Sleep is interruptible - key for Effect's interruption model\n yield* Effect.sleep(Duration.millis(pollInterval));\n }\n }\n });\n\n yield* pollEffect.pipe(\n Effect.timeout(Duration.millis(timeout)),\n Effect.catchTag(\"TimeoutException\", () =>\n Effect.fail(\n new OffchainSignatureTimeoutError({\n message: `Off-chain signature for ${messageHash} not available within ${timeout}ms`,\n messageHash,\n timeout,\n })\n )\n )\n );\n\n if (found === null) {\n return yield* Effect.fail(\n new OffchainSignatureTimeoutError({\n message: `Off-chain signature for ${messageHash} not available within timeout`,\n messageHash,\n timeout,\n })\n );\n }\n\n return { messageHash, signature: found };\n }).pipe(\n Effect.withSpan(SpanNames.SAFE_POLL_OFFCHAIN_SIG, {\n attributes: { messageHash },\n })\n );\n\n const enableOffchainSigning = () =>\n Effect.tryPromise({\n catch: (cause) =>\n new SafeSettingsError({\n cause,\n message: \"Failed to enable off-chain signing mode\",\n }),\n try: () => sdk.eth.setSafeSettings([{ offChainSigning: true }]),\n })\n .pipe(Effect.asVoid)\n .pipe(Effect.withSpan(SpanNames.SAFE_ENABLE_OFFCHAIN));\n\n return SafeAppsService.of({\n enableOffchainSigning,\n getInfo,\n getOffchainSignature,\n getTx,\n pollOffchainSignature,\n sendTxs,\n signTypedData,\n waitForTxReceipt,\n });\n })\n );\n"]}
|
package/dist/safe/service.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { Effect, Option } from "effect";
|
|
2
|
-
import { Context } from "effect";
|
|
3
|
-
import type { Hash, Hex } from "viem";
|
|
4
|
-
import type { ClientNotFoundError, ReceiptTimeoutError, TransactionFailedError } from "../core/errors/index.js";
|
|
5
|
-
import type { OffchainSignatureTimeoutError, SafeInfoUnavailableError, SafeSettingsError, SafeTxExecutionTimeoutError, SafeTxLookupError, SafeTxSubmissionError, SignTypedDataError } from "./errors.js";
|
|
6
|
-
import type { EIP712TypedData, OffchainSignaturePolicy, OffchainSignatureResult, SafeInfo, SafeMultisigTx, SafeTxResult, SafeTxSubmission, SafeWaitPolicy, SignTypedDataResult } from "./types.js";
|
|
7
|
-
export type SafeAppsServiceShape = {
|
|
8
|
-
readonly getInfo: () => Effect.Effect<SafeInfo, SafeInfoUnavailableError>;
|
|
9
|
-
readonly sendTxs: (txs: readonly SafeMultisigTx[], params?: {
|
|
10
|
-
safeTxGas?: number;
|
|
11
|
-
}) => Effect.Effect<SafeTxSubmission, SafeTxSubmissionError>;
|
|
12
|
-
readonly getTx: (safeTxHash: Hash) => Effect.Effect<{
|
|
13
|
-
txHash: Option.Option<Hash>;
|
|
14
|
-
status: string;
|
|
15
|
-
}, SafeTxLookupError>;
|
|
16
|
-
readonly waitForTxReceipt: (safeTxHash: Hash, policy?: SafeWaitPolicy) => Effect.Effect<SafeTxResult, SafeTxExecutionTimeoutError | SafeTxLookupError | TransactionFailedError | ReceiptTimeoutError | ClientNotFoundError>;
|
|
17
|
-
readonly signTypedData: (typedData: EIP712TypedData) => Effect.Effect<SignTypedDataResult, SignTypedDataError>;
|
|
18
|
-
readonly getOffchainSignature: (messageHash: Hex) => Effect.Effect<Option.Option<Hex>, SafeTxLookupError>;
|
|
19
|
-
readonly pollOffchainSignature: (messageHash: Hex, policy?: OffchainSignaturePolicy) => Effect.Effect<OffchainSignatureResult, OffchainSignatureTimeoutError | SafeTxLookupError>;
|
|
20
|
-
readonly enableOffchainSigning: () => Effect.Effect<void, SafeSettingsError>;
|
|
21
|
-
};
|
|
22
|
-
declare const SafeAppsService_base: Context.TagClass<SafeAppsService, "ew3/SafeApps", SafeAppsServiceShape>;
|
|
23
|
-
export declare class SafeAppsService extends SafeAppsService_base {
|
|
24
|
-
}
|
|
25
|
-
export {};
|
|
26
|
-
//# sourceMappingURL=service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EACV,6BAA6B,EAC7B,wBAAwB,EACxB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAAG;IAEjC,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;IAG1E,QAAQ,CAAC,OAAO,EAAE,CAChB,GAAG,EAAE,SAAS,cAAc,EAAE,EAC9B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;IAG5D,QAAQ,CAAC,KAAK,EAAE,CACd,UAAU,EAAE,IAAI,KACb,MAAM,CAAC,MAAM,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,iBAAiB,CAAC,CAAC;IAGvF,QAAQ,CAAC,gBAAgB,EAAE,CACzB,UAAU,EAAE,IAAI,EAChB,MAAM,CAAC,EAAE,cAAc,KACpB,MAAM,CAAC,MAAM,CAChB,YAAY,EACV,2BAA2B,GAC3B,iBAAiB,GACjB,sBAAsB,GACtB,mBAAmB,GACnB,mBAAmB,CACtB,CAAC;IAGF,QAAQ,CAAC,aAAa,EAAE,CACtB,SAAS,EAAE,eAAe,KACvB,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;IAG5D,QAAQ,CAAC,oBAAoB,EAAE,CAC7B,WAAW,EAAE,GAAG,KACb,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAG1D,QAAQ,CAAC,qBAAqB,EAAE,CAC9B,WAAW,EAAE,GAAG,EAChB,MAAM,CAAC,EAAE,uBAAuB,KAC7B,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,6BAA6B,GAAG,iBAAiB,CAAC,CAAC;IAG/F,QAAQ,CAAC,qBAAqB,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;CAC9E,CAAC;;AAEF,qBAAa,eAAgB,SAAQ,oBAGlC;CAAG"}
|
package/dist/safe/service.js
DELETED
package/dist/safe/service.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/safe/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AA4EjC,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAG7D;CAAG","sourcesContent":["import type { Effect, Option } from \"effect\";\nimport { Context } from \"effect\";\nimport type { Hash, Hex } from \"viem\";\nimport type {\n ClientNotFoundError,\n ReceiptTimeoutError,\n TransactionFailedError,\n} from \"@/src/core/errors/index.js\";\nimport type {\n OffchainSignatureTimeoutError,\n SafeInfoUnavailableError,\n SafeSettingsError,\n SafeTxExecutionTimeoutError,\n SafeTxLookupError,\n SafeTxSubmissionError,\n SignTypedDataError,\n} from \"./errors.js\";\nimport type {\n EIP712TypedData,\n OffchainSignaturePolicy,\n OffchainSignatureResult,\n SafeInfo,\n SafeMultisigTx,\n SafeTxResult,\n SafeTxSubmission,\n SafeWaitPolicy,\n SignTypedDataResult,\n} from \"./types.js\";\n\nexport type SafeAppsServiceShape = {\n /** Get Safe info (cached after first call) */\n readonly getInfo: () => Effect.Effect<SafeInfo, SafeInfoUnavailableError>;\n\n /** Send txs to Safe for execution */\n readonly sendTxs: (\n txs: readonly SafeMultisigTx[],\n params?: { safeTxGas?: number }\n ) => Effect.Effect<SafeTxSubmission, SafeTxSubmissionError>;\n\n /** Get Safe tx details by safeTxHash */\n readonly getTx: (\n safeTxHash: Hash\n ) => Effect.Effect<{ txHash: Option.Option<Hash>; status: string }, SafeTxLookupError>;\n\n /** Wait for Safe tx to execute and return receipt */\n readonly waitForTxReceipt: (\n safeTxHash: Hash,\n policy?: SafeWaitPolicy\n ) => Effect.Effect<\n SafeTxResult,\n | SafeTxExecutionTimeoutError\n | SafeTxLookupError\n | TransactionFailedError\n | ReceiptTimeoutError\n | ClientNotFoundError\n >;\n\n /** Sign typed data (returns discriminated union based on Safe settings) */\n readonly signTypedData: (\n typedData: EIP712TypedData\n ) => Effect.Effect<SignTypedDataResult, SignTypedDataError>;\n\n /** Get off-chain signature (returns Option.none if not yet available) */\n readonly getOffchainSignature: (\n messageHash: Hex\n ) => Effect.Effect<Option.Option<Hex>, SafeTxLookupError>;\n\n /** Poll for off-chain signature until available or timeout */\n readonly pollOffchainSignature: (\n messageHash: Hex,\n policy?: OffchainSignaturePolicy\n ) => Effect.Effect<OffchainSignatureResult, OffchainSignatureTimeoutError | SafeTxLookupError>;\n\n /** Enable off-chain signing mode */\n readonly enableOffchainSigning: () => Effect.Effect<void, SafeSettingsError>;\n};\n\nexport class SafeAppsService extends Context.Tag(\"ew3/SafeApps\")<\n SafeAppsService,\n SafeAppsServiceShape\n>() {}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"service.test.integration.d.ts","sourceRoot":"","sources":["../../src/safe/service.test.integration.ts"],"names":[],"mappings":""}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "@effect/vitest";
|
|
2
|
-
import { Effect, Layer, Option } from "effect";
|
|
3
|
-
import { MIN_TX_GAS } from "../constants/index.js";
|
|
4
|
-
import { TEST_ADDRESS, TEST_CHAIN_ID, TEST_TX_HASH } from "../testing-kit/index.js";
|
|
5
|
-
import { SafeAppsService } from "./service.js";
|
|
6
|
-
const TEST_SAFE_ADDRESS = TEST_ADDRESS;
|
|
7
|
-
const TEST_SAFE_TX_HASH = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
|
|
8
|
-
const TEST_MESSAGE_HASH = "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890";
|
|
9
|
-
const TEST_SIGNATURE = "0xsignature";
|
|
10
|
-
const TEST_RECEIPT = {
|
|
11
|
-
blockHash: "0xblock",
|
|
12
|
-
blockNumber: 123n,
|
|
13
|
-
contractAddress: null,
|
|
14
|
-
cumulativeGasUsed: MIN_TX_GAS,
|
|
15
|
-
effectiveGasPrice: 1n,
|
|
16
|
-
from: "0xfrom",
|
|
17
|
-
gasUsed: MIN_TX_GAS,
|
|
18
|
-
logs: [],
|
|
19
|
-
logsBloom: "0x",
|
|
20
|
-
status: "success",
|
|
21
|
-
to: "0xto",
|
|
22
|
-
transactionHash: TEST_TX_HASH,
|
|
23
|
-
transactionIndex: 0,
|
|
24
|
-
type: "0x2",
|
|
25
|
-
};
|
|
26
|
-
const makeMockSafeAppsService = (config) => {
|
|
27
|
-
const defaultInfo = {
|
|
28
|
-
chainId: TEST_CHAIN_ID,
|
|
29
|
-
safeAddress: TEST_SAFE_ADDRESS,
|
|
30
|
-
};
|
|
31
|
-
return Layer.succeed(SafeAppsService, SafeAppsService.of({
|
|
32
|
-
enableOffchainSigning: () => Effect.void,
|
|
33
|
-
getInfo: () => Effect.succeed(config.getInfoResult ?? defaultInfo),
|
|
34
|
-
getOffchainSignature: () => Effect.succeed(config.offchainSignature ?? Option.none()),
|
|
35
|
-
getTx: () => Effect.succeed(config.getTxResult ?? {
|
|
36
|
-
status: "AWAITING_EXECUTION",
|
|
37
|
-
txHash: Option.some(TEST_TX_HASH),
|
|
38
|
-
}),
|
|
39
|
-
pollOffchainSignature: (messageHash) => Effect.succeed({ messageHash, signature: TEST_SIGNATURE }),
|
|
40
|
-
sendTxs: () => Effect.succeed({
|
|
41
|
-
chainId: TEST_CHAIN_ID,
|
|
42
|
-
safeAddress: TEST_SAFE_ADDRESS,
|
|
43
|
-
safeTxHash: config.sendTxResult?.safeTxHash ?? TEST_SAFE_TX_HASH,
|
|
44
|
-
}),
|
|
45
|
-
signTypedData: () => Effect.succeed(config.signTypedDataResult ?? {
|
|
46
|
-
_tag: "Onchain",
|
|
47
|
-
safeTxHash: TEST_SAFE_TX_HASH,
|
|
48
|
-
}),
|
|
49
|
-
waitForTxReceipt: (safeTxHash) => Effect.succeed({
|
|
50
|
-
chainId: TEST_CHAIN_ID,
|
|
51
|
-
onchainHash: TEST_TX_HASH,
|
|
52
|
-
receipt: TEST_RECEIPT,
|
|
53
|
-
safeAddress: TEST_SAFE_ADDRESS,
|
|
54
|
-
safeTxHash,
|
|
55
|
-
}),
|
|
56
|
-
}));
|
|
57
|
-
};
|
|
58
|
-
describe("SafeAppsService", () => {
|
|
59
|
-
describe("getInfo", () => {
|
|
60
|
-
it.effect("returns Safe info with address and chainId", () => Effect.gen(function* () {
|
|
61
|
-
const service = yield* SafeAppsService;
|
|
62
|
-
const info = yield* service.getInfo();
|
|
63
|
-
expect(info.safeAddress).toBe(TEST_SAFE_ADDRESS);
|
|
64
|
-
expect(info.chainId).toBe(TEST_CHAIN_ID);
|
|
65
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({}))));
|
|
66
|
-
});
|
|
67
|
-
describe("sendTxs", () => {
|
|
68
|
-
it.effect("returns safeTxHash with safeAddress and chainId", () => Effect.gen(function* () {
|
|
69
|
-
const service = yield* SafeAppsService;
|
|
70
|
-
const result = yield* service.sendTxs([{ data: "0x", to: TEST_ADDRESS, value: 0n }]);
|
|
71
|
-
expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);
|
|
72
|
-
expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);
|
|
73
|
-
expect(result.chainId).toBe(TEST_CHAIN_ID);
|
|
74
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({}))));
|
|
75
|
-
});
|
|
76
|
-
describe("getTx", () => {
|
|
77
|
-
it.effect("returns txHash as Option when executed", () => Effect.gen(function* () {
|
|
78
|
-
const service = yield* SafeAppsService;
|
|
79
|
-
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);
|
|
83
|
-
}
|
|
84
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({}))));
|
|
85
|
-
it.effect("returns Option.none when not yet executed", () => Effect.gen(function* () {
|
|
86
|
-
const service = yield* SafeAppsService;
|
|
87
|
-
const result = yield* service.getTx(TEST_SAFE_TX_HASH);
|
|
88
|
-
expect(Option.isNone(result.txHash)).toBe(true);
|
|
89
|
-
expect(result.status).toBe("AWAITING_CONFIRMATIONS");
|
|
90
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({
|
|
91
|
-
getTxResult: {
|
|
92
|
-
status: "AWAITING_CONFIRMATIONS",
|
|
93
|
-
txHash: Option.none(),
|
|
94
|
-
},
|
|
95
|
-
}))));
|
|
96
|
-
});
|
|
97
|
-
describe("waitForTxReceipt", () => {
|
|
98
|
-
it.effect("returns SafeTxResult with receipt", () => Effect.gen(function* () {
|
|
99
|
-
const service = yield* SafeAppsService;
|
|
100
|
-
const result = yield* service.waitForTxReceipt(TEST_SAFE_TX_HASH);
|
|
101
|
-
expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);
|
|
102
|
-
expect(result.onchainHash).toBe(TEST_TX_HASH);
|
|
103
|
-
expect(result.receipt.status).toBe("success");
|
|
104
|
-
expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);
|
|
105
|
-
expect(result.chainId).toBe(TEST_CHAIN_ID);
|
|
106
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({}))));
|
|
107
|
-
});
|
|
108
|
-
describe("signTypedData", () => {
|
|
109
|
-
it.effect("returns Onchain variant for on-chain signing", () => Effect.gen(function* () {
|
|
110
|
-
const service = yield* SafeAppsService;
|
|
111
|
-
const result = yield* service.signTypedData({
|
|
112
|
-
domain: { chainId: 1, name: "Test" },
|
|
113
|
-
message: { value: "test" },
|
|
114
|
-
types: { Test: [{ name: "value", type: "string" }] },
|
|
115
|
-
});
|
|
116
|
-
expect(result._tag).toBe("Onchain");
|
|
117
|
-
if (result._tag === "Onchain") {
|
|
118
|
-
expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);
|
|
119
|
-
}
|
|
120
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({}))));
|
|
121
|
-
it.effect("returns Offchain variant for off-chain signing", () => Effect.gen(function* () {
|
|
122
|
-
const service = yield* SafeAppsService;
|
|
123
|
-
const result = yield* service.signTypedData({
|
|
124
|
-
domain: { chainId: 1, name: "Test" },
|
|
125
|
-
message: { value: "test" },
|
|
126
|
-
types: { Test: [{ name: "value", type: "string" }] },
|
|
127
|
-
});
|
|
128
|
-
expect(result._tag).toBe("Offchain");
|
|
129
|
-
if (result._tag === "Offchain") {
|
|
130
|
-
expect(result.messageHash).toBe(TEST_MESSAGE_HASH);
|
|
131
|
-
}
|
|
132
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({
|
|
133
|
-
signTypedDataResult: {
|
|
134
|
-
_tag: "Offchain",
|
|
135
|
-
messageHash: TEST_MESSAGE_HASH,
|
|
136
|
-
},
|
|
137
|
-
}))));
|
|
138
|
-
});
|
|
139
|
-
describe("getOffchainSignature", () => {
|
|
140
|
-
it.effect("returns Option.none when signature not yet available", () => Effect.gen(function* () {
|
|
141
|
-
const service = yield* SafeAppsService;
|
|
142
|
-
const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);
|
|
143
|
-
expect(Option.isNone(result)).toBe(true);
|
|
144
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({}))));
|
|
145
|
-
it.effect("returns Option.some when signature available", () => Effect.gen(function* () {
|
|
146
|
-
const service = yield* SafeAppsService;
|
|
147
|
-
const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);
|
|
148
|
-
expect(Option.isSome(result)).toBe(true);
|
|
149
|
-
if (Option.isSome(result)) {
|
|
150
|
-
expect(result.value).toBe(TEST_SIGNATURE);
|
|
151
|
-
}
|
|
152
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({
|
|
153
|
-
offchainSignature: Option.some(TEST_SIGNATURE),
|
|
154
|
-
}))));
|
|
155
|
-
});
|
|
156
|
-
describe("pollOffchainSignature", () => {
|
|
157
|
-
it.effect("returns signature when available", () => Effect.gen(function* () {
|
|
158
|
-
const service = yield* SafeAppsService;
|
|
159
|
-
const result = yield* service.pollOffchainSignature(TEST_MESSAGE_HASH);
|
|
160
|
-
expect(result.messageHash).toBe(TEST_MESSAGE_HASH);
|
|
161
|
-
expect(result.signature).toBe(TEST_SIGNATURE);
|
|
162
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({}))));
|
|
163
|
-
});
|
|
164
|
-
describe("enableOffchainSigning", () => {
|
|
165
|
-
it.effect("completes without error", () => Effect.gen(function* () {
|
|
166
|
-
const service = yield* SafeAppsService;
|
|
167
|
-
yield* service.enableOffchainSigning();
|
|
168
|
-
}).pipe(Effect.provide(makeMockSafeAppsService({}))));
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
//# sourceMappingURL=service.test.integration.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"service.test.integration.js","sourceRoot":"","sources":["../../src/safe/service.test.integration.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"@effect/vitest\";\nimport { Effect, Layer, Option } from \"effect\";\nimport type { Hash, Hex, TransactionReceipt } from \"viem\";\nimport { MIN_TX_GAS } from \"@/src/constants/index.js\";\nimport { TEST_ADDRESS, TEST_CHAIN_ID, TEST_TX_HASH } from \"@/src/testing-kit/index.js\";\nimport { SafeAppsService } from \"./service.js\";\nimport type { SafeInfo } from \"./types.js\";\n\n// Test fixtures\nconst TEST_SAFE_ADDRESS = TEST_ADDRESS;\nconst TEST_SAFE_TX_HASH =\n \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\" as Hash;\nconst TEST_MESSAGE_HASH =\n \"0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890\" as Hex;\nconst TEST_SIGNATURE = \"0xsignature\" as Hex;\n\nconst TEST_RECEIPT: TransactionReceipt = {\n blockHash: \"0xblock\",\n blockNumber: 123n,\n contractAddress: null,\n cumulativeGasUsed: MIN_TX_GAS,\n effectiveGasPrice: 1n,\n from: \"0xfrom\",\n gasUsed: MIN_TX_GAS,\n logs: [],\n logsBloom: \"0x\",\n status: \"success\",\n to: \"0xto\",\n transactionHash: TEST_TX_HASH,\n transactionIndex: 0,\n type: \"0x2\",\n};\n\n// Mock SafeAppsService for testing without actual SDK\nconst makeMockSafeAppsService = (config: {\n getInfoResult?: SafeInfo;\n sendTxResult?: { safeTxHash: Hash };\n getTxResult?: { txHash: Option.Option<Hash>; status: string };\n signTypedDataResult?:\n | { _tag: \"Offchain\"; messageHash: Hex }\n | { _tag: \"Onchain\"; safeTxHash: Hash };\n offchainSignature?: Option.Option<Hex>;\n}) => {\n const defaultInfo: SafeInfo = {\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n };\n\n return Layer.succeed(\n SafeAppsService,\n SafeAppsService.of({\n enableOffchainSigning: () => Effect.void,\n getInfo: () => Effect.succeed(config.getInfoResult ?? defaultInfo),\n getOffchainSignature: () => Effect.succeed(config.offchainSignature ?? Option.none()),\n getTx: () =>\n Effect.succeed(\n config.getTxResult ?? {\n status: \"AWAITING_EXECUTION\",\n txHash: Option.some(TEST_TX_HASH),\n }\n ),\n pollOffchainSignature: (messageHash) =>\n Effect.succeed({ messageHash, signature: TEST_SIGNATURE }),\n sendTxs: () =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash: config.sendTxResult?.safeTxHash ?? TEST_SAFE_TX_HASH,\n }),\n signTypedData: () =>\n Effect.succeed(\n config.signTypedDataResult ?? {\n _tag: \"Onchain\" as const,\n safeTxHash: TEST_SAFE_TX_HASH,\n }\n ),\n waitForTxReceipt: (safeTxHash) =>\n Effect.succeed({\n chainId: TEST_CHAIN_ID,\n onchainHash: TEST_TX_HASH,\n receipt: TEST_RECEIPT,\n safeAddress: TEST_SAFE_ADDRESS,\n safeTxHash,\n }),\n })\n );\n};\n\ndescribe(\"SafeAppsService\", () => {\n describe(\"getInfo\", () => {\n it.effect(\"returns Safe info with address and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const info = yield* service.getInfo();\n\n expect(info.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(info.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"sendTxs\", () => {\n it.effect(\"returns safeTxHash with safeAddress and chainId\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.sendTxs([{ data: \"0x\", to: TEST_ADDRESS, value: 0n }]);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"getTx\", () => {\n it.effect(\"returns txHash as Option when executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTx(TEST_SAFE_TX_HASH);\n\n expect(Option.isSome(result.txHash)).toBe(true);\n if (Option.isSome(result.txHash)) {\n expect(result.txHash.value).toBe(TEST_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.none when not yet executed\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getTx(TEST_SAFE_TX_HASH);\n\n expect(Option.isNone(result.txHash)).toBe(true);\n expect(result.status).toBe(\"AWAITING_CONFIRMATIONS\");\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n getTxResult: {\n status: \"AWAITING_CONFIRMATIONS\",\n txHash: Option.none(),\n },\n })\n )\n )\n );\n });\n\n describe(\"waitForTxReceipt\", () => {\n it.effect(\"returns SafeTxResult with receipt\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.waitForTxReceipt(TEST_SAFE_TX_HASH);\n\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n expect(result.onchainHash).toBe(TEST_TX_HASH);\n expect(result.receipt.status).toBe(\"success\");\n expect(result.safeAddress).toBe(TEST_SAFE_ADDRESS);\n expect(result.chainId).toBe(TEST_CHAIN_ID);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"signTypedData\", () => {\n it.effect(\"returns Onchain variant for on-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Onchain\");\n if (result._tag === \"Onchain\") {\n expect(result.safeTxHash).toBe(TEST_SAFE_TX_HASH);\n }\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Offchain variant for off-chain signing\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.signTypedData({\n domain: { chainId: 1, name: \"Test\" },\n message: { value: \"test\" },\n types: { Test: [{ name: \"value\", type: \"string\" }] },\n });\n\n expect(result._tag).toBe(\"Offchain\");\n if (result._tag === \"Offchain\") {\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n signTypedDataResult: {\n _tag: \"Offchain\",\n messageHash: TEST_MESSAGE_HASH,\n },\n })\n )\n )\n );\n });\n\n describe(\"getOffchainSignature\", () => {\n it.effect(\"returns Option.none when signature not yet available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isNone(result)).toBe(true);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n\n it.effect(\"returns Option.some when signature available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.getOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(Option.isSome(result)).toBe(true);\n if (Option.isSome(result)) {\n expect(result.value).toBe(TEST_SIGNATURE);\n }\n }).pipe(\n Effect.provide(\n makeMockSafeAppsService({\n offchainSignature: Option.some(TEST_SIGNATURE),\n })\n )\n )\n );\n });\n\n describe(\"pollOffchainSignature\", () => {\n it.effect(\"returns signature when available\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n const result = yield* service.pollOffchainSignature(TEST_MESSAGE_HASH);\n\n expect(result.messageHash).toBe(TEST_MESSAGE_HASH);\n expect(result.signature).toBe(TEST_SIGNATURE);\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n\n describe(\"enableOffchainSigning\", () => {\n it.effect(\"completes without error\", () =>\n Effect.gen(function* () {\n const service = yield* SafeAppsService;\n yield* service.enableOffchainSigning();\n // Success if no error thrown\n }).pipe(Effect.provide(makeMockSafeAppsService({})))\n );\n });\n});\n"]}
|