@seams/wallet 0.9.0 → 0.9.2

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 (60) hide show
  1. package/README.md +3 -3
  2. package/dist/.build-inputs.sha256 +1 -1
  3. package/dist/esm/core/signingEngine/chains/evm/bytes.js +15 -1
  4. package/dist/esm/core/signingEngine/flows/signEvmFamily/signingFlow.js +1 -1
  5. package/dist/esm/core/signingEngine/flows/signNear/shared/ed25519YaoNormalSigning.js +84 -38
  6. package/dist/esm/core/signingEngine/flows/signNear/signTransactions.js +49 -2
  7. package/dist/esm/core/signingEngine/uiConfirm/ui/confirm-surface-resize.js +173 -2
  8. package/dist/esm/core/signingEngine/uiConfirm/ui/surface-resize-events.js +6 -1
  9. package/dist/esm/core/signingEngine/uiConfirm/ui/transaction-display/abi/abiDecode.js +315 -0
  10. package/dist/esm/core/signingEngine/uiConfirm/ui/transaction-display/abi/enrichDisplayModelWithAbi.js +77 -0
  11. package/dist/esm/core/signingEngine/uiConfirm/ui/transaction-display/formatters.js +10 -1
  12. package/dist/esm/core/signingEngine/uiConfirm/ui/transaction-display/renderers/fallback.js +52 -0
  13. package/dist/esm/core/signingEngine/uiConfirm/ui/transaction-display/renderers/types.js +62 -0
  14. package/dist/esm/core/signingEngine/uiConfirm/ui/transaction-display/tree.js +249 -0
  15. package/dist/esm/sdk/{host-B1CdRGoI.js → host-c1__wJwz.js} +1 -1
  16. package/dist/esm/sdk/{runtime-auth-tgfe70hU.js → runtime-auth-BKFyLISf.js} +1 -1
  17. package/dist/{public/sdk/runtime-device-link-BUxuQupR.js → esm/sdk/runtime-device-link-ENxdEXQW.js} +1 -1
  18. package/dist/{public/sdk/runtime-ecdsa-tempo-DOBk_EtI.js → esm/sdk/runtime-ecdsa-tempo-DhGEb9U7.js} +1 -1
  19. package/dist/esm/sdk/{runtime-email-otp-CsAJKvYC.js → runtime-email-otp-dgsP7XZi.js} +1 -1
  20. package/dist/esm/sdk/{runtime-export-7REbcnBl.js → runtime-export-D2RCm5Gk.js} +1 -1
  21. package/dist/esm/sdk/{runtime-near-BA0DQf6H.js → runtime-near-Bf-9MFBQ.js} +1 -1
  22. package/dist/esm/sdk/{runtime-preferences-cRViPE8a.js → runtime-preferences-LQ8SPE7o.js} +1 -1
  23. package/dist/esm/sdk/{runtime-recovery-RRc8Yz1y.js → runtime-recovery-BuEzJzuZ.js} +1 -1
  24. package/dist/esm/sdk/shared-8ffIBYw2.js +6 -0
  25. package/dist/esm/sdk/signNear-BhTkDm2-.js +1 -0
  26. package/dist/esm/sdk/wallet-iframe-host-ecdsa.js +1 -1
  27. package/dist/esm/sdk/wallet-iframe-host-full.js +1 -1
  28. package/dist/esm/sdk/wallet-iframe-host-near.js +1 -1
  29. package/dist/esm/sdk/wallet-iframe-host-runtime.js +1 -1
  30. package/dist/esm/utils/intentDigest.js +59 -1
  31. package/dist/public/headers.manifest.json +1 -1
  32. package/dist/public/sdk/{host-B1CdRGoI.js → host-c1__wJwz.js} +1 -1
  33. package/dist/public/sdk/{runtime-auth-tgfe70hU.js → runtime-auth-BKFyLISf.js} +1 -1
  34. package/dist/{esm/sdk/runtime-device-link-BUxuQupR.js → public/sdk/runtime-device-link-ENxdEXQW.js} +1 -1
  35. package/dist/{esm/sdk/runtime-ecdsa-tempo-DOBk_EtI.js → public/sdk/runtime-ecdsa-tempo-DhGEb9U7.js} +1 -1
  36. package/dist/public/sdk/{runtime-email-otp-CsAJKvYC.js → runtime-email-otp-dgsP7XZi.js} +1 -1
  37. package/dist/public/sdk/{runtime-export-7REbcnBl.js → runtime-export-D2RCm5Gk.js} +1 -1
  38. package/dist/public/sdk/{runtime-near-BA0DQf6H.js → runtime-near-Bf-9MFBQ.js} +1 -1
  39. package/dist/public/sdk/{runtime-preferences-cRViPE8a.js → runtime-preferences-LQ8SPE7o.js} +1 -1
  40. package/dist/public/sdk/{runtime-recovery-RRc8Yz1y.js → runtime-recovery-BuEzJzuZ.js} +1 -1
  41. package/dist/public/sdk/shared-8ffIBYw2.js +6 -0
  42. package/dist/public/sdk/signNear-BhTkDm2-.js +1 -0
  43. package/dist/public/sdk/wallet-iframe-host-ecdsa.js +1 -1
  44. package/dist/public/sdk/wallet-iframe-host-full.js +1 -1
  45. package/dist/public/sdk/wallet-iframe-host-near.js +1 -1
  46. package/dist/public/sdk/wallet-iframe-host-runtime.js +1 -1
  47. package/dist/public/wallet-assets.manifest.json +26 -26
  48. package/dist/public/wallet-service/index.html +4 -4
  49. package/dist/types/wallet/src/core/signingEngine/flows/signNear/shared/ed25519YaoNormalSigning.d.ts +16 -4
  50. package/dist/types/wallet/src/core/signingEngine/flows/signNear/shared/signatureOnlySigning.d.ts +3 -3
  51. package/dist/types/wallet/src/core/signingEngine/nonce/nearTransactionReadiness.d.ts +3 -0
  52. package/dist/types/wallet/src/core/signingEngine/stepUpConfirmation/confirmOperation.d.ts +3 -1
  53. package/dist/types/wallet/src/core/signingEngine/uiConfirm/handlers/flows/signing.d.ts +2 -0
  54. package/dist/types/wallet/src/core/signingEngine/uiConfirm/handlers/handlePromptFromWorker.d.ts +2 -0
  55. package/dist/types/wallet/src/core/signingEngine/uiConfirm/uiConfirm.types.d.ts +3 -0
  56. package/package.json +1 -1
  57. package/dist/esm/sdk/shared-DdfxBUGY.js +0 -6
  58. package/dist/esm/sdk/signNear-CO5bx24Z.js +0 -1
  59. package/dist/public/sdk/shared-DdfxBUGY.js +0 -6
  60. package/dist/public/sdk/signNear-CO5bx24Z.js +0 -1
