@bananapus/nana-sdk-core 3.5.2 → 4.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 (292) hide show
  1. package/bin/wallet-check.mjs +489 -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 +52 -0
  11. package/dist/cjs/review/confirm.d.ts.map +1 -0
  12. package/dist/cjs/review/confirm.js +88 -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 +8 -7
  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.map +1 -1
  27. package/dist/cjs/review/heldWrite.js +5 -4
  28. package/dist/cjs/review/heldWrite.js.map +1 -1
  29. package/dist/cjs/review/index.d.ts +11 -0
  30. package/dist/cjs/review/index.d.ts.map +1 -1
  31. package/dist/cjs/review/index.js +24 -0
  32. package/dist/cjs/review/index.js.map +1 -1
  33. package/dist/cjs/review/intents.d.ts +10 -0
  34. package/dist/cjs/review/intents.d.ts.map +1 -1
  35. package/dist/cjs/review/intents.js +13 -0
  36. package/dist/cjs/review/intents.js.map +1 -1
  37. package/dist/cjs/review/lineError.d.ts +34 -0
  38. package/dist/cjs/review/lineError.d.ts.map +1 -0
  39. package/dist/cjs/review/lineError.js +42 -0
  40. package/dist/cjs/review/lineError.js.map +1 -0
  41. package/dist/cjs/review/messages.d.ts +15 -3
  42. package/dist/cjs/review/messages.d.ts.map +1 -1
  43. package/dist/cjs/review/messages.js +16 -4
  44. package/dist/cjs/review/messages.js.map +1 -1
  45. package/dist/cjs/review/model.d.ts +149 -0
  46. package/dist/cjs/review/model.d.ts.map +1 -0
  47. package/dist/cjs/review/model.js +750 -0
  48. package/dist/cjs/review/model.js.map +1 -0
  49. package/dist/cjs/review/plan.d.ts +63 -0
  50. package/dist/cjs/review/plan.d.ts.map +1 -0
  51. package/dist/cjs/review/plan.js +149 -0
  52. package/dist/cjs/review/plan.js.map +1 -0
  53. package/dist/cjs/review/react/index.d.ts +1 -0
  54. package/dist/cjs/review/react/index.d.ts.map +1 -1
  55. package/dist/cjs/review/react/index.js +1 -0
  56. package/dist/cjs/review/react/index.js.map +1 -1
  57. package/dist/cjs/review/react/useReviewedRun.d.ts +96 -0
  58. package/dist/cjs/review/react/useReviewedRun.d.ts.map +1 -0
  59. package/dist/cjs/review/react/useReviewedRun.js +261 -0
  60. package/dist/cjs/review/react/useReviewedRun.js.map +1 -0
  61. package/dist/cjs/review/receipt.d.ts +4 -1
  62. package/dist/cjs/review/receipt.d.ts.map +1 -1
  63. package/dist/cjs/review/receipt.js +7 -3
  64. package/dist/cjs/review/receipt.js.map +1 -1
  65. package/dist/cjs/review/relayr.d.ts +13 -4
  66. package/dist/cjs/review/relayr.d.ts.map +1 -1
  67. package/dist/cjs/review/relayr.js +51 -8
  68. package/dist/cjs/review/relayr.js.map +1 -1
  69. package/dist/cjs/review/relayrSend.d.ts +135 -0
  70. package/dist/cjs/review/relayrSend.d.ts.map +1 -0
  71. package/dist/cjs/review/relayrSend.js +943 -0
  72. package/dist/cjs/review/relayrSend.js.map +1 -0
  73. package/dist/cjs/review/reviewQueue.d.ts +10 -9
  74. package/dist/cjs/review/reviewQueue.d.ts.map +1 -1
  75. package/dist/cjs/review/reviewQueue.js +19 -29
  76. package/dist/cjs/review/reviewQueue.js.map +1 -1
  77. package/dist/cjs/review/reviewRequests.d.ts +86 -0
  78. package/dist/cjs/review/reviewRequests.d.ts.map +1 -0
  79. package/dist/cjs/review/reviewRequests.js +266 -0
  80. package/dist/cjs/review/reviewRequests.js.map +1 -0
  81. package/dist/cjs/review/safeRelayr.d.ts +3 -1
  82. package/dist/cjs/review/safeRelayr.d.ts.map +1 -1
  83. package/dist/cjs/review/safeRelayr.js +5 -1
  84. package/dist/cjs/review/safeRelayr.js.map +1 -1
  85. package/dist/cjs/review/safeSend.d.ts +69 -0
  86. package/dist/cjs/review/safeSend.d.ts.map +1 -0
  87. package/dist/cjs/review/safeSend.js +308 -0
  88. package/dist/cjs/review/safeSend.js.map +1 -0
  89. package/dist/cjs/review/send.d.ts +241 -0
  90. package/dist/cjs/review/send.d.ts.map +1 -0
  91. package/dist/cjs/review/send.js +1017 -0
  92. package/dist/cjs/review/send.js.map +1 -0
  93. package/dist/cjs/review/sequence.d.ts +77 -0
  94. package/dist/cjs/review/sequence.d.ts.map +1 -0
  95. package/dist/cjs/review/sequence.js +232 -0
  96. package/dist/cjs/review/sequence.js.map +1 -0
  97. package/dist/cjs/review/sign.d.ts +109 -0
  98. package/dist/cjs/review/sign.d.ts.map +1 -0
  99. package/dist/cjs/review/sign.js +374 -0
  100. package/dist/cjs/review/sign.js.map +1 -0
  101. package/dist/cjs/review/simulation.d.ts +41 -2
  102. package/dist/cjs/review/simulation.d.ts.map +1 -1
  103. package/dist/cjs/review/simulation.js +99 -29
  104. package/dist/cjs/review/simulation.js.map +1 -1
  105. package/dist/cjs/review/transaction-message.d.ts +13 -0
  106. package/dist/cjs/review/transaction-message.d.ts.map +1 -1
  107. package/dist/cjs/review/transaction-message.js +25 -0
  108. package/dist/cjs/review/transaction-message.js.map +1 -1
  109. package/dist/cjs/review/transactionReview.d.ts +27 -19
  110. package/dist/cjs/review/transactionReview.d.ts.map +1 -1
  111. package/dist/cjs/review/transactionReview.js +22 -63
  112. package/dist/cjs/review/transactionReview.js.map +1 -1
  113. package/dist/cjs/review/wallet.d.ts +82 -0
  114. package/dist/cjs/review/wallet.d.ts.map +1 -0
  115. package/dist/cjs/review/wallet.js +157 -0
  116. package/dist/cjs/review/wallet.js.map +1 -0
  117. package/dist/cjs/review/writeHold.d.ts +100 -12
  118. package/dist/cjs/review/writeHold.d.ts.map +1 -1
  119. package/dist/cjs/review/writeHold.js +61 -13
  120. package/dist/cjs/review/writeHold.js.map +1 -1
  121. package/dist/cjs/review/writeRecovery.d.ts +6 -1
  122. package/dist/cjs/review/writeRecovery.d.ts.map +1 -1
  123. package/dist/cjs/review/writeRecovery.js +108 -40
  124. package/dist/cjs/review/writeRecovery.js.map +1 -1
  125. package/dist/cjs/safeService.d.ts +27 -4
  126. package/dist/cjs/safeService.d.ts.map +1 -1
  127. package/dist/cjs/safeService.js +120 -3
  128. package/dist/cjs/safeService.js.map +1 -1
  129. package/dist/cjs/testing.d.ts +24 -0
  130. package/dist/cjs/testing.d.ts.map +1 -1
  131. package/dist/cjs/testing.js +26 -1
  132. package/dist/cjs/testing.js.map +1 -1
  133. package/dist/cjs/v6/defifa.d.ts.map +1 -1
  134. package/dist/cjs/v6/defifa.js +24 -23
  135. package/dist/cjs/v6/defifa.js.map +1 -1
  136. package/dist/cjs/v6/executionErrors.d.ts.map +1 -1
  137. package/dist/cjs/v6/executionErrors.js +3 -2
  138. package/dist/cjs/v6/executionErrors.js.map +1 -1
  139. package/dist/cjs/v6/pay.d.ts +25 -8
  140. package/dist/cjs/v6/pay.d.ts.map +1 -1
  141. package/dist/cjs/v6/pay.js +117 -23
  142. package/dist/cjs/v6/pay.js.map +1 -1
  143. package/dist/cjs/v6/suckers.d.ts +30 -0
  144. package/dist/cjs/v6/suckers.d.ts.map +1 -1
  145. package/dist/cjs/v6/suckers.js +69 -5
  146. package/dist/cjs/v6/suckers.js.map +1 -1
  147. package/dist/esm/actions/suckerPairs.d.ts +5 -3
  148. package/dist/esm/actions/suckerPairs.d.ts.map +1 -1
  149. package/dist/esm/actions/suckerPairs.js +7 -27
  150. package/dist/esm/actions/suckerPairs.js.map +1 -1
  151. package/dist/esm/pause.d.ts +2 -0
  152. package/dist/esm/pause.d.ts.map +1 -1
  153. package/dist/esm/pause.js +16 -0
  154. package/dist/esm/pause.js.map +1 -1
  155. package/dist/esm/review/confirm.d.ts +52 -0
  156. package/dist/esm/review/confirm.d.ts.map +1 -0
  157. package/dist/esm/review/confirm.js +83 -0
  158. package/dist/esm/review/confirm.js.map +1 -0
  159. package/dist/esm/review/contractWrite.d.ts +5 -3
  160. package/dist/esm/review/contractWrite.d.ts.map +1 -1
  161. package/dist/esm/review/contractWrite.js +8 -7
  162. package/dist/esm/review/contractWrite.js.map +1 -1
  163. package/dist/esm/review/decode.d.ts +19 -1
  164. package/dist/esm/review/decode.d.ts.map +1 -1
  165. package/dist/esm/review/decode.js +29 -14
  166. package/dist/esm/review/decode.js.map +1 -1
  167. package/dist/esm/review/decodeCall.d.ts +21 -0
  168. package/dist/esm/review/decodeCall.d.ts.map +1 -0
  169. package/dist/esm/review/decodeCall.js +180 -0
  170. package/dist/esm/review/decodeCall.js.map +1 -0
  171. package/dist/esm/review/heldWrite.d.ts.map +1 -1
  172. package/dist/esm/review/heldWrite.js +5 -4
  173. package/dist/esm/review/heldWrite.js.map +1 -1
  174. package/dist/esm/review/index.d.ts +11 -0
  175. package/dist/esm/review/index.d.ts.map +1 -1
  176. package/dist/esm/review/index.js +11 -0
  177. package/dist/esm/review/index.js.map +1 -1
  178. package/dist/esm/review/intents.d.ts +10 -0
  179. package/dist/esm/review/intents.d.ts.map +1 -1
  180. package/dist/esm/review/intents.js +12 -0
  181. package/dist/esm/review/intents.js.map +1 -1
  182. package/dist/esm/review/lineError.d.ts +34 -0
  183. package/dist/esm/review/lineError.d.ts.map +1 -0
  184. package/dist/esm/review/lineError.js +36 -0
  185. package/dist/esm/review/lineError.js.map +1 -0
  186. package/dist/esm/review/messages.d.ts +15 -3
  187. package/dist/esm/review/messages.d.ts.map +1 -1
  188. package/dist/esm/review/messages.js +15 -3
  189. package/dist/esm/review/messages.js.map +1 -1
  190. package/dist/esm/review/model.d.ts +149 -0
  191. package/dist/esm/review/model.d.ts.map +1 -0
  192. package/dist/esm/review/model.js +746 -0
  193. package/dist/esm/review/model.js.map +1 -0
  194. package/dist/esm/review/plan.d.ts +63 -0
  195. package/dist/esm/review/plan.d.ts.map +1 -0
  196. package/dist/esm/review/plan.js +141 -0
  197. package/dist/esm/review/plan.js.map +1 -0
  198. package/dist/esm/review/react/index.d.ts +1 -0
  199. package/dist/esm/review/react/index.d.ts.map +1 -1
  200. package/dist/esm/review/react/index.js +1 -0
  201. package/dist/esm/review/react/index.js.map +1 -1
  202. package/dist/esm/review/react/useReviewedRun.d.ts +96 -0
  203. package/dist/esm/review/react/useReviewedRun.d.ts.map +1 -0
  204. package/dist/esm/review/react/useReviewedRun.js +257 -0
  205. package/dist/esm/review/react/useReviewedRun.js.map +1 -0
  206. package/dist/esm/review/receipt.d.ts +4 -1
  207. package/dist/esm/review/receipt.d.ts.map +1 -1
  208. package/dist/esm/review/receipt.js +6 -2
  209. package/dist/esm/review/receipt.js.map +1 -1
  210. package/dist/esm/review/relayr.d.ts +13 -4
  211. package/dist/esm/review/relayr.d.ts.map +1 -1
  212. package/dist/esm/review/relayr.js +50 -8
  213. package/dist/esm/review/relayr.js.map +1 -1
  214. package/dist/esm/review/relayrSend.d.ts +135 -0
  215. package/dist/esm/review/relayrSend.d.ts.map +1 -0
  216. package/dist/esm/review/relayrSend.js +934 -0
  217. package/dist/esm/review/relayrSend.js.map +1 -0
  218. package/dist/esm/review/reviewQueue.d.ts +10 -9
  219. package/dist/esm/review/reviewQueue.d.ts.map +1 -1
  220. package/dist/esm/review/reviewQueue.js +17 -26
  221. package/dist/esm/review/reviewQueue.js.map +1 -1
  222. package/dist/esm/review/reviewRequests.d.ts +86 -0
  223. package/dist/esm/review/reviewRequests.d.ts.map +1 -0
  224. package/dist/esm/review/reviewRequests.js +263 -0
  225. package/dist/esm/review/reviewRequests.js.map +1 -0
  226. package/dist/esm/review/safeRelayr.d.ts +3 -1
  227. package/dist/esm/review/safeRelayr.d.ts.map +1 -1
  228. package/dist/esm/review/safeRelayr.js +5 -1
  229. package/dist/esm/review/safeRelayr.js.map +1 -1
  230. package/dist/esm/review/safeSend.d.ts +69 -0
  231. package/dist/esm/review/safeSend.d.ts.map +1 -0
  232. package/dist/esm/review/safeSend.js +303 -0
  233. package/dist/esm/review/safeSend.js.map +1 -0
  234. package/dist/esm/review/send.d.ts +241 -0
  235. package/dist/esm/review/send.d.ts.map +1 -0
  236. package/dist/esm/review/send.js +1011 -0
  237. package/dist/esm/review/send.js.map +1 -0
  238. package/dist/esm/review/sequence.d.ts +77 -0
  239. package/dist/esm/review/sequence.d.ts.map +1 -0
  240. package/dist/esm/review/sequence.js +223 -0
  241. package/dist/esm/review/sequence.js.map +1 -0
  242. package/dist/esm/review/sign.d.ts +109 -0
  243. package/dist/esm/review/sign.d.ts.map +1 -0
  244. package/dist/esm/review/sign.js +368 -0
  245. package/dist/esm/review/sign.js.map +1 -0
  246. package/dist/esm/review/simulation.d.ts +41 -2
  247. package/dist/esm/review/simulation.d.ts.map +1 -1
  248. package/dist/esm/review/simulation.js +95 -29
  249. package/dist/esm/review/simulation.js.map +1 -1
  250. package/dist/esm/review/transaction-message.d.ts +13 -0
  251. package/dist/esm/review/transaction-message.d.ts.map +1 -1
  252. package/dist/esm/review/transaction-message.js +23 -0
  253. package/dist/esm/review/transaction-message.js.map +1 -1
  254. package/dist/esm/review/transactionReview.d.ts +27 -19
  255. package/dist/esm/review/transactionReview.d.ts.map +1 -1
  256. package/dist/esm/review/transactionReview.js +19 -56
  257. package/dist/esm/review/transactionReview.js.map +1 -1
  258. package/dist/esm/review/wallet.d.ts +82 -0
  259. package/dist/esm/review/wallet.d.ts.map +1 -0
  260. package/dist/esm/review/wallet.js +150 -0
  261. package/dist/esm/review/wallet.js.map +1 -0
  262. package/dist/esm/review/writeHold.d.ts +100 -12
  263. package/dist/esm/review/writeHold.d.ts.map +1 -1
  264. package/dist/esm/review/writeHold.js +59 -13
  265. package/dist/esm/review/writeHold.js.map +1 -1
  266. package/dist/esm/review/writeRecovery.d.ts +6 -1
  267. package/dist/esm/review/writeRecovery.d.ts.map +1 -1
  268. package/dist/esm/review/writeRecovery.js +111 -43
  269. package/dist/esm/review/writeRecovery.js.map +1 -1
  270. package/dist/esm/safeService.d.ts +27 -4
  271. package/dist/esm/safeService.d.ts.map +1 -1
  272. package/dist/esm/safeService.js +119 -4
  273. package/dist/esm/safeService.js.map +1 -1
  274. package/dist/esm/testing.d.ts +24 -0
  275. package/dist/esm/testing.d.ts.map +1 -1
  276. package/dist/esm/testing.js +23 -1
  277. package/dist/esm/testing.js.map +1 -1
  278. package/dist/esm/v6/defifa.d.ts.map +1 -1
  279. package/dist/esm/v6/defifa.js +24 -23
  280. package/dist/esm/v6/defifa.js.map +1 -1
  281. package/dist/esm/v6/executionErrors.d.ts.map +1 -1
  282. package/dist/esm/v6/executionErrors.js +3 -2
  283. package/dist/esm/v6/executionErrors.js.map +1 -1
  284. package/dist/esm/v6/pay.d.ts +25 -8
  285. package/dist/esm/v6/pay.d.ts.map +1 -1
  286. package/dist/esm/v6/pay.js +115 -22
  287. package/dist/esm/v6/pay.js.map +1 -1
  288. package/dist/esm/v6/suckers.d.ts +30 -0
  289. package/dist/esm/v6/suckers.d.ts.map +1 -1
  290. package/dist/esm/v6/suckers.js +67 -5
  291. package/dist/esm/v6/suckers.js.map +1 -1
  292. package/package.json +11 -2
