@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.
Files changed (304) hide show
  1. package/bin/wallet-check.mjs +495 -0
  2. package/dist/cjs/actions/suckerPairs.d.ts +5 -3
  3. package/dist/cjs/actions/suckerPairs.d.ts.map +1 -1
  4. package/dist/cjs/actions/suckerPairs.js +6 -26
  5. package/dist/cjs/actions/suckerPairs.js.map +1 -1
  6. package/dist/cjs/pause.d.ts +2 -0
  7. package/dist/cjs/pause.d.ts.map +1 -1
  8. package/dist/cjs/pause.js +17 -0
  9. package/dist/cjs/pause.js.map +1 -1
  10. package/dist/cjs/review/confirm.d.ts +56 -0
  11. package/dist/cjs/review/confirm.d.ts.map +1 -0
  12. package/dist/cjs/review/confirm.js +99 -0
  13. package/dist/cjs/review/confirm.js.map +1 -0
  14. package/dist/cjs/review/contractWrite.d.ts +5 -3
  15. package/dist/cjs/review/contractWrite.d.ts.map +1 -1
  16. package/dist/cjs/review/contractWrite.js +10 -8
  17. package/dist/cjs/review/contractWrite.js.map +1 -1
  18. package/dist/cjs/review/decode.d.ts +19 -1
  19. package/dist/cjs/review/decode.d.ts.map +1 -1
  20. package/dist/cjs/review/decode.js +30 -11
  21. package/dist/cjs/review/decode.js.map +1 -1
  22. package/dist/cjs/review/decodeCall.d.ts +21 -0
  23. package/dist/cjs/review/decodeCall.d.ts.map +1 -0
  24. package/dist/cjs/review/decodeCall.js +183 -0
  25. package/dist/cjs/review/decodeCall.js.map +1 -0
  26. package/dist/cjs/review/heldWrite.d.ts +4 -0
  27. package/dist/cjs/review/heldWrite.d.ts.map +1 -1
  28. package/dist/cjs/review/heldWrite.js +35 -31
  29. package/dist/cjs/review/heldWrite.js.map +1 -1
  30. package/dist/cjs/review/index.d.ts +12 -1
  31. package/dist/cjs/review/index.d.ts.map +1 -1
  32. package/dist/cjs/review/index.js +29 -1
  33. package/dist/cjs/review/index.js.map +1 -1
  34. package/dist/cjs/review/intents.d.ts +10 -0
  35. package/dist/cjs/review/intents.d.ts.map +1 -1
  36. package/dist/cjs/review/intents.js +13 -0
  37. package/dist/cjs/review/intents.js.map +1 -1
  38. package/dist/cjs/review/lineError.d.ts +72 -0
  39. package/dist/cjs/review/lineError.d.ts.map +1 -0
  40. package/dist/cjs/review/lineError.js +76 -0
  41. package/dist/cjs/review/lineError.js.map +1 -0
  42. package/dist/cjs/review/messages.d.ts +15 -3
  43. package/dist/cjs/review/messages.d.ts.map +1 -1
  44. package/dist/cjs/review/messages.js +16 -4
  45. package/dist/cjs/review/messages.js.map +1 -1
  46. package/dist/cjs/review/model.d.ts +149 -0
  47. package/dist/cjs/review/model.d.ts.map +1 -0
  48. package/dist/cjs/review/model.js +750 -0
  49. package/dist/cjs/review/model.js.map +1 -0
  50. package/dist/cjs/review/plan.d.ts +61 -0
  51. package/dist/cjs/review/plan.d.ts.map +1 -0
  52. package/dist/cjs/review/plan.js +143 -0
  53. package/dist/cjs/review/plan.js.map +1 -0
  54. package/dist/cjs/review/react/index.d.ts +1 -0
  55. package/dist/cjs/review/react/index.d.ts.map +1 -1
  56. package/dist/cjs/review/react/index.js +1 -0
  57. package/dist/cjs/review/react/index.js.map +1 -1
  58. package/dist/cjs/review/react/useHeldSend.js +3 -4
  59. package/dist/cjs/review/react/useHeldSend.js.map +1 -1
  60. package/dist/cjs/review/react/useHeldWrite.d.ts.map +1 -1
  61. package/dist/cjs/review/react/useHeldWrite.js +2 -1
  62. package/dist/cjs/review/react/useHeldWrite.js.map +1 -1
  63. package/dist/cjs/review/react/useReviewedRun.d.ts +122 -0
  64. package/dist/cjs/review/react/useReviewedRun.d.ts.map +1 -0
  65. package/dist/cjs/review/react/useReviewedRun.js +443 -0
  66. package/dist/cjs/review/react/useReviewedRun.js.map +1 -0
  67. package/dist/cjs/review/receipt.d.ts +37 -1
  68. package/dist/cjs/review/receipt.d.ts.map +1 -1
  69. package/dist/cjs/review/receipt.js +76 -3
  70. package/dist/cjs/review/receipt.js.map +1 -1
  71. package/dist/cjs/review/relayr.d.ts +13 -4
  72. package/dist/cjs/review/relayr.d.ts.map +1 -1
  73. package/dist/cjs/review/relayr.js +52 -8
  74. package/dist/cjs/review/relayr.js.map +1 -1
  75. package/dist/cjs/review/relayrSend.d.ts +106 -0
  76. package/dist/cjs/review/relayrSend.d.ts.map +1 -0
  77. package/dist/cjs/review/relayrSend.js +795 -0
  78. package/dist/cjs/review/relayrSend.js.map +1 -0
  79. package/dist/cjs/review/reviewQueue.d.ts +10 -9
  80. package/dist/cjs/review/reviewQueue.d.ts.map +1 -1
  81. package/dist/cjs/review/reviewQueue.js +19 -29
  82. package/dist/cjs/review/reviewQueue.js.map +1 -1
  83. package/dist/cjs/review/reviewRequests.d.ts +86 -0
  84. package/dist/cjs/review/reviewRequests.d.ts.map +1 -0
  85. package/dist/cjs/review/reviewRequests.js +266 -0
  86. package/dist/cjs/review/reviewRequests.js.map +1 -0
  87. package/dist/cjs/review/safeRelayr.d.ts +3 -1
  88. package/dist/cjs/review/safeRelayr.d.ts.map +1 -1
  89. package/dist/cjs/review/safeRelayr.js +9 -9
  90. package/dist/cjs/review/safeRelayr.js.map +1 -1
  91. package/dist/cjs/review/safeSend.d.ts +69 -0
  92. package/dist/cjs/review/safeSend.d.ts.map +1 -0
  93. package/dist/cjs/review/safeSend.js +306 -0
  94. package/dist/cjs/review/safeSend.js.map +1 -0
  95. package/dist/cjs/review/send.d.ts +272 -0
  96. package/dist/cjs/review/send.d.ts.map +1 -0
  97. package/dist/cjs/review/send.js +1163 -0
  98. package/dist/cjs/review/send.js.map +1 -0
  99. package/dist/cjs/review/sequence.d.ts +77 -0
  100. package/dist/cjs/review/sequence.d.ts.map +1 -0
  101. package/dist/cjs/review/sequence.js +232 -0
  102. package/dist/cjs/review/sequence.js.map +1 -0
  103. package/dist/cjs/review/sign.d.ts +111 -0
  104. package/dist/cjs/review/sign.d.ts.map +1 -0
  105. package/dist/cjs/review/sign.js +378 -0
  106. package/dist/cjs/review/sign.js.map +1 -0
  107. package/dist/cjs/review/simulation.d.ts +41 -2
  108. package/dist/cjs/review/simulation.d.ts.map +1 -1
  109. package/dist/cjs/review/simulation.js +99 -29
  110. package/dist/cjs/review/simulation.js.map +1 -1
  111. package/dist/cjs/review/transaction-message.d.ts +13 -0
  112. package/dist/cjs/review/transaction-message.d.ts.map +1 -1
  113. package/dist/cjs/review/transaction-message.js +25 -0
  114. package/dist/cjs/review/transaction-message.js.map +1 -1
  115. package/dist/cjs/review/transactionReview.d.ts +27 -19
  116. package/dist/cjs/review/transactionReview.d.ts.map +1 -1
  117. package/dist/cjs/review/transactionReview.js +22 -63
  118. package/dist/cjs/review/transactionReview.js.map +1 -1
  119. package/dist/cjs/review/wallet.d.ts +98 -0
  120. package/dist/cjs/review/wallet.d.ts.map +1 -0
  121. package/dist/cjs/review/wallet.js +234 -0
  122. package/dist/cjs/review/wallet.js.map +1 -0
  123. package/dist/cjs/review/writeHold.d.ts +138 -13
  124. package/dist/cjs/review/writeHold.d.ts.map +1 -1
  125. package/dist/cjs/review/writeHold.js +98 -18
  126. package/dist/cjs/review/writeHold.js.map +1 -1
  127. package/dist/cjs/review/writeRecovery.d.ts +17 -1
  128. package/dist/cjs/review/writeRecovery.d.ts.map +1 -1
  129. package/dist/cjs/review/writeRecovery.js +146 -45
  130. package/dist/cjs/review/writeRecovery.js.map +1 -1
  131. package/dist/cjs/safeService.d.ts +27 -4
  132. package/dist/cjs/safeService.d.ts.map +1 -1
  133. package/dist/cjs/safeService.js +120 -3
  134. package/dist/cjs/safeService.js.map +1 -1
  135. package/dist/cjs/testing.d.ts +24 -0
  136. package/dist/cjs/testing.d.ts.map +1 -1
  137. package/dist/cjs/testing.js +26 -1
  138. package/dist/cjs/testing.js.map +1 -1
  139. package/dist/cjs/v6/defifa.d.ts.map +1 -1
  140. package/dist/cjs/v6/defifa.js +24 -23
  141. package/dist/cjs/v6/defifa.js.map +1 -1
  142. package/dist/cjs/v6/executionErrors.d.ts.map +1 -1
  143. package/dist/cjs/v6/executionErrors.js +3 -2
  144. package/dist/cjs/v6/executionErrors.js.map +1 -1
  145. package/dist/cjs/v6/pay.d.ts +25 -8
  146. package/dist/cjs/v6/pay.d.ts.map +1 -1
  147. package/dist/cjs/v6/pay.js +117 -23
  148. package/dist/cjs/v6/pay.js.map +1 -1
  149. package/dist/cjs/v6/suckers.d.ts +30 -0
  150. package/dist/cjs/v6/suckers.d.ts.map +1 -1
  151. package/dist/cjs/v6/suckers.js +69 -5
  152. package/dist/cjs/v6/suckers.js.map +1 -1
  153. package/dist/esm/actions/suckerPairs.d.ts +5 -3
  154. package/dist/esm/actions/suckerPairs.d.ts.map +1 -1
  155. package/dist/esm/actions/suckerPairs.js +7 -27
  156. package/dist/esm/actions/suckerPairs.js.map +1 -1
  157. package/dist/esm/pause.d.ts +2 -0
  158. package/dist/esm/pause.d.ts.map +1 -1
  159. package/dist/esm/pause.js +16 -0
  160. package/dist/esm/pause.js.map +1 -1
  161. package/dist/esm/review/confirm.d.ts +56 -0
  162. package/dist/esm/review/confirm.d.ts.map +1 -0
  163. package/dist/esm/review/confirm.js +93 -0
  164. package/dist/esm/review/confirm.js.map +1 -0
  165. package/dist/esm/review/contractWrite.d.ts +5 -3
  166. package/dist/esm/review/contractWrite.d.ts.map +1 -1
  167. package/dist/esm/review/contractWrite.js +10 -8
  168. package/dist/esm/review/contractWrite.js.map +1 -1
  169. package/dist/esm/review/decode.d.ts +19 -1
  170. package/dist/esm/review/decode.d.ts.map +1 -1
  171. package/dist/esm/review/decode.js +29 -14
  172. package/dist/esm/review/decode.js.map +1 -1
  173. package/dist/esm/review/decodeCall.d.ts +21 -0
  174. package/dist/esm/review/decodeCall.d.ts.map +1 -0
  175. package/dist/esm/review/decodeCall.js +180 -0
  176. package/dist/esm/review/decodeCall.js.map +1 -0
  177. package/dist/esm/review/heldWrite.d.ts +4 -0
  178. package/dist/esm/review/heldWrite.d.ts.map +1 -1
  179. package/dist/esm/review/heldWrite.js +34 -30
  180. package/dist/esm/review/heldWrite.js.map +1 -1
  181. package/dist/esm/review/index.d.ts +12 -1
  182. package/dist/esm/review/index.d.ts.map +1 -1
  183. package/dist/esm/review/index.js +12 -1
  184. package/dist/esm/review/index.js.map +1 -1
  185. package/dist/esm/review/intents.d.ts +10 -0
  186. package/dist/esm/review/intents.d.ts.map +1 -1
  187. package/dist/esm/review/intents.js +12 -0
  188. package/dist/esm/review/intents.js.map +1 -1
  189. package/dist/esm/review/lineError.d.ts +72 -0
  190. package/dist/esm/review/lineError.d.ts.map +1 -0
  191. package/dist/esm/review/lineError.js +68 -0
  192. package/dist/esm/review/lineError.js.map +1 -0
  193. package/dist/esm/review/messages.d.ts +15 -3
  194. package/dist/esm/review/messages.d.ts.map +1 -1
  195. package/dist/esm/review/messages.js +15 -3
  196. package/dist/esm/review/messages.js.map +1 -1
  197. package/dist/esm/review/model.d.ts +149 -0
  198. package/dist/esm/review/model.d.ts.map +1 -0
  199. package/dist/esm/review/model.js +746 -0
  200. package/dist/esm/review/model.js.map +1 -0
  201. package/dist/esm/review/plan.d.ts +61 -0
  202. package/dist/esm/review/plan.d.ts.map +1 -0
  203. package/dist/esm/review/plan.js +136 -0
  204. package/dist/esm/review/plan.js.map +1 -0
  205. package/dist/esm/review/react/index.d.ts +1 -0
  206. package/dist/esm/review/react/index.d.ts.map +1 -1
  207. package/dist/esm/review/react/index.js +1 -0
  208. package/dist/esm/review/react/index.js.map +1 -1
  209. package/dist/esm/review/react/useHeldSend.js +3 -4
  210. package/dist/esm/review/react/useHeldSend.js.map +1 -1
  211. package/dist/esm/review/react/useHeldWrite.d.ts.map +1 -1
  212. package/dist/esm/review/react/useHeldWrite.js +2 -1
  213. package/dist/esm/review/react/useHeldWrite.js.map +1 -1
  214. package/dist/esm/review/react/useReviewedRun.d.ts +122 -0
  215. package/dist/esm/review/react/useReviewedRun.d.ts.map +1 -0
  216. package/dist/esm/review/react/useReviewedRun.js +439 -0
  217. package/dist/esm/review/react/useReviewedRun.js.map +1 -0
  218. package/dist/esm/review/receipt.d.ts +37 -1
  219. package/dist/esm/review/receipt.d.ts.map +1 -1
  220. package/dist/esm/review/receipt.js +72 -2
  221. package/dist/esm/review/receipt.js.map +1 -1
  222. package/dist/esm/review/relayr.d.ts +13 -4
  223. package/dist/esm/review/relayr.d.ts.map +1 -1
  224. package/dist/esm/review/relayr.js +51 -8
  225. package/dist/esm/review/relayr.js.map +1 -1
  226. package/dist/esm/review/relayrSend.d.ts +106 -0
  227. package/dist/esm/review/relayrSend.d.ts.map +1 -0
  228. package/dist/esm/review/relayrSend.js +787 -0
  229. package/dist/esm/review/relayrSend.js.map +1 -0
  230. package/dist/esm/review/reviewQueue.d.ts +10 -9
  231. package/dist/esm/review/reviewQueue.d.ts.map +1 -1
  232. package/dist/esm/review/reviewQueue.js +17 -26
  233. package/dist/esm/review/reviewQueue.js.map +1 -1
  234. package/dist/esm/review/reviewRequests.d.ts +86 -0
  235. package/dist/esm/review/reviewRequests.d.ts.map +1 -0
  236. package/dist/esm/review/reviewRequests.js +263 -0
  237. package/dist/esm/review/reviewRequests.js.map +1 -0
  238. package/dist/esm/review/safeRelayr.d.ts +3 -1
  239. package/dist/esm/review/safeRelayr.d.ts.map +1 -1
  240. package/dist/esm/review/safeRelayr.js +9 -9
  241. package/dist/esm/review/safeRelayr.js.map +1 -1
  242. package/dist/esm/review/safeSend.d.ts +69 -0
  243. package/dist/esm/review/safeSend.d.ts.map +1 -0
  244. package/dist/esm/review/safeSend.js +301 -0
  245. package/dist/esm/review/safeSend.js.map +1 -0
  246. package/dist/esm/review/send.d.ts +272 -0
  247. package/dist/esm/review/send.d.ts.map +1 -0
  248. package/dist/esm/review/send.js +1156 -0
  249. package/dist/esm/review/send.js.map +1 -0
  250. package/dist/esm/review/sequence.d.ts +77 -0
  251. package/dist/esm/review/sequence.d.ts.map +1 -0
  252. package/dist/esm/review/sequence.js +223 -0
  253. package/dist/esm/review/sequence.js.map +1 -0
  254. package/dist/esm/review/sign.d.ts +111 -0
  255. package/dist/esm/review/sign.d.ts.map +1 -0
  256. package/dist/esm/review/sign.js +372 -0
  257. package/dist/esm/review/sign.js.map +1 -0
  258. package/dist/esm/review/simulation.d.ts +41 -2
  259. package/dist/esm/review/simulation.d.ts.map +1 -1
  260. package/dist/esm/review/simulation.js +95 -29
  261. package/dist/esm/review/simulation.js.map +1 -1
  262. package/dist/esm/review/transaction-message.d.ts +13 -0
  263. package/dist/esm/review/transaction-message.d.ts.map +1 -1
  264. package/dist/esm/review/transaction-message.js +23 -0
  265. package/dist/esm/review/transaction-message.js.map +1 -1
  266. package/dist/esm/review/transactionReview.d.ts +27 -19
  267. package/dist/esm/review/transactionReview.d.ts.map +1 -1
  268. package/dist/esm/review/transactionReview.js +19 -56
  269. package/dist/esm/review/transactionReview.js.map +1 -1
  270. package/dist/esm/review/wallet.d.ts +98 -0
  271. package/dist/esm/review/wallet.d.ts.map +1 -0
  272. package/dist/esm/review/wallet.js +227 -0
  273. package/dist/esm/review/wallet.js.map +1 -0
  274. package/dist/esm/review/writeHold.d.ts +138 -13
  275. package/dist/esm/review/writeHold.d.ts.map +1 -1
  276. package/dist/esm/review/writeHold.js +96 -19
  277. package/dist/esm/review/writeHold.js.map +1 -1
  278. package/dist/esm/review/writeRecovery.d.ts +17 -1
  279. package/dist/esm/review/writeRecovery.d.ts.map +1 -1
  280. package/dist/esm/review/writeRecovery.js +149 -48
  281. package/dist/esm/review/writeRecovery.js.map +1 -1
  282. package/dist/esm/safeService.d.ts +27 -4
  283. package/dist/esm/safeService.d.ts.map +1 -1
  284. package/dist/esm/safeService.js +119 -4
  285. package/dist/esm/safeService.js.map +1 -1
  286. package/dist/esm/testing.d.ts +24 -0
  287. package/dist/esm/testing.d.ts.map +1 -1
  288. package/dist/esm/testing.js +23 -1
  289. package/dist/esm/testing.js.map +1 -1
  290. package/dist/esm/v6/defifa.d.ts.map +1 -1
  291. package/dist/esm/v6/defifa.js +24 -23
  292. package/dist/esm/v6/defifa.js.map +1 -1
  293. package/dist/esm/v6/executionErrors.d.ts.map +1 -1
  294. package/dist/esm/v6/executionErrors.js +3 -2
  295. package/dist/esm/v6/executionErrors.js.map +1 -1
  296. package/dist/esm/v6/pay.d.ts +25 -8
  297. package/dist/esm/v6/pay.d.ts.map +1 -1
  298. package/dist/esm/v6/pay.js +115 -22
  299. package/dist/esm/v6/pay.js.map +1 -1
  300. package/dist/esm/v6/suckers.d.ts +30 -0
  301. package/dist/esm/v6/suckers.d.ts.map +1 -1
  302. package/dist/esm/v6/suckers.js +67 -5
  303. package/dist/esm/v6/suckers.js.map +1 -1
  304. package/package.json +11 -2