@@ -0,0 +1,315 @@
1
+ import { keccak256Bytes } from "../../../../../../shared-ts/src/utils/keccak.js";
2
+ import { bytesToHex, hexToBytes } from "../../../../chains/evm/bytes.js";
3
+ import { deriveSelectorFromHexData, normalizeHexData, normalizeHexSelector } from "../../../../chains/evm/display/normalization.js";
4
+ //#region src/core/signingEngine/uiConfirm/ui/transaction-display/abi/abiDecode.ts
5
+ const WORD_SIZE = 32;
6
+ const MAX_DECODE_ARRAY_LENGTH = 256;
7
+ const ABI_FUNCTION_LOOKUP_CACHE = /* @__PURE__ */ new WeakMap();
8
+ function selectorFromDataHex(dataHex) {
9
+ return deriveSelectorFromHexData(dataHex) || null;
10
+ }
11
+ function buildAbiFunctionEntries(abi) {
12
+ const out = [];
13
+ for (const entry of abi) {
14
+ if (!entry || typeof entry !== "object") continue;
15
+ const type = String(entry.type || "function").trim();
16
+ if (type !== "" && type !== "function") continue;
17
+ const name = String(entry.name || "").trim();
18
+ if (!name) continue;
19
+ const rawInputs = entry.inputs;
20
+ const inputs = Array.isArray(rawInputs) ? rawInputs : [];
21
+ const selector = selectorFromSignature(`${name}(${inputs.map((input) => canonicalAbiTypeFromParameter(input)).join(",")})`);
22
+ if (!selector) continue;
23
+ const normalizedInputs = normalizeAbiComponentNodes(inputs);
24
+ out.push({
25
+ name,
26
+ selector,
27
+ inputs: normalizedInputs
28
+ });
29
+ }
30
+ return out;
31
+ }
32
+ function resolveAbiFunctionLookup(abi) {
33
+ if (!Array.isArray(abi) || abi.length === 0) return void 0;
34
+ const cached = ABI_FUNCTION_LOOKUP_CACHE.get(abi);
35
+ if (cached) return cached;
36
+ const entries = buildAbiFunctionEntries(abi);
37
+ if (!entries.length) return void 0;
38
+ const bySelector = /* @__PURE__ */ new Map();
39
+ for (const entry of entries) if (!bySelector.has(entry.selector)) bySelector.set(entry.selector, entry);
40
+ const lookup = { bySelector };
41
+ ABI_FUNCTION_LOOKUP_CACHE.set(abi, lookup);
42
+ return lookup;
43
+ }
44
+ function selectorFromSignature(signature) {
45
+ const normalized = String(signature || "").trim();
46
+ if (!normalized) return null;
47
+ return normalizeHexSelector(bytesToHex(keccak256Bytes(new TextEncoder().encode(normalized)).slice(0, 4))) || null;
48
+ }
49
+ function canonicalAbiTypeFromParameter(input) {
50
+ const type = String(input?.type || "").trim().toLowerCase();
51
+ if (!type) return "";
52
+ const components = Array.isArray(input?.components) ? input.components : [];
53
+ if (type.startsWith("tuple")) {
54
+ const suffix = type.slice(5);
55
+ return `${`(${components.map((component) => canonicalAbiTypeFromParameter(component)).join(",")})`}${suffix}`;
56
+ }
57
+ return type;
58
+ }
59
+ function normalizeAbiComponentNodes(inputs) {
60
+ const out = [];
61
+ for (let index = 0; index < inputs.length; index += 1) {
62
+ const input = inputs[index];
63
+ const typeName = String(input?.type || "").trim().toLowerCase();
64
+ if (!typeName) continue;
65
+ const typeNode = parseAbiTypeNode({
66
+ type: typeName,
67
+ components: input?.components
68
+ });
69
+ if (!typeNode) continue;
70
+ const name = String(input?.name || "").trim();
71
+ out.push({
72
+ name: name || `arg${index}`,
73
+ typeName,
74
+ typeNode
75
+ });
76
+ }
77
+ return out;
78
+ }
79
+ function parseAbiTypeNode(args) {
80
+ const baseTypeRaw = String(args.type || "").trim().toLowerCase();
81
+ if (!baseTypeRaw) return null;
82
+ let baseType = baseTypeRaw;
83
+ const arrayDimensions = [];
84
+ while (baseType.endsWith("]")) {
85
+ const openBracket = baseType.lastIndexOf("[");
86
+ if (openBracket < 0) return null;
87
+ const rawLength = baseType.slice(openBracket + 1, -1).trim();
88
+ if (!/^\d*$/.test(rawLength)) return null;
89
+ const length = rawLength === "" ? null : Number.parseInt(rawLength, 10);
90
+ if (length != null && (!Number.isFinite(length) || length < 0)) return null;
91
+ arrayDimensions.push(length);
92
+ baseType = baseType.slice(0, openBracket);
93
+ }
94
+ let node = null;
95
+ if (baseType === "tuple") {
96
+ const normalizedComponents = normalizeAbiComponentNodes(Array.isArray(args.components) ? args.components : []);
97
+ node = {
98
+ kind: "tuple",
99
+ canonicalType: `(${normalizedComponents.map((component) => component.typeNode.canonicalType).join(",")})`,
100
+ dynamic: normalizedComponents.some((component) => component.typeNode.dynamic),
101
+ components: normalizedComponents
102
+ };
103
+ } else node = {
104
+ kind: "scalar",
105
+ typeName: baseType,
106
+ canonicalType: baseType,
107
+ dynamic: baseType === "bytes" || baseType === "string"
108
+ };
109
+ for (let i = arrayDimensions.length - 1; i >= 0; i -= 1) {
110
+ const length = arrayDimensions[i];
111
+ node = {
112
+ kind: "array",
113
+ canonicalType: `${node.canonicalType}[${length == null ? "" : String(length)}]`,
114
+ dynamic: length == null || node.dynamic,
115
+ item: node,
116
+ length
117
+ };
118
+ }
119
+ return node;
120
+ }
121
+ function readWord(bytes, offset) {
122
+ if (!Number.isInteger(offset) || offset < 0) return null;
123
+ if (offset + WORD_SIZE > bytes.length) return null;
124
+ return bytes.slice(offset, offset + WORD_SIZE);
125
+ }
126
+ function readWordBigInt(bytes, offset) {
127
+ const word = readWord(bytes, offset);
128
+ if (!word) return null;
129
+ let out = 0n;
130
+ for (const byte of word) out = (out << 8n) + BigInt(byte);
131
+ return out;
132
+ }
133
+ function readWordNumber(bytes, offset) {
134
+ const value = readWordBigInt(bytes, offset);
135
+ if (value == null) return null;
136
+ if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < 0n) return null;
137
+ return Number(value);
138
+ }
139
+ function staticWordLength(typeNode) {
140
+ if (typeNode.dynamic) return 1;
141
+ if (typeNode.kind === "scalar") return 1;
142
+ if (typeNode.kind === "tuple") return typeNode.components.reduce((sum, component) => sum + staticWordLength(component.typeNode), 0);
143
+ if (typeNode.length == null) return 1;
144
+ return typeNode.length * staticWordLength(typeNode.item);
145
+ }
146
+ function decodeScalar(typeName, bytes, offset) {
147
+ const normalizedType = String(typeName || "").trim().toLowerCase();
148
+ if (!normalizedType) return null;
149
+ if (normalizedType === "bytes") {
150
+ const length = readWordNumber(bytes, offset);
151
+ if (length == null) return null;
152
+ const start = offset + WORD_SIZE;
153
+ const end = start + length;
154
+ if (end > bytes.length) return null;
155
+ return bytesToHex(bytes.slice(start, end)).toLowerCase();
156
+ }
157
+ if (normalizedType === "string") {
158
+ const length = readWordNumber(bytes, offset);
159
+ if (length == null) return null;
160
+ const start = offset + WORD_SIZE;
161
+ const end = start + length;
162
+ if (end > bytes.length) return null;
163
+ const valueBytes = bytes.slice(start, end);
164
+ try {
165
+ return new TextDecoder().decode(valueBytes);
166
+ } catch {
167
+ return bytesToHex(valueBytes).toLowerCase();
168
+ }
169
+ }
170
+ const word = readWord(bytes, offset);
171
+ if (!word) return null;
172
+ const wordValue = readWordBigInt(bytes, offset);
173
+ if (wordValue == null) return null;
174
+ if (normalizedType === "bool") return wordValue !== 0n;
175
+ if (normalizedType === "address") return bytesToHex(word.slice(12)).toLowerCase();
176
+ if (normalizedType === "function") return bytesToHex(word.slice(0, 24)).toLowerCase();
177
+ const fixedBytesMatch = normalizedType.match(/^bytes(\d{1,2})$/);
178
+ if (fixedBytesMatch) {
179
+ const byteLength = Number.parseInt(fixedBytesMatch[1], 10);
180
+ if (!Number.isFinite(byteLength) || byteLength <= 0 || byteLength > 32) return null;
181
+ return bytesToHex(word.slice(0, byteLength)).toLowerCase();
182
+ }
183
+ if (normalizedType.match(/^uint(\d{0,3})$/)) return wordValue.toString(10);
184
+ const intMatch = normalizedType.match(/^int(\d{0,3})$/);
185
+ if (intMatch) {
186
+ const bitsRaw = intMatch[1];
187
+ const bits = bitsRaw ? Number.parseInt(bitsRaw, 10) : 256;
188
+ if (!Number.isFinite(bits) || bits <= 0 || bits > 256 || bits % 8 !== 0) return wordValue.toString(10);
189
+ const bitWidth = BigInt(bits);
190
+ const modulus = 1n << bitWidth;
191
+ return (wordValue >= 1n << bitWidth - 1n ? wordValue - modulus : wordValue).toString(10);
192
+ }
193
+ return bytesToHex(word).toLowerCase();
194
+ }
195
+ function decodeTypeAt(typeNode, bytes, offset) {
196
+ if (typeNode.kind === "scalar") return decodeScalar(typeNode.typeName, bytes, offset);
197
+ if (typeNode.kind === "tuple") {
198
+ const decodedItems = decodeTupleComponents(typeNode.components, bytes, offset);
199
+ if (!decodedItems) return null;
200
+ const out = {};
201
+ for (let i = 0; i < typeNode.components.length; i += 1) {
202
+ const component = typeNode.components[i];
203
+ const baseName = String(component.name || "").trim() || `item${i}`;
204
+ let name = baseName;
205
+ let counter = 1;
206
+ while (Object.prototype.hasOwnProperty.call(out, name)) {
207
+ counter += 1;
208
+ name = `${baseName}_${counter}`;
209
+ }
210
+ out[name] = decodedItems[i];
211
+ }
212
+ return out;
213
+ }
214
+ const expectedLength = typeNode.length;
215
+ const isDynamicArray = expectedLength == null;
216
+ const arrayLength = isDynamicArray ? readWordNumber(bytes, offset) : expectedLength;
217
+ if (arrayLength == null) return null;
218
+ if (arrayLength < 0 || arrayLength > MAX_DECODE_ARRAY_LENGTH) return null;
219
+ const baseOffset = isDynamicArray ? offset + WORD_SIZE : offset;
220
+ const items = [];
221
+ if (typeNode.item.dynamic) {
222
+ for (let i = 0; i < arrayLength; i += 1) {
223
+ const itemRelativeOffset = readWordNumber(bytes, baseOffset + i * WORD_SIZE);
224
+ if (itemRelativeOffset == null) return null;
225
+ const decoded = decodeTypeAt(typeNode.item, bytes, baseOffset + itemRelativeOffset);
226
+ if (decoded == null) return null;
227
+ items.push(decoded);
228
+ }
229
+ return items;
230
+ }
231
+ const itemWords = staticWordLength(typeNode.item);
232
+ for (let i = 0; i < arrayLength; i += 1) {
233
+ const itemOffset = baseOffset + i * itemWords * WORD_SIZE;
234
+ const decoded = decodeTypeAt(typeNode.item, bytes, itemOffset);
235
+ if (decoded == null) return null;
236
+ items.push(decoded);
237
+ }
238
+ return items;
239
+ }
240
+ function decodeTupleComponents(components, bytes, tupleOffset) {
241
+ let cursorWords = 0;
242
+ const headOffsets = [];
243
+ for (const component of components) {
244
+ headOffsets.push(cursorWords * WORD_SIZE);
245
+ cursorWords += component.typeNode.dynamic ? 1 : staticWordLength(component.typeNode);
246
+ }
247
+ const out = [];
248
+ for (let i = 0; i < components.length; i += 1) {
249
+ const component = components[i];
250
+ const headOffset = tupleOffset + headOffsets[i];
251
+ if (component.typeNode.dynamic) {
252
+ const relativeOffset = readWordNumber(bytes, headOffset);
253
+ if (relativeOffset == null) return null;
254
+ const decoded = decodeTypeAt(component.typeNode, bytes, tupleOffset + relativeOffset);
255
+ if (decoded == null) return null;
256
+ out.push(decoded);
257
+ continue;
258
+ }
259
+ const decoded = decodeTypeAt(component.typeNode, bytes, headOffset);
260
+ if (decoded == null) return null;
261
+ out.push(decoded);
262
+ }
263
+ return out;
264
+ }
265
+ function formatDecodedArgumentsJsonText(args) {
266
+ if (!args.length) return void 0;
267
+ const payload = {};
268
+ for (let index = 0; index < args.length; index += 1) {
269
+ const arg = args[index];
270
+ const baseKey = String(arg.key || "").trim() || `arg${index}`;
271
+ let nextKey = baseKey;
272
+ let suffix = 2;
273
+ while (Object.prototype.hasOwnProperty.call(payload, nextKey)) {
274
+ nextKey = `${baseKey}_${suffix}`;
275
+ suffix += 1;
276
+ }
277
+ payload[nextKey] = arg.value;
278
+ }
279
+ try {
280
+ return JSON.stringify(payload, null, 2);
281
+ } catch {
282
+ return;
283
+ }
284
+ }
285
+ function decodeCallDataWithAbi(args) {
286
+ const selector = selectorFromDataHex(args.dataHex);
287
+ if (!selector) return void 0;
288
+ const abiLookup = resolveAbiFunctionLookup(args.abi);
289
+ if (!abiLookup) return void 0;
290
+ const matched = abiLookup.bySelector.get(selector);
291
+ if (!matched) return void 0;
292
+ const normalizedDataHex = normalizeHexData(args.dataHex, { lowercase: true });
293
+ let argsBytes;
294
+ try {
295
+ const bytes = hexToBytes(normalizedDataHex);
296
+ if (bytes.length < 4) return { functionLabel: `${matched.name}()` };
297
+ argsBytes = bytes.slice(4);
298
+ } catch {
299
+ return { functionLabel: `${matched.name}()` };
300
+ }
301
+ const decodedValues = decodeTupleComponents(matched.inputs, argsBytes, 0);
302
+ if (!decodedValues) return { functionLabel: `${matched.name}()` };
303
+ const decodedArguments = matched.inputs.map((input, index) => ({
304
+ key: String(input.name || "").trim() || `arg${index}`,
305
+ value: decodedValues[index]
306
+ }));
307
+ return {
308
+ functionLabel: `${matched.name}()`,
309
+ decodedArgumentsJsonText: formatDecodedArgumentsJsonText(decodedArguments)
310
+ };
311
+ }
312
+ //#endregion
313
+ export { decodeCallDataWithAbi };
314
+
315
+ //# sourceMappingURL=abiDecode.js.map
@@ -0,0 +1,77 @@
1
+ import { decodeCallDataWithAbi } from "./abiDecode.js";
2
+ //#region src/core/signingEngine/uiConfirm/ui/transaction-display/abi/enrichDisplayModelWithAbi.ts
3
+ function isGenericContractCallOperation(operation) {
4
+ return operation.kind === "generic.contractCall";
5
+ }
6
+ function rewriteCallingLabel(label, functionLabel) {
7
+ const normalized = String(label || "").trim();
8
+ const match = normalized.match(/^Calling\s+.+?\s+using\s+(.+)$/i);
9
+ if (!match) return normalized;
10
+ return `Calling ${functionLabel} using ${match[1]}`;
11
+ }
12
+ function isDataField(field) {
13
+ return String(field.label || "").trim().toLowerCase() === "data";
14
+ }
15
+ function rewriteDataFieldWithDecodedArgs(args) {
16
+ const next = Array.isArray(args.fields) ? [...args.fields] : [];
17
+ const dataFieldIndex = next.findIndex((field) => isDataField(field));
18
+ const existingDataField = dataFieldIndex >= 0 ? next[dataFieldIndex] : void 0;
19
+ const rawFallbackValue = String(existingDataField?.value || "").trim() || String(args.fallbackRawDataHex || "").trim();
20
+ const rewrittenDataField = {
21
+ ...existingDataField || { label: "Data" },
22
+ value: args.decodedArgsJsonText,
23
+ renderAs: "file-content",
24
+ hideChevron: typeof existingDataField?.hideChevron === "boolean" ? existingDataField.hideChevron : true,
25
+ contentVariants: {
26
+ decoded: args.decodedArgsJsonText,
27
+ raw: rawFallbackValue,
28
+ defaultMode: "decoded"
29
+ }
30
+ };
31
+ if (dataFieldIndex >= 0) {
32
+ next[dataFieldIndex] = rewrittenDataField;
33
+ return next;
34
+ }
35
+ next.push(rewrittenDataField);
36
+ return next;
37
+ }
38
+ function maybeDecodeOperationWithAbi(operation) {
39
+ const hint = operation.abiDecodeHint;
40
+ if (!hint || !Array.isArray(hint.abi) || hint.abi.length === 0) return operation;
41
+ const decoded = decodeCallDataWithAbi({
42
+ dataHex: hint.dataHex,
43
+ abi: hint.abi
44
+ });
45
+ if (!decoded) return operation;
46
+ const fields = decoded.decodedArgumentsJsonText ? rewriteDataFieldWithDecodedArgs({
47
+ fields: operation.fields,
48
+ decodedArgsJsonText: decoded.decodedArgumentsJsonText,
49
+ fallbackRawDataHex: hint.dataHex
50
+ }) : operation.fields;
51
+ return {
52
+ ...operation,
53
+ label: rewriteCallingLabel(operation.label, decoded.functionLabel),
54
+ fields
55
+ };
56
+ }
57
+ function enrichOperation(operation) {
58
+ const children = Array.isArray(operation.children) ? operation.children.map((child) => enrichOperation(child)) : operation.children;
59
+ const operationWithChildren = children === operation.children ? operation : {
60
+ ...operation,
61
+ children
62
+ };
63
+ if (!isGenericContractCallOperation(operationWithChildren)) return operationWithChildren;
64
+ return maybeDecodeOperationWithAbi(operationWithChildren);
65
+ }
66
+ function enrichDisplayModelWithAbi(model) {
67
+ if (!Array.isArray(model.operations) || model.operations.length === 0) return model;
68
+ const operations = model.operations.map((operation) => enrichOperation(operation));
69
+ return {
70
+ ...model,
71
+ operations
72
+ };
73
+ }
74
+ //#endregion
75
+ export { enrichDisplayModelWithAbi };
76
+
77
+ //# sourceMappingURL=enrichDisplayModelWithAbi.js.map
@@ -1,4 +1,13 @@
1
1
  //#region src/core/signingEngine/uiConfirm/ui/transaction-display/formatters.ts
