@haneullabs/wallet-sdk 0.1.0 → 0.1.1

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 (197) hide show
  1. package/CHANGELOG.md +47 -18
  2. package/dist/auto-approvals/analyzer.d.mts +83 -0
  3. package/dist/auto-approvals/analyzer.d.mts.map +1 -0
  4. package/dist/auto-approvals/analyzer.mjs +43 -0
  5. package/dist/auto-approvals/analyzer.mjs.map +1 -0
  6. package/dist/auto-approvals/index.d.mts +6 -0
  7. package/dist/auto-approvals/intent.d.mts +9 -0
  8. package/dist/auto-approvals/intent.d.mts.map +1 -0
  9. package/dist/auto-approvals/intent.mjs +40 -0
  10. package/dist/auto-approvals/intent.mjs.map +1 -0
  11. package/dist/auto-approvals/manager.d.mts +38 -0
  12. package/dist/auto-approvals/manager.d.mts.map +1 -0
  13. package/dist/auto-approvals/manager.mjs +192 -0
  14. package/dist/auto-approvals/manager.mjs.map +1 -0
  15. package/dist/auto-approvals/schemas/index.d.mts +2 -0
  16. package/dist/auto-approvals/schemas/policy.d.mts +149 -0
  17. package/dist/auto-approvals/schemas/policy.d.mts.map +1 -0
  18. package/dist/auto-approvals/schemas/policy.mjs +49 -0
  19. package/dist/auto-approvals/schemas/policy.mjs.map +1 -0
  20. package/dist/auto-approvals/schemas/state.d.mts +115 -0
  21. package/dist/auto-approvals/schemas/state.d.mts.map +1 -0
  22. package/dist/auto-approvals/schemas/state.mjs +20 -0
  23. package/dist/auto-approvals/schemas/state.mjs.map +1 -0
  24. package/dist/index.d.mts +16 -0
  25. package/dist/index.mjs +9 -0
  26. package/dist/transaction-analyzer/analyzer.d.mts +39 -0
  27. package/dist/transaction-analyzer/analyzer.d.mts.map +1 -0
  28. package/dist/transaction-analyzer/analyzer.mjs +46 -0
  29. package/dist/transaction-analyzer/analyzer.mjs.map +1 -0
  30. package/dist/transaction-analyzer/index.d.mts +8 -0
  31. package/dist/transaction-analyzer/rules/accessLevel.mjs +65 -0
  32. package/dist/transaction-analyzer/rules/accessLevel.mjs.map +1 -0
  33. package/dist/transaction-analyzer/rules/coin-flows.d.mts +12 -0
  34. package/dist/transaction-analyzer/rules/coin-flows.d.mts.map +1 -0
  35. package/dist/transaction-analyzer/rules/coin-flows.mjs +122 -0
  36. package/dist/transaction-analyzer/rules/coin-flows.mjs.map +1 -0
  37. package/dist/transaction-analyzer/rules/coin-value.d.mts +25 -0
  38. package/dist/transaction-analyzer/rules/coin-value.d.mts.map +1 -0
  39. package/dist/transaction-analyzer/rules/coin-value.mjs +36 -0
  40. package/dist/transaction-analyzer/rules/coin-value.mjs.map +1 -0
  41. package/dist/transaction-analyzer/rules/coins.d.mts +12 -0
  42. package/dist/transaction-analyzer/rules/coins.d.mts.map +1 -0
  43. package/dist/transaction-analyzer/rules/coins.mjs +48 -0
  44. package/dist/transaction-analyzer/rules/coins.mjs.map +1 -0
  45. package/dist/transaction-analyzer/rules/commands.d.mts +79 -0
  46. package/dist/transaction-analyzer/rules/commands.d.mts.map +1 -0
  47. package/dist/transaction-analyzer/rules/commands.mjs +141 -0
  48. package/dist/transaction-analyzer/rules/commands.mjs.map +1 -0
  49. package/dist/transaction-analyzer/rules/core.mjs +48 -0
  50. package/dist/transaction-analyzer/rules/core.mjs.map +1 -0
  51. package/dist/transaction-analyzer/rules/functions.mjs +31 -0
  52. package/dist/transaction-analyzer/rules/functions.mjs.map +1 -0
  53. package/dist/transaction-analyzer/rules/index.d.mts +2125 -0
  54. package/dist/transaction-analyzer/rules/index.d.mts.map +1 -0
  55. package/dist/transaction-analyzer/rules/index.mjs +34 -0
  56. package/dist/transaction-analyzer/rules/index.mjs.map +1 -0
  57. package/dist/transaction-analyzer/rules/inputs.d.mts +20 -0
  58. package/dist/transaction-analyzer/rules/inputs.d.mts.map +1 -0
  59. package/dist/transaction-analyzer/rules/inputs.mjs +38 -0
  60. package/dist/transaction-analyzer/rules/inputs.mjs.map +1 -0
  61. package/dist/transaction-analyzer/rules/objects.d.mts +12 -0
  62. package/dist/transaction-analyzer/rules/objects.d.mts.map +1 -0
  63. package/dist/transaction-analyzer/rules/objects.mjs +92 -0
  64. package/dist/transaction-analyzer/rules/objects.mjs.map +1 -0
  65. package/dist/util.d.mts +7 -0
  66. package/dist/util.d.mts.map +1 -0
  67. package/package.json +27 -25
  68. package/dist/cjs/auto-approvals/analyzer.d.ts +0 -71
  69. package/dist/cjs/auto-approvals/analyzer.js +0 -70
  70. package/dist/cjs/auto-approvals/analyzer.js.map +0 -7
  71. package/dist/cjs/auto-approvals/index.d.ts +0 -6
  72. package/dist/cjs/auto-approvals/index.js +0 -33
  73. package/dist/cjs/auto-approvals/index.js.map +0 -7
  74. package/dist/cjs/auto-approvals/intent.d.ts +0 -5
  75. package/dist/cjs/auto-approvals/intent.js +0 -65
  76. package/dist/cjs/auto-approvals/intent.js.map +0 -7
  77. package/dist/cjs/auto-approvals/manager.d.ts +0 -31
  78. package/dist/cjs/auto-approvals/manager.js +0 -328
  79. package/dist/cjs/auto-approvals/manager.js.map +0 -7
  80. package/dist/cjs/auto-approvals/schemas/index.d.ts +0 -4
  81. package/dist/cjs/auto-approvals/schemas/index.js +0 -28
  82. package/dist/cjs/auto-approvals/schemas/index.js.map +0 -7
  83. package/dist/cjs/auto-approvals/schemas/policy.d.ts +0 -145
  84. package/dist/cjs/auto-approvals/schemas/policy.js +0 -79
  85. package/dist/cjs/auto-approvals/schemas/policy.js.map +0 -7
  86. package/dist/cjs/auto-approvals/schemas/state.d.ts +0 -115
  87. package/dist/cjs/auto-approvals/schemas/state.js +0 -49
  88. package/dist/cjs/auto-approvals/schemas/state.js.map +0 -7
  89. package/dist/cjs/index.d.ts +0 -2
  90. package/dist/cjs/index.js +0 -20
  91. package/dist/cjs/index.js.map +0 -7
  92. package/dist/cjs/package.json +0 -5
  93. package/dist/cjs/transaction-analyzer/analyzer.d.ts +0 -34
  94. package/dist/cjs/transaction-analyzer/analyzer.js +0 -94
  95. package/dist/cjs/transaction-analyzer/analyzer.js.map +0 -7
  96. package/dist/cjs/transaction-analyzer/index.d.ts +0 -9
  97. package/dist/cjs/transaction-analyzer/index.js +0 -28
  98. package/dist/cjs/transaction-analyzer/index.js.map +0 -7
  99. package/dist/cjs/transaction-analyzer/rules/accessLevel.d.ts +0 -29
  100. package/dist/cjs/transaction-analyzer/rules/accessLevel.js +0 -106
  101. package/dist/cjs/transaction-analyzer/rules/accessLevel.js.map +0 -7
  102. package/dist/cjs/transaction-analyzer/rules/coin-flows.d.ts +0 -313
  103. package/dist/cjs/transaction-analyzer/rules/coin-flows.js +0 -179
  104. package/dist/cjs/transaction-analyzer/rules/coin-flows.js.map +0 -7
  105. package/dist/cjs/transaction-analyzer/rules/coin-value.d.ts +0 -42
  106. package/dist/cjs/transaction-analyzer/rules/coin-value.js +0 -60
  107. package/dist/cjs/transaction-analyzer/rules/coin-value.js.map +0 -7
  108. package/dist/cjs/transaction-analyzer/rules/coins.d.ts +0 -337
  109. package/dist/cjs/transaction-analyzer/rules/coins.js +0 -78
  110. package/dist/cjs/transaction-analyzer/rules/coins.js.map +0 -7
  111. package/dist/cjs/transaction-analyzer/rules/commands.d.ts +0 -366
  112. package/dist/cjs/transaction-analyzer/rules/commands.js +0 -148
  113. package/dist/cjs/transaction-analyzer/rules/commands.js.map +0 -7
  114. package/dist/cjs/transaction-analyzer/rules/core.d.ts +0 -314
  115. package/dist/cjs/transaction-analyzer/rules/core.js +0 -73
  116. package/dist/cjs/transaction-analyzer/rules/core.js.map +0 -7
  117. package/dist/cjs/transaction-analyzer/rules/functions.d.ts +0 -292
  118. package/dist/cjs/transaction-analyzer/rules/functions.js +0 -58
  119. package/dist/cjs/transaction-analyzer/rules/functions.js.map +0 -7
  120. package/dist/cjs/transaction-analyzer/rules/index.d.ts +0 -2244
  121. package/dist/cjs/transaction-analyzer/rules/index.js +0 -52
  122. package/dist/cjs/transaction-analyzer/rules/index.js.map +0 -7
  123. package/dist/cjs/transaction-analyzer/rules/inputs.d.ts +0 -313
  124. package/dist/cjs/transaction-analyzer/rules/inputs.js +0 -49
  125. package/dist/cjs/transaction-analyzer/rules/inputs.js.map +0 -7
  126. package/dist/cjs/transaction-analyzer/rules/objects.d.ts +0 -359
  127. package/dist/cjs/transaction-analyzer/rules/objects.js +0 -124
  128. package/dist/cjs/transaction-analyzer/rules/objects.js.map +0 -7
  129. package/dist/cjs/util.d.ts +0 -5
  130. package/dist/cjs/util.js +0 -17
  131. package/dist/cjs/util.js.map +0 -7
  132. package/dist/esm/auto-approvals/analyzer.d.ts +0 -71
  133. package/dist/esm/auto-approvals/analyzer.js +0 -50
  134. package/dist/esm/auto-approvals/analyzer.js.map +0 -7
  135. package/dist/esm/auto-approvals/index.d.ts +0 -6
  136. package/dist/esm/auto-approvals/index.js +0 -12
  137. package/dist/esm/auto-approvals/index.js.map +0 -7
  138. package/dist/esm/auto-approvals/intent.d.ts +0 -5
  139. package/dist/esm/auto-approvals/intent.js +0 -45
  140. package/dist/esm/auto-approvals/intent.js.map +0 -7
  141. package/dist/esm/auto-approvals/manager.d.ts +0 -31
  142. package/dist/esm/auto-approvals/manager.js +0 -308
  143. package/dist/esm/auto-approvals/manager.js.map +0 -7
  144. package/dist/esm/auto-approvals/schemas/index.d.ts +0 -4
  145. package/dist/esm/auto-approvals/schemas/index.js +0 -8
  146. package/dist/esm/auto-approvals/schemas/index.js.map +0 -7
  147. package/dist/esm/auto-approvals/schemas/policy.d.ts +0 -145
  148. package/dist/esm/auto-approvals/schemas/policy.js +0 -49
  149. package/dist/esm/auto-approvals/schemas/policy.js.map +0 -7
  150. package/dist/esm/auto-approvals/schemas/state.d.ts +0 -115
  151. package/dist/esm/auto-approvals/schemas/state.js +0 -19
  152. package/dist/esm/auto-approvals/schemas/state.js.map +0 -7
  153. package/dist/esm/index.d.ts +0 -2
  154. package/dist/esm/index.js +0 -3
  155. package/dist/esm/index.js.map +0 -7
  156. package/dist/esm/package.json +0 -5
  157. package/dist/esm/transaction-analyzer/analyzer.d.ts +0 -34
  158. package/dist/esm/transaction-analyzer/analyzer.js +0 -74
  159. package/dist/esm/transaction-analyzer/analyzer.js.map +0 -7
  160. package/dist/esm/transaction-analyzer/index.d.ts +0 -9
  161. package/dist/esm/transaction-analyzer/index.js +0 -8
  162. package/dist/esm/transaction-analyzer/index.js.map +0 -7
  163. package/dist/esm/transaction-analyzer/rules/accessLevel.d.ts +0 -29
  164. package/dist/esm/transaction-analyzer/rules/accessLevel.js +0 -86
  165. package/dist/esm/transaction-analyzer/rules/accessLevel.js.map +0 -7
  166. package/dist/esm/transaction-analyzer/rules/coin-flows.d.ts +0 -313
  167. package/dist/esm/transaction-analyzer/rules/coin-flows.js +0 -159
  168. package/dist/esm/transaction-analyzer/rules/coin-flows.js.map +0 -7
  169. package/dist/esm/transaction-analyzer/rules/coin-value.d.ts +0 -42
  170. package/dist/esm/transaction-analyzer/rules/coin-value.js +0 -40
  171. package/dist/esm/transaction-analyzer/rules/coin-value.js.map +0 -7
  172. package/dist/esm/transaction-analyzer/rules/coins.d.ts +0 -337
  173. package/dist/esm/transaction-analyzer/rules/coins.js +0 -58
  174. package/dist/esm/transaction-analyzer/rules/coins.js.map +0 -7
  175. package/dist/esm/transaction-analyzer/rules/commands.d.ts +0 -366
  176. package/dist/esm/transaction-analyzer/rules/commands.js +0 -128
  177. package/dist/esm/transaction-analyzer/rules/commands.js.map +0 -7
  178. package/dist/esm/transaction-analyzer/rules/core.d.ts +0 -314
  179. package/dist/esm/transaction-analyzer/rules/core.js +0 -53
  180. package/dist/esm/transaction-analyzer/rules/core.js.map +0 -7
  181. package/dist/esm/transaction-analyzer/rules/functions.d.ts +0 -292
  182. package/dist/esm/transaction-analyzer/rules/functions.js +0 -38
  183. package/dist/esm/transaction-analyzer/rules/functions.js.map +0 -7
  184. package/dist/esm/transaction-analyzer/rules/index.d.ts +0 -2244
  185. package/dist/esm/transaction-analyzer/rules/index.js +0 -32
  186. package/dist/esm/transaction-analyzer/rules/index.js.map +0 -7
  187. package/dist/esm/transaction-analyzer/rules/inputs.d.ts +0 -313
  188. package/dist/esm/transaction-analyzer/rules/inputs.js +0 -29
  189. package/dist/esm/transaction-analyzer/rules/inputs.js.map +0 -7
  190. package/dist/esm/transaction-analyzer/rules/objects.d.ts +0 -359
  191. package/dist/esm/transaction-analyzer/rules/objects.js +0 -104
  192. package/dist/esm/transaction-analyzer/rules/objects.js.map +0 -7
  193. package/dist/esm/util.d.ts +0 -5
  194. package/dist/esm/util.js +0 -1
  195. package/dist/esm/util.js.map +0 -7
  196. package/dist/tsconfig.esm.tsbuildinfo +0 -1
  197. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,122 @@