@@ -1,6 +1,7 @@
1
- import { decodeFunctionData, isAddress, keccak256, } from "viem";
2
- import { lookAtSafeProposal, readSafeAppExecution, readSafeTransaction, SAFE_EXEC_ABI, safeProposalFor, safeTransactionMatchesCall, } from "../safeService.js";
3
- import { multiSendCallsOf } from "../safe.js";
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 Error {
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 Error("Invalid reviewed write recovery evidence.");
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 Error("Invalid reviewed write recovery evidence.");
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 Error("Invalid saved write recovery record. Keep this action pending.");
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 Error("Invalid write recovery namespace.");
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 Error("Write recovery storage is unavailable.");
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 Error("Invalid write hold match.");
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 Error("Invalid write recovery key.");
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 Error("Provide a write recovery namespace.");
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 Error("Saved write recovery scope does not match.");
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 Error("Write recovery changes require the browser lock.");
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 Error("Write recovery storage did not retain the action.");
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 Error("Write recovery changed. Keep the current action pending.");
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 Error("Write recovery storage did not clear the action.");
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 Error("Write recovery storage did not clear the action.");
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 Error("The wallet returned an invalid transaction identity.");
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 Error("Write recovery changed before submission was recorded.");
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 Error("Write recovery changed before submission was recorded.");
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 Error("The adopted write has a different recovery scope.");
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 Error("Invalid write recovery nonce evidence.");
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 Error("An earlier wallet write is still unresolved. Check it before trying again.");
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 Error("An earlier wallet write is still unresolved. Check it before trying again.");
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
- const raw = store.getItem(settledKey);
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 Error("Invalid execution transaction identity.");
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 Error("Write recovery changed. Keep the current action pending.");
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 Error("Release a held write only after the user confirms they checked their wallet.");
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 Error("This write ran onchain. Keep it held until its result is known.");
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 Error("Write recovery changed. Keep the current action pending.");
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 Error("Write recovery storage did not release the action.");
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 Error("This wallet action is already open in another tab.");
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
- /** Whether `transaction` is the Safe's execTransaction of exactly the held batch: its MultiSend target, calldata, zero value and DELEGATECALL. */
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() === record.call.to &&
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
- return safeTransactionMatchesCall(proposal, {
1543
- ...record.call,
1544
- value: BigInt(record.call.value),
1545
- ...(heldBatch({ ...record, version: 1, id: "" })
1546
- ? { operation: 1 }
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 Error("The saved wallet write is not yet proven. Keep this action pending.");
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 Error("The saved Safe proposal is not proven expired. Keep this action pending.");
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)