2
+ function formatArgs(args) {
3
+ if (!args) return "";
4
+ if (typeof args === "string") return args;
5
+ try {
6
+ return JSON.stringify(args, (_k, v) => typeof v === "bigint" ? v.toString() : v, 2);
7
+ } catch {
8
+ return String(args);
9
+ }
10
+ }
2
11
  function formatDeposit(deposit) {
3
12
  if (!deposit || deposit === "0") return "0 NEAR";
4
13
  try {
@@ -43,6 +52,6 @@ function formatCodeSize(code) {
43
52
  return "unknown";
44
53
  }
45
54
  //#endregion
46
- export { formatCodeSize, formatDeposit, formatGas, shortenPubkey };
55
+ export { formatArgs, formatCodeSize, formatDeposit, formatGas, shortenPubkey };
47
56
 
48
57
  //# sourceMappingURL=formatters.js.map
@@ -0,0 +1,52 @@
1
+ import { buildFieldNodes } from "./types.js";
2
+ //#region src/core/signingEngine/uiConfirm/ui/transaction-display/renderers/fallback.ts
3
+ const renderFallbackDisplayOperation = ({ operation, depth, path, renderChild }) => {
4
+ const opId = String(operation.id || "").trim() || `op-${path}`;
5
+ const contractAddress = (() => {
6
+ const raw = String(operation.to || "").trim();
7
+ return /^0x[0-9a-fA-F]{40}$/.test(raw) ? raw : void 0;
8
+ })();
9
+ const description = String(operation.description || "").trim();
10
+ const childOps = Array.isArray(operation.children) ? operation.children.map((child, childIndex) => renderChild(child, depth + 1, `${path}.${childIndex}`)) : [];
11
+ const fieldNodes = buildFieldNodes(opId, operation.fields);
12
+ const metadataNodes = description ? [{
13
+ id: `${opId}-description`,
14
+ label: description,
15
+ type: "file",
16
+ open: false
17
+ }] : [];
18
+ if (operation.kind === "raw.fallback") {
19
+ const rawValue = String(operation.raw || "").trim();
20
+ if (rawValue) metadataNodes.push({
21
+ id: `${opId}-raw`,
22
+ label: "Raw payload",
23
+ type: "file",
24
+ open: false,
25
+ content: rawValue
26
+ });
27
+ }
28
+ const children = [
29
+ ...metadataNodes,
30
+ ...fieldNodes,
31
+ ...childOps
32
+ ];
33
+ if (children.length === 0) return {
34
+ id: opId,
35
+ label: String(operation.label || operation.kind),
36
+ type: "file",
37
+ open: false,
38
+ contractAddress
39
+ };
40
+ return {
41
+ id: opId,
42
+ label: String(operation.label || operation.kind),
43
+ type: "folder",
44
+ open: depth < 1,
45
+ contractAddress,
46
+ children
47
+ };
48
+ };
49
+ //#endregion
50
+ export { renderFallbackDisplayOperation };
51
+
52
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1,62 @@
1
+ //#region src/core/signingEngine/uiConfirm/ui/transaction-display/renderers/types.ts
2
+ function sanitizeContentVariants(variants) {
3
+ if (!variants) return void 0;
4
+ const decoded = String(variants.decoded || "");
5
+ const raw = String(variants.raw || "");
6
+ if (!decoded || !raw) return void 0;
7
+ if (decoded === raw) return void 0;
8
+ return {
9
+ decoded,
10
+ raw,
11
+ defaultMode: variants.defaultMode === "raw" ? "raw" : "decoded"
12
+ };
13
+ }
14
+ function isZeroWeiDisplayField(label, value) {
15
+ if (!/Value \(wei\)$/i.test(label.trim())) return false;
16
+ const normalized = value.trim();
17
+ if (!normalized) return false;
18
+ if (normalized === "0") return true;
19
+ if (/^0x0+$/i.test(normalized)) return true;
20
+ try {
21
+ return BigInt(normalized) === 0n;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+ function buildFieldNodes(parentId, fields) {
27
+ if (!Array.isArray(fields) || fields.length === 0) return [];
28
+ return fields.flatMap((field, fieldIndex) => {
29
+ const label = String(field.label || "").trim();
30
+ const value = String(field.value || "");
31
+ const renderAs = field.renderAs || "inline";
32
+ if (isZeroWeiDisplayField(label, value)) return [];
33
+ if (renderAs === "file-content") {
34
+ const contentVariants = sanitizeContentVariants(field.contentVariants);
35
+ const content = contentVariants?.defaultMode === "raw" ? contentVariants.raw : contentVariants?.decoded || value;
36
+ return [{
37
+ id: `${parentId}-field-${fieldIndex}`,
38
+ label: label ? `${label}:` : "",
39
+ fieldLabel: label ? `${label}:` : void 0,
40
+ type: "file",
41
+ open: false,
42
+ content,
43
+ ...contentVariants ? { contentVariants } : {},
44
+ copyValue: typeof field.copyValue === "string" ? field.copyValue : void 0,
45
+ hideLabel: Boolean(field.hideLabel),
46
+ hideChevron: typeof field.hideChevron === "boolean" ? field.hideChevron : true
47
+ }];
48
+ }
49
+ return [{
50
+ id: `${parentId}-field-${fieldIndex}`,
51
+ label: label ? `${label}: ${value}` : value,
52
+ fieldLabel: label ? `${label}:` : void 0,
53
+ type: "file",
54
+ open: false,
55
+ copyValue: typeof field.copyValue === "string" ? field.copyValue : void 0
56
+ }];
57
+ });
58
+ }
59
+ //#endregion
60
+ export { buildFieldNodes };
61
+
62
+ //# sourceMappingURL=types.js.map