|
1 |
+ |
class ContractCall extends HTMLElement { |
|
2 |
+ |
// Constructor and lifecycle methods |
|
3 |
+ |
constructor() { |
|
4 |
+ |
super(); |
|
5 |
+ |
this.attachShadow({ mode: "open" }); |
|
6 |
+ |
this.loading = false; |
|
7 |
+ |
this.result = null; |
|
8 |
+ |
this.error = null; |
|
9 |
+ |
this.abi = null; |
|
10 |
+ |
this.methodData = null; |
|
11 |
+ |
this.contractAddress = ""; |
|
12 |
+ |
this.chainId = "0x1"; |
|
13 |
+ |
this.methodName = ""; |
|
14 |
+ |
this.methodArgs = []; |
|
15 |
+ |
this.abiUrl = ""; |
|
16 |
+ |
this.buttonText = "Call Contract"; |
|
17 |
+ |
this.isReadOnly = false; |
|
18 |
+ |
} |
|
19 |
+ |
|
|
20 |
+ |
static get observedAttributes() { |
|
21 |
+ |
return [ |
|
22 |
+ |
"contract-address", |
|
23 |
+ |
"chain-id", |
|
24 |
+ |
"method-name", |
|
25 |
+ |
"method-args", |
|
26 |
+ |
"abi-url", |
|
27 |
+ |
"abi", |
|
28 |
+ |
"button-text", |
|
29 |
+ |
"background", |
|
30 |
+ |
"foreground", |
|
31 |
+ |
"primary", |
|
32 |
+ |
"secondary", |
|
33 |
+ |
"border-radius", |
|
34 |
+ |
]; |
|
35 |
+ |
} |
|
36 |
+ |
|
|
37 |
+ |
attributeChangedCallback(name, oldValue, newValue) { |
|
38 |
+ |
if (oldValue === newValue) return; |
|
39 |
+ |
|
|
40 |
+ |
switch (name) { |
|
41 |
+ |
case "contract-address": |
|
42 |
+ |
this.contractAddress = newValue || ""; |
|
43 |
+ |
break; |
|
44 |
+ |
case "chain-id": |
|
45 |
+ |
this.chainId = newValue || "0x1"; |
|
46 |
+ |
break; |
|
47 |
+ |
case "method-name": |
|
48 |
+ |
this.methodName = newValue || ""; |
|
49 |
+ |
this.parseMethodFromAbi(); |
|
50 |
+ |
break; |
|
51 |
+ |
case "method-args": |
|
52 |
+ |
try { |
|
53 |
+ |
this.methodArgs = newValue ? JSON.parse(newValue) : []; |
|
54 |
+ |
} catch (e) { |
|
55 |
+ |
console.error("Invalid method-args JSON:", e); |
|
56 |
+ |
this.methodArgs = []; |
|
57 |
+ |
} |
|
58 |
+ |
break; |
|
59 |
+ |
case "abi-url": |
|
60 |
+ |
this.abiUrl = newValue || ""; |
|
61 |
+ |
if (this.abiUrl) { |
|
62 |
+ |
this.fetchAbi(); |
|
63 |
+ |
} |
|
64 |
+ |
break; |
|
65 |
+ |
case "abi": |
|
66 |
+ |
try { |
|
67 |
+ |
this.abi = newValue ? JSON.parse(newValue) : null; |
|
68 |
+ |
this.parseMethodFromAbi(); |
|
69 |
+ |
} catch (e) { |
|
70 |
+ |
console.error("Invalid ABI JSON:", e); |
|
71 |
+ |
this.abi = null; |
|
72 |
+ |
} |
|
73 |
+ |
break; |
|
74 |
+ |
case "button-text": |
|
75 |
+ |
this.buttonText = newValue || "Call Contract"; |
|
76 |
+ |
break; |
|
77 |
+ |
default: |
|
78 |
+ |
if ( |
|
79 |
+ |
[ |
|
80 |
+ |
"background", |
|
81 |
+ |
"foreground", |
|
82 |
+ |
"primary", |
|
83 |
+ |
"secondary", |
|
84 |
+ |
"border-radius", |
|
85 |
+ |
].includes(name) |
|
86 |
+ |
) { |
|
87 |
+ |
this.render(); |
|
88 |
+ |
} |
|
89 |
+ |
} |
|
90 |
+ |
} |
|
91 |
+ |
|
|
92 |
+ |
connectedCallback() { |
|
93 |
+ |
this.contractAddress = this.getAttribute("contract-address") || ""; |
|
94 |
+ |
this.chainId = this.getAttribute("chain-id") || "0x1"; |
|
95 |
+ |
this.methodName = this.getAttribute("method-name") || ""; |
|
96 |
+ |
this.buttonText = this.getAttribute("button-text") || "Call Contract"; |
|
97 |
+ |
this.abiUrl = this.getAttribute("abi-url") || ""; |
|
98 |
+ |
|
|
99 |
+ |
try { |
|
100 |
+ |
const methodArgsAttr = this.getAttribute("method-args"); |
|
101 |
+ |
this.methodArgs = methodArgsAttr ? JSON.parse(methodArgsAttr) : []; |
|
102 |
+ |
} catch (e) { |
|
103 |
+ |
console.error("Invalid method-args JSON:", e); |
|
104 |
+ |
this.methodArgs = []; |
|
105 |
+ |
} |
|
106 |
+ |
|
|
107 |
+ |
try { |
|
108 |
+ |
const abiAttr = this.getAttribute("abi"); |
|
109 |
+ |
this.abi = abiAttr ? JSON.parse(abiAttr) : null; |
|
110 |
+ |
} catch (e) { |
|
111 |
+ |
console.error("Invalid ABI JSON:", e); |
|
112 |
+ |
this.abi = null; |
|
113 |
+ |
} |
|
114 |
+ |
|
|
115 |
+ |
if (this.abiUrl && !this.abi) { |
|
116 |
+ |
this.fetchAbi(); |
|
117 |
+ |
} else if (this.abi) { |
|
118 |
+ |
this.parseMethodFromAbi(); |
|
119 |
+ |
} |
|
120 |
+ |
|
|
121 |
+ |
this.render(); |
|
122 |
+ |
} |
|
123 |
+ |
|
|
124 |
+ |
// ABI and method parsing |
|
125 |
+ |
async fetchAbi() { |
|
126 |
+ |
if (!this.abiUrl) return; |
|
127 |
+ |
|
|
128 |
+ |
try { |
|
129 |
+ |
this.loading = true; |
|
130 |
+ |
this.render(); |
|
131 |
+ |
|
|
132 |
+ |
const response = await fetch(this.abiUrl); |
|
133 |
+ |
if (!response.ok) { |
|
134 |
+ |
throw new Error(`Failed to fetch ABI: ${response.statusText}`); |
|
135 |
+ |
} |
|
136 |
+ |
|
|
137 |
+ |
this.abi = await response.json(); |
|
138 |
+ |
this.parseMethodFromAbi(); |
|
139 |
+ |
this.loading = false; |
|
140 |
+ |
this.render(); |
|
141 |
+ |
|
|
142 |
+ |
this.dispatchEvent( |
|
143 |
+ |
new CustomEvent("abi-loaded", { |
|
144 |
+ |
detail: { abi: this.abi }, |
|
145 |
+ |
}), |
|
146 |
+ |
); |
|
147 |
+ |
} catch (error) { |
|
148 |
+ |
console.error("Failed to fetch ABI:", error); |
|
149 |
+ |
this.error = error.message; |
|
150 |
+ |
this.loading = false; |
|
151 |
+ |
this.render(); |
|
152 |
+ |
|
|
153 |
+ |
this.dispatchEvent( |
|
154 |
+ |
new CustomEvent("abi-error", { |
|
155 |
+ |
detail: { error: error.message }, |
|
156 |
+ |
}), |
|
157 |
+ |
); |
|
158 |
+ |
} |
|
159 |
+ |
} |
|
160 |
+ |
|
|
161 |
+ |
parseMethodFromAbi() { |
|
162 |
+ |
if (!this.abi || !this.methodName) return; |
|
163 |
+ |
|
|
164 |
+ |
const method = this.abi.find( |
|
165 |
+ |
(item) => item.type === "function" && item.name === this.methodName, |
|
166 |
+ |
); |
|
167 |
+ |
|
|
168 |
+ |
if (!method) { |
|
169 |
+ |
this.error = `Method '${this.methodName}' not found in ABI`; |
|
170 |
+ |
this.render(); |
|
171 |
+ |
return; |
|
172 |
+ |
} |
|
173 |
+ |
|
|
174 |
+ |
this.methodData = method; |
|
175 |
+ |
this.isReadOnly = |
|
176 |
+ |
method.stateMutability === "view" || method.stateMutability === "pure"; |
|
177 |
+ |
this.error = null; |
|
178 |
+ |
this.render(); |
|
179 |
+ |
} |
|
180 |
+ |
|
|
181 |
+ |
// Contract interaction methods |
|
182 |
+ |
async callContract() { |
|
183 |
+ |
if (!window.ethereum) { |
|
184 |
+ |
this.error = "Please install a wallet extension like MetaMask"; |
|
185 |
+ |
this.render(); |
|
186 |
+ |
return; |
|
187 |
+ |
} |
|
188 |
+ |
|
|
189 |
+ |
if (!this.contractAddress || !this.methodName || !this.methodData) { |
|
190 |
+ |
this.error = "Missing required contract information"; |
|
191 |
+ |
this.render(); |
|
192 |
+ |
return; |
|
193 |
+ |
} |
|
194 |
+ |
|
|
195 |
+ |
try { |
|
196 |
+ |
this.loading = true; |
|
197 |
+ |
this.result = null; |
|
198 |
+ |
this.error = null; |
|
199 |
+ |
this.render(); |
|
200 |
+ |
|
|
201 |
+ |
// Check if wallet is connected |
|
202 |
+ |
const accounts = await window.ethereum.request({ |
|
203 |
+ |
method: "eth_accounts", |
|
204 |
+ |
}); |
|
205 |
+ |
|
|
206 |
+ |
if (accounts.length === 0) { |
|
207 |
+ |
throw new Error("Please connect your wallet first"); |
|
208 |
+ |
} |
|
209 |
+ |
|
|
210 |
+ |
// Check chain |
|
211 |
+ |
const currentChainId = await window.ethereum.request({ |
|
212 |
+ |
method: "eth_chainId", |
|
213 |
+ |
}); |
|
214 |
+ |
|
|
215 |
+ |
if (currentChainId !== this.chainId) { |
|
216 |
+ |
await this.switchChain(); |
|
217 |
+ |
} |
|
218 |
+ |
|
|
219 |
+ |
// Encode method call |
|
220 |
+ |
const methodSignature = this.encodeMethodSignature(); |
|
221 |
+ |
const encodedArgs = this.encodeArguments(); |
|
222 |
+ |
const data = methodSignature + encodedArgs; |
|
223 |
+ |
|
|
224 |
+ |
let result; |
|
225 |
+ |
|
|
226 |
+ |
if (this.isReadOnly) { |
|
227 |
+ |
// For read-only methods, use eth_call |
|
228 |
+ |
result = await window.ethereum.request({ |
|
229 |
+ |
method: "eth_call", |
|
230 |
+ |
params: [ |
|
231 |
+ |
{ |
|
232 |
+ |
to: this.contractAddress, |
|
233 |
+ |
data: data, |
|
234 |
+ |
}, |
|
235 |
+ |
"latest", |
|
236 |
+ |
], |
|
237 |
+ |
}); |
|
238 |
+ |
this.result = this.decodeResult(result); |
|
239 |
+ |
} else { |
|
240 |
+ |
// For write methods, send transaction |
|
241 |
+ |
const txHash = await window.ethereum.request({ |
|
242 |
+ |
method: "eth_sendTransaction", |
|
243 |
+ |
params: [ |
|
244 |
+ |
{ |
|
245 |
+ |
from: accounts[0], |
|
246 |
+ |
to: this.contractAddress, |
|
247 |
+ |
data: data, |
|
248 |
+ |
gas: "0x30D40", // 200000 in hex - higher gas limit for contract calls |
|
249 |
+ |
gasPrice: "0x4A817C800", // 20 gwei in hex |
|
250 |
+ |
}, |
|
251 |
+ |
], |
|
252 |
+ |
}); |
|
253 |
+ |
this.result = { transactionHash: txHash }; |
|
254 |
+ |
} |
|
255 |
+ |
|
|
256 |
+ |
this.loading = false; |
|
257 |
+ |
this.render(); |
|
258 |
+ |
|
|
259 |
+ |
this.dispatchEvent( |
|
260 |
+ |
new CustomEvent("contract-call-success", { |
|
261 |
+ |
detail: { |
|
262 |
+ |
result: this.result, |
|
263 |
+ |
method: this.methodName, |
|
264 |
+ |
args: this.methodArgs, |
|
265 |
+ |
isReadOnly: this.isReadOnly, |
|
266 |
+ |
}, |
|
267 |
+ |
}), |
|
268 |
+ |
); |
|
269 |
+ |
} catch (error) { |
|
270 |
+ |
console.error("Contract call failed:", error); |
|
271 |
+ |
this.error = error.message; |
|
272 |
+ |
this.loading = false; |
|
273 |
+ |
this.render(); |
|
274 |
+ |
|
|
275 |
+ |
this.dispatchEvent( |
|
276 |
+ |
new CustomEvent("contract-call-error", { |
|
277 |
+ |
detail: { error: error.message }, |
|
278 |
+ |
}), |
|
279 |
+ |
); |
|
280 |
+ |
} |
|
281 |
+ |
} |
|
282 |
+ |
|
|
283 |
+ |
async switchChain() { |
|
284 |
+ |
try { |
|
285 |
+ |
await window.ethereum.request({ |
|
286 |
+ |
method: "wallet_switchEthereumChain", |
|
287 |
+ |
params: [{ chainId: this.chainId }], |
|
288 |
+ |
}); |
|
289 |
+ |
} catch (switchError) { |
|
290 |
+ |
throw new Error(`Failed to switch chain: ${switchError.message}`); |
|
291 |
+ |
} |
|
292 |
+ |
} |
|
293 |
+ |
|
|
294 |
+ |
// Encoding and decoding methods |
|
295 |
+ |
encodeMethodSignature() { |
|
296 |
+ |
const inputs = this.methodData.inputs || []; |
|
297 |
+ |
const types = inputs.map((input) => input.type).join(","); |
|
298 |
+ |
const signature = `${this.methodName}(${types})`; |
|
299 |
+ |
|
|
300 |
+ |
// Use proper keccak256 hash - for production use a crypto library |
|
301 |
+ |
const hash = this.keccak256(signature); |
|
302 |
+ |
return hash.slice(0, 10); // First 4 bytes (function selector) |
|
303 |
+ |
} |
|
304 |
+ |
|
|
305 |
+ |
encodeArguments() { |
|
306 |
+ |
const inputs = this.methodData.inputs || []; |
|
307 |
+ |
|
|
308 |
+ |
// If method has no inputs or no args provided, return empty string |
|
309 |
+ |
if (!inputs.length || !this.methodArgs.length) return ""; |
|
310 |
+ |
|
|
311 |
+ |
// This is a simplified encoding - in production, use ethers.js or web3.js |
|
312 |
+ |
let encoded = ""; |
|
313 |
+ |
|
|
314 |
+ |
for (let i = 0; i < this.methodArgs.length; i++) { |
|
315 |
+ |
const arg = this.methodArgs[i]; |
|
316 |
+ |
const input = inputs[i]; |
|
317 |
+ |
|
|
318 |
+ |
if (!input) continue; |
|
319 |
+ |
|
|
320 |
+ |
encoded += this.encodeValue(arg, input.type); |
|
321 |
+ |
} |
|
322 |
+ |
|
|
323 |
+ |
return encoded; |
|
324 |
+ |
} |
|
325 |
+ |
|
|
326 |
+ |
encodeValue(value, type) { |
|
327 |
+ |
// Simplified encoding - use proper ABI encoding library in production |
|
328 |
+ |
if (type === "uint256" || type === "uint") { |
|
329 |
+ |
return BigInt(value).toString(16).padStart(64, "0"); |
|
330 |
+ |
} else if (type === "address") { |
|
331 |
+ |
return value.toLowerCase().replace("0x", "").padStart(64, "0"); |
|
332 |
+ |
} else if (type === "string") { |
|
333 |
+ |
const hex = Array.from(new TextEncoder().encode(value)) |
|
334 |
+ |
.map((b) => b.toString(16).padStart(2, "0")) |
|
335 |
+ |
.join(""); |
|
336 |
+ |
return hex.padEnd(64, "0"); |
|
337 |
+ |
} |
|
338 |
+ |
return "".padStart(64, "0"); |
|
339 |
+ |
} |
|
340 |
+ |
|
|
341 |
+ |
decodeResult(result) { |
|
342 |
+ |
if (!result || result === "0x") return null; |
|
343 |
+ |
|
|
344 |
+ |
// Simplified decoding - use proper ABI decoding library in production |
|
345 |
+ |
const outputs = this.methodData.outputs || []; |
|
346 |
+ |
if (outputs.length === 0) return result; |
|
347 |
+ |
|
|
348 |
+ |
const output = outputs[0]; |
|
349 |
+ |
const data = result.replace("0x", ""); |
|
350 |
+ |
|
|
351 |
+ |
if (output.type === "uint256" || output.type === "uint") { |
|
352 |
+ |
return BigInt("0x" + data).toString(); |
|
353 |
+ |
} else if (output.type === "address") { |
|
354 |
+ |
return "0x" + data.slice(-40); |
|
355 |
+ |
} else if (output.type === "string") { |
|
356 |
+ |
// Simplified string decoding |
|
357 |
+ |
try { |
|
358 |
+ |
const bytes = |
|
359 |
+ |
data.match(/.{2}/g)?.map((byte) => parseInt(byte, 16)) || []; |
|
360 |
+ |
return new TextDecoder().decode(new Uint8Array(bytes)); |
|
361 |
+ |
} catch (e) { |
|
362 |
+ |
return data; |
|
363 |
+ |
} |
|
364 |
+ |
} |
|
365 |
+ |
|
|
366 |
+ |
return result; |
|
367 |
+ |
} |
|
368 |
+ |
|
|
369 |
+ |
keccak256(input) { |
|
370 |
+ |
// Use the keccak256 function defined at the bottom of this file |
|
371 |
+ |
return keccak256(input); |
|
372 |
+ |
} |
|
373 |
+ |
|
|
374 |
+ |
// UI helper methods |
|
375 |
+ |
getCSSVariable(name, defaultValue) { |
|
376 |
+ |
return this.getAttribute(name) || defaultValue; |
|
377 |
+ |
} |
|
378 |
+ |
|
|
379 |
+ |
getStatusColor() { |
|
380 |
+ |
if (this.error) return "#ef4444"; |
|
381 |
+ |
if (this.result) return "#22c55e"; |
|
382 |
+ |
return this.getCSSVariable("primary", "#5F8787"); |
|
383 |
+ |
} |
|
384 |
+ |
|
|
385 |
+ |
getStatusText() { |
|
386 |
+ |
if (this.loading) return "Processing..."; |
|
387 |
+ |
if (this.error) return `Error: ${this.error}`; |
|
388 |
+ |
if (this.result) { |
|
389 |
+ |
if (this.isReadOnly) { |
|
390 |
+ |
return `Result: ${JSON.stringify(this.result)}`; |
|
391 |
+ |
} else { |
|
392 |
+ |
return `Transaction: ${this.result.transactionHash}`; |
|
393 |
+ |
} |
|
394 |
+ |
} |
|
395 |
+ |
return ""; |
|
396 |
+ |
} |
|
397 |
+ |
|
|
398 |
+ |
// Render methods |
|
399 |
+ |
render() { |
|
400 |
+ |
const background = this.getCSSVariable("background", "#232323"); |
|
401 |
+ |
const foreground = this.getCSSVariable("foreground", "#ffffff"); |
|
402 |
+ |
const primary = this.getCSSVariable("primary", "#5F8787"); |
|
403 |
+ |
const secondary = this.getCSSVariable("secondary", "#6F9797"); |
|
404 |
+ |
const borderRadius = this.getCSSVariable("border-radius", "4px"); |
|
405 |
+ |
|
|
406 |
+ |
this.shadowRoot.innerHTML = ` |
|
407 |
+ |
<style> |
|
408 |
+ |
:host { |
|
409 |
+ |
--color-background: ${background}; |
|
410 |
+ |
--color-foreground: ${foreground}; |
|
411 |
+ |
--color-primary: ${primary}; |
|
412 |
+ |
--color-secondary: ${secondary}; |
|
413 |
+ |
--border-radius: ${borderRadius}; |
|
414 |
+ |
display: inline-block; |
|
415 |
+ |
font-family: sans-serif; |
|
416 |
+ |
} |
|
417 |
+ |
|
|
418 |
+ |
.container { |
|
419 |
+ |
display: flex; |
|
420 |
+ |
flex-direction: column; |
|
421 |
+ |
gap: 12px; |
|
422 |
+ |
padding: 16px; |
|
423 |
+ |
background: var(--color-background); |
|
424 |
+ |
border: 1px solid rgba(255, 255, 255, 0.1); |
|
425 |
+ |
border-radius: var(--border-radius); |
|
426 |
+ |
color: var(--color-foreground); |
|
427 |
+ |
min-width: 300px; |
|
428 |
+ |
} |
|
429 |
+ |
|
|
430 |
+ |
.contract-info { |
|
431 |
+ |
display: flex; |
|
432 |
+ |
flex-direction: column; |
|
433 |
+ |
gap: 8px; |
|
434 |
+ |
font-size: 14px; |
|
435 |
+ |
opacity: 0.8; |
|
436 |
+ |
} |
|
437 |
+ |
|
|
438 |
+ |
.info-row { |
|
439 |
+ |
display: flex; |
|
440 |
+ |
justify-content: space-between; |
|
441 |
+ |
align-items: center; |
|
442 |
+ |
} |
|
443 |
+ |
|
|
444 |
+ |
.info-label { |
|
445 |
+ |
font-weight: 600; |
|
446 |
+ |
min-width: 80px; |
|
447 |
+ |
} |
|
448 |
+ |
|
|
449 |
+ |
.info-value { |
|
450 |
+ |
font-family: monospace; |
|
451 |
+ |
word-break: break-all; |
|
452 |
+ |
text-align: right; |
|
453 |
+ |
flex: 1; |
|
454 |
+ |
margin-left: 12px; |
|
455 |
+ |
} |
|
456 |
+ |
|
|
457 |
+ |
.method-info { |
|
458 |
+ |
background: rgba(255, 255, 255, 0.05); |
|
459 |
+ |
border-radius: calc(var(--border-radius) / 2); |
|
460 |
+ |
padding: 12px; |
|
461 |
+ |
} |
|
462 |
+ |
|
|
463 |
+ |
.method-signature { |
|
464 |
+ |
font-family: monospace; |
|
465 |
+ |
font-size: 13px; |
|
466 |
+ |
color: var(--color-primary); |
|
467 |
+ |
margin-bottom: 8px; |
|
468 |
+ |
} |
|
469 |
+ |
|
|
470 |
+ |
button { |
|
471 |
+ |
padding: 12px 20px; |
|
472 |
+ |
background: var(--color-primary); |
|
473 |
+ |
color: var(--color-foreground); |
|
474 |
+ |
border: none; |
|
475 |
+ |
border-radius: var(--border-radius); |
|
476 |
+ |
cursor: pointer; |
|
477 |
+ |
font-size: 16px; |
|
478 |
+ |
font-weight: 600; |
|
479 |
+ |
transition: background-color 0.3s ease; |
|
480 |
+ |
} |
|
481 |
+ |
|
|
482 |
+ |
button:hover:not(:disabled) { |
|
483 |
+ |
background: var(--color-secondary); |
|
484 |
+ |
} |
|
485 |
+ |
|
|
486 |
+ |
button:disabled { |
|
487 |
+ |
opacity: 0.7; |
|
488 |
+ |
cursor: not-allowed; |
|
489 |
+ |
} |
|
490 |
+ |
|
|
491 |
+ |
.status { |
|
492 |
+ |
padding: 12px; |
|
493 |
+ |
border-radius: calc(var(--border-radius) / 2); |
|
494 |
+ |
font-size: 14px; |
|
495 |
+ |
word-break: break-all; |
|
496 |
+ |
border: 1px solid; |
|
497 |
+ |
border-color: ${this.getStatusColor()}; |
|
498 |
+ |
background: ${this.getStatusColor()}20; |
|
499 |
+ |
color: ${this.getStatusColor()}; |
|
500 |
+ |
} |
|
501 |
+ |
|
|
502 |
+ |
.loading { |
|
503 |
+ |
display: flex; |
|
504 |
+ |
align-items: center; |
|
505 |
+ |
gap: 8px; |
|
506 |
+ |
} |
|
507 |
+ |
|
|
508 |
+ |
.spinner { |
|
509 |
+ |
width: 16px; |
|
510 |
+ |
height: 16px; |
|
511 |
+ |
border: 2px solid rgba(255, 255, 255, 0.3); |
|
512 |
+ |
border-top: 2px solid var(--color-foreground); |
|
513 |
+ |
border-radius: 50%; |
|
514 |
+ |
animation: spin 1s linear infinite; |
|
515 |
+ |
} |
|
516 |
+ |
|
|
517 |
+ |
@keyframes spin { |
|
518 |
+ |
from { transform: rotate(0deg); } |
|
519 |
+ |
to { transform: rotate(360deg); } |
|
520 |
+ |
} |
|
521 |
+ |
|
|
522 |
+ |
.error { |
|
523 |
+ |
color: #ef4444; |
|
524 |
+ |
} |
|
525 |
+ |
|
|
526 |
+ |
.success { |
|
527 |
+ |
color: #22c55e; |
|
528 |
+ |
} |
|
529 |
+ |
</style> |
|
530 |
+ |
`; |
|
531 |
+ |
|
|
532 |
+ |
const container = document.createElement("div"); |
|
533 |
+ |
container.className = "container"; |
|
534 |
+ |
|
|
535 |
+ |
// Contract info section |
|
536 |
+ |
const contractInfo = document.createElement("div"); |
|
537 |
+ |
contractInfo.className = "contract-info"; |
|
538 |
+ |
|
|
539 |
+ |
if (this.contractAddress) { |
|
540 |
+ |
contractInfo.innerHTML = ` |
|
541 |
+ |
<div class="info-row"> |
|
542 |
+ |
<span class="info-label">Contract:</span> |
|
543 |
+ |
<span class="info-value">${this.contractAddress}</span> |
|
544 |
+ |
</div> |
|
545 |
+ |
`; |
|
546 |
+ |
} |
|
547 |
+ |
|
|
548 |
+ |
// Method info section |
|
549 |
+ |
if (this.methodData) { |
|
550 |
+ |
const methodInfo = document.createElement("div"); |
|
551 |
+ |
methodInfo.className = "method-info"; |
|
552 |
+ |
|
|
553 |
+ |
const inputs = this.methodData.inputs || []; |
|
554 |
+ |
const inputTypes = |
|
555 |
+ |
inputs.length > 0 |
|
556 |
+ |
? inputs.map((input) => `${input.type} ${input.name}`).join(", ") |
|
557 |
+ |
: ""; |
|
558 |
+ |
const signature = `${this.methodName}(${inputTypes})`; |
|
559 |
+ |
|
|
560 |
+ |
methodInfo.innerHTML = ` |
|
561 |
+ |
<div class="method-signature">${signature}</div> |
|
562 |
+ |
`; |
|
563 |
+ |
|
|
564 |
+ |
container.appendChild(methodInfo); |
|
565 |
+ |
} |
|
566 |
+ |
|
|
567 |
+ |
container.appendChild(contractInfo); |
|
568 |
+ |
|
|
569 |
+ |
// Button |
|
570 |
+ |
const button = document.createElement("button"); |
|
571 |
+ |
button.disabled = this.loading || !this.contractAddress || !this.methodData; |
|
572 |
+ |
|
|
573 |
+ |
if (this.loading) { |
|
574 |
+ |
button.innerHTML = ` |
|
575 |
+ |
<div class="loading"> |
|
576 |
+ |
<div class="spinner"></div> |
|
577 |
+ |
<span>Processing...</span> |
|
578 |
+ |
</div> |
|
579 |
+ |
`; |
|
580 |
+ |
} else { |
|
581 |
+ |
button.textContent = this.buttonText; |
|
582 |
+ |
} |
|
583 |
+ |
|
|
584 |
+ |
button.addEventListener("click", () => this.callContract()); |
|
585 |
+ |
container.appendChild(button); |
|
586 |
+ |
|
|
587 |
+ |
// Status section |
|
588 |
+ |
const statusText = this.getStatusText(); |
|
589 |
+ |
if (statusText) { |
|
590 |
+ |
const status = document.createElement("div"); |
|
591 |
+ |
status.className = "status"; |
|
592 |
+ |
status.textContent = statusText; |
|
593 |
+ |
container.appendChild(status); |
|
594 |
+ |
} |
|
595 |
+ |
|
|
596 |
+ |
this.shadowRoot.appendChild(container); |
|
597 |
+ |
} |
|
598 |
+ |
} |
|
599 |
+ |
|
|
600 |
+ |
customElements.define("contract-call", ContractCall); |
|
601 |
+ |
|
|
602 |
+ |
/** |
|
603 |
+ |
* Minimal Keccak256 implementation for browser use |
|
604 |
+ |
* Based on js-sha3 by emn178 |
|
605 |
+ |
* https://github.com/emn178/js-sha3 |
|
606 |
+ |
*/ |
|
607 |
+ |
|
|
608 |
+ |
// Keccak constants |
|
609 |
+ |
const KECCAK_PADDING = [1, 256, 65536, 16777216]; |
|
610 |
+ |
const SHIFT = [0, 8, 16, 24]; |
|
611 |
+ |
const RC = [ |
|
612 |
+ |
1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, |
|
613 |
+ |
2147483649, 0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, |
|
614 |
+ |
2147516425, 0, 2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, |
|
615 |
+ |
2147483648, 32771, 2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, |
|
616 |
+ |
2147483658, 2147483648, 2147516545, 2147483648, 32896, 2147483648, 2147483649, |
|
617 |
+ |
0, 2147516424, 2147483648, |
|
618 |
+ |
]; |
|
619 |
+ |
|
|
620 |
+ |
function Keccak(bits) { |
|
621 |
+ |
this.blocks = []; |
|
622 |
+ |
this.s = []; |
|
623 |
+ |
this.padding = KECCAK_PADDING; |
|
624 |
+ |
this.outputBits = bits; |
|
625 |
+ |
this.reset = true; |
|
626 |
+ |
this.finalized = false; |
|
627 |
+ |
this.block = 0; |
|
628 |
+ |
this.start = 0; |
|
629 |
+ |
this.blockCount = (1600 - (bits << 1)) >> 5; |
|
630 |
+ |
this.byteCount = this.blockCount << 2; |
|
631 |
+ |
this.outputBlocks = bits >> 5; |
|
632 |
+ |
this.extraBytes = (bits & 31) >> 3; |
|
633 |
+ |
|
|
634 |
+ |
for (var i = 0; i < 50; ++i) { |
|
635 |
+ |
this.s[i] = 0; |
|
636 |
+ |
} |
|
637 |
+ |
} |
|
638 |
+ |
|
|
639 |
+ |
Keccak.prototype.update = function (message) { |
|
640 |
+ |
if (this.finalized) { |
|
641 |
+ |
throw new Error("finalized"); |
|
642 |
+ |
} |
|
643 |
+ |
var notString, |
|
644 |
+ |
type = typeof message; |
|
645 |
+ |
if (type !== "string") { |
|
646 |
+ |
if (type === "object") { |
|
647 |
+ |
if (message === null) { |
|
648 |
+ |
throw new Error("message is null"); |
|
649 |
+ |
} else if ( |
|
650 |
+ |
Array.isArray(message) || |
|
651 |
+ |
(typeof ArrayBuffer !== "undefined" && |
|
652 |
+ |
message.constructor === ArrayBuffer) |
|
653 |
+ |
) { |
|
654 |
+ |
message = new Uint8Array(message); |
|
655 |
+ |
} else if (!ArrayBuffer.isView(message)) { |
|
656 |
+ |
throw new Error("invalid message type"); |
|
657 |
+ |
} |
|
658 |
+ |
} else { |
|
659 |
+ |
throw new Error("invalid message type"); |
|
660 |
+ |
} |
|
661 |
+ |
notString = true; |
|
662 |
+ |
} |
|
663 |
+ |
var blocks = this.blocks, |
|
664 |
+ |
byteCount = this.byteCount, |
|
665 |
+ |
length = message.length, |
|
666 |
+ |
blockCount = this.blockCount, |
|
667 |
+ |
index = 0, |
|
668 |
+ |
s = this.s, |
|
669 |
+ |
i, |
|
670 |
+ |
code; |
|
671 |
+ |
|
|
672 |
+ |
while (index < length) { |
|
673 |
+ |
if (this.reset) { |
|
674 |
+ |
this.reset = false; |
|
675 |
+ |
blocks[0] = this.block; |
|
676 |
+ |
for (i = 1; i < blockCount + 1; ++i) { |
|
677 |
+ |
blocks[i] = 0; |
|
678 |
+ |
} |
|
679 |
+ |
} |
|
680 |
+ |
if (notString) { |
|
681 |
+ |
for (i = this.start; index < length && i < byteCount; ++index) { |
|
682 |
+ |
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; |
|
683 |
+ |
} |
|
684 |
+ |
} else { |
|
685 |
+ |
for (i = this.start; index < length && i < byteCount; ++index) { |
|
686 |
+ |
code = message.charCodeAt(index); |
|
687 |
+ |
if (code < 0x80) { |
|
688 |
+ |
blocks[i >> 2] |= code << SHIFT[i++ & 3]; |
|
689 |
+ |
} else if (code < 0x800) { |
|
690 |
+ |
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; |
|
691 |
+ |
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; |
|
692 |
+ |
} else if (code < 0xd800 || code >= 0xe000) { |
|
693 |
+ |
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; |
|
694 |
+ |
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; |
|
695 |
+ |
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; |
|
696 |
+ |
} else { |
|
697 |
+ |
code = |
|
698 |
+ |
0x10000 + |
|
699 |
+ |
(((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); |
|
700 |
+ |
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; |
|
701 |
+ |
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; |
|
702 |
+ |
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; |
|
703 |
+ |
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; |
|
704 |
+ |
} |
|
705 |
+ |
} |
|
706 |
+ |
} |
|
707 |
+ |
|
|
708 |
+ |
this.lastByteIndex = i; |
|
709 |
+ |
if (i >= byteCount) { |
|
710 |
+ |
this.start = i - byteCount; |
|
711 |
+ |
this.block = blocks[blockCount]; |
|
712 |
+ |
for (i = 0; i < blockCount; ++i) { |
|
713 |
+ |
s[i] ^= blocks[i]; |
|
714 |
+ |
} |
|
715 |
+ |
f(s); |
|
716 |
+ |
this.reset = true; |
|
717 |
+ |
} else { |
|
718 |
+ |
this.start = i; |
|
719 |
+ |
} |
|
720 |
+ |
} |
|
721 |
+ |
return this; |
|
722 |
+ |
}; |
|
723 |
+ |
|
|
724 |
+ |
Keccak.prototype.finalize = function () { |
|
725 |
+ |
if (this.finalized) { |
|
726 |
+ |
return; |
|
727 |
+ |
} |
|
728 |
+ |
this.finalized = true; |
|
729 |
+ |
var blocks = this.blocks, |
|
730 |
+ |
i = this.lastByteIndex, |
|
731 |
+ |
blockCount = this.blockCount, |
|
732 |
+ |
s = this.s; |
|
733 |
+ |
blocks[i >> 2] |= this.padding[i & 3]; |
|
734 |
+ |
if (this.lastByteIndex === this.byteCount) { |
|
735 |
+ |
blocks[0] = blocks[blockCount]; |
|
736 |
+ |
for (i = 1; i < blockCount + 1; ++i) { |
|
737 |
+ |
blocks[i] = 0; |
|
738 |
+ |
} |
|
739 |
+ |
} |
|
740 |
+ |
blocks[blockCount - 1] |= 0x80000000; |
|
741 |
+ |
for (i = 0; i < blockCount; ++i) { |
|
742 |
+ |
s[i] ^= blocks[i]; |
|
743 |
+ |
} |
|
744 |
+ |
f(s); |
|
745 |
+ |
}; |
|
746 |
+ |
|
|
747 |
+ |
Keccak.prototype.toString = Keccak.prototype.hex = function () { |
|
748 |
+ |
this.finalize(); |
|
749 |
+ |
|
|
750 |
+ |
var blockCount = this.blockCount, |
|
751 |
+ |
s = this.s, |
|
752 |
+ |
outputBlocks = this.outputBlocks, |
|
753 |
+ |
extraBytes = this.extraBytes, |
|
754 |
+ |
i = 0, |
|
755 |
+ |
j = 0; |
|
756 |
+ |
var hex = "", |
|
757 |
+ |
block; |
|
758 |
+ |
while (j < outputBlocks) { |
|
759 |
+ |
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) { |
|
760 |
+ |
block = s[i]; |
|
761 |
+ |
hex += |
|
762 |
+ |
HEX_CHARS[(block >> 4) & 0x0f] + |
|
763 |
+ |
HEX_CHARS[block & 0x0f] + |
|
764 |
+ |
HEX_CHARS[(block >> 12) & 0x0f] + |
|
765 |
+ |
HEX_CHARS[(block >> 8) & 0x0f] + |
|
766 |
+ |
HEX_CHARS[(block >> 20) & 0x0f] + |
|
767 |
+ |
HEX_CHARS[(block >> 16) & 0x0f] + |
|
768 |
+ |
HEX_CHARS[(block >> 28) & 0x0f] + |
|
769 |
+ |
HEX_CHARS[(block >> 24) & 0x0f]; |
|
770 |
+ |
} |
|
771 |
+ |
if (j % blockCount === 0) { |
|
772 |
+ |
f(s); |
|
773 |
+ |
i = 0; |
|
774 |
+ |
} |
|
775 |
+ |
} |
|
776 |
+ |
if (extraBytes) { |
|
777 |
+ |
block = s[i]; |
|
778 |
+ |
hex += HEX_CHARS[(block >> 4) & 0x0f] + HEX_CHARS[block & 0x0f]; |
|
779 |
+ |
if (extraBytes > 1) { |
|
780 |
+ |
hex += HEX_CHARS[(block >> 12) & 0x0f] + HEX_CHARS[(block >> 8) & 0x0f]; |
|
781 |
+ |
} |
|
782 |
+ |
if (extraBytes > 2) { |
|
783 |
+ |
hex += HEX_CHARS[(block >> 20) & 0x0f] + HEX_CHARS[(block >> 16) & 0x0f]; |
|
784 |
+ |
} |
|
785 |
+ |
} |
|
786 |
+ |
return hex; |
|
787 |
+ |
}; |
|
788 |
+ |
|
|
789 |
+ |
const HEX_CHARS = "0123456789abcdef".split(""); |
|
790 |
+ |
|
|
791 |
+ |
var f = function (s) { |
|
792 |
+ |
var h, |
|
793 |
+ |
l, |
|
794 |
+ |
n, |
|
795 |
+ |
c0, |
|
796 |
+ |
c1, |
|
797 |
+ |
c2, |
|
798 |
+ |
c3, |
|
799 |
+ |
c4, |
|
800 |
+ |
c5, |
|
801 |
+ |
c6, |
|
802 |
+ |
c7, |
|
803 |
+ |
c8, |
|
804 |
+ |
c9, |
|
805 |
+ |
b0, |
|
806 |
+ |
b1, |
|
807 |
+ |
b2, |
|
808 |
+ |
b3, |
|
809 |
+ |
b4, |
|
810 |
+ |
b5, |
|
811 |
+ |
b6, |
|
812 |
+ |
b7, |
|
813 |
+ |
b8, |
|
814 |
+ |
b9, |
|
815 |
+ |
b10, |
|
816 |
+ |
b11, |
|
817 |
+ |
b12, |
|
818 |
+ |
b13, |
|
819 |
+ |
b14, |
|
820 |
+ |
b15, |
|
821 |
+ |
b16, |
|
822 |
+ |
b17, |
|
823 |
+ |
b18, |
|
824 |
+ |
b19, |
|
825 |
+ |
b20, |
|
826 |
+ |
b21, |
|
827 |
+ |
b22, |
|
828 |
+ |
b23, |
|
829 |
+ |
b24, |
|
830 |
+ |
b25, |
|
831 |
+ |
b26, |
|
832 |
+ |
b27, |
|
833 |
+ |
b28, |
|
834 |
+ |
b29, |
|
835 |
+ |
b30, |
|
836 |
+ |
b31, |
|
837 |
+ |
b32, |
|
838 |
+ |
b33, |
|
839 |
+ |
b34, |
|
840 |
+ |
b35, |
|
841 |
+ |
b36, |
|
842 |
+ |
b37, |
|
843 |
+ |
b38, |
|
844 |
+ |
b39, |
|
845 |
+ |
b40, |
|
846 |
+ |
b41, |
|
847 |
+ |
b42, |
|
848 |
+ |
b43, |
|
849 |
+ |
b44, |
|
850 |
+ |
b45, |
|
851 |
+ |
b46, |
|
852 |
+ |
b47, |
|
853 |
+ |
b48, |
|
854 |
+ |
b49; |
|
855 |
+ |
for (n = 0; n < 48; n += 2) { |
|
856 |
+ |
c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40]; |
|
857 |
+ |
c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41]; |
|
858 |
+ |
c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42]; |
|
859 |
+ |
c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43]; |
|
860 |
+ |
c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44]; |
|
861 |
+ |
c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45]; |
|
862 |
+ |
c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46]; |
|
863 |
+ |
c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47]; |
|
864 |
+ |
c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48]; |
|
865 |
+ |
c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49]; |
|
866 |
+ |
|
|
867 |
+ |
h = c8 ^ ((c2 << 1) | (c3 >>> 31)); |
|
868 |
+ |
l = c9 ^ ((c3 << 1) | (c2 >>> 31)); |
|
869 |
+ |
s[0] ^= h; |
|
870 |
+ |
s[1] ^= l; |
|
871 |
+ |
s[10] ^= h; |
|
872 |
+ |
s[11] ^= l; |
|
873 |
+ |
s[20] ^= h; |
|
874 |
+ |
s[21] ^= l; |
|
875 |
+ |
s[30] ^= h; |
|
876 |
+ |
s[31] ^= l; |
|
877 |
+ |
s[40] ^= h; |
|
878 |
+ |
s[41] ^= l; |
|
879 |
+ |
h = c0 ^ ((c4 << 1) | (c5 >>> 31)); |
|
880 |
+ |
l = c1 ^ ((c5 << 1) | (c4 >>> 31)); |
|
881 |
+ |
s[2] ^= h; |
|
882 |
+ |
s[3] ^= l; |
|
883 |
+ |
s[12] ^= h; |
|
884 |
+ |
s[13] ^= l; |
|
885 |
+ |
s[22] ^= h; |
|
886 |
+ |
s[23] ^= l; |
|
887 |
+ |
s[32] ^= h; |
|
888 |
+ |
s[33] ^= l; |
|
889 |
+ |
s[42] ^= h; |
|
890 |
+ |
s[43] ^= l; |
|
891 |
+ |
h = c2 ^ ((c6 << 1) | (c7 >>> 31)); |
|
892 |
+ |
l = c3 ^ ((c7 << 1) | (c6 >>> 31)); |
|
893 |
+ |
s[4] ^= h; |
|
894 |
+ |
s[5] ^= l; |
|
895 |
+ |
s[14] ^= h; |
|
896 |
+ |
s[15] ^= l; |
|
897 |
+ |
s[24] ^= h; |
|
898 |
+ |
s[25] ^= l; |
|
899 |
+ |
s[34] ^= h; |
|
900 |
+ |
s[35] ^= l; |
|
901 |
+ |
s[44] ^= h; |
|
902 |
+ |
s[45] ^= l; |
|
903 |
+ |
h = c4 ^ ((c8 << 1) | (c9 >>> 31)); |
|
904 |
+ |
l = c5 ^ ((c9 << 1) | (c8 >>> 31)); |
|
905 |
+ |
s[6] ^= h; |
|
906 |
+ |
s[7] ^= l; |
|
907 |
+ |
s[16] ^= h; |
|
908 |
+ |
s[17] ^= l; |
|
909 |
+ |
s[26] ^= h; |
|
910 |
+ |
s[27] ^= l; |
|
911 |
+ |
s[36] ^= h; |
|
912 |
+ |
s[37] ^= l; |
|
913 |
+ |
s[46] ^= h; |
|
914 |
+ |
s[47] ^= l; |
|
915 |
+ |
h = c6 ^ ((c0 << 1) | (c1 >>> 31)); |
|
916 |
+ |
l = c7 ^ ((c1 << 1) | (c0 >>> 31)); |
|
917 |
+ |
s[8] ^= h; |
|
918 |
+ |
s[9] ^= l; |
|
919 |
+ |
s[18] ^= h; |
|
920 |
+ |
s[19] ^= l; |
|
921 |
+ |
s[28] ^= h; |
|
922 |
+ |
s[29] ^= l; |
|
923 |
+ |
s[38] ^= h; |
|
924 |
+ |
s[39] ^= l; |
|
925 |
+ |
s[48] ^= h; |
|
926 |
+ |
s[49] ^= l; |
|
927 |
+ |
|
|
928 |
+ |
b0 = s[0]; |
|
929 |
+ |
b1 = s[1]; |
|
930 |
+ |
b32 = (s[11] << 4) | (s[10] >>> 28); |
|
931 |
+ |
b33 = (s[10] << 4) | (s[11] >>> 28); |
|
932 |
+ |
b14 = (s[20] << 3) | (s[21] >>> 29); |
|
933 |
+ |
b15 = (s[21] << 3) | (s[20] >>> 29); |
|
934 |
+ |
b46 = (s[31] << 9) | (s[30] >>> 23); |
|
935 |
+ |
b47 = (s[30] << 9) | (s[31] >>> 23); |
|
936 |
+ |
b28 = (s[40] << 18) | (s[41] >>> 14); |
|
937 |
+ |
b29 = (s[41] << 18) | (s[40] >>> 14); |
|
938 |
+ |
b20 = (s[2] << 1) | (s[3] >>> 31); |
|
939 |
+ |
b21 = (s[3] << 1) | (s[2] >>> 31); |
|
940 |
+ |
b2 = (s[13] << 12) | (s[12] >>> 20); |
|
941 |
+ |
b3 = (s[12] << 12) | (s[13] >>> 20); |
|
942 |
+ |
b34 = (s[22] << 10) | (s[23] >>> 22); |
|
943 |
+ |
b35 = (s[23] << 10) | (s[22] >>> 22); |
|
944 |
+ |
b16 = (s[33] << 13) | (s[32] >>> 19); |
|
945 |
+ |
b17 = (s[32] << 13) | (s[33] >>> 19); |
|
946 |
+ |
b48 = (s[42] << 2) | (s[43] >>> 30); |
|
947 |
+ |
b49 = (s[43] << 2) | (s[42] >>> 30); |
|
948 |
+ |
b40 = (s[5] << 30) | (s[4] >>> 2); |
|
949 |
+ |
b41 = (s[4] << 30) | (s[5] >>> 2); |
|
950 |
+ |
b22 = (s[14] << 6) | (s[15] >>> 26); |
|
951 |
+ |
b23 = (s[15] << 6) | (s[14] >>> 26); |
|
952 |
+ |
b4 = (s[25] << 11) | (s[24] >>> 21); |
|
953 |
+ |
b5 = (s[24] << 11) | (s[25] >>> 21); |
|
954 |
+ |
b36 = (s[34] << 15) | (s[35] >>> 17); |
|
955 |
+ |
b37 = (s[35] << 15) | (s[34] >>> 17); |
|
956 |
+ |
b18 = (s[45] << 29) | (s[44] >>> 3); |
|
957 |
+ |
b19 = (s[44] << 29) | (s[45] >>> 3); |
|
958 |
+ |
b10 = (s[6] << 28) | (s[7] >>> 4); |
|
959 |
+ |
b11 = (s[7] << 28) | (s[6] >>> 4); |
|
960 |
+ |
b42 = (s[17] << 23) | (s[16] >>> 9); |
|
961 |
+ |
b43 = (s[16] << 23) | (s[17] >>> 9); |
|
962 |
+ |
b24 = (s[26] << 25) | (s[27] >>> 7); |
|
963 |
+ |
b25 = (s[27] << 25) | (s[26] >>> 7); |
|
964 |
+ |
b6 = (s[36] << 21) | (s[37] >>> 11); |
|
965 |
+ |
b7 = (s[37] << 21) | (s[36] >>> 11); |
|
966 |
+ |
b38 = (s[47] << 24) | (s[46] >>> 8); |
|
967 |
+ |
b39 = (s[46] << 24) | (s[47] >>> 8); |
|
968 |
+ |
b30 = (s[8] << 27) | (s[9] >>> 5); |
|
969 |
+ |
b31 = (s[9] << 27) | (s[8] >>> 5); |
|
970 |
+ |
b12 = (s[18] << 20) | (s[19] >>> 12); |
|
971 |
+ |
b13 = (s[19] << 20) | (s[18] >>> 12); |
|
972 |
+ |
b44 = (s[29] << 7) | (s[28] >>> 25); |
|
973 |
+ |
b45 = (s[28] << 7) | (s[29] >>> 25); |
|
974 |
+ |
b26 = (s[38] << 8) | (s[39] >>> 24); |
|
975 |
+ |
b27 = (s[39] << 8) | (s[38] >>> 24); |
|
976 |
+ |
b8 = (s[48] << 14) | (s[49] >>> 18); |
|
977 |
+ |
b9 = (s[49] << 14) | (s[48] >>> 18); |
|
978 |
+ |
|
|
979 |
+ |
s[0] = b0 ^ (~b2 & b4); |
|
980 |
+ |
s[1] = b1 ^ (~b3 & b5); |
|
981 |
+ |
s[10] = b10 ^ (~b12 & b14); |
|
982 |
+ |
s[11] = b11 ^ (~b13 & b15); |
|
983 |
+ |
s[20] = b20 ^ (~b22 & b24); |
|
984 |
+ |
s[21] = b21 ^ (~b23 & b25); |
|
985 |
+ |
s[30] = b30 ^ (~b32 & b34); |
|
986 |
+ |
s[31] = b31 ^ (~b33 & b35); |
|
987 |
+ |
s[40] = b40 ^ (~b42 & b44); |
|
988 |
+ |
s[41] = b41 ^ (~b43 & b45); |
|
989 |
+ |
s[2] = b2 ^ (~b4 & b6); |
|
990 |
+ |
s[3] = b3 ^ (~b5 & b7); |
|
991 |
+ |
s[12] = b12 ^ (~b14 & b16); |
|
992 |
+ |
s[13] = b13 ^ (~b15 & b17); |
|
993 |
+ |
s[22] = b22 ^ (~b24 & b26); |
|
994 |
+ |
s[23] = b23 ^ (~b25 & b27); |
|
995 |
+ |
s[32] = b32 ^ (~b34 & b36); |
|
996 |
+ |
s[33] = b33 ^ (~b35 & b37); |
|
997 |
+ |
s[42] = b42 ^ (~b44 & b46); |
|
998 |
+ |
s[43] = b43 ^ (~b45 & b47); |
|
999 |
+ |
s[4] = b4 ^ (~b6 & b8); |
|
1000 |
+ |
s[5] = b5 ^ (~b7 & b9); |
|
1001 |
+ |
s[14] = b14 ^ (~b16 & b18); |
|
1002 |
+ |
s[15] = b15 ^ (~b17 & b19); |
|
1003 |
+ |
s[24] = b24 ^ (~b26 & b28); |
|
1004 |
+ |
s[25] = b25 ^ (~b27 & b29); |
|
1005 |
+ |
s[34] = b34 ^ (~b36 & b38); |
|
1006 |
+ |
s[35] = b35 ^ (~b37 & b39); |
|
1007 |
+ |
s[44] = b44 ^ (~b46 & b48); |
|
1008 |
+ |
s[45] = b45 ^ (~b47 & b49); |
|
1009 |
+ |
s[6] = b6 ^ (~b8 & b0); |
|
1010 |
+ |
s[7] = b7 ^ (~b9 & b1); |
|
1011 |
+ |
s[16] = b16 ^ (~b18 & b10); |
|
1012 |
+ |
s[17] = b17 ^ (~b19 & b11); |
|
1013 |
+ |
s[26] = b26 ^ (~b28 & b20); |
|
1014 |
+ |
s[27] = b27 ^ (~b29 & b21); |
|
1015 |
+ |
s[36] = b36 ^ (~b38 & b30); |
|
1016 |
+ |
s[37] = b37 ^ (~b39 & b31); |
|
1017 |
+ |
s[46] = b46 ^ (~b48 & b40); |
|
1018 |
+ |
s[47] = b47 ^ (~b49 & b41); |
|
1019 |
+ |
s[8] = b8 ^ (~b0 & b2); |
|
1020 |
+ |
s[9] = b9 ^ (~b1 & b3); |
|
1021 |
+ |
s[18] = b18 ^ (~b10 & b12); |
|
1022 |
+ |
s[19] = b19 ^ (~b11 & b13); |
|
1023 |
+ |
s[28] = b28 ^ (~b20 & b22); |
|
1024 |
+ |
s[29] = b29 ^ (~b21 & b23); |
|
1025 |
+ |
s[38] = b38 ^ (~b30 & b32); |
|
1026 |
+ |
s[39] = b39 ^ (~b31 & b33); |
|
1027 |
+ |
s[48] = b48 ^ (~b40 & b42); |
|
1028 |
+ |
s[49] = b49 ^ (~b41 & b43); |
|
1029 |
+ |
|
|
1030 |
+ |
s[0] ^= RC[n]; |
|
1031 |
+ |
s[1] ^= RC[n + 1]; |
|
1032 |
+ |
} |
|
1033 |
+ |
}; |
|
1034 |
+ |
|
|
1035 |
+ |
// Export keccak256 function |
|
1036 |
+ |
export function keccak256(message) { |
|
1037 |
+ |
const keccak = new Keccak(256); |
|
1038 |
+ |
keccak.update(message); |
|
1039 |
+ |
return "0x" + keccak.hex(); |
|
1040 |
+ |
} |
|
1041 |
+ |
|
|
1042 |
+ |
// For CommonJS compatibility |
|
1043 |
+ |
if (typeof module !== "undefined" && module.exports) { |
|
1044 |
+ |
module.exports = { keccak256 }; |
|
1045 |
+ |
} |