@@ -0,0 +1,750 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildReviewModel = buildReviewModel;
4
+ exports.enrichReviewModel = enrichReviewModel;
5
+ const viem_1 = require("viem");
6
+ const constants_js_1 = require("../constants.js");
7
+ const pureConstants_js_1 = require("../pureConstants.js");
8
+ const decode_js_1 = require("./decode.js");
9
+ const transactionReview_js_1 = require("./transactionReview.js");
10
+ const SAFE_GAS_NONZERO = "If this call fails, the Safe still executes and uses this nonce.";
11
+ const DELEGATECALL = "DELEGATECALL: runs foreign code with the Safe's own storage and funds";
12
+ const ABI_UNAVAILABLE = "This call’s ABI is not available in this flow. Check the complete calldata in Raw before continuing.";
13
+ const UNKNOWN_CONTRACT = "This destination is not a contract the app recognizes. Check the address before continuing.";
14
+ const UNLIMITED_APPROVAL = "Unlimited approval: the spender can move all of this token you hold, now and later.";
15
+ const OWNER_ACTION = "This changes who or what controls this contract or project.";
16
+ const PERMISSION_GRANT = "This lets another address act for you.";
17
+ const DECIMALS_UNKNOWN = "The token's decimals could not be read, so its amount shows in base units.";
18
+ const UNREADABLE = "Part of this request can't be read here. Check it in your wallet before continuing.";
19
+ const POSSIBLE_TOKEN_ID = "ERC-721 NFTs use this same function, so this number may be an NFT's token ID rather than an amount.";
20
+ /** Address arguments that give the address a part, by argument name. */
21
+ const ROLE_OF = {
22
+ spender: "spender",
23
+ recipient: "recipient",
24
+ beneficiary: "beneficiary",
25
+ owner: "owner",
26
+ newOwner: "owner",
27
+ operator: "operator",
28
+ };
29
+ /**
30
+ * ERC-20, ERC-2612 and Permit2 approvals and transfers by signature.
31
+ * ERC-721 shares `approve(address,uint256)` and
32
+ * `transferFrom(address,address,uint256)`; where the ABI names the last
33
+ * argument `tokenId`, it is a token ID, not an amount.
34
+ */
35
+ const TOKEN_CALLS = {
36
+ "approve(address,uint256)": {
37
+ spender: 0,
38
+ amount: 1,
39
+ sharedWithErc721: true,
40
+ },
41
+ "increaseAllowance(address,uint256)": { spender: 0, amount: 1 },
42
+ "transfer(address,uint256)": { recipient: 0, amount: 1 },
43
+ "transferFrom(address,address,uint256)": {
44
+ recipient: 1,
45
+ amount: 2,
46
+ sharedWithErc721: true,
47
+ },
48
+ "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": {
49
+ spender: 1,
50
+ amount: 2,
51
+ },
52
+ "approve(address,address,uint160,uint48)": {
53
+ token: 0,
54
+ spender: 1,
55
+ amount: 2,
56
+ },
57
+ };
58
+ /** The token call `fn` is, with no amount for an ERC-721 token ID; null for any other function. */
59
+ function tokenCallOf(fn) {
60
+ const shape = TOKEN_CALLS[`${fn.name}(${fn.inputs.map((input) => input.type).join(",")})`];
61
+ if (!shape)
62
+ return null;
63
+ return shape.amount !== undefined &&
64
+ fn.inputs[shape.amount].name === "tokenId"
65
+ ? { ...shape, amount: undefined, tokenId: shape.amount }
66
+ : shape;
67
+ }
68
+ /**
69
+ * Calls that change a contract's owner, a Safe's owners or threshold, what
70
+ * else can act as the Safe, or a project's controller or terminals.
71
+ */
72
+ const OWNER_ACTIONS = new Set([
73
+ "transferOwnership",
74
+ "renounceOwnership",
75
+ "addOwnerWithThreshold",
76
+ "removeOwner",
77
+ "swapOwner",
78
+ "changeThreshold",
79
+ "enableModule",
80
+ "setGuard",
81
+ "setFallbackHandler",
82
+ "transferOwnershipToProject",
83
+ "setControllerOf",
84
+ "setTerminalsOf",
85
+ ]);
86
+ /** MultiSend's `transactions` argument is where its decoded calls show. */
87
+ function nestsCallsInArgument(fn) {
88
+ return (fn?.name === "multiSend" &&
89
+ fn.inputs.some((input) => input.name === "transactions"));
90
+ }
91
+ function isOne(value) {
92
+ return value === 1 || value === 1n;
93
+ }
94
+ /** A decoder's view of one argument, or null for {@link readableValue}'s text alone. */
95
+ function specialArgument(call, fn, inputName, value) {
96
+ const steps = (found) => found ? { steps: found } : null;
97
+ switch (fn.name) {
98
+ case "modifyLiquidities": {
99
+ if (inputName !== "unlockData")
100
+ return null;
101
+ const v4Plan = (0, decode_js_1.describeV4UnlockData)(value);
102
+ return v4Plan ? { v4Plan } : null;
103
+ }
104
+ case "pay":
105
+ case "addToBalanceOf":
106
+ return inputName === "metadata"
107
+ ? steps((0, decode_js_1.describeJBHookMetadata)("pay", value))
108
+ : null;
109
+ case "cashOutTokensOf":
110
+ return inputName === "metadata"
111
+ ? steps((0, decode_js_1.describeJBHookMetadata)("cashOut", value))
112
+ : null;
113
+ case "claim":
114
+ return steps((0, decode_js_1.describeSuckerClaim)(call.chainId, value));
115
+ case "execTransaction":
116
+ if (inputName === "data") {
117
+ return steps((0, decode_js_1.describeSafeInnerCall)(call.chainId, call.args?.[0], value));
118
+ }
119
+ if (inputName !== "operation")
120
+ return null;
121
+ return {
122
+ text: isOne(value)
123
+ ? `1 — ${DELEGATECALL}`
124
+ : value === 0 || value === 0n
125
+ ? "0 — CALL"
126
+ : String(value),
127
+ };
128
+ case "createProxyWithNonce":
129
+ return inputName === "initializer"
130
+ ? steps((0, decode_js_1.describeSafeInitializer)(call.chainId, value))
131
+ : null;
132
+ case "setPermissionsFor":
133
+ return inputName === "permissionsData"
134
+ ? steps((0, decode_js_1.describePermissionsData)(call.chainId, value))
135
+ : null;
136
+ case "setSplitGroupsOf":
137
+ return inputName === "splitGroups"
138
+ ? steps((0, decode_js_1.describeSplitGroups)(call.chainId, value))
139
+ : null;
140
+ }
141
+ return inputName === "transactions" &&
142
+ nestsCallsInArgument(fn) &&
143
+ call.calls?.length
144
+ ? { nested: call.calls.map(reviewCall) }
145
+ : null;
146
+ }
147
+ function reviewValue(parameter, value, chainId) {
148
+ return {
149
+ name: parameter.name ?? "",
150
+ type: parameter.type,
151
+ text: (0, decode_js_1.readableValue)(parameter.type, value, chainId),
152
+ children: reviewChildren(parameter, value, chainId),
153
+ };
154
+ }
155
+ function reviewChildren(parameter, value, chainId) {
156
+ const array = /^(.*)\[\d*\]$/u.exec(parameter.type);
157
+ if (array && Array.isArray(value)) {
158
+ return value.map((item, index) => reviewValue({ ...parameter, name: `[${index}]`, type: array[1] }, item, chainId));
159
+ }
160
+ if ("components" in parameter && Array.isArray(parameter.components)) {
161
+ return parameter.components.map((component, index) => reviewValue(component, (0, decode_js_1.namedValue)(value, component.name ?? "", index), chainId));
162
+ }
163
+ return null;
164
+ }
165
+ /** Every address argument, a tuple's components and an array's elements included, under its own name. */
166
+ function addressArguments(parameter, value) {
167
+ const array = /^(.*)\[\d*\]$/u.exec(parameter.type);
168
+ if (array && Array.isArray(value)) {
169
+ const item = { ...parameter, type: array[1] };
170
+ return value.flatMap((element) => addressArguments(item, element));
171
+ }
172
+ if ("components" in parameter && Array.isArray(parameter.components)) {
173
+ return parameter.components.flatMap((component, index) => addressArguments(component, (0, decode_js_1.namedValue)(value, component.name ?? "", index)));
174
+ }
175
+ return parameter.type === "address" ? [[parameter.name ?? "", value]] : [];
176
+ }
177
+ function reviewRoles(call, fn) {
178
+ const roles = [];
179
+ const seen = new Set();
180
+ const add = (role, address) => {
181
+ if (!role || typeof address !== "string")
182
+ return;
183
+ const key = `${role}:${address.toLowerCase()}`;
184
+ if (seen.has(key))
185
+ return;
186
+ seen.add(key);
187
+ roles.push({
188
+ role,
189
+ address: address,
190
+ name: (0, decode_js_1.knownAddressName)(call.chainId, address),
191
+ });
192
+ };
193
+ const tokenCall = tokenCallOf(fn);
194
+ if (tokenCall?.spender !== undefined) {
195
+ add("spender", call.args?.[tokenCall.spender]);
196
+ }
197
+ if (tokenCall?.recipient !== undefined) {
198
+ add("recipient", call.args?.[tokenCall.recipient]);
199
+ }
200
+ fn.inputs.forEach((input, index) => {
201
+ for (const [name, address] of addressArguments(input, call.args?.[index])) {
202
+ add(ROLE_OF[name], address);
203
+ }
204
+ });
205
+ return roles;
206
+ }
207
+ /** Native ETH and USDC need no read. */
208
+ function knownToken(chainId, token) {
209
+ if (token === "native")
210
+ return { decimals: 18, symbol: "ETH" };
211
+ const usdc = pureConstants_js_1.USDC_ADDRESSES[chainId];
212
+ return usdc?.toLowerCase() === token.toLowerCase()
213
+ ? { decimals: 6, symbol: "USDC" }
214
+ : { decimals: null, symbol: null };
215
+ }
216
+ function tokenAmount(chainId, address, amount) {
217
+ if (typeof address !== "string" || typeof amount !== "bigint")
218
+ return null;
219
+ const token = address.toLowerCase() === constants_js_1.NATIVE_TOKEN.toLowerCase()
220
+ ? "native"
221
+ : address;
222
+ return { token, amount, ...knownToken(chainId, token) };
223
+ }
224
+ /**
225
+ * What a terminal payment sends, or what an ERC-20 or Permit2 approval or
226
+ * transfer moves. A native payment sends the call's value, whatever its
227
+ * `amount` argument says.
228
+ */
229
+ function tokenAmountOf(call, fn) {
230
+ const args = call.args ?? [];
231
+ if (fn.name === "pay" || fn.name === "addToBalanceOf") {
232
+ const token = fn.inputs.findIndex((input) => input.name === "token");
233
+ const amount = fn.inputs.findIndex((input) => input.name === "amount");
234
+ if (token < 0 || amount < 0)
235
+ return null;
236
+ const native = typeof args[token] === "string" &&
237
+ args[token].toLowerCase() === constants_js_1.NATIVE_TOKEN.toLowerCase();
238
+ return tokenAmount(call.chainId, args[token], native ? (call.value ?? 0n) : args[amount]);
239
+ }
240
+ const tokenCall = tokenCallOf(fn);
241
+ if (tokenCall?.amount === undefined)
242
+ return null;
243
+ return tokenAmount(call.chainId, tokenCall.token === undefined ? call.to : args[tokenCall.token], args[tokenCall.amount]);
244
+ }
245
+ /** An approval of the type's largest amount, which never runs down. */
246
+ function isUnlimitedApproval(call, fn) {
247
+ const tokenCall = tokenCallOf(fn);
248
+ if (tokenCall?.spender === undefined || tokenCall.amount === undefined) {
249
+ return false;
250
+ }
251
+ const bits = BigInt(fn.inputs[tokenCall.amount].type.slice(4) || 256);
252
+ return call.args?.[tokenCall.amount] === (1n << bits) - 1n;
253
+ }
254
+ /** An address the app does not name, other than zero, which grants nothing. */
255
+ function isUnnamed(chainId, address) {
256
+ return (typeof address === "string" &&
257
+ !/^0x0{40}$/iu.test(address) &&
258
+ (0, decode_js_1.knownAddressName)(chainId, address) === null);
259
+ }
260
+ /**
261
+ * An operator grant, or an approval, permit or approval for all that lets an
262
+ * address the app does not name move the signer's tokens. A zero ERC-20
263
+ * approval revokes and grants nothing, but only once the token is known to
264
+ * be ERC-20: to ERC-721, zero is a token ID. {@link enrichReviewModel}
265
+ * clears the grant when it confirms the token.
266
+ */
267
+ function grantsPermission(call, fn) {
268
+ if (fn.name === "setPermissionsFor")
269
+ return true;
270
+ if (fn.name === "setApprovalForAll") {
271
+ return call.args?.[1] === true && isUnnamed(call.chainId, call.args[0]);
272
+ }
273
+ const tokenCall = tokenCallOf(fn);
274
+ if (tokenCall?.spender === undefined)
275
+ return false;
276
+ return (isUnnamed(call.chainId, call.args?.[tokenCall.spender]) &&
277
+ (tokenCall.amount === undefined ||
278
+ call.args?.[tokenCall.amount] !== 0n ||
279
+ mayBeTokenId(call, fn)));
280
+ }
281
+ /** An ERC-20 reading of a call ERC-721 shares, to a contract the SDK does not know. */
282
+ function mayBeTokenId(call, fn) {
283
+ const tokenCall = tokenCallOf(fn);
284
+ return (tokenCall?.sharedWithErc721 === true &&
285
+ tokenCall.amount !== undefined &&
286
+ (0, decode_js_1.knownAddressName)(call.chainId, call.to) === null);
287
+ }
288
+ /** The NFT a call names where its ABI calls the argument a token ID. */
289
+ function nftOf(call, fn) {
290
+ const tokenCall = tokenCallOf(fn);
291
+ const tokenId = tokenCall?.tokenId === undefined ? null : call.args?.[tokenCall.tokenId];
292
+ return typeof tokenId === "bigint" ? { token: call.to, tokenId } : null;
293
+ }
294
+ function reviewArguments(call, fn) {
295
+ const values = call.args ?? [];
296
+ const plain = fn.inputs.map((input, index) => ({
297
+ ...reviewValue(input, values[index], call.chainId),
298
+ steps: null,
299
+ v4Plan: null,
300
+ nested: null,
301
+ }));
302
+ const plan = fn.name === "execute"
303
+ ? (0, decode_js_1.describeUniversalRouterExecute)(call.chainId, values)
304
+ : null;
305
+ if (plan) {
306
+ plain[0].steps = plan;
307
+ const deadline = values[2];
308
+ if (plain[2] &&
309
+ (typeof deadline === "bigint" || typeof deadline === "number")) {
310
+ plain[2].text = (0, decode_js_1.unixTime)(deadline);
311
+ }
312
+ return plain;
313
+ }
314
+ return plain.map((argument, index) => ({
315
+ ...argument,
316
+ ...specialArgument(call, fn, argument.name, values[index]),
317
+ }));
318
+ }
319
+ function reviewCall(call) {
320
+ const fn = (0, decode_js_1.functionFromCall)(call);
321
+ const args = fn ? reviewArguments(call, fn) : null;
322
+ const batched = call.calls?.length && !nestsCallsInArgument(fn) ? call.calls : null;
323
+ const warnings = [];
324
+ if (call.safeTxGas !== undefined && call.safeTxGas !== 0n) {
325
+ warnings.push({ code: "safe-gas-nonzero", text: SAFE_GAS_NONZERO });
326
+ }
327
+ if (!fn) {
328
+ warnings.push({ code: "abi-unavailable", text: ABI_UNAVAILABLE });
329
+ }
330
+ else if (fn.name === "execTransaction") {
331
+ const operation = fn.inputs.findIndex((input) => input.name === "operation");
332
+ if (isOne(call.args?.[operation])) {
333
+ warnings.push({ code: "delegatecall", text: DELEGATECALL });
334
+ }
335
+ }
336
+ const contractName = call.contractName ?? (0, decode_js_1.knownAddressName)(call.chainId, call.to);
337
+ if (contractName === null && call.data.length >= 10) {
338
+ warnings.push({ code: "unknown-contract", text: UNKNOWN_CONTRACT });
339
+ }
340
+ if (fn && isUnlimitedApproval(call, fn)) {
341
+ warnings.push({ code: "unlimited-approval", text: UNLIMITED_APPROVAL });
342
+ }
343
+ if (fn && OWNER_ACTIONS.has(fn.name)) {
344
+ warnings.push({ code: "owner-action", text: OWNER_ACTION });
345
+ }
346
+ if (fn && grantsPermission(call, fn)) {
347
+ warnings.push({ code: "permission-grant", text: PERMISSION_GRANT });
348
+ }
349
+ if (fn && mayBeTokenId(call, fn)) {
350
+ warnings.push({ code: "possible-token-id", text: POSSIBLE_TOKEN_ID });
351
+ }
352
+ const amount = fn ? tokenAmountOf(call, fn) : null;
353
+ const tokenAmounts = amount ? [amount] : [];
354
+ return {
355
+ chainId: call.chainId,
356
+ from: call.from ?? null,
357
+ to: call.to,
358
+ contractName,
359
+ value: call.value ?? 0n,
360
+ valueText: (0, decode_js_1.nativeValue)(call.value),
361
+ gas: call.gas ?? null,
362
+ safeTxGas: call.safeTxGas ?? null,
363
+ label: call.label ?? null,
364
+ functionName: fn?.name ?? null,
365
+ data: call.data,
366
+ selector: call.data.slice(0, 10),
367
+ byteLength: Math.max(0, (call.data.length - 2) / 2),
368
+ args,
369
+ calls: batched ? batched.map(reviewCall) : null,
370
+ roles: fn ? reviewRoles(call, fn) : [],
371
+ tokenAmounts,
372
+ nft: fn ? nftOf(call, fn) : null,
373
+ warnings: withDecimalsWarning(warnings, tokenAmounts),
374
+ };
375
+ }
376
+ /**
377
+ * JSON-ready data with object keys sorted at every depth, so equal data
378
+ * encodes alike, and a bigint tagged as `{ $bigint }` so it never encodes like
379
+ * a string. A key that starts with `$` gains another, so no input can forge
380
+ * the tag. Anything JSON would not keep exactly (a boxed primitive, a class
381
+ * instance, a non-finite number) throws rather than bind as something else.
382
+ */
383
+ function canonical(value) {
384
+ if (typeof value === "bigint")
385
+ return { $bigint: value.toString() };
386
+ if (typeof value === "number" && !Number.isFinite(value)) {
387
+ throw new Error(`The review cannot bind the number ${value}.`);
388
+ }
389
+ if (Array.isArray(value))
390
+ return value.map(canonical);
391
+ if (value && typeof value === "object") {
392
+ const prototype = Object.getPrototypeOf(value);
393
+ if (prototype !== Object.prototype && prototype !== null) {
394
+ throw new Error("The review can only bind plain data.");
395
+ }
396
+ return Object.fromEntries(Object.keys(value)
397
+ .sort()
398
+ .map((key) => [
399
+ key.startsWith("$") ? `$${key}` : key,
400
+ canonical(value[key]),
401
+ ]));
402
+ }
403
+ return value;
404
+ }
405
+ /** What a call sends, and the decoded calls the review shows inside it. */
406
+ function bindingCall(call) {
407
+ return {
408
+ chainId: call.chainId,
409
+ from: call.from ?? null,
410
+ to: call.to,
411
+ value: call.value ?? 0n,
412
+ gas: call.gas ?? null,
413
+ safeTxGas: call.safeTxGas ?? null,
414
+ data: call.data,
415
+ calls: call.calls?.length ? call.calls.map(bindingCall) : null,
416
+ // Bound only when set, so a model without it keeps its id.
417
+ ...(call.adoptIgnoringArgs
418
+ ? { adoptIgnoringArgs: [...call.adoptIgnoringArgs] }
419
+ : {}),
420
+ };
421
+ }
422
+ /**
423
+ * The plain-data review of a request: what every client's review dialog
424
+ * shows, decoded once. `context` is display only and never feeds `calls`.
425
+ * It never throws: a request it can't read or bind exactly gets a model with
426
+ * an `unreadable` warning, showing what it can read, and an id that matches
427
+ * no other model. Core's own prompts refuse such a model: it confirms nothing.
428
+ */
429
+ function buildReviewModel(request) {
430
+ try {
431
+ return readModel(request);
432
+ }
433
+ catch {
434
+ try {
435
+ return unreadableModel(request);
436
+ }
437
+ catch {
438
+ // Even its parts can't be read: the warning alone.
439
+ return unreadableModel(null);
440
+ }
441
+ }
442
+ }
443
+ function readModel(request) {
444
+ // Copies, so the request changing after review never changes what the model shows.
445
+ const signatures = (request.signatures ?? []).map(reviewSignature);
446
+ const signsMessage = request.authorization?.kind ===
447
+ "message";
448
+ const kind = request.kind === "authorization"
449
+ ? signsMessage
450
+ ? "message"
451
+ : "authorization"
452
+ : !request.calls.length && signatures.length
453
+ ? signatures.every((signature) => signature.kind === "message")
454
+ ? "message"
455
+ : "authorization"
456
+ : "transaction";
457
+ const context = (request.context ?? []).map((row) => ({
458
+ ...row,
459
+ ...(row.lines ? { lines: [...row.lines] } : {}),
460
+ }));
461
+ const authorization = structuredClone(request.authorization ?? null);
462
+ const messages = signatures.filter((signature) => signature.message !== null);
463
+ const message = messages.length === 1 ? messages[0].message : null;
464
+ const binding = {
465
+ kind,
466
+ calls: request.calls.map(bindingCall),
467
+ authorization,
468
+ message,
469
+ context,
470
+ ...(signatures.length
471
+ ? {
472
+ signatures: signatures.map((signature, index) => ({
473
+ kind: signature.kind,
474
+ chainId: signature.chainId,
475
+ typedData: signature.typedData,
476
+ message: signature.message,
477
+ calls: (request.signatures[index].calls ?? []).map(bindingCall),
478
+ })),
479
+ }
480
+ : {}),
481
+ };
482
+ return {
483
+ id: (0, viem_1.keccak256)((0, viem_1.toHex)(JSON.stringify(canonical(binding)))),
484
+ kind,
485
+ title: request.title ?? null,
486
+ description: (0, decode_js_1.reviewDescription)(request),
487
+ confirmLabel: request.confirmLabel ?? null,
488
+ context,
489
+ calls: request.calls.map(reviewCall),
490
+ authorization,
491
+ message,
492
+ signatures,
493
+ rawJson: (0, transactionReview_js_1.transactionReviewJson)(request),
494
+ warnings: [],
495
+ };
496
+ }
497
+ /** `read()`, or `fallback` when it throws. */
498
+ function attempt(read, fallback) {
499
+ try {
500
+ return read();
501
+ }
502
+ catch {
503
+ return fallback;
504
+ }
505
+ }
506
+ const text = (value) => typeof value === "string" ? value : "";
507
+ /** The parts of a request {@link readModel} could not take whole, each read on its own. */
508
+ function unreadableModel(input) {
509
+ const request = (input && typeof input === "object" ? input : {});
510
+ const list = (value) => Array.isArray(value) ? value : [];
511
+ const warning = { code: "unreadable", text: UNREADABLE };
512
+ return {
513
+ id: (0, viem_1.keccak256)((0, viem_1.toHex)(globalThis.crypto.randomUUID())),
514
+ kind: request.kind === "authorization" ? "authorization" : "transaction",
515
+ title: typeof request.title === "string" ? request.title : null,
516
+ description: attempt(() => (0, decode_js_1.reviewDescription)(request), ""),
517
+ confirmLabel: typeof request.confirmLabel === "string" ? request.confirmLabel : null,
518
+ context: list(request.context).map((row) => {
519
+ const item = (row ?? {});
520
+ return {
521
+ label: text(item.label),
522
+ value: text(item.value),
523
+ ...(Array.isArray(item.lines) ? { lines: item.lines.map(text) } : {}),
524
+ ...(typeof item.note === "string" ? { note: item.note } : {}),
525
+ ...(item.strong === true ? { strong: true } : {}),
526
+ ...(item.mono === true ? { mono: true } : {}),
527
+ };
528
+ }),
529
+ calls: list(request.calls).map((call) => attempt(() => reviewCall(call), null) ?? rawCall(call)),
530
+ authorization: attempt(() => structuredClone(request.authorization ?? null), null),
531
+ message: null,
532
+ signatures: list(request.signatures).flatMap((signature) => attempt(() => [reviewSignature(signature)], [])),
533
+ rawJson: attempt(() => (0, transactionReview_js_1.transactionReviewJson)(request), ""),
534
+ warnings: [warning],
535
+ };
536
+ }
537
+ /** A call {@link reviewCall} could not read: its destination, value and bytes, as far as they read. */
538
+ function rawCall(input) {
539
+ const call = (input ?? {});
540
+ const data = typeof call.data === "string" && /^0x[\da-f]*$/iu.test(call.data)
541
+ ? call.data
542
+ : "0x";
543
+ const value = typeof call.value === "bigint" ? call.value : 0n;
544
+ return {
545
+ chainId: typeof call.chainId === "number" ? call.chainId : 0,
546
+ from: null,
547
+ to: text(call.to),
548
+ contractName: null,
549
+ value,
550
+ valueText: (0, decode_js_1.nativeValue)(value),
551
+ gas: null,
552
+ safeTxGas: null,
553
+ label: typeof call.label === "string" ? call.label : null,
554
+ functionName: null,
555
+ data,
556
+ selector: data.slice(0, 10),
557
+ byteLength: (data.length - 2) / 2,
558
+ args: null,
559
+ calls: null,
560
+ roles: [],
561
+ tokenAmounts: [],
562
+ nft: null,
563
+ warnings: [{ code: "unreadable", text: UNREADABLE }],
564
+ };
565
+ }
566
+ function reviewSignature(signature) {
567
+ return {
568
+ kind: signature.kind,
569
+ chainId: signature.chainId,
570
+ typedData: structuredClone(signature.typedData ?? null),
571
+ message: signature.message ?? null,
572
+ calls: (signature.calls ?? []).map(reviewCall),
573
+ steps: structuredClone([...(signature.steps ?? [])]),
574
+ };
575
+ }
576
+ /** `warnings` with one `decimals-unknown` last when any amount's decimals are unknown. */
577
+ function withDecimalsWarning(warnings, tokenAmounts) {
578
+ const kept = warnings.filter((warning) => warning.code !== "decimals-unknown");
579
+ return tokenAmounts.some((amount) => amount.decimals === null)
580
+ ? [...kept, { code: "decimals-unknown", text: DECIMALS_UNKNOWN }]
581
+ : kept;
582
+ }
583
+ const ERC165_ABI = [
584
+ {
585
+ type: "function",
586
+ name: "supportsInterface",
587
+ stateMutability: "view",
588
+ inputs: [{ name: "interfaceId", type: "bytes4" }],
589
+ outputs: [{ type: "bool" }],
590
+ },
591
+ ];
592
+ const ERC721_INTERFACE_ID = "0x80ac58cd";
593
+ /**
594
+ * A token's decimals and symbol, and when `probe` is set whether it is
595
+ * ERC-721. Each is null when its read fails or returns something else.
596
+ */
597
+ async function readToken(client, token, probe) {
598
+ if (!client)
599
+ return { decimals: null, symbol: null, erc721: null };
600
+ const read = async (request) => {
601
+ try {
602
+ return await request();
603
+ }
604
+ catch {
605
+ return null;
606
+ }
607
+ };
608
+ const [decimals, symbol, erc721] = await Promise.all([
609
+ read(() => client.readContract({
610
+ address: token,
611
+ abi: viem_1.erc20Abi,
612
+ functionName: "decimals",
613
+ })),
614
+ read(() => client.readContract({
615
+ address: token,
616
+ abi: viem_1.erc20Abi,
617
+ functionName: "symbol",
618
+ })),
619
+ probe
620
+ ? read(() => client.readContract({
621
+ address: token,
622
+ abi: ERC165_ABI,
623
+ functionName: "supportsInterface",
624
+ args: [ERC721_INTERFACE_ID],
625
+ }))
626
+ : null,
627
+ ]);
628
+ return {
629
+ erc721: typeof erc721 === "boolean" ? erc721 : null,
630
+ decimals: typeof decimals === "number" &&
631
+ Number.isInteger(decimals) &&
632
+ decimals >= 0 &&
633
+ decimals <= 255
634
+ ? decimals
635
+ : null,
636
+ symbol: typeof symbol === "string" && symbol.trim() && symbol.length <= 32
637
+ ? symbol.trim()
638
+ : null,
639
+ };
640
+ }
641
+ /** Every call the model shows, the ones inside other calls and arguments included. */
642
+ function eachCall(calls, visit) {
643
+ for (const call of calls) {
644
+ visit(call);
645
+ eachCall(call.calls ?? [], visit);
646
+ for (const argument of call.args ?? []) {
647
+ eachCall(argument.nested ?? [], visit);
648
+ }
649
+ }
650
+ }
651
+ /**
652
+ * The model with each token's decimals and symbol read from the token, once
653
+ * per token per chain. A failed read leaves them null, never zero, and keeps
654
+ * the `decimals-unknown` warning. A call ERC-721 shares, to an unknown
655
+ * contract, also asks the contract whether it is ERC-721: a yes shows the
656
+ * number as the NFT's token ID; a no, or decimals it answers, clears
657
+ * `possible-token-id`; no answer keeps it. The id is unchanged: the reads
658
+ * only explain the calls already bound.
659
+ */
660
+ async function enrichReviewModel(model, clientFor) {
661
+ const wanted = new Map();
662
+ const key = (chainId, token) => `${chainId}:${token.toLowerCase()}`;
663
+ const probes = (call) => call.warnings.some((warning) => warning.code === "possible-token-id");
664
+ const signed = model.signatures.flatMap((signature) => signature.calls);
665
+ eachCall([...model.calls, ...signed], (call) => {
666
+ for (const { token, decimals, symbol } of call.tokenAmounts) {
667
+ if (token === "native" || (decimals !== null && symbol !== null)) {
668
+ continue;
669
+ }
670
+ const id = key(call.chainId, token);
671
+ const probe = probes(call) && token.toLowerCase() === call.to.toLowerCase();
672
+ const seen = wanted.get(id);
673
+ wanted.set(id, {
674
+ chainId: call.chainId,
675
+ token,
676
+ probe: probe || (seen?.probe ?? false),
677
+ });
678
+ }
679
+ });
680
+ const read = new Map(await Promise.all([...wanted].map(async ([id, { chainId, token, probe }]) => {
681
+ let client;
682
+ try {
683
+ client = clientFor(chainId);
684
+ }
685
+ catch {
686
+ client = undefined;
687
+ }
688
+ return [id, await readToken(client, token, probe)];
689
+ })));
690
+ const enrich = (call) => {
691
+ const nested = {
692
+ args: call.args?.map((argument) => argument.nested
693
+ ? { ...argument, nested: argument.nested.map(enrich) }
694
+ : argument) ?? null,
695
+ calls: call.calls?.map(enrich) ?? null,
696
+ };
697
+ const target = probes(call) ? read.get(key(call.chainId, call.to)) : null;
698
+ if (target?.erc721 === true) {
699
+ const [{ amount: tokenId }] = call.tokenAmounts;
700
+ const cleared = new Set([
701
+ "possible-token-id",
702
+ "unlimited-approval",
703
+ "decimals-unknown",
704
+ ]);
705
+ return {
706
+ ...call,
707
+ ...nested,
708
+ tokenAmounts: [],
709
+ nft: { token: call.to, tokenId },
710
+ warnings: call.warnings.filter((warning) => !cleared.has(warning.code)),
711
+ };
712
+ }
713
+ // Decimals it answers, and no ERC-721 yes, confirm ERC-20: a zero
714
+ // approval then revokes rather than grants.
715
+ const revokes = target?.decimals !== null &&
716
+ target?.decimals !== undefined &&
717
+ call.tokenAmounts[0]?.amount === 0n;
718
+ const warnings = target && (target.erc721 === false || target.decimals !== null)
719
+ ? call.warnings.filter((warning) => warning.code !== "possible-token-id" &&
720
+ !(revokes && warning.code === "permission-grant"))
721
+ : call.warnings;
722
+ const tokenAmounts = call.tokenAmounts.map((amount) => {
723
+ const found = amount.token === "native"
724
+ ? undefined
725
+ : read.get(key(call.chainId, amount.token));
726
+ return found
727
+ ? {
728
+ ...amount,
729
+ decimals: amount.decimals ?? found.decimals,
730
+ symbol: amount.symbol ?? found.symbol,
731
+ }
732
+ : amount;
733
+ });
734
+ return {
735
+ ...call,
736
+ ...nested,
737
+ tokenAmounts,
738
+ warnings: withDecimalsWarning(warnings, tokenAmounts),
739
+ };
740
+ };
741
+ return {
742
+ ...model,
743
+ calls: model.calls.map(enrich),
744
+ signatures: model.signatures.map((signature) => ({
745
+ ...signature,
746
+ calls: signature.calls.map(enrich),
747
+ })),
748
+ };
749
+ }
750
+ //# sourceMappingURL=model.js.map