@bananapus/nana-sdk-core 3.5.2 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/wallet-check.mjs +495 -0
- package/dist/cjs/actions/suckerPairs.d.ts +5 -3
- package/dist/cjs/actions/suckerPairs.d.ts.map +1 -1
- package/dist/cjs/actions/suckerPairs.js +6 -26
- package/dist/cjs/actions/suckerPairs.js.map +1 -1
- package/dist/cjs/pause.d.ts +2 -0
- package/dist/cjs/pause.d.ts.map +1 -1
- package/dist/cjs/pause.js +17 -0
- package/dist/cjs/pause.js.map +1 -1
- package/dist/cjs/review/confirm.d.ts +56 -0
- package/dist/cjs/review/confirm.d.ts.map +1 -0
- package/dist/cjs/review/confirm.js +99 -0
- package/dist/cjs/review/confirm.js.map +1 -0
- package/dist/cjs/review/contractWrite.d.ts +5 -3
- package/dist/cjs/review/contractWrite.d.ts.map +1 -1
- package/dist/cjs/review/contractWrite.js +10 -8
- package/dist/cjs/review/contractWrite.js.map +1 -1
- package/dist/cjs/review/decode.d.ts +19 -1
- package/dist/cjs/review/decode.d.ts.map +1 -1
- package/dist/cjs/review/decode.js +30 -11
- package/dist/cjs/review/decode.js.map +1 -1
- package/dist/cjs/review/decodeCall.d.ts +21 -0
- package/dist/cjs/review/decodeCall.d.ts.map +1 -0
- package/dist/cjs/review/decodeCall.js +183 -0
- package/dist/cjs/review/decodeCall.js.map +1 -0
- package/dist/cjs/review/heldWrite.d.ts +4 -0
- package/dist/cjs/review/heldWrite.d.ts.map +1 -1
- package/dist/cjs/review/heldWrite.js +35 -31
- package/dist/cjs/review/heldWrite.js.map +1 -1
- package/dist/cjs/review/index.d.ts +12 -1
- package/dist/cjs/review/index.d.ts.map +1 -1
- package/dist/cjs/review/index.js +29 -1
- package/dist/cjs/review/index.js.map +1 -1
- package/dist/cjs/review/intents.d.ts +10 -0
- package/dist/cjs/review/intents.d.ts.map +1 -1
- package/dist/cjs/review/intents.js +13 -0
- package/dist/cjs/review/intents.js.map +1 -1
- package/dist/cjs/review/lineError.d.ts +72 -0
- package/dist/cjs/review/lineError.d.ts.map +1 -0
- package/dist/cjs/review/lineError.js +76 -0
- package/dist/cjs/review/lineError.js.map +1 -0
- package/dist/cjs/review/messages.d.ts +15 -3
- package/dist/cjs/review/messages.d.ts.map +1 -1
- package/dist/cjs/review/messages.js +16 -4
- package/dist/cjs/review/messages.js.map +1 -1
- package/dist/cjs/review/model.d.ts +149 -0
- package/dist/cjs/review/model.d.ts.map +1 -0
- package/dist/cjs/review/model.js +750 -0
- package/dist/cjs/review/model.js.map +1 -0
- package/dist/cjs/review/plan.d.ts +61 -0
- package/dist/cjs/review/plan.d.ts.map +1 -0
- package/dist/cjs/review/plan.js +143 -0
- package/dist/cjs/review/plan.js.map +1 -0
- package/dist/cjs/review/react/index.d.ts +1 -0
- package/dist/cjs/review/react/index.d.ts.map +1 -1
- package/dist/cjs/review/react/index.js +1 -0
- package/dist/cjs/review/react/index.js.map +1 -1
- package/dist/cjs/review/react/useHeldSend.js +3 -4
- package/dist/cjs/review/react/useHeldSend.js.map +1 -1
- package/dist/cjs/review/react/useHeldWrite.d.ts.map +1 -1
- package/dist/cjs/review/react/useHeldWrite.js +2 -1
- package/dist/cjs/review/react/useHeldWrite.js.map +1 -1
- package/dist/cjs/review/react/useReviewedRun.d.ts +122 -0
- package/dist/cjs/review/react/useReviewedRun.d.ts.map +1 -0
- package/dist/cjs/review/react/useReviewedRun.js +443 -0
- package/dist/cjs/review/react/useReviewedRun.js.map +1 -0
- package/dist/cjs/review/receipt.d.ts +37 -1
- package/dist/cjs/review/receipt.d.ts.map +1 -1
- package/dist/cjs/review/receipt.js +76 -3
- package/dist/cjs/review/receipt.js.map +1 -1
- package/dist/cjs/review/relayr.d.ts +13 -4
- package/dist/cjs/review/relayr.d.ts.map +1 -1
- package/dist/cjs/review/relayr.js +52 -8
- package/dist/cjs/review/relayr.js.map +1 -1
- package/dist/cjs/review/relayrSend.d.ts +106 -0
- package/dist/cjs/review/relayrSend.d.ts.map +1 -0
- package/dist/cjs/review/relayrSend.js +795 -0
- package/dist/cjs/review/relayrSend.js.map +1 -0
- package/dist/cjs/review/reviewQueue.d.ts +10 -9
- package/dist/cjs/review/reviewQueue.d.ts.map +1 -1
- package/dist/cjs/review/reviewQueue.js +19 -29
- package/dist/cjs/review/reviewQueue.js.map +1 -1
- package/dist/cjs/review/reviewRequests.d.ts +86 -0
- package/dist/cjs/review/reviewRequests.d.ts.map +1 -0
- package/dist/cjs/review/reviewRequests.js +266 -0
- package/dist/cjs/review/reviewRequests.js.map +1 -0
- package/dist/cjs/review/safeRelayr.d.ts +3 -1
- package/dist/cjs/review/safeRelayr.d.ts.map +1 -1
- package/dist/cjs/review/safeRelayr.js +9 -9
- package/dist/cjs/review/safeRelayr.js.map +1 -1
- package/dist/cjs/review/safeSend.d.ts +69 -0
- package/dist/cjs/review/safeSend.d.ts.map +1 -0
- package/dist/cjs/review/safeSend.js +306 -0
- package/dist/cjs/review/safeSend.js.map +1 -0
- package/dist/cjs/review/send.d.ts +272 -0
- package/dist/cjs/review/send.d.ts.map +1 -0
- package/dist/cjs/review/send.js +1163 -0
- package/dist/cjs/review/send.js.map +1 -0
- package/dist/cjs/review/sequence.d.ts +77 -0
- package/dist/cjs/review/sequence.d.ts.map +1 -0
- package/dist/cjs/review/sequence.js +232 -0
- package/dist/cjs/review/sequence.js.map +1 -0
- package/dist/cjs/review/sign.d.ts +111 -0
- package/dist/cjs/review/sign.d.ts.map +1 -0
- package/dist/cjs/review/sign.js +378 -0
- package/dist/cjs/review/sign.js.map +1 -0
- package/dist/cjs/review/simulation.d.ts +41 -2
- package/dist/cjs/review/simulation.d.ts.map +1 -1
- package/dist/cjs/review/simulation.js +99 -29
- package/dist/cjs/review/simulation.js.map +1 -1
- package/dist/cjs/review/transaction-message.d.ts +13 -0
- package/dist/cjs/review/transaction-message.d.ts.map +1 -1
- package/dist/cjs/review/transaction-message.js +25 -0
- package/dist/cjs/review/transaction-message.js.map +1 -1
- package/dist/cjs/review/transactionReview.d.ts +27 -19
- package/dist/cjs/review/transactionReview.d.ts.map +1 -1
- package/dist/cjs/review/transactionReview.js +22 -63
- package/dist/cjs/review/transactionReview.js.map +1 -1
- package/dist/cjs/review/wallet.d.ts +98 -0
- package/dist/cjs/review/wallet.d.ts.map +1 -0
- package/dist/cjs/review/wallet.js +234 -0
- package/dist/cjs/review/wallet.js.map +1 -0
- package/dist/cjs/review/writeHold.d.ts +138 -13
- package/dist/cjs/review/writeHold.d.ts.map +1 -1
- package/dist/cjs/review/writeHold.js +98 -18
- package/dist/cjs/review/writeHold.js.map +1 -1
- package/dist/cjs/review/writeRecovery.d.ts +17 -1
- package/dist/cjs/review/writeRecovery.d.ts.map +1 -1
- package/dist/cjs/review/writeRecovery.js +146 -45
- package/dist/cjs/review/writeRecovery.js.map +1 -1
- package/dist/cjs/safeService.d.ts +27 -4
- package/dist/cjs/safeService.d.ts.map +1 -1
- package/dist/cjs/safeService.js +120 -3
- package/dist/cjs/safeService.js.map +1 -1
- package/dist/cjs/testing.d.ts +24 -0
- package/dist/cjs/testing.d.ts.map +1 -1
- package/dist/cjs/testing.js +26 -1
- package/dist/cjs/testing.js.map +1 -1
- package/dist/cjs/v6/defifa.d.ts.map +1 -1
- package/dist/cjs/v6/defifa.js +24 -23
- package/dist/cjs/v6/defifa.js.map +1 -1
- package/dist/cjs/v6/executionErrors.d.ts.map +1 -1
- package/dist/cjs/v6/executionErrors.js +3 -2
- package/dist/cjs/v6/executionErrors.js.map +1 -1
- package/dist/cjs/v6/pay.d.ts +25 -8
- package/dist/cjs/v6/pay.d.ts.map +1 -1
- package/dist/cjs/v6/pay.js +117 -23
- package/dist/cjs/v6/pay.js.map +1 -1
- package/dist/cjs/v6/suckers.d.ts +30 -0
- package/dist/cjs/v6/suckers.d.ts.map +1 -1
- package/dist/cjs/v6/suckers.js +69 -5
- package/dist/cjs/v6/suckers.js.map +1 -1
- package/dist/esm/actions/suckerPairs.d.ts +5 -3
- package/dist/esm/actions/suckerPairs.d.ts.map +1 -1
- package/dist/esm/actions/suckerPairs.js +7 -27
- package/dist/esm/actions/suckerPairs.js.map +1 -1
- package/dist/esm/pause.d.ts +2 -0
- package/dist/esm/pause.d.ts.map +1 -1
- package/dist/esm/pause.js +16 -0
- package/dist/esm/pause.js.map +1 -1
- package/dist/esm/review/confirm.d.ts +56 -0
- package/dist/esm/review/confirm.d.ts.map +1 -0
- package/dist/esm/review/confirm.js +93 -0
- package/dist/esm/review/confirm.js.map +1 -0
- package/dist/esm/review/contractWrite.d.ts +5 -3
- package/dist/esm/review/contractWrite.d.ts.map +1 -1
- package/dist/esm/review/contractWrite.js +10 -8
- package/dist/esm/review/contractWrite.js.map +1 -1
- package/dist/esm/review/decode.d.ts +19 -1
- package/dist/esm/review/decode.d.ts.map +1 -1
- package/dist/esm/review/decode.js +29 -14
- package/dist/esm/review/decode.js.map +1 -1
- package/dist/esm/review/decodeCall.d.ts +21 -0
- package/dist/esm/review/decodeCall.d.ts.map +1 -0
- package/dist/esm/review/decodeCall.js +180 -0
- package/dist/esm/review/decodeCall.js.map +1 -0
- package/dist/esm/review/heldWrite.d.ts +4 -0
- package/dist/esm/review/heldWrite.d.ts.map +1 -1
- package/dist/esm/review/heldWrite.js +34 -30
- package/dist/esm/review/heldWrite.js.map +1 -1
- package/dist/esm/review/index.d.ts +12 -1
- package/dist/esm/review/index.d.ts.map +1 -1
- package/dist/esm/review/index.js +12 -1
- package/dist/esm/review/index.js.map +1 -1
- package/dist/esm/review/intents.d.ts +10 -0
- package/dist/esm/review/intents.d.ts.map +1 -1
- package/dist/esm/review/intents.js +12 -0
- package/dist/esm/review/intents.js.map +1 -1
- package/dist/esm/review/lineError.d.ts +72 -0
- package/dist/esm/review/lineError.d.ts.map +1 -0
- package/dist/esm/review/lineError.js +68 -0
- package/dist/esm/review/lineError.js.map +1 -0
- package/dist/esm/review/messages.d.ts +15 -3
- package/dist/esm/review/messages.d.ts.map +1 -1
- package/dist/esm/review/messages.js +15 -3
- package/dist/esm/review/messages.js.map +1 -1
- package/dist/esm/review/model.d.ts +149 -0
- package/dist/esm/review/model.d.ts.map +1 -0
- package/dist/esm/review/model.js +746 -0
- package/dist/esm/review/model.js.map +1 -0
- package/dist/esm/review/plan.d.ts +61 -0
- package/dist/esm/review/plan.d.ts.map +1 -0
- package/dist/esm/review/plan.js +136 -0
- package/dist/esm/review/plan.js.map +1 -0
- package/dist/esm/review/react/index.d.ts +1 -0
- package/dist/esm/review/react/index.d.ts.map +1 -1
- package/dist/esm/review/react/index.js +1 -0
- package/dist/esm/review/react/index.js.map +1 -1
- package/dist/esm/review/react/useHeldSend.js +3 -4
- package/dist/esm/review/react/useHeldSend.js.map +1 -1
- package/dist/esm/review/react/useHeldWrite.d.ts.map +1 -1
- package/dist/esm/review/react/useHeldWrite.js +2 -1
- package/dist/esm/review/react/useHeldWrite.js.map +1 -1
- package/dist/esm/review/react/useReviewedRun.d.ts +122 -0
- package/dist/esm/review/react/useReviewedRun.d.ts.map +1 -0
- package/dist/esm/review/react/useReviewedRun.js +439 -0
- package/dist/esm/review/react/useReviewedRun.js.map +1 -0
- package/dist/esm/review/receipt.d.ts +37 -1
- package/dist/esm/review/receipt.d.ts.map +1 -1
- package/dist/esm/review/receipt.js +72 -2
- package/dist/esm/review/receipt.js.map +1 -1
- package/dist/esm/review/relayr.d.ts +13 -4
- package/dist/esm/review/relayr.d.ts.map +1 -1
- package/dist/esm/review/relayr.js +51 -8
- package/dist/esm/review/relayr.js.map +1 -1
- package/dist/esm/review/relayrSend.d.ts +106 -0
- package/dist/esm/review/relayrSend.d.ts.map +1 -0
- package/dist/esm/review/relayrSend.js +787 -0
- package/dist/esm/review/relayrSend.js.map +1 -0
- package/dist/esm/review/reviewQueue.d.ts +10 -9
- package/dist/esm/review/reviewQueue.d.ts.map +1 -1
- package/dist/esm/review/reviewQueue.js +17 -26
- package/dist/esm/review/reviewQueue.js.map +1 -1
- package/dist/esm/review/reviewRequests.d.ts +86 -0
- package/dist/esm/review/reviewRequests.d.ts.map +1 -0
- package/dist/esm/review/reviewRequests.js +263 -0
- package/dist/esm/review/reviewRequests.js.map +1 -0
- package/dist/esm/review/safeRelayr.d.ts +3 -1
- package/dist/esm/review/safeRelayr.d.ts.map +1 -1
- package/dist/esm/review/safeRelayr.js +9 -9
- package/dist/esm/review/safeRelayr.js.map +1 -1
- package/dist/esm/review/safeSend.d.ts +69 -0
- package/dist/esm/review/safeSend.d.ts.map +1 -0
- package/dist/esm/review/safeSend.js +301 -0
- package/dist/esm/review/safeSend.js.map +1 -0
- package/dist/esm/review/send.d.ts +272 -0
- package/dist/esm/review/send.d.ts.map +1 -0
- package/dist/esm/review/send.js +1156 -0
- package/dist/esm/review/send.js.map +1 -0
- package/dist/esm/review/sequence.d.ts +77 -0
- package/dist/esm/review/sequence.d.ts.map +1 -0
- package/dist/esm/review/sequence.js +223 -0
- package/dist/esm/review/sequence.js.map +1 -0
- package/dist/esm/review/sign.d.ts +111 -0
- package/dist/esm/review/sign.d.ts.map +1 -0
- package/dist/esm/review/sign.js +372 -0
- package/dist/esm/review/sign.js.map +1 -0
- package/dist/esm/review/simulation.d.ts +41 -2
- package/dist/esm/review/simulation.d.ts.map +1 -1
- package/dist/esm/review/simulation.js +95 -29
- package/dist/esm/review/simulation.js.map +1 -1
- package/dist/esm/review/transaction-message.d.ts +13 -0
- package/dist/esm/review/transaction-message.d.ts.map +1 -1
- package/dist/esm/review/transaction-message.js +23 -0
- package/dist/esm/review/transaction-message.js.map +1 -1
- package/dist/esm/review/transactionReview.d.ts +27 -19
- package/dist/esm/review/transactionReview.d.ts.map +1 -1
- package/dist/esm/review/transactionReview.js +19 -56
- package/dist/esm/review/transactionReview.js.map +1 -1
- package/dist/esm/review/wallet.d.ts +98 -0
- package/dist/esm/review/wallet.d.ts.map +1 -0
- package/dist/esm/review/wallet.js +227 -0
- package/dist/esm/review/wallet.js.map +1 -0
- package/dist/esm/review/writeHold.d.ts +138 -13
- package/dist/esm/review/writeHold.d.ts.map +1 -1
- package/dist/esm/review/writeHold.js +96 -19
- package/dist/esm/review/writeHold.js.map +1 -1
- package/dist/esm/review/writeRecovery.d.ts +17 -1
- package/dist/esm/review/writeRecovery.d.ts.map +1 -1
- package/dist/esm/review/writeRecovery.js +149 -48
- package/dist/esm/review/writeRecovery.js.map +1 -1
- package/dist/esm/safeService.d.ts +27 -4
- package/dist/esm/safeService.d.ts.map +1 -1
- package/dist/esm/safeService.js +119 -4
- package/dist/esm/safeService.js.map +1 -1
- package/dist/esm/testing.d.ts +24 -0
- package/dist/esm/testing.d.ts.map +1 -1
- package/dist/esm/testing.js +23 -1
- package/dist/esm/testing.js.map +1 -1
- package/dist/esm/v6/defifa.d.ts.map +1 -1
- package/dist/esm/v6/defifa.js +24 -23
- package/dist/esm/v6/defifa.js.map +1 -1
- package/dist/esm/v6/executionErrors.d.ts.map +1 -1
- package/dist/esm/v6/executionErrors.js +3 -2
- package/dist/esm/v6/executionErrors.js.map +1 -1
- package/dist/esm/v6/pay.d.ts +25 -8
- package/dist/esm/v6/pay.d.ts.map +1 -1
- package/dist/esm/v6/pay.js +115 -22
- package/dist/esm/v6/pay.js.map +1 -1
- package/dist/esm/v6/suckers.d.ts +30 -0
- package/dist/esm/v6/suckers.d.ts.map +1 -1
- package/dist/esm/v6/suckers.js +67 -5
- package/dist/esm/v6/suckers.js.map +1 -1
- package/package.json +11 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { ReviewLineError } from "./lineError.js";
|
|
2
|
+
import { decodeFunctionData, isAddress, numberToHex, keccak256, } from "viem";
|
|
3
|
+
import { lookAtSafeProposal, readSafeAppExecution, readSafeTransaction, isSafeExecTransaction, safeExecTransactionResult, SAFE_EXEC_ABI, safeProposalFor, safeTransactionMatchesCall, } from "../safeService.js";
|
|
4
|
+
import { MULTI_SEND_CALL_ONLY_DEPLOYMENTS, multiSendCallsOf, readAuthorityIdentity, } from "../safe.js";
|
|
4
5
|
import { TAB } from "./tabState.js";
|
|
5
6
|
import { isBytes32, isHexBytes, uint256 } from "../untrusted.js";
|
|
6
7
|
import { atCanonicalFinalizedBlock, } from "./relayr.js";
|
|
@@ -11,7 +12,7 @@ const TAB_SEEN = TAB.seen;
|
|
|
11
12
|
// failed. It is visible only while the exact durable reservation still exists.
|
|
12
13
|
const unpersistedSubmissions = new WeakMap();
|
|
13
14
|
/** The wallet returned this identity, but storing it failed. Keep it in memory and retry submitted(hash, record). */
|
|
14
|
-
export class SubmittedWritePersistenceError extends
|
|
15
|
+
export class SubmittedWritePersistenceError extends ReviewLineError {
|
|
15
16
|
constructor(record, cause) {
|
|
16
17
|
super("The wallet returned a transaction identity, but recovery storage is unavailable. Keep this transaction pending.");
|
|
17
18
|
this.name = "SubmittedWritePersistenceError";
|
|
@@ -23,7 +24,7 @@ function normalizedIdentity(input) {
|
|
|
23
24
|
if (!Number.isSafeInteger(input?.chainId) ||
|
|
24
25
|
input.chainId <= 0 ||
|
|
25
26
|
!isAddress(input?.account, { strict: false }))
|
|
26
|
-
throw new
|
|
27
|
+
throw new ReviewLineError("Invalid reviewed write recovery evidence.");
|
|
27
28
|
return {
|
|
28
29
|
chainId: input.chainId,
|
|
29
30
|
account: input.account.toLowerCase(),
|
|
@@ -36,7 +37,7 @@ function normalized(input) {
|
|
|
36
37
|
!isAddress(input?.call?.to, { strict: false }) ||
|
|
37
38
|
!isHexBytes(input?.call?.data) ||
|
|
38
39
|
value === null)
|
|
39
|
-
throw new
|
|
40
|
+
throw new ReviewLineError("Invalid reviewed write recovery evidence.");
|
|
40
41
|
return {
|
|
41
42
|
...normalizedIdentity(input),
|
|
42
43
|
safe: input.safe,
|
|
@@ -80,7 +81,7 @@ function recordOf(value) {
|
|
|
80
81
|
(record.executed !== undefined && record.executed !== true) ||
|
|
81
82
|
(record.executionHash !== undefined &&
|
|
82
83
|
(record.executed !== true || !isBytes32(record.executionHash))))
|
|
83
|
-
throw new
|
|
84
|
+
throw new ReviewLineError("Invalid saved write recovery record. Keep this action pending.");
|
|
84
85
|
return {
|
|
85
86
|
version: 1,
|
|
86
87
|
id: record.id,
|
|
@@ -157,7 +158,7 @@ function namespaceOf(value) {
|
|
|
157
158
|
return undefined;
|
|
158
159
|
if (typeof value !== "string" ||
|
|
159
160
|
!/^[a-z0-9][a-z0-9:._/-]{0,127}$/.test(value))
|
|
160
|
-
throw new
|
|
161
|
+
throw new ReviewLineError("Invalid write recovery namespace.");
|
|
161
162
|
return value;
|
|
162
163
|
}
|
|
163
164
|
function namespaceScope(input) {
|
|
@@ -171,7 +172,7 @@ function scope(input) {
|
|
|
171
172
|
function recoveryStorage(store) {
|
|
172
173
|
const result = store ?? globalThis.localStorage;
|
|
173
174
|
if (!result)
|
|
174
|
-
throw new
|
|
175
|
+
throw new ReviewLineError("Write recovery storage is unavailable.");
|
|
175
176
|
return result;
|
|
176
177
|
}
|
|
177
178
|
/** Every key `store` holds: its own `keys()`, or Web Storage's `length` and `key()`. */
|
|
@@ -363,7 +364,7 @@ export function findReviewedWrites(input, options = {}) {
|
|
|
363
364
|
const identity = normalizedIdentity(input);
|
|
364
365
|
if (!isAddress(input.to, { strict: false }) ||
|
|
365
366
|
!/^0x[0-9a-fA-F]{8}$/.test(input.selector))
|
|
366
|
-
throw new
|
|
367
|
+
throw new ReviewLineError("Invalid write hold match.");
|
|
367
368
|
const to = input.to.toLowerCase();
|
|
368
369
|
const selector = input.selector.toLowerCase();
|
|
369
370
|
const store = recoveryStorage(options.storage);
|
|
@@ -401,7 +402,7 @@ function foundAt(input, at) {
|
|
|
401
402
|
(at.startsWith(prefix) &&
|
|
402
403
|
/^\d+:0x[0-9a-f]{64}$/.test(at.slice(prefix.length)))))
|
|
403
404
|
return at;
|
|
404
|
-
throw new
|
|
405
|
+
throw new ReviewLineError("Invalid write recovery key.");
|
|
405
406
|
}
|
|
406
407
|
/**
|
|
407
408
|
* Every unresolved write saved for `account` on `chainId`, with the key it
|
|
@@ -449,7 +450,7 @@ export function readBrowserWriteRecovery(input, options = {}) {
|
|
|
449
450
|
const identity = normalizedIdentity(input);
|
|
450
451
|
const namespace = namespaceOf(input?.namespace);
|
|
451
452
|
if (namespace === undefined)
|
|
452
|
-
throw new
|
|
453
|
+
throw new ReviewLineError("Provide a write recovery namespace.");
|
|
453
454
|
return readRecovery(recoveryStorage(options.storage), namespaceScope({ ...identity, namespace }));
|
|
454
455
|
}
|
|
455
456
|
/**
|
|
@@ -460,12 +461,20 @@ export function readBrowserWriteRecovery(input, options = {}) {
|
|
|
460
461
|
function releasedKey(key, id) {
|
|
461
462
|
return `${key}:released:${id}`;
|
|
462
463
|
}
|
|
464
|
+
/**
|
|
465
|
+
* The key that marks the record `id` saved at `key` as ended by the user's
|
|
466
|
+
* exit or as never sent, never by a settlement's cleanup: only it lets a
|
|
467
|
+
* saved sequence send that step again.
|
|
468
|
+
*/
|
|
469
|
+
function exitedKey(key, id) {
|
|
470
|
+
return `${key}:exited:${id}`;
|
|
471
|
+
}
|
|
463
472
|
function readStored(raw, key, scopeOf = scope, store) {
|
|
464
473
|
if (raw === null)
|
|
465
474
|
return null;
|
|
466
475
|
const record = recordOf(JSON.parse(raw));
|
|
467
476
|
if (scopeOf(record) !== key)
|
|
468
|
-
throw new
|
|
477
|
+
throw new ReviewLineError("Saved write recovery scope does not match.");
|
|
469
478
|
if (store && store.getItem(releasedKey(key, record.id)) !== null)
|
|
470
479
|
return null;
|
|
471
480
|
return record;
|
|
@@ -669,6 +678,19 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
669
678
|
function scopeAt(at) {
|
|
670
679
|
return at === key ? keyOf : legacyScope;
|
|
671
680
|
}
|
|
681
|
+
/**
|
|
682
|
+
* Set `flag` on the saved settlement with this (lowercase) hash: false when
|
|
683
|
+
* it was already set, true otherwise (another settlement stays as it is).
|
|
684
|
+
*/
|
|
685
|
+
function flagSettled(store, hash, flag) {
|
|
686
|
+
const saved = JSON.parse(store.getItem(settledKey) ?? "null");
|
|
687
|
+
if (saved?.hash !== hash)
|
|
688
|
+
return true;
|
|
689
|
+
if (saved[flag] === true)
|
|
690
|
+
return false;
|
|
691
|
+
store.setItem(settledKey, JSON.stringify({ ...saved, [flag]: true }));
|
|
692
|
+
return true;
|
|
693
|
+
}
|
|
672
694
|
function storage() {
|
|
673
695
|
const store = recoveryStorage(options.storage);
|
|
674
696
|
lastStorage = store;
|
|
@@ -690,7 +712,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
690
712
|
}
|
|
691
713
|
function requireLock() {
|
|
692
714
|
if (!locked)
|
|
693
|
-
throw new
|
|
715
|
+
throw new ReviewLineError("Write recovery changes require the browser lock.");
|
|
694
716
|
}
|
|
695
717
|
function read() {
|
|
696
718
|
const store = storage();
|
|
@@ -702,7 +724,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
702
724
|
const store = storage();
|
|
703
725
|
store.setItem(at, raw);
|
|
704
726
|
if (store.getItem(at) !== raw)
|
|
705
|
-
throw new
|
|
727
|
+
throw new ReviewLineError("Write recovery storage did not retain the action.");
|
|
706
728
|
}
|
|
707
729
|
function clear(expected) {
|
|
708
730
|
requireLock();
|
|
@@ -718,7 +740,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
718
740
|
if (!current)
|
|
719
741
|
return;
|
|
720
742
|
if (JSON.stringify(current) !== JSON.stringify(recordOf(expected))) {
|
|
721
|
-
throw new
|
|
743
|
+
throw new ReviewLineError("Write recovery changed. Keep the current action pending.");
|
|
722
744
|
}
|
|
723
745
|
// The last record of an attempt goes only once its generation is the
|
|
724
746
|
// committed latest marker; otherwise it stays, released, and carries it.
|
|
@@ -726,13 +748,13 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
726
748
|
const marker = releasedKey(at, current.id);
|
|
727
749
|
store.setItem(marker, "1");
|
|
728
750
|
if (store.getItem(marker) !== "1")
|
|
729
|
-
throw new
|
|
751
|
+
throw new ReviewLineError("Write recovery storage did not clear the action.");
|
|
730
752
|
unpersistedSubmissions.get(store)?.delete(at);
|
|
731
753
|
return;
|
|
732
754
|
}
|
|
733
755
|
store.removeItem(at);
|
|
734
756
|
if (store.getItem(at) !== null)
|
|
735
|
-
throw new
|
|
757
|
+
throw new ReviewLineError("Write recovery storage did not clear the action.");
|
|
736
758
|
unpersistedSubmissions.get(store)?.delete(at);
|
|
737
759
|
}
|
|
738
760
|
/** Add `fields` to exactly `expected`, a hashed record `when` allows; extra evidence only. */
|
|
@@ -760,6 +782,12 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
760
782
|
const current = read();
|
|
761
783
|
if (current?.id === owned.id && current.hash)
|
|
762
784
|
return;
|
|
785
|
+
try {
|
|
786
|
+
storage().setItem(exitedKey(locate(storage()).at, owned.id), "1");
|
|
787
|
+
}
|
|
788
|
+
catch {
|
|
789
|
+
/* Unsaved, a sequence resumed over it asks for the user's check. */
|
|
790
|
+
}
|
|
763
791
|
// Removing the record must not uncover a settlement of an earlier
|
|
764
792
|
// attempt: unless this reservation is the verified latest, it stays as
|
|
765
793
|
// released instead, which still invalidates that settlement.
|
|
@@ -815,13 +843,13 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
815
843
|
function record(hash, expected, replace) {
|
|
816
844
|
requireLock();
|
|
817
845
|
if (!isBytes32(hash))
|
|
818
|
-
throw new
|
|
846
|
+
throw new ReviewLineError("The wallet returned an invalid transaction identity.");
|
|
819
847
|
const previous = expected && recordOf(expected);
|
|
820
848
|
const submittedHash = hash.toLowerCase();
|
|
821
849
|
if (!previous ||
|
|
822
850
|
keyOf(previous) !== key ||
|
|
823
851
|
(!replace && previous.hash && previous.hash !== submittedHash)) {
|
|
824
|
-
throw new
|
|
852
|
+
throw new ReviewLineError("Write recovery changed before submission was recorded.");
|
|
825
853
|
}
|
|
826
854
|
// A hash the wallet returns now starts its clock; a speed-up found at its nonce keeps it.
|
|
827
855
|
const submittedAt = replace || previous.hash === submittedHash
|
|
@@ -858,7 +886,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
858
886
|
submittedAt: undefined,
|
|
859
887
|
}) ||
|
|
860
888
|
(!replace && current.hash && current.hash !== submittedHash)) {
|
|
861
|
-
throw new
|
|
889
|
+
throw new ReviewLineError("Write recovery changed before submission was recorded.");
|
|
862
890
|
}
|
|
863
891
|
owned = recordOf(submitted);
|
|
864
892
|
if (current.hash !== submittedHash) {
|
|
@@ -892,15 +920,15 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
892
920
|
? normalized({ ...reviewed, call: actualCall })
|
|
893
921
|
: reviewed;
|
|
894
922
|
if (legacyScope(actual) !== legacyScope(reviewed))
|
|
895
|
-
throw new
|
|
923
|
+
throw new ReviewLineError("The adopted write has a different recovery scope.");
|
|
896
924
|
const nonce = evidence && uint256(evidence.nonce);
|
|
897
925
|
const fromBlock = evidence && uint256(evidence.blockNumber);
|
|
898
926
|
if (evidence && (nonce === null || fromBlock === null))
|
|
899
|
-
throw new
|
|
927
|
+
throw new ReviewLineError("Invalid write recovery nonce evidence.");
|
|
900
928
|
const store = storage();
|
|
901
929
|
const { at, raw } = locate(store);
|
|
902
930
|
if (readRecovery(store, at, raw, scopeAt(at)))
|
|
903
|
-
throw new
|
|
931
|
+
throw new ReviewLineError("An earlier wallet write is still unresolved. Check it before trying again.");
|
|
904
932
|
// The record this one replaces, if the user released it: its marker goes too.
|
|
905
933
|
let replaced;
|
|
906
934
|
try {
|
|
@@ -939,6 +967,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
939
967
|
if (typeof replaced === "string" && replaced !== record.id)
|
|
940
968
|
try {
|
|
941
969
|
store.removeItem(releasedKey(key, replaced));
|
|
970
|
+
store.removeItem(exitedKey(key, replaced));
|
|
942
971
|
}
|
|
943
972
|
catch {
|
|
944
973
|
/* A leftover marker names only the old record. */
|
|
@@ -971,7 +1000,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
971
1000
|
requireLock();
|
|
972
1001
|
const current = read();
|
|
973
1002
|
if (current && current.mirrorOf !== of)
|
|
974
|
-
throw new
|
|
1003
|
+
throw new ReviewLineError("An earlier wallet write is still unresolved. Check it before trying again.");
|
|
975
1004
|
const mirrored = recordOf({
|
|
976
1005
|
version: 1,
|
|
977
1006
|
id: source.id,
|
|
@@ -1011,6 +1040,16 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1011
1040
|
return undefined;
|
|
1012
1041
|
}
|
|
1013
1042
|
},
|
|
1043
|
+
/** Whether the record `id` ended by the user's exit, or because nothing was sent. */
|
|
1044
|
+
released(id) {
|
|
1045
|
+
try {
|
|
1046
|
+
const store = storage();
|
|
1047
|
+
return store.getItem(exitedKey(locate(store).at, id)) !== null;
|
|
1048
|
+
}
|
|
1049
|
+
catch {
|
|
1050
|
+
return false;
|
|
1051
|
+
}
|
|
1052
|
+
},
|
|
1014
1053
|
/**
|
|
1015
1054
|
* The call's latest reservation id: the record saved at the key (held,
|
|
1016
1055
|
* or released by its exit), or else the saved latest marker.
|
|
@@ -1074,6 +1113,10 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1074
1113
|
id: expected.id,
|
|
1075
1114
|
result: settlement.result,
|
|
1076
1115
|
hash: settlement.hash.toLowerCase(),
|
|
1116
|
+
...(settlement.blockHash
|
|
1117
|
+
? { blockHash: settlement.blockHash.toLowerCase() }
|
|
1118
|
+
: {}),
|
|
1119
|
+
...(settlement.safe ? { safe: true } : {}),
|
|
1077
1120
|
at: Date.now(),
|
|
1078
1121
|
}));
|
|
1079
1122
|
}
|
|
@@ -1087,17 +1130,29 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1087
1130
|
*/
|
|
1088
1131
|
acknowledgeSettled(settled) {
|
|
1089
1132
|
requireLock();
|
|
1090
|
-
const store = storage();
|
|
1091
1133
|
try {
|
|
1092
|
-
|
|
1093
|
-
const saved = JSON.parse(raw ?? "null");
|
|
1094
|
-
if (saved?.hash === settled.hash.toLowerCase())
|
|
1095
|
-
store.setItem(settledKey, JSON.stringify({ ...saved, acknowledged: true }));
|
|
1134
|
+
flagSettled(storage(), settled.hash.toLowerCase(), "acknowledged");
|
|
1096
1135
|
}
|
|
1097
1136
|
catch {
|
|
1098
1137
|
/* An unreadable settlement names none; a refused write keeps it unacknowledged. */
|
|
1099
1138
|
}
|
|
1100
1139
|
},
|
|
1140
|
+
/**
|
|
1141
|
+
* Claim the one `onConfirmed` notice of the saved settlement `settled`
|
|
1142
|
+
* names (its hash): true for the first claim in any tab or run, false
|
|
1143
|
+
* after. A settlement no longer saved there can't be marked, so every
|
|
1144
|
+
* claim of it is true: a repeated notice over a lost one.
|
|
1145
|
+
*/
|
|
1146
|
+
claimConfirmedSettled(settled) {
|
|
1147
|
+
requireLock();
|
|
1148
|
+
try {
|
|
1149
|
+
return flagSettled(storage(), settled.hash.toLowerCase(), "confirmed");
|
|
1150
|
+
}
|
|
1151
|
+
catch {
|
|
1152
|
+
// Storage unavailable: told rather than lost.
|
|
1153
|
+
return true;
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1101
1156
|
/**
|
|
1102
1157
|
* How the call's last write ended, if {@link markSettled} saved it for
|
|
1103
1158
|
* the call's latest reservation; a settlement of an earlier one reads as
|
|
@@ -1121,6 +1176,10 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1121
1176
|
? {
|
|
1122
1177
|
result: saved.result,
|
|
1123
1178
|
hash: saved.hash,
|
|
1179
|
+
...(isBytes32(saved.blockHash)
|
|
1180
|
+
? { blockHash: saved.blockHash }
|
|
1181
|
+
: {}),
|
|
1182
|
+
...(saved.safe === true ? { safe: true } : {}),
|
|
1124
1183
|
// Saved before 2.39 (a latest marker with no time): the user
|
|
1125
1184
|
// saw it then, so it reads as acknowledged.
|
|
1126
1185
|
...(saved.acknowledged === true || typeof latest.at !== "number"
|
|
@@ -1271,7 +1330,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1271
1330
|
executed(expected, executionHash) {
|
|
1272
1331
|
requireLock();
|
|
1273
1332
|
if (executionHash !== undefined && !isBytes32(executionHash))
|
|
1274
|
-
throw new
|
|
1333
|
+
throw new ReviewLineError("Invalid execution transaction identity.");
|
|
1275
1334
|
const store = storage();
|
|
1276
1335
|
const { at, raw } = locate(store);
|
|
1277
1336
|
const current = readRecovery(store, at, raw, scopeAt(at));
|
|
@@ -1279,7 +1338,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1279
1338
|
if (!current?.hash ||
|
|
1280
1339
|
current.id !== wanted.id ||
|
|
1281
1340
|
current.hash !== wanted.hash)
|
|
1282
|
-
throw new
|
|
1341
|
+
throw new ReviewLineError("Write recovery changed. Keep the current action pending.");
|
|
1283
1342
|
const next = recordOf({
|
|
1284
1343
|
...current,
|
|
1285
1344
|
executed: true,
|
|
@@ -1318,7 +1377,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1318
1377
|
*/
|
|
1319
1378
|
abandon(expected, acknowledgement) {
|
|
1320
1379
|
if (acknowledgement?.checkedWallet !== true)
|
|
1321
|
-
throw new
|
|
1380
|
+
throw new ReviewLineError("Release a held write only after the user confirms they checked their wallet.");
|
|
1322
1381
|
const wanted = JSON.stringify(recordOf(expected));
|
|
1323
1382
|
const store = storage();
|
|
1324
1383
|
const { at, raw } = locate(store);
|
|
@@ -1326,15 +1385,21 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1326
1385
|
if (!durable)
|
|
1327
1386
|
return;
|
|
1328
1387
|
if (durable.executed)
|
|
1329
|
-
throw new
|
|
1388
|
+
throw new ReviewLineError("This write ran onchain. Keep it held until its result is known.");
|
|
1330
1389
|
const shown = readRecovery(store, at, raw, scopeAt(at));
|
|
1331
1390
|
if (JSON.stringify(durable) !== wanted &&
|
|
1332
1391
|
JSON.stringify(shown) !== wanted)
|
|
1333
|
-
throw new
|
|
1392
|
+
throw new ReviewLineError("Write recovery changed. Keep the current action pending.");
|
|
1334
1393
|
const marker = releasedKey(at, durable.id);
|
|
1394
|
+
try {
|
|
1395
|
+
store.setItem(exitedKey(at, durable.id), "1");
|
|
1396
|
+
}
|
|
1397
|
+
catch {
|
|
1398
|
+
/* Unsaved, a sequence resumed over it asks for the user's check. */
|
|
1399
|
+
}
|
|
1335
1400
|
store.setItem(marker, "1");
|
|
1336
1401
|
if (store.getItem(marker) !== "1")
|
|
1337
|
-
throw new
|
|
1402
|
+
throw new ReviewLineError("Write recovery storage did not release the action.");
|
|
1338
1403
|
const memory = unpersistedSubmissions.get(store);
|
|
1339
1404
|
if (memory?.get(at)?.id === durable.id)
|
|
1340
1405
|
memory.delete(at);
|
|
@@ -1345,7 +1410,7 @@ export function createBrowserWriteRecovery(input, options = {}) {
|
|
|
1345
1410
|
const locks = options.locks ?? browserLocks();
|
|
1346
1411
|
return locks.request(key, { mode: "exclusive", ...(!wait && { ifAvailable: true }) }, async (lock) => {
|
|
1347
1412
|
if (!lock)
|
|
1348
|
-
throw new
|
|
1413
|
+
throw new ReviewLineError("This wallet action is already open in another tab.");
|
|
1349
1414
|
locked = true;
|
|
1350
1415
|
try {
|
|
1351
1416
|
return await work();
|
|
@@ -1503,7 +1568,13 @@ function heldBatch(record) {
|
|
|
1503
1568
|
: null;
|
|
1504
1569
|
return inner && inner.map((call) => normalized({ ...record, call }).call);
|
|
1505
1570
|
}
|
|
1506
|
-
/**
|
|
1571
|
+
/**
|
|
1572
|
+
* The MultiSend targets a held batch may run through: a Safe app folds the
|
|
1573
|
+
* same calls into its own version's MultiSendCallOnly, so any recognized
|
|
1574
|
+
* deployment carries exactly the held calldata.
|
|
1575
|
+
*/
|
|
1576
|
+
const BATCH_TARGETS = MULTI_SEND_CALL_ONLY_DEPLOYMENTS.map((to) => to.toLowerCase());
|
|
1577
|
+
/** Whether `transaction` is the Safe's execTransaction of exactly the held batch: a recognized MultiSendCallOnly, its calldata, zero value and DELEGATECALL. */
|
|
1507
1578
|
function runsHeldBatch(transaction, record) {
|
|
1508
1579
|
try {
|
|
1509
1580
|
const { functionName, args } = decodeFunctionData({
|
|
@@ -1513,7 +1584,7 @@ function runsHeldBatch(transaction, record) {
|
|
|
1513
1584
|
if (functionName !== "execTransaction")
|
|
1514
1585
|
return false;
|
|
1515
1586
|
const [to, value, data, operation] = args;
|
|
1516
|
-
return (to.toLowerCase()
|
|
1587
|
+
return (BATCH_TARGETS.includes(to.toLowerCase()) &&
|
|
1517
1588
|
value === 0n &&
|
|
1518
1589
|
data.toLowerCase() === record.call.data &&
|
|
1519
1590
|
operation === 1);
|
|
@@ -1539,13 +1610,14 @@ export function heldSafeProposal(input, nonce) {
|
|
|
1539
1610
|
*/
|
|
1540
1611
|
export function safeProposalIsHeldCall(proposal, input) {
|
|
1541
1612
|
const record = normalized(input);
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
:
|
|
1548
|
-
|
|
1613
|
+
const call = { ...record.call, value: BigInt(record.call.value) };
|
|
1614
|
+
return heldBatch({ ...record, version: 1, id: "" })
|
|
1615
|
+
? BATCH_TARGETS.some((to) => safeTransactionMatchesCall(proposal, {
|
|
1616
|
+
...call,
|
|
1617
|
+
to: to,
|
|
1618
|
+
operation: 1,
|
|
1619
|
+
}))
|
|
1620
|
+
: safeTransactionMatchesCall(proposal, call);
|
|
1549
1621
|
}
|
|
1550
1622
|
/**
|
|
1551
1623
|
* Authenticate the saved wallet identity, canonical inclusion and Safe effect.
|
|
@@ -1559,7 +1631,7 @@ export function safeProposalIsHeldCall(proposal, input) {
|
|
|
1559
1631
|
*/
|
|
1560
1632
|
export async function verifyReviewedWriteReceipt(client, saved, receipt, proof, { finality = true } = {}) {
|
|
1561
1633
|
const record = recordOf(saved);
|
|
1562
|
-
const pending = () => new
|
|
1634
|
+
const pending = () => new ReviewLineError("The saved wallet write is not yet proven. Keep this action pending.");
|
|
1563
1635
|
// A batch hold's call is its MultiSend: its proof is the calls it encodes.
|
|
1564
1636
|
const batch = heldBatch(record);
|
|
1565
1637
|
let calls = batch ?? [record.call];
|
|
@@ -1646,6 +1718,35 @@ export async function verifyReviewedWriteReceipt(client, saved, receipt, proof,
|
|
|
1646
1718
|
throw pending();
|
|
1647
1719
|
status = result.status;
|
|
1648
1720
|
}
|
|
1721
|
+
else if (status === "success" && isSafeExecTransaction(record.call.data)) {
|
|
1722
|
+
// A Safe's execTransaction succeeds only with the Safe's own
|
|
1723
|
+
// ExecutionSuccess for its exact hash: an ExecutionFailure, or no event
|
|
1724
|
+
// for it, is a failure whatever the receipt's status. A call that only
|
|
1725
|
+
// shares the selector, to anything but a Safe, is decided as any other.
|
|
1726
|
+
if (!client.request)
|
|
1727
|
+
throw pending();
|
|
1728
|
+
const { request } = client;
|
|
1729
|
+
const at = (blockNumber) => blockNumber === undefined ? "latest" : numberToHex(blockNumber);
|
|
1730
|
+
// Every read through the one `request` the receipt client has.
|
|
1731
|
+
const identity = await readAuthorityIdentity({
|
|
1732
|
+
request,
|
|
1733
|
+
getCode: ({ address, blockNumber }) => request({
|
|
1734
|
+
method: "eth_getCode",
|
|
1735
|
+
params: [address, at(blockNumber)],
|
|
1736
|
+
}),
|
|
1737
|
+
getStorageAt: ({ address, slot, blockNumber }) => request({
|
|
1738
|
+
method: "eth_getStorageAt",
|
|
1739
|
+
params: [address, slot, at(blockNumber)],
|
|
1740
|
+
}),
|
|
1741
|
+
}, record.call.to, { blockNumber: canonical.blockNumber });
|
|
1742
|
+
if (!identity)
|
|
1743
|
+
throw pending();
|
|
1744
|
+
if (identity.kind === "safe") {
|
|
1745
|
+
const execution = await safeExecTransactionResult({ request: client.request }, record.chainId, record.call.to, record.call.data, canonical);
|
|
1746
|
+
if (execution?.status !== "success")
|
|
1747
|
+
status = "failed";
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1649
1750
|
const isCanonical = async () => {
|
|
1650
1751
|
const block = await client.getBlock({ blockNumber: canonical.blockNumber });
|
|
1651
1752
|
return (block.number === canonical.blockNumber &&
|
|
@@ -1666,7 +1767,7 @@ export async function verifyReviewedWriteReceipt(client, saved, receipt, proof,
|
|
|
1666
1767
|
*/
|
|
1667
1768
|
export async function verifyReviewedWriteExpiry(client, saved, service) {
|
|
1668
1769
|
const record = recordOf(saved);
|
|
1669
|
-
const pending = () => new
|
|
1770
|
+
const pending = () => new ReviewLineError("The saved Safe proposal is not proven expired. Keep this action pending.");
|
|
1670
1771
|
if (!record.safe ||
|
|
1671
1772
|
!record.hash ||
|
|
1672
1773
|
(await client.getChainId()) !== record.chainId)
|