1
+ import { createAnalyzer } from "../analyzer.mjs";
2
+ import { data } from "./core.mjs";
3
+ import { coins, gasCoins } from "./coins.mjs";
4
+ import { inputs } from "./inputs.mjs";
5
+ import { commands } from "./commands.mjs";
6
+ import { bcs } from "@haneullabs/haneul/bcs";
7
+ import { normalizeStructTag } from "@haneullabs/haneul/utils";
8
+
9
+ //#region src/transaction-analyzer/rules/coin-flows.ts
10
+ const coinFlows = createAnalyzer({
11
+ dependencies: {
12
+ data,
13
+ commands,
14
+ inputs,
15
+ coins,
16
+ gasCoins
17
+ },
18
+ analyze: () => async ({ data: data$1, commands: commands$1, inputs: inputs$1, coins: coins$1, gasCoins: gasCoins$1 }) => {
19
+ const getTrackedCoin = (ref) => {
20
+ switch (ref.$kind) {
21
+ case "GasCoin": return trackedCoins.get("gas") ?? null;
22
+ case "Object": return trackedCoins.get(`input:${ref.index}`) ?? null;
23
+ case "Result": return trackedCoins.get(`result:${ref.index[0]},${ref.index[1]}`) ?? null;
24
+ case "Unknown":
25
+ case "Pure": return null;
26
+ }
27
+ };
28
+ const splitCoin = (command) => {
29
+ const coin = getTrackedCoin(command.coin);
30
+ if (!coin) return;
31
+ if (!command.amounts.every((a) => a.$kind === "Pure")) {
32
+ coin.consume();
33
+ return;
34
+ }
35
+ const amounts = command.amounts.map((a) => {
36
+ if (a.$kind !== "Pure") throw new Error("Expected pure value");
37
+ return BigInt(bcs.u64().fromBase64(a.bytes));
38
+ });
39
+ coin.remainingBalance -= amounts.reduce((a, b) => a + b, 0n);
40
+ amounts.forEach((amount, i) => {
41
+ trackedCoins.set(`result:${command.index},${i}`, new TrackedCoin(coin.coinType, amount, false));
42
+ });
43
+ };
44
+ const mergeCoins = (command) => {
45
+ const sources = command.sources.map(getTrackedCoin);
46
+ const amount = sources.reduce((a, c) => a + (c?.remainingBalance ?? 0n), 0n);
47
+ for (const src of sources) src?.consume();
48
+ const dest = getTrackedCoin(command.destination);
49
+ if (!dest) return;
50
+ dest.remainingBalance += amount;
51
+ };
52
+ const transferObjects = (command) => {
53
+ const address = command.address.$kind === "Pure" ? bcs.Address.fromBase64(command.address.bytes) : null;
54
+ for (const obj of command.objects) {
55
+ const tracked = getTrackedCoin(obj);
56
+ if (tracked && address && data$1.sender === address) trackedCoins.get("gas").remainingBalance += tracked.remainingBalance;
57
+ tracked?.consume();
58
+ }
59
+ };
60
+ const issues = [];
61
+ const trackedCoins = /* @__PURE__ */ new Map();
62
+ trackedCoins.set("gas", new TrackedCoin(normalizeStructTag("0x2::haneul::HANEUL"), gasCoins$1.reduce((a, c) => a + c.balance, 0n), true));
63
+ if (data$1.gasData.budget) trackedCoins.get("gas").remainingBalance -= BigInt(data$1.gasData.budget);
64
+ else issues.push({ message: "Gas budget not set in Transaction" });
65
+ for (const input of inputs$1) if (input.$kind === "Object" && coins$1[input.object.objectId]) {
66
+ const coin = coins$1[input.object.objectId];
67
+ trackedCoins.set(`input:${input.index}`, new TrackedCoin(coin.coinType, coin.balance, true));
68
+ }
69
+ for (const command of commands$1) switch (command.$kind) {
70
+ case "SplitCoins":
71
+ splitCoin(command);
72
+ break;
73
+ case "MergeCoins":
74
+ mergeCoins(command);
75
+ break;
76
+ case "TransferObjects":
77
+ transferObjects(command);
78
+ break;
79
+ case "MakeMoveVec":
80
+ command.elements.forEach((el) => {
81
+ getTrackedCoin(el)?.consume();
82
+ });
83
+ break;
84
+ case "MoveCall":
85
+ command.arguments.forEach((arg) => {
86
+ getTrackedCoin(arg)?.consume();
87
+ });
88
+ break;
89
+ case "Upgrade":
90
+ case "Publish": break;
91
+ default: throw new Error(`Unsupported command type: ${command.$kind}`);
92
+ }
93
+ const outflows = {};
94
+ for (const coin of trackedCoins.values()) {
95
+ if (!coin.owned) continue;
96
+ if (!outflows[coin.coinType]) outflows[coin.coinType] = {
97
+ coinType: coin.coinType,
98
+ amount: 0n
99
+ };
100
+ outflows[coin.coinType].amount += coin.initialBalance - coin.remainingBalance;
101
+ }
102
+ if (issues.length) return { issues };
103
+ return { result: { outflows: Object.values(outflows) } };
104
+ }
105
+ });
106
+ var TrackedCoin = class {
107
+ constructor(coinType, balance, owned) {
108
+ this.consumed = false;
109
+ this.coinType = coinType;
110
+ this.initialBalance = balance;
111
+ this.remainingBalance = balance;
112
+ this.owned = owned;
113
+ }
114
+ consume() {
115
+ this.remainingBalance = 0n;
116
+ this.consumed = true;
117
+ }
118
+ };
119
+
120
+ //#endregion
121
+ export { coinFlows };
122
+ //# sourceMappingURL=coin-flows.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coin-flows.mjs","names":["data","gasCoins","inputs","coins","commands"],"sources":["../../../src/transaction-analyzer/rules/coin-flows.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { normalizeStructTag } from '@haneullabs/haneul/utils';\nimport type { TransactionAnalysisIssue } from '../analyzer.js';\nimport { createAnalyzer } from '../analyzer.js';\nimport { bcs } from '@haneullabs/haneul/bcs';\nimport { commands } from './commands.js';\nimport type { AnalyzedCommand, AnalyzedCommandArgument } from './commands.js';\nimport { data } from './core.js';\nimport { inputs } from './inputs.js';\nimport { coins, gasCoins } from './coins.js';\n\nexport interface CoinFlow {\n\tcoinType: string;\n\tamount: bigint;\n}\n\nexport const coinFlows = createAnalyzer({\n\tdependencies: { data, commands, inputs, coins, gasCoins },\n\tanalyze:\n\t\t() =>\n\t\tasync ({ data, commands, inputs, coins, gasCoins }) => {\n\t\t\tconst getTrackedCoin = (ref: AnalyzedCommandArgument): TrackedCoin | null => {\n\t\t\t\tswitch (ref.$kind) {\n\t\t\t\t\tcase 'GasCoin':\n\t\t\t\t\t\treturn trackedCoins.get('gas') ?? null;\n\t\t\t\t\tcase 'Object':\n\t\t\t\t\t\treturn trackedCoins.get(`input:${ref.index}`) ?? null;\n\t\t\t\t\tcase 'Result':\n\t\t\t\t\t\treturn trackedCoins.get(`result:${ref.index[0]},${ref.index[1]}`) ?? null;\n\t\t\t\t\tcase 'Unknown':\n\t\t\t\t\tcase 'Pure':\n\t\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst splitCoin = (command: Extract<AnalyzedCommand, { $kind: 'SplitCoins' }>) => {\n\t\t\t\tconst coin = getTrackedCoin(command.coin);\n\n\t\t\t\tif (!coin) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// If any amounts are dynamic we need to assume the coin is fully consumed\n\t\t\t\tif (!command.amounts.every((a) => a.$kind === 'Pure')) {\n\t\t\t\t\tcoin.consume();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst amounts = command.amounts.map((a) => {\n\t\t\t\t\tif (a.$kind !== 'Pure') {\n\t\t\t\t\t\tthrow new Error('Expected pure value');\n\t\t\t\t\t}\n\t\t\t\t\treturn BigInt(bcs.u64().fromBase64(a.bytes));\n\t\t\t\t});\n\n\t\t\t\tcoin.remainingBalance -= amounts.reduce((a, b) => a + b, 0n);\n\n\t\t\t\tamounts.forEach((amount, i) => {\n\t\t\t\t\ttrackedCoins.set(\n\t\t\t\t\t\t`result:${command.index},${i}`,\n\t\t\t\t\t\tnew TrackedCoin(coin.coinType, amount, false),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst mergeCoins = (command: Extract<AnalyzedCommand, { $kind: 'MergeCoins' }>) => {\n\t\t\t\tconst sources = command.sources.map(getTrackedCoin);\n\t\t\t\tconst amount = sources.reduce((a, c) => a + (c?.remainingBalance ?? 0n), 0n);\n\n\t\t\t\tfor (const src of sources) {\n\t\t\t\t\tsrc?.consume();\n\t\t\t\t}\n\n\t\t\t\tconst dest = getTrackedCoin(command.destination);\n\n\t\t\t\tif (!dest) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tdest.remainingBalance += amount;\n\t\t\t};\n\n\t\t\tconst transferObjects = (command: Extract<AnalyzedCommand, { $kind: 'TransferObjects' }>) => {\n\t\t\t\tconst address =\n\t\t\t\t\tcommand.address.$kind === 'Pure' ? bcs.Address.fromBase64(command.address.bytes) : null;\n\n\t\t\t\tfor (const obj of command.objects) {\n\t\t\t\t\tconst tracked = getTrackedCoin(obj);\n\n\t\t\t\t\t// If coin is transferred to the sender, we can track the transfer in the gas coin\n\t\t\t\t\tif (tracked && address && data.sender === address) {\n\t\t\t\t\t\ttrackedCoins.get('gas')!.remainingBalance += tracked.remainingBalance;\n\t\t\t\t\t}\n\n\t\t\t\t\ttracked?.consume();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst issues: TransactionAnalysisIssue[] = [];\n\n\t\t\tconst trackedCoins = new Map<string, TrackedCoin>();\n\n\t\t\ttrackedCoins.set(\n\t\t\t\t'gas',\n\t\t\t\tnew TrackedCoin(\n\t\t\t\t\tnormalizeStructTag('0x2::haneul::HANEUL'),\n\t\t\t\t\tgasCoins.reduce((a, c) => a + c.balance, 0n),\n\t\t\t\t\ttrue,\n\t\t\t\t),\n\t\t\t);\n\n\t\t\tif (data.gasData.budget) {\n\t\t\t\ttrackedCoins.get('gas')!.remainingBalance -= BigInt(data.gasData.budget);\n\t\t\t} else {\n\t\t\t\tissues.push({ message: 'Gas budget not set in Transaction' });\n\t\t\t}\n\n\t\t\tfor (const input of inputs) {\n\t\t\t\tif (input.$kind === 'Object' && coins[input.object.objectId]) {\n\t\t\t\t\tconst coin = coins[input.object.objectId];\n\t\t\t\t\ttrackedCoins.set(\n\t\t\t\t\t\t`input:${input.index}`,\n\t\t\t\t\t\tnew TrackedCoin(coin.coinType, coin.balance, true),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const command of commands) {\n\t\t\t\tswitch (command.$kind) {\n\t\t\t\t\tcase 'SplitCoins':\n\t\t\t\t\t\tsplitCoin(command);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'MergeCoins':\n\t\t\t\t\t\tmergeCoins(command);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'TransferObjects':\n\t\t\t\t\t\ttransferObjects(command);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'MakeMoveVec':\n\t\t\t\t\t\tcommand.elements.forEach((el) => {\n\t\t\t\t\t\t\tconst tracked = getTrackedCoin(el);\n\t\t\t\t\t\t\ttracked?.consume();\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'MoveCall':\n\t\t\t\t\t\tcommand.arguments.forEach((arg) => {\n\t\t\t\t\t\t\tconst tracked = getTrackedCoin(arg);\n\t\t\t\t\t\t\ttracked?.consume();\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Upgrade':\n\t\t\t\t\tcase 'Publish':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new Error(`Unsupported command type: ${command.$kind}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst outflows: Record<string, CoinFlow> = {};\n\n\t\t\tfor (const coin of trackedCoins.values()) {\n\t\t\t\tif (!coin.owned) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!outflows[coin.coinType]) {\n\t\t\t\t\toutflows[coin.coinType] = { coinType: coin.coinType, amount: 0n };\n\t\t\t\t}\n\n\t\t\t\toutflows[coin.coinType].amount += coin.initialBalance - coin.remainingBalance;\n\t\t\t}\n\n\t\t\tif (issues.length) {\n\t\t\t\treturn { issues };\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tresult: {\n\t\t\t\t\toutflows: Object.values(outflows),\n\t\t\t\t},\n\t\t\t};\n\t\t},\n});\n\nclass TrackedCoin {\n\tcoinType: string;\n\tinitialBalance: bigint;\n\tremainingBalance: bigint;\n\towned: boolean;\n\tconsumed = false;\n\n\tconstructor(coinType: string, balance: bigint, owned: boolean) {\n\t\tthis.coinType = coinType;\n\t\tthis.initialBalance = balance;\n\t\tthis.remainingBalance = balance;\n\t\tthis.owned = owned;\n\t}\n\n\tconsume() {\n\t\tthis.remainingBalance = 0n;\n\t\tthis.consumed = true;\n\t}\n}\n"],"mappings":";;;;;;;;;AAkBA,MAAa,YAAY,eAAe;CACvC,cAAc;EAAE;EAAM;EAAU;EAAQ;EAAO;EAAU;CACzD,eAEC,OAAO,EAAE,cAAM,sBAAU,kBAAQ,gBAAO,2BAAe;EACtD,MAAM,kBAAkB,QAAqD;AAC5E,WAAQ,IAAI,OAAZ;IACC,KAAK,UACJ,QAAO,aAAa,IAAI,MAAM,IAAI;IACnC,KAAK,SACJ,QAAO,aAAa,IAAI,SAAS,IAAI,QAAQ,IAAI;IAClD,KAAK,SACJ,QAAO,aAAa,IAAI,UAAU,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,KAAK,IAAI;IACtE,KAAK;IACL,KAAK,OACJ,QAAO;;;EAIV,MAAM,aAAa,YAA+D;GACjF,MAAM,OAAO,eAAe,QAAQ,KAAK;AAEzC,OAAI,CAAC,KACJ;AAGD,OAAI,CAAC,QAAQ,QAAQ,OAAO,MAAM,EAAE,UAAU,OAAO,EAAE;AACtD,SAAK,SAAS;AACd;;GAGD,MAAM,UAAU,QAAQ,QAAQ,KAAK,MAAM;AAC1C,QAAI,EAAE,UAAU,OACf,OAAM,IAAI,MAAM,sBAAsB;AAEvC,WAAO,OAAO,IAAI,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC;KAC3C;AAEF,QAAK,oBAAoB,QAAQ,QAAQ,GAAG,MAAM,IAAI,GAAG,GAAG;AAE5D,WAAQ,SAAS,QAAQ,MAAM;AAC9B,iBAAa,IACZ,UAAU,QAAQ,MAAM,GAAG,KAC3B,IAAI,YAAY,KAAK,UAAU,QAAQ,MAAM,CAC7C;KACA;;EAGH,MAAM,cAAc,YAA+D;GAClF,MAAM,UAAU,QAAQ,QAAQ,IAAI,eAAe;GACnD,MAAM,SAAS,QAAQ,QAAQ,GAAG,MAAM,KAAK,GAAG,oBAAoB,KAAK,GAAG;AAE5E,QAAK,MAAM,OAAO,QACjB,MAAK,SAAS;GAGf,MAAM,OAAO,eAAe,QAAQ,YAAY;AAEhD,OAAI,CAAC,KACJ;AAGD,QAAK,oBAAoB;;EAG1B,MAAM,mBAAmB,YAAoE;GAC5F,MAAM,UACL,QAAQ,QAAQ,UAAU,SAAS,IAAI,QAAQ,WAAW,QAAQ,QAAQ,MAAM,GAAG;AAEpF,QAAK,MAAM,OAAO,QAAQ,SAAS;IAClC,MAAM,UAAU,eAAe,IAAI;AAGnC,QAAI,WAAW,WAAWA,OAAK,WAAW,QACzC,cAAa,IAAI,MAAM,CAAE,oBAAoB,QAAQ;AAGtD,aAAS,SAAS;;;EAIpB,MAAM,SAAqC,EAAE;EAE7C,MAAM,+BAAe,IAAI,KAA0B;AAEnD,eAAa,IACZ,OACA,IAAI,YACH,mBAAmB,sBAAsB,EACzCC,WAAS,QAAQ,GAAG,MAAM,IAAI,EAAE,SAAS,GAAG,EAC5C,KACA,CACD;AAED,MAAID,OAAK,QAAQ,OAChB,cAAa,IAAI,MAAM,CAAE,oBAAoB,OAAOA,OAAK,QAAQ,OAAO;MAExE,QAAO,KAAK,EAAE,SAAS,qCAAqC,CAAC;AAG9D,OAAK,MAAM,SAASE,SACnB,KAAI,MAAM,UAAU,YAAYC,QAAM,MAAM,OAAO,WAAW;GAC7D,MAAM,OAAOA,QAAM,MAAM,OAAO;AAChC,gBAAa,IACZ,SAAS,MAAM,SACf,IAAI,YAAY,KAAK,UAAU,KAAK,SAAS,KAAK,CAClD;;AAIH,OAAK,MAAM,WAAWC,WACrB,SAAQ,QAAQ,OAAhB;GACC,KAAK;AACJ,cAAU,QAAQ;AAClB;GACD,KAAK;AACJ,eAAW,QAAQ;AACnB;GACD,KAAK;AACJ,oBAAgB,QAAQ;AACxB;GACD,KAAK;AACJ,YAAQ,SAAS,SAAS,OAAO;AAEhC,KADgB,eAAe,GAAG,EACzB,SAAS;MACjB;AACF;GACD,KAAK;AACJ,YAAQ,UAAU,SAAS,QAAQ;AAElC,KADgB,eAAe,IAAI,EAC1B,SAAS;MACjB;AACF;GACD,KAAK;GACL,KAAK,UACJ;GACD,QACC,OAAM,IAAI,MAAM,6BAA6B,QAAQ,QAAQ;;EAIhE,MAAM,WAAqC,EAAE;AAE7C,OAAK,MAAM,QAAQ,aAAa,QAAQ,EAAE;AACzC,OAAI,CAAC,KAAK,MACT;AAED,OAAI,CAAC,SAAS,KAAK,UAClB,UAAS,KAAK,YAAY;IAAE,UAAU,KAAK;IAAU,QAAQ;IAAI;AAGlE,YAAS,KAAK,UAAU,UAAU,KAAK,iBAAiB,KAAK;;AAG9D,MAAI,OAAO,OACV,QAAO,EAAE,QAAQ;AAGlB,SAAO,EACN,QAAQ,EACP,UAAU,OAAO,OAAO,SAAS,EACjC,EACD;;CAEH,CAAC;AAEF,IAAM,cAAN,MAAkB;CAOjB,YAAY,UAAkB,SAAiB,OAAgB;kBAFpD;AAGV,OAAK,WAAW;AAChB,OAAK,iBAAiB;AACtB,OAAK,mBAAmB;AACxB,OAAK,QAAQ;;CAGd,UAAU;AACT,OAAK,mBAAmB;AACxB,OAAK,WAAW"}
@@ -0,0 +1,25 @@
1
+ import "../analyzer.mjs";
2
+ import "./coin-flows.mjs";
3
+
4
+ //#region src/transaction-analyzer/rules/coin-value.d.ts
5
+ interface CoinValueAnalyzerOptions {
6
+ getCoinPrices: (coinTypes: string[]) => Promise<{
7
+ coinType: string;
8
+ decimals: number;
9
+ price: number | null;
10
+ }[]>;
11
+ }
12
+ interface CoinValueAnalysis {
13
+ coinTypesWithoutPrice: string[];
14
+ total: number;
15
+ coinTypes: {
16
+ coinType: string;
17
+ decimals: number;
18
+ price: number;
19
+ amount: bigint;
20
+ convertedAmount: number;
21
+ }[];
22
+ }
23
+ //#endregion
24
+ export { CoinValueAnalysis, CoinValueAnalyzerOptions };
25
+ //# sourceMappingURL=coin-value.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coin-value.d.mts","names":[],"sources":["../../../src/transaction-analyzer/rules/coin-value.ts"],"sourcesContent":[],"mappings":";;;;UAMiB,wBAAA;0CACwB;;;IADxB,KAAA,EAAA,MAAA,GAAA,IAAA;EAUA,CAAA,EAAA,CAAA;;UAAA,iBAAA"}
@@ -0,0 +1,36 @@
1
+ import { createAnalyzer } from "../analyzer.mjs";
2
+ import { coinFlows } from "./coin-flows.mjs";
3
+
4
+ //#region src/transaction-analyzer/rules/coin-value.ts
5
+ const coinValues = createAnalyzer({
6
+ dependencies: { coinFlows },
7
+ analyze: ({ getCoinPrices }) => async ({ coinFlows: coinFlows$1 }) => {
8
+ const prices = await getCoinPrices(coinFlows$1.outflows.map((cf) => cf.coinType));
9
+ let total = 0;
10
+ const coinTypesWithoutPrice = [];
11
+ const coinTypes = [];
12
+ for (const flow of coinFlows$1.outflows) if (flow.amount > 0n) {
13
+ const result = prices.find((p) => p.coinType === flow.coinType);
14
+ if (result?.price != null) {
15
+ const amount = Number(flow.amount) / 10 ** result.decimals * result.price;
16
+ total += amount;
17
+ coinTypes.push({
18
+ coinType: flow.coinType,
19
+ decimals: result.decimals,
20
+ price: result.price,
21
+ amount: flow.amount,
22
+ convertedAmount: amount
23
+ });
24
+ } else coinTypesWithoutPrice.push(flow.coinType);
25
+ }
26
+ return { result: {
27
+ total,
28
+ coinTypesWithoutPrice,
29
+ coinTypes
30
+ } };
31
+ }
32
+ });
33
+
34
+ //#endregion
35
+ export { coinValues };
36
+ //# sourceMappingURL=coin-value.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coin-value.mjs","names":["coinFlows"],"sources":["../../../src/transaction-analyzer/rules/coin-value.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { createAnalyzer } from '../analyzer.js';\nimport { coinFlows } from './coin-flows.js';\n\nexport interface CoinValueAnalyzerOptions {\n\tgetCoinPrices: (coinTypes: string[]) => Promise<\n\t\t{\n\t\t\tcoinType: string;\n\t\t\tdecimals: number;\n\t\t\tprice: number | null;\n\t\t}[]\n\t>;\n}\n\nexport interface CoinValueAnalysis {\n\tcoinTypesWithoutPrice: string[];\n\ttotal: number;\n\tcoinTypes: {\n\t\tcoinType: string;\n\t\tdecimals: number;\n\t\tprice: number;\n\t\tamount: bigint;\n\t\tconvertedAmount: number;\n\t}[];\n}\n\nexport const coinValues = createAnalyzer({\n\tdependencies: { coinFlows },\n\tanalyze:\n\t\t({ getCoinPrices }: CoinValueAnalyzerOptions) =>\n\t\tasync ({ coinFlows }) => {\n\t\t\tconst prices = await getCoinPrices(coinFlows.outflows.map((cf) => cf.coinType));\n\n\t\t\tlet total = 0;\n\t\t\tconst coinTypesWithoutPrice: string[] = [];\n\n\t\t\tconst coinTypes: {\n\t\t\t\tcoinType: string;\n\t\t\t\tdecimals: number;\n\t\t\t\tprice: number;\n\t\t\t\tamount: bigint;\n\t\t\t\tconvertedAmount: number;\n\t\t\t}[] = [];\n\n\t\t\tfor (const flow of coinFlows.outflows) {\n\t\t\t\tif (flow.amount > 0n) {\n\t\t\t\t\tconst result = prices.find((p) => p.coinType === flow.coinType);\n\n\t\t\t\t\tif (result?.price != null) {\n\t\t\t\t\t\tconst amount = (Number(flow.amount) / 10 ** result.decimals) * result.price;\n\t\t\t\t\t\ttotal += amount;\n\t\t\t\t\t\tcoinTypes.push({\n\t\t\t\t\t\t\tcoinType: flow.coinType,\n\t\t\t\t\t\t\tdecimals: result.decimals,\n\t\t\t\t\t\t\tprice: result.price,\n\t\t\t\t\t\t\tamount: flow.amount,\n\t\t\t\t\t\t\tconvertedAmount: amount,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcoinTypesWithoutPrice.push(flow.coinType);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tresult: {\n\t\t\t\t\ttotal: total,\n\t\t\t\t\tcoinTypesWithoutPrice,\n\t\t\t\t\tcoinTypes: coinTypes,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n});\n"],"mappings":";;;;AA4BA,MAAa,aAAa,eAAe;CACxC,cAAc,EAAE,WAAW;CAC3B,UACE,EAAE,oBACH,OAAO,EAAE,6BAAgB;EACxB,MAAM,SAAS,MAAM,cAAcA,YAAU,SAAS,KAAK,OAAO,GAAG,SAAS,CAAC;EAE/E,IAAI,QAAQ;EACZ,MAAM,wBAAkC,EAAE;EAE1C,MAAM,YAMA,EAAE;AAER,OAAK,MAAM,QAAQA,YAAU,SAC5B,KAAI,KAAK,SAAS,IAAI;GACrB,MAAM,SAAS,OAAO,MAAM,MAAM,EAAE,aAAa,KAAK,SAAS;AAE/D,OAAI,QAAQ,SAAS,MAAM;IAC1B,MAAM,SAAU,OAAO,KAAK,OAAO,GAAG,MAAM,OAAO,WAAY,OAAO;AACtE,aAAS;AACT,cAAU,KAAK;KACd,UAAU,KAAK;KACf,UAAU,OAAO;KACjB,OAAO,OAAO;KACd,QAAQ,KAAK;KACb,iBAAiB;KACjB,CAAC;SAEF,uBAAsB,KAAK,KAAK,SAAS;;AAK5C,SAAO,EACN,QAAQ;GACA;GACP;GACW;GACX,EACD;;CAEH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import "../analyzer.mjs";
2
+ import { AnalyzedObject } from "./objects.mjs";
3
+ import "@haneullabs/haneul/bcs";
4
+
5
+ //#region src/transaction-analyzer/rules/coins.d.ts
6
+ type AnalyzedCoin = AnalyzedObject & {
7
+ balance: bigint;
8
+ coinType: string;
9
+ };
10
+ //#endregion
11
+ export { AnalyzedCoin };
12
+ //# sourceMappingURL=coins.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coins.d.mts","names":[],"sources":["../../../src/transaction-analyzer/rules/coins.ts"],"sourcesContent":[],"mappings":";;;;;KAUY,YAAA,GAAe"}
@@ -0,0 +1,48 @@
1
+ import { createAnalyzer } from "../analyzer.mjs";
2
+ import { data } from "./core.mjs";
3
+ import { objects, objectsById } from "./objects.mjs";
4
+ import { bcs } from "@haneullabs/haneul/bcs";
5
+ import { normalizeStructTag, parseStructTag } from "@haneullabs/haneul/utils";
6
+
7
+ //#region src/transaction-analyzer/rules/coins.ts
8
+ const Coin = bcs.struct("Coin", {
9
+ id: bcs.Address,
10
+ balance: bcs.U64
11
+ });
12
+ const parsedCoinStruct = parseStructTag("0x2::coin::Coin<0x2::haneul::HANEUL>");
13
+ const coins = createAnalyzer({
14
+ dependencies: { objects },
15
+ analyze: () => async ({ objects: objects$1 }) => {
16
+ return { result: Object.fromEntries(await Promise.all(objects$1.filter((obj) => {
17
+ const parsed = parseStructTag(obj.type);
18
+ return parsed.address === parsedCoinStruct.address && parsed.module === parsedCoinStruct.module && parsed.name === parsedCoinStruct.name && parsed.typeParams.length === 1;
19
+ }).map(async (obj) => {
20
+ return [obj.objectId, {
21
+ ...obj,
22
+ coinType: normalizeStructTag(parseStructTag(obj.type).typeParams[0]),
23
+ balance: BigInt(Coin.parse(obj.content).balance)
24
+ }];
25
+ }))) };
26
+ }
27
+ });
28
+ const gasCoins = createAnalyzer({
29
+ dependencies: {
30
+ objectsById,
31
+ data
32
+ },
33
+ analyze: () => async ({ objectsById: objectsById$1, data: data$1 }) => {
34
+ return { result: await Promise.all((data$1.gasData.payment ?? []).map(async (coin) => {
35
+ const obj = objectsById$1.get(coin.objectId);
36
+ const content = Coin.parse(obj.content);
37
+ return {
38
+ ...obj,
39
+ coinType: normalizeStructTag(parseStructTag(obj.type).typeParams[0]),
40
+ balance: BigInt(content.balance)
41
+ };
42
+ })) };
43
+ }
44
+ });
45
+
46
+ //#endregion
47
+ export { coins, gasCoins };
48
+ //# sourceMappingURL=coins.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coins.mjs","names":["objects","data","objectsById"],"sources":["../../../src/transaction-analyzer/rules/coins.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { bcs } from '@haneullabs/haneul/bcs';\nimport { objects, objectsById } from './objects.js';\nimport type { AnalyzedObject } from './objects.js';\nimport { createAnalyzer } from '../analyzer.js';\nimport { normalizeStructTag, parseStructTag } from '@haneullabs/haneul/utils';\nimport { data } from './core.js';\n\nexport type AnalyzedCoin = AnalyzedObject & { balance: bigint; coinType: string };\n\nexport const Coin = bcs.struct('Coin', {\n\tid: bcs.Address,\n\tbalance: bcs.U64,\n});\nconst parsedCoinStruct = parseStructTag('0x2::coin::Coin<0x2::haneul::HANEUL>');\n\nexport const coins = createAnalyzer({\n\tdependencies: { objects },\n\tanalyze:\n\t\t() =>\n\t\tasync ({ objects }) => {\n\t\t\treturn {\n\t\t\t\tresult: Object.fromEntries(\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tobjects\n\t\t\t\t\t\t\t.filter((obj) => {\n\t\t\t\t\t\t\t\tconst parsed = parseStructTag(obj.type);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\tparsed.address === parsedCoinStruct.address &&\n\t\t\t\t\t\t\t\t\tparsed.module === parsedCoinStruct.module &&\n\t\t\t\t\t\t\t\t\tparsed.name === parsedCoinStruct.name &&\n\t\t\t\t\t\t\t\t\tparsed.typeParams.length === 1\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.map(async (obj) => {\n\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\tobj.objectId,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t...obj,\n\t\t\t\t\t\t\t\t\t\tcoinType: normalizeStructTag(parseStructTag(obj.type).typeParams[0]),\n\t\t\t\t\t\t\t\t\t\tbalance: BigInt(Coin.parse(obj.content).balance),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t};\n\t\t},\n});\n\nexport const gasCoins = createAnalyzer({\n\tdependencies: { objectsById, data },\n\tanalyze:\n\t\t() =>\n\t\tasync ({ objectsById, data }) => {\n\t\t\treturn {\n\t\t\t\tresult: await Promise.all(\n\t\t\t\t\t(data.gasData.payment ?? []).map(async (coin) => {\n\t\t\t\t\t\tconst obj = objectsById.get(coin.objectId)!;\n\t\t\t\t\t\tconst content = Coin.parse(obj.content);\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...obj,\n\t\t\t\t\t\t\tcoinType: normalizeStructTag(parseStructTag(obj.type).typeParams[0]),\n\t\t\t\t\t\t\tbalance: BigInt(content.balance),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t},\n});\n"],"mappings":";;;;;;;AAYA,MAAa,OAAO,IAAI,OAAO,QAAQ;CACtC,IAAI,IAAI;CACR,SAAS,IAAI;CACb,CAAC;AACF,MAAM,mBAAmB,eAAe,uCAAuC;AAE/E,MAAa,QAAQ,eAAe;CACnC,cAAc,EAAE,SAAS;CACzB,eAEC,OAAO,EAAE,yBAAc;AACtB,SAAO,EACN,QAAQ,OAAO,YACd,MAAM,QAAQ,IACbA,UACE,QAAQ,QAAQ;GAChB,MAAM,SAAS,eAAe,IAAI,KAAK;AACvC,UACC,OAAO,YAAY,iBAAiB,WACpC,OAAO,WAAW,iBAAiB,UACnC,OAAO,SAAS,iBAAiB,QACjC,OAAO,WAAW,WAAW;IAE7B,CACD,IAAI,OAAO,QAAQ;AACnB,UAAO,CACN,IAAI,UACJ;IACC,GAAG;IACH,UAAU,mBAAmB,eAAe,IAAI,KAAK,CAAC,WAAW,GAAG;IACpE,SAAS,OAAO,KAAK,MAAM,IAAI,QAAQ,CAAC,QAAQ;IAChD,CACD;IACA,CACH,CACD,EACD;;CAEH,CAAC;AAEF,MAAa,WAAW,eAAe;CACtC,cAAc;EAAE;EAAa;EAAM;CACnC,eAEC,OAAO,EAAE,4BAAa,mBAAW;AAChC,SAAO,EACN,QAAQ,MAAM,QAAQ,KACpBC,OAAK,QAAQ,WAAW,EAAE,EAAE,IAAI,OAAO,SAAS;GAChD,MAAM,MAAMC,cAAY,IAAI,KAAK,SAAS;GAC1C,MAAM,UAAU,KAAK,MAAM,IAAI,QAAQ;AACvC,UAAO;IACN,GAAG;IACH,UAAU,mBAAmB,eAAe,IAAI,KAAK,CAAC,WAAW,GAAG;IACpE,SAAS,OAAO,QAAQ,QAAQ;IAChC;IACA,CACF,EACD;;CAEH,CAAC"}
@@ -0,0 +1,79 @@
1
+ import "../analyzer.mjs";
2
+ import { AnalyzedCommandInput } from "./inputs.mjs";
3
+ import { Command } from "@haneullabs/haneul/transactions";
4
+ import { HaneulClientTypes } from "@haneullabs/haneul/client";
5
+
6
+ //#region src/transaction-analyzer/rules/commands.d.ts
7
+ type AnalyzedCommandArgument = AnalyzedCommandInput | {
8
+ $kind: 'Unknown';
9
+ accessLevel: 'read' | 'mutate' | 'transfer';
10
+ } | {
11
+ $kind: 'GasCoin';
12
+ accessLevel: 'read' | 'mutate' | 'transfer';
13
+ } | {
14
+ $kind: 'Result';
15
+ index: [number, number];
16
+ accessLevel: 'read' | 'mutate' | 'transfer';
17
+ };
18
+ type AnalyzedCommand = {
19
+ $kind: 'MoveCall';
20
+ index: number;
21
+ arguments: AnalyzedCommandArgument[];
22
+ function: HaneulClientTypes.FunctionResponse;
23
+ command: Extract<Command, {
24
+ $kind: 'MoveCall';
25
+ }>['MoveCall'];
26
+ } | {
27
+ $kind: 'TransferObjects';
28
+ index: number;
29
+ objects: AnalyzedCommandArgument[];
30
+ address: AnalyzedCommandArgument;
31
+ command: Extract<Command, {
32
+ $kind: 'TransferObjects';
33
+ }>['TransferObjects'];
34
+ } | {
35
+ $kind: 'MergeCoins';
36
+ index: number;
37
+ sources: AnalyzedCommandArgument[];
38
+ destination: AnalyzedCommandArgument;
39
+ command: Extract<Command, {
40
+ $kind: 'MergeCoins';
41
+ }>['MergeCoins'];
42
+ } | {
43
+ $kind: 'SplitCoins';
44
+ index: number;
45
+ coin: AnalyzedCommandArgument;
46
+ amounts: AnalyzedCommandArgument[];
47
+ command: Extract<Command, {
48
+ $kind: 'SplitCoins';
49
+ }>['SplitCoins'];
50
+ } | {
51
+ $kind: 'MakeMoveVec';
52
+ index: number;
53
+ elements: AnalyzedCommandArgument[];
54
+ command: Extract<Command, {
55
+ $kind: 'MakeMoveVec';
56
+ }>['MakeMoveVec'];
57
+ } | {
58
+ $kind: 'Upgrade';
59
+ index: number;
60
+ ticket: AnalyzedCommandArgument;
61
+ command: Extract<Command, {
62
+ $kind: 'Upgrade';
63
+ }>['Upgrade'];
64
+ } | {
65
+ $kind: 'Publish';
66
+ index: number;
67
+ command: Extract<Command, {
68
+ $kind: 'Publish';
69
+ }>['Publish'];
70
+ } | {
71
+ $kind: 'Unknown';
72
+ index: number;
73
+ command: Extract<Command, {
74
+ $kind: 'Unknown';
75
+ }>['Unknown'];
76
+ };
77
+ //#endregion
78
+ export { AnalyzedCommand, AnalyzedCommandArgument };
79
+ //# sourceMappingURL=commands.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.mts","names":[],"sources":["../../../src/transaction-analyzer/rules/commands.ts"],"sourcesContent":[],"mappings":";;;;;;KAYY,uBAAA,GACT;;;AADH,CAAA,GAAY;EAgBA,KAAA,EAAA,SAAA;EAIE,WAAA,EAAA,MAAA,GAAA,QAAA,GAAA,UAAA;CACD,GAAA;EACO,KAAA,EAAA,QAAA;EAAR,KAAA,EAAA,CAAA,MAAA,EAAA,MAAA,CAAA;EAKA,WAAA,EAAA,MAAA,GAAA,QAAA,GAAA,UAAA;CACA;AACQ,KAbR,eAAA,GAaQ;EAAR,KAAA,EAAA,UAAA;EAKA,KAAA,EAAA,MAAA;EACI,SAAA,EAfF,uBAeE,EAAA;EACI,QAAA,EAfP,iBAAA,CAAkB,gBAeX;EAAR,OAAA,EAdA,OAcA,CAdQ,OAcR,EAAA;IAKH,KAAA,EAAA,UAAA;EACG,CAAA,CAAA,CAAA,UAAA,CAAA;CACQ,GAAA;EAAR,KAAA,EAAA,iBAAA;EAKC,KAAA,EAAA,MAAA;EACO,OAAA,EAtBR,uBAsBQ,EAAA;EAAR,OAAA,EArBA,uBAqBA;EAKD,OAAA,EAzBC,OAyBD,CAzBS,OAyBT,EAAA;IACS,KAAA,EAAA,iBAAA;EAAR,CAAA,CAAA,CAAA,iBAAA,CAAA;CAKQ,GAAA;EAAR,KAAA,EAAA,YAAA;EAKQ,KAAA,EAAA,MAAA;EAAR,OAAA,EA/BA,uBA+BA,EAAA;EAAO,WAAA,EA9BH,uBA8BG;WA7BP,QAAQ;;;;;;QAKX;WACG;WACA,QAAQ;;;;;;YAKP;WACD,QAAQ;;;;;;UAKT;WACC,QAAQ;;;;;;WAKR,QAAQ;;;;;;WAKR,QAAQ"}
@@ -0,0 +1,141 @@
1
+ import { createAnalyzer } from "../analyzer.mjs";
2
+ import { data } from "./core.mjs";
3
+ import { inputs } from "./inputs.mjs";
4
+ import { moveFunctions } from "./functions.mjs";
5
+
6
+ //#region src/transaction-analyzer/rules/commands.ts
7
+ const commands = createAnalyzer({
8
+ dependencies: {
9
+ data,
10
+ moveFunctions,
11
+ inputs
12
+ },
13
+ analyze: () => ({ data: data$1, moveFunctions: moveFunctions$1, inputs: inputs$1 }) => {
14
+ const issues = [];
15
+ const commands$1 = [];
16
+ const mapInput = (arg, accessLevel = "transfer") => {
17
+ switch (arg.$kind) {
18
+ case "Input": break;
19
+ case "GasCoin": return {
20
+ $kind: "GasCoin",
21
+ accessLevel
22
+ };
23
+ case "Result": return {
24
+ $kind: "Result",
25
+ index: [arg.Result, 0],
26
+ accessLevel
27
+ };
28
+ case "NestedResult": return {
29
+ $kind: "Result",
30
+ index: arg.NestedResult,
31
+ accessLevel
32
+ };
33
+ default:
34
+ issues.push({ message: `Unexpected input type: ${JSON.stringify(arg)}` });
35
+ return {
36
+ $kind: "Unknown",
37
+ accessLevel
38
+ };
39
+ }
40
+ const input = inputs$1[arg.Input];
41
+ if (!input) {
42
+ issues.push({ message: `Missing input for index ${arg.Input}` });
43
+ return {
44
+ $kind: "Unknown",
45
+ accessLevel
46
+ };
47
+ }
48
+ return {
49
+ ...input,
50
+ accessLevel
51
+ };
52
+ };
53
+ for (let index = 0; index < data$1.commands.length; index++) {
54
+ const command = data$1.commands[index];
55
+ switch (command.$kind) {
56
+ case "$Intent":
57
+ issues.push({ message: `Unexpected $Intent command: ${JSON.stringify(command)}` });
58
+ break;
59
+ case "MakeMoveVec":
60
+ commands$1.push({
61
+ $kind: "MakeMoveVec",
62
+ index,
63
+ elements: command.MakeMoveVec.elements.map((el) => mapInput(el)),
64
+ command: command.MakeMoveVec
65
+ });
66
+ break;
67
+ case "TransferObjects":
68
+ commands$1.push({
69
+ $kind: "TransferObjects",
70
+ index,
71
+ address: mapInput(command.TransferObjects.address),
72
+ objects: command.TransferObjects.objects.map((obj) => mapInput(obj)),
73
+ command: command.TransferObjects
74
+ });
75
+ break;
76
+ case "MergeCoins":
77
+ commands$1.push({
78
+ $kind: "MergeCoins",
79
+ index,
80
+ sources: command.MergeCoins.sources.map((src) => mapInput(src)),
81
+ destination: mapInput(command.MergeCoins.destination, "mutate"),
82
+ command: command.MergeCoins
83
+ });
84
+ break;
85
+ case "SplitCoins":
86
+ commands$1.push({
87
+ $kind: "SplitCoins",
88
+ index,
89
+ coin: mapInput(command.SplitCoins.coin, "mutate"),
90
+ amounts: command.SplitCoins.amounts.map((amt) => mapInput(amt, "transfer")),
91
+ command: command.SplitCoins
92
+ });
93
+ break;
94
+ case "MoveCall": {
95
+ const func = moveFunctions$1.find((fn) => fn.packageId === command.MoveCall.package && fn.moduleName === command.MoveCall.module && fn.name === command.MoveCall.function);
96
+ commands$1.push({
97
+ $kind: "MoveCall",
98
+ index,
99
+ arguments: command.MoveCall.arguments.map((arg, i) => {
100
+ let accessLevel = "transfer";
101
+ switch (func.parameters[i].reference) {
102
+ case "mutable":
103
+ accessLevel = "mutate";
104
+ break;
105
+ case "immutable":
106
+ accessLevel = "read";
107
+ break;
108
+ }
109
+ return mapInput(arg, accessLevel);
110
+ }),
111
+ command: command.MoveCall,
112
+ function: func
113
+ });
114
+ break;
115
+ }
116
+ case "Publish":
117
+ commands$1.push({
118
+ $kind: "Publish",
119
+ index,
120
+ command: command.Publish
121
+ });
122
+ break;
123
+ case "Upgrade":
124
+ commands$1.push({
125
+ $kind: "Upgrade",
126
+ index,
127
+ ticket: mapInput(command.Upgrade.ticket),
128
+ command: command.Upgrade
129
+ });
130
+ break;
131
+ default: throw new Error("Unknown command type: " + command.$kind);
132
+ }
133
+ }
134
+ if (issues.length) return { issues };
135
+ return { result: commands$1 };
136
+ }
137
+ });
138
+
139
+ //#endregion
140
+ export { commands };
141
+ //# sourceMappingURL=commands.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.mjs","names":["commands","inputs","data","moveFunctions"],"sources":["../../../src/transaction-analyzer/rules/commands.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Argument, Command } from '@haneullabs/haneul/transactions';\nimport type { HaneulClientTypes } from '@haneullabs/haneul/client';\nimport { inputs } from './inputs.js';\nimport type { AnalyzedCommandInput } from './inputs.js';\nimport type { TransactionAnalysisIssue } from '../analyzer.js';\nimport { createAnalyzer } from '../analyzer.js';\nimport { data } from './core.js';\nimport { moveFunctions } from './functions.js';\n\nexport type AnalyzedCommandArgument =\n\t| AnalyzedCommandInput\n\t| {\n\t\t\t$kind: 'Unknown';\n\t\t\taccessLevel: 'read' | 'mutate' | 'transfer';\n\t }\n\t| {\n\t\t\t$kind: 'GasCoin';\n\t\t\taccessLevel: 'read' | 'mutate' | 'transfer';\n\t }\n\t| {\n\t\t\t$kind: 'Result';\n\t\t\tindex: [number, number];\n\t\t\taccessLevel: 'read' | 'mutate' | 'transfer';\n\t };\n\nexport type AnalyzedCommand =\n\t| {\n\t\t\t$kind: 'MoveCall';\n\t\t\tindex: number;\n\t\t\targuments: AnalyzedCommandArgument[];\n\t\t\tfunction: HaneulClientTypes.FunctionResponse;\n\t\t\tcommand: Extract<Command, { $kind: 'MoveCall' }>['MoveCall'];\n\t }\n\t| {\n\t\t\t$kind: 'TransferObjects';\n\t\t\tindex: number;\n\t\t\tobjects: AnalyzedCommandArgument[];\n\t\t\taddress: AnalyzedCommandArgument;\n\t\t\tcommand: Extract<Command, { $kind: 'TransferObjects' }>['TransferObjects'];\n\t }\n\t| {\n\t\t\t$kind: 'MergeCoins';\n\t\t\tindex: number;\n\t\t\tsources: AnalyzedCommandArgument[];\n\t\t\tdestination: AnalyzedCommandArgument;\n\t\t\tcommand: Extract<Command, { $kind: 'MergeCoins' }>['MergeCoins'];\n\t }\n\t| {\n\t\t\t$kind: 'SplitCoins';\n\t\t\tindex: number;\n\t\t\tcoin: AnalyzedCommandArgument;\n\t\t\tamounts: AnalyzedCommandArgument[];\n\t\t\tcommand: Extract<Command, { $kind: 'SplitCoins' }>['SplitCoins'];\n\t }\n\t| {\n\t\t\t$kind: 'MakeMoveVec';\n\t\t\tindex: number;\n\t\t\telements: AnalyzedCommandArgument[];\n\t\t\tcommand: Extract<Command, { $kind: 'MakeMoveVec' }>['MakeMoveVec'];\n\t }\n\t| {\n\t\t\t$kind: 'Upgrade';\n\t\t\tindex: number;\n\t\t\tticket: AnalyzedCommandArgument;\n\t\t\tcommand: Extract<Command, { $kind: 'Upgrade' }>['Upgrade'];\n\t }\n\t| {\n\t\t\t$kind: 'Publish';\n\t\t\tindex: number;\n\t\t\tcommand: Extract<Command, { $kind: 'Publish' }>['Publish'];\n\t }\n\t| {\n\t\t\t$kind: 'Unknown';\n\t\t\tindex: number;\n\t\t\tcommand: Extract<Command, { $kind: 'Unknown' }>['Unknown'];\n\t };\n\nexport const commands = createAnalyzer({\n\tdependencies: {\n\t\tdata,\n\t\tmoveFunctions,\n\t\tinputs,\n\t},\n\tanalyze:\n\t\t() =>\n\t\t({ data, moveFunctions, inputs }) => {\n\t\t\tconst issues: TransactionAnalysisIssue[] = [];\n\t\t\tconst commands: AnalyzedCommand[] = [];\n\n\t\t\tconst mapInput = (\n\t\t\t\targ: Argument,\n\t\t\t\taccessLevel: 'read' | 'mutate' | 'transfer' = 'transfer',\n\t\t\t): AnalyzedCommandArgument => {\n\t\t\t\tswitch (arg.$kind) {\n\t\t\t\t\tcase 'Input':\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'GasCoin':\n\t\t\t\t\t\treturn { $kind: 'GasCoin', accessLevel };\n\t\t\t\t\tcase 'Result':\n\t\t\t\t\t\treturn { $kind: 'Result', index: [arg.Result, 0], accessLevel };\n\t\t\t\t\tcase 'NestedResult':\n\t\t\t\t\t\treturn { $kind: 'Result', index: arg.NestedResult, accessLevel };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tissues.push({ message: `Unexpected input type: ${JSON.stringify(arg)}` });\n\t\t\t\t\t\treturn { $kind: 'Unknown', accessLevel };\n\t\t\t\t}\n\n\t\t\t\tconst input = inputs[arg.Input];\n\n\t\t\t\tif (!input) {\n\t\t\t\t\tissues.push({ message: `Missing input for index ${arg.Input}` });\n\t\t\t\t\treturn { $kind: 'Unknown', accessLevel };\n\t\t\t\t}\n\n\t\t\t\treturn { ...input, accessLevel };\n\t\t\t};\n\n\t\t\tfor (let index = 0; index < data.commands.length; index++) {\n\t\t\t\tconst command = data.commands[index];\n\t\t\t\tswitch (command.$kind) {\n\t\t\t\t\tcase '$Intent':\n\t\t\t\t\t\tissues.push({ message: `Unexpected $Intent command: ${JSON.stringify(command)}` });\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'MakeMoveVec':\n\t\t\t\t\t\tcommands.push({\n\t\t\t\t\t\t\t$kind: 'MakeMoveVec',\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\telements: command.MakeMoveVec.elements.map((el) => mapInput(el)),\n\t\t\t\t\t\t\tcommand: command.MakeMoveVec,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'TransferObjects':\n\t\t\t\t\t\tcommands.push({\n\t\t\t\t\t\t\t$kind: 'TransferObjects',\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\taddress: mapInput(command.TransferObjects.address),\n\t\t\t\t\t\t\tobjects: command.TransferObjects.objects.map((obj) => mapInput(obj)),\n\t\t\t\t\t\t\tcommand: command.TransferObjects,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'MergeCoins':\n\t\t\t\t\t\tcommands.push({\n\t\t\t\t\t\t\t$kind: 'MergeCoins',\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\tsources: command.MergeCoins.sources.map((src) => mapInput(src)),\n\t\t\t\t\t\t\tdestination: mapInput(command.MergeCoins.destination, 'mutate'),\n\t\t\t\t\t\t\tcommand: command.MergeCoins,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'SplitCoins':\n\t\t\t\t\t\tcommands.push({\n\t\t\t\t\t\t\t$kind: 'SplitCoins',\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\tcoin: mapInput(command.SplitCoins.coin, 'mutate'),\n\t\t\t\t\t\t\tamounts: command.SplitCoins.amounts.map((amt) => mapInput(amt, 'transfer')),\n\t\t\t\t\t\t\tcommand: command.SplitCoins,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'MoveCall': {\n\t\t\t\t\t\tconst func = moveFunctions.find(\n\t\t\t\t\t\t\t(fn) =>\n\t\t\t\t\t\t\t\tfn.packageId === command.MoveCall.package &&\n\t\t\t\t\t\t\t\tfn.moduleName === command.MoveCall.module &&\n\t\t\t\t\t\t\t\tfn.name === command.MoveCall.function,\n\t\t\t\t\t\t)!;\n\t\t\t\t\t\tcommands.push({\n\t\t\t\t\t\t\t$kind: 'MoveCall',\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\targuments: command.MoveCall.arguments.map((arg, i) => {\n\t\t\t\t\t\t\t\tlet accessLevel: 'read' | 'mutate' | 'transfer' = 'transfer';\n\t\t\t\t\t\t\t\tswitch (func.parameters[i].reference) {\n\t\t\t\t\t\t\t\t\tcase 'mutable':\n\t\t\t\t\t\t\t\t\t\taccessLevel = 'mutate';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 'immutable':\n\t\t\t\t\t\t\t\t\t\taccessLevel = 'read';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn mapInput(arg, accessLevel);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tcommand: command.MoveCall,\n\t\t\t\t\t\t\tfunction: func,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'Publish':\n\t\t\t\t\t\tcommands.push({\n\t\t\t\t\t\t\t$kind: 'Publish',\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\tcommand: command.Publish,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Upgrade':\n\t\t\t\t\t\tcommands.push({\n\t\t\t\t\t\t\t$kind: 'Upgrade',\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\tticket: mapInput(command.Upgrade.ticket),\n\t\t\t\t\t\t\tcommand: command.Upgrade,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new Error('Unknown command type: ' + (command as { $kind: string }).$kind);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (issues.length) {\n\t\t\t\treturn { issues };\n\t\t\t}\n\n\t\t\treturn { result: commands };\n\t\t},\n});\n"],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { createAnalyzer } from "../analyzer.mjs";
2
+ import { TransactionDataBuilder } from "@haneullabs/haneul/transactions";
3
+
4
+ //#region src/transaction-analyzer/rules/core.ts
5
+ const bytes = createAnalyzer({
6
+ cacheKey: "bytes@1.0.0",
7
+ analyze: (options, transaction) => async () => {
8
+ try {
9
+ return { result: await transaction.build({ client: options.client }) };
10
+ } catch {
11
+ return { issues: [{ message: "Failed to build transaction" }] };
12
+ }
13
+ }
14
+ });
15
+ const data = createAnalyzer({
16
+ dependencies: { bytes },
17
+ analyze: (_, tx) => () => {
18
+ return { result: tx.getData() };
19
+ }
20
+ });
21
+ const digest = createAnalyzer({
22
+ dependencies: { bytes },
23
+ analyze: () => ({ bytes: bytes$1 }) => {
24
+ return { result: TransactionDataBuilder.getDigestFromBytes(bytes$1) };
25
+ }
26
+ });
27
+ const transactionResponse = createAnalyzer({
28
+ cacheKey: "transactionResponse@1.0.0",
29
+ dependencies: { bytes },
30
+ analyze: (options) => async ({ bytes: bytes$1 }) => {
31
+ try {
32
+ const result = await options.client.core.simulateTransaction({ transaction: bytes$1 });
33
+ return { result: options.transactionResponse ?? result.Transaction ?? result.FailedTransaction };
34
+ } catch {
35
+ return { issues: [{ message: "Failed to dry run transaction" }] };
36
+ }
37
+ }
38
+ });
39
+ const balanceChanges = createAnalyzer({
40
+ dependencies: { transactionResponse },
41
+ analyze: () => ({ transactionResponse: transactionResponse$1 }) => {
42
+ return { result: transactionResponse$1.balanceChanges || [] };
43
+ }
44
+ });
45
+
46
+ //#endregion
47
+ export { balanceChanges, bytes, data, digest, transactionResponse };
48
+ //# sourceMappingURL=core.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.mjs","names":["bytes","transactionResponse"],"sources":["../../../src/transaction-analyzer/rules/core.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Transaction } from '@haneullabs/haneul/transactions';\nimport { TransactionDataBuilder } from '@haneullabs/haneul/transactions';\nimport type { ClientWithCoreApi, HaneulClientTypes } from '@haneullabs/haneul/client';\nimport type { AnalyzerResult } from '../analyzer.js';\nimport { createAnalyzer } from '../analyzer.js';\n\nexport const bytes = createAnalyzer({\n\tcacheKey: 'bytes@1.0.0',\n\tanalyze:\n\t\t(options: { client: ClientWithCoreApi }, transaction: Transaction) =>\n\t\tasync (): Promise<AnalyzerResult<Uint8Array>> => {\n\t\t\ttry {\n\t\t\t\treturn {\n\t\t\t\t\tresult: await transaction.build({ client: options.client }),\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\treturn { issues: [{ message: 'Failed to build transaction' }] };\n\t\t\t}\n\t\t},\n});\n\nexport const data = createAnalyzer({\n\tdependencies: { bytes },\n\tanalyze: (_, tx) => () => {\n\t\treturn { result: tx.getData() };\n\t},\n});\n\nexport const digest = createAnalyzer({\n\tdependencies: { bytes },\n\tanalyze:\n\t\t() =>\n\t\t({ bytes }) => {\n\t\t\treturn { result: TransactionDataBuilder.getDigestFromBytes(bytes) };\n\t\t},\n});\n\nexport const transactionResponse = createAnalyzer({\n\tcacheKey: 'transactionResponse@1.0.0',\n\tdependencies: { bytes },\n\tanalyze:\n\t\t(options: { client: ClientWithCoreApi; transactionResponse?: HaneulClientTypes.Transaction }) =>\n\t\tasync ({ bytes }): Promise<AnalyzerResult<HaneulClientTypes.Transaction>> => {\n\t\t\ttry {\n\t\t\t\tconst result = await options.client.core.simulateTransaction({ transaction: bytes });\n\t\t\t\treturn {\n\t\t\t\t\tresult: options.transactionResponse ?? result.Transaction ?? result.FailedTransaction,\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\treturn { issues: [{ message: 'Failed to dry run transaction' }] };\n\t\t\t}\n\t\t},\n});\n\nexport const balanceChanges = createAnalyzer({\n\tdependencies: { transactionResponse },\n\tanalyze:\n\t\t() =>\n\t\t({ transactionResponse }) => {\n\t\t\treturn { result: transactionResponse.balanceChanges || [] };\n\t\t},\n});\n"],"mappings":";;;;AASA,MAAa,QAAQ,eAAe;CACnC,UAAU;CACV,UACE,SAAwC,gBACzC,YAAiD;AAChD,MAAI;AACH,UAAO,EACN,QAAQ,MAAM,YAAY,MAAM,EAAE,QAAQ,QAAQ,QAAQ,CAAC,EAC3D;UACM;AACP,UAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,+BAA+B,CAAC,EAAE;;;CAGlE,CAAC;AAEF,MAAa,OAAO,eAAe;CAClC,cAAc,EAAE,OAAO;CACvB,UAAU,GAAG,aAAa;AACzB,SAAO,EAAE,QAAQ,GAAG,SAAS,EAAE;;CAEhC,CAAC;AAEF,MAAa,SAAS,eAAe;CACpC,cAAc,EAAE,OAAO;CACvB,gBAEE,EAAE,qBAAY;AACd,SAAO,EAAE,QAAQ,uBAAuB,mBAAmBA,QAAM,EAAE;;CAErE,CAAC;AAEF,MAAa,sBAAsB,eAAe;CACjD,UAAU;CACV,cAAc,EAAE,OAAO;CACvB,UACE,YACD,OAAO,EAAE,qBAAoE;AAC5E,MAAI;GACH,MAAM,SAAS,MAAM,QAAQ,OAAO,KAAK,oBAAoB,EAAE,aAAaA,SAAO,CAAC;AACpF,UAAO,EACN,QAAQ,QAAQ,uBAAuB,OAAO,eAAe,OAAO,mBACpE;UACM;AACP,UAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,iCAAiC,CAAC,EAAE;;;CAGpE,CAAC;AAEF,MAAa,iBAAiB,eAAe;CAC5C,cAAc,EAAE,qBAAqB;CACrC,gBAEE,EAAE,iDAA0B;AAC5B,SAAO,EAAE,QAAQC,sBAAoB,kBAAkB,EAAE,EAAE;;CAE7D,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { createAnalyzer } from "../analyzer.mjs";
2
+ import { data } from "./core.mjs";
3
+
4
+ //#region src/transaction-analyzer/rules/functions.ts
5
+ const moveFunctions = createAnalyzer({
6
+ cacheKey: "moveFunctions@1.0.0",
7
+ dependencies: { data },
8
+ analyze: ({ client }) => async ({ data: data$1 }) => {
9
+ const issues = [];
10
+ const functions = new Set(data$1.commands.filter((cmd) => cmd.$kind === "MoveCall").map((cmd) => `${cmd.MoveCall.package}::${cmd.MoveCall.module}::${cmd.MoveCall.function}`));
11
+ const results = await Promise.all(Array.from(functions).map(async (functionId) => {
12
+ const [packageId, moduleName, name] = functionId.split("::");
13
+ try {
14
+ return (await client.core.getMoveFunction({
15
+ packageId,
16
+ moduleName,
17
+ name
18
+ })).function;
19
+ } catch {
20
+ issues.push({ message: `Failed to fetch Move function: ${functionId}` });
21
+ return null;
22
+ }
23
+ }));
24
+ if (issues.length) return { issues };
25
+ return { result: results.filter((fn) => fn !== null) };
26
+ }
27
+ });
28
+
29
+ //#endregion
30
+ export { moveFunctions };
31
+ //# sourceMappingURL=functions.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.mjs","names":["data"],"sources":["../../../src/transaction-analyzer/rules/functions.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ClientWithCoreApi, HaneulClientTypes } from '@haneullabs/haneul/client';\nimport type { TransactionAnalysisIssue } from '../analyzer.js';\nimport { createAnalyzer } from '../analyzer.js';\nimport { data } from './core.js';\n\nexport const moveFunctions = createAnalyzer({\n\tcacheKey: 'moveFunctions@1.0.0',\n\tdependencies: { data },\n\tanalyze:\n\t\t({ client }: { client: ClientWithCoreApi }) =>\n\t\tasync ({ data }) => {\n\t\t\tconst issues: TransactionAnalysisIssue[] = [];\n\n\t\t\tconst functions = new Set(\n\t\t\t\tdata.commands\n\t\t\t\t\t.filter((cmd) => cmd.$kind === 'MoveCall')\n\t\t\t\t\t.map(\n\t\t\t\t\t\t(cmd) => `${cmd.MoveCall.package}::${cmd.MoveCall.module}::${cmd.MoveCall.function}`,\n\t\t\t\t\t),\n\t\t\t);\n\n\t\t\tconst results = await Promise.all(\n\t\t\t\tArray.from(functions).map(async (functionId) => {\n\t\t\t\t\tconst [packageId, moduleName, name] = functionId.split('::');\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst res = await client.core.getMoveFunction({ packageId, moduleName, name });\n\t\t\t\t\t\treturn res.function;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tissues.push({ message: `Failed to fetch Move function: ${functionId}` });\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tif (issues.length) {\n\t\t\t\treturn { issues };\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tresult: results.filter((fn): fn is HaneulClientTypes.FunctionResponse => fn !== null),\n\t\t\t};\n\t\t},\n});\n"],"mappings":";;;;AAQA,MAAa,gBAAgB,eAAe;CAC3C,UAAU;CACV,cAAc,EAAE,MAAM;CACtB,UACE,EAAE,aACH,OAAO,EAAE,mBAAW;EACnB,MAAM,SAAqC,EAAE;EAE7C,MAAM,YAAY,IAAI,IACrBA,OAAK,SACH,QAAQ,QAAQ,IAAI,UAAU,WAAW,CACzC,KACC,QAAQ,GAAG,IAAI,SAAS,QAAQ,IAAI,IAAI,SAAS,OAAO,IAAI,IAAI,SAAS,WAC1E,CACF;EAED,MAAM,UAAU,MAAM,QAAQ,IAC7B,MAAM,KAAK,UAAU,CAAC,IAAI,OAAO,eAAe;GAC/C,MAAM,CAAC,WAAW,YAAY,QAAQ,WAAW,MAAM,KAAK;AAC5D,OAAI;AAEH,YADY,MAAM,OAAO,KAAK,gBAAgB;KAAE;KAAW;KAAY;KAAM,CAAC,EACnE;WACJ;AACP,WAAO,KAAK,EAAE,SAAS,kCAAkC,cAAc,CAAC;AACxE,WAAO;;IAEP,CACF;AAED,MAAI,OAAO,OACV,QAAO,EAAE,QAAQ;AAGlB,SAAO,EACN,QAAQ,QAAQ,QAAQ,OAAiD,OAAO,KAAK,EACrF;;CAEH,CAAC"}