From a4072552b04a4d7149b262bfb5d39ef5f8db9882 Mon Sep 17 00:00:00 2001 From: Fernando Montero Date: Fri, 22 Aug 2025 11:29:17 +0100 Subject: [PATCH 1/5] workflow? --- pnpm-lock.yaml | 678 ++++++++++++++++++ src/workflows/on-chain-write/abi.ts | 126 ++++ .../on-chain-write/on-chain-write.ts | 263 +++++++ 3 files changed, 1067 insertions(+) create mode 100644 pnpm-lock.yaml create mode 100644 src/workflows/on-chain-write/abi.ts create mode 100644 src/workflows/on-chain-write/on-chain-write.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..43fe9124 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,678 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@bufbuild/protobuf': + specifier: 2.6.3 + version: 2.6.3 + '@bufbuild/protoc-gen-es': + specifier: 2.6.3 + version: 2.6.3(@bufbuild/protobuf@2.6.3) + '@standard-schema/spec': + specifier: 1.0.0 + version: 1.0.0 + rxjs: + specifier: 7.8.2 + version: 7.8.2 + viem: + specifier: 2.34.0 + version: 2.34.0(typescript@5.9.2)(zod@3.25.76) + zod: + specifier: 3.25.76 + version: 3.25.76 + devDependencies: + '@biomejs/biome': + specifier: 2.1.3 + version: 2.1.3 + '@bufbuild/buf': + specifier: 1.56.0 + version: 1.56.0 + '@types/bun': + specifier: 1.2.19 + version: 1.2.19(@types/react@19.1.10) + fast-glob: + specifier: 3.3.3 + version: 3.3.3 + ts-proto: + specifier: 2.7.5 + version: 2.7.5 + typescript: + specifier: 5.9.2 + version: 5.9.2 + +packages: + + '@adraffy/ens-normalize@1.11.0': + resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} + + '@biomejs/biome@2.1.3': + resolution: {integrity: sha512-KE/tegvJIxTkl7gJbGWSgun7G6X/n2M6C35COT6ctYrAy7SiPyNvi6JtoQERVK/VRbttZfgGq96j2bFmhmnH4w==} + engines: {node: '>=14.21.3'} + hasBin: true + + '@biomejs/cli-darwin-arm64@2.1.3': + resolution: {integrity: sha512-LFLkSWRoSGS1wVUD/BE6Nlt2dSn0ulH3XImzg2O/36BoToJHKXjSxzPEMAqT9QvwVtk7/9AQhZpTneERU9qaXA==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + + '@biomejs/cli-darwin-x64@2.1.3': + resolution: {integrity: sha512-Q/4OTw8P9No9QeowyxswcWdm0n2MsdCwWcc5NcKQQvzwPjwuPdf8dpPPf4r+x0RWKBtl1FLiAUtJvBlri6DnYw==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + + '@biomejs/cli-linux-arm64-musl@2.1.3': + resolution: {integrity: sha512-KXouFSBnoxAWZYDQrnNRzZBbt5s9UJkIm40hdvSL9mBxSSoxRFQJbtg1hP3aa8A2SnXyQHxQfpiVeJlczZt76w==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-arm64@2.1.3': + resolution: {integrity: sha512-2hS6LgylRqMFmAZCOFwYrf77QMdUwJp49oe8PX/O8+P2yKZMSpyQTf3Eo5ewnsMFUEmYbPOskafdV1ds1MZMJA==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-x64-musl@2.1.3': + resolution: {integrity: sha512-KaLAxnROouzIWtl6a0Y88r/4hW5oDUJTIqQorOTVQITaKQsKjZX4XCUmHIhdEk8zMnaiLZzRTAwk1yIAl+mIew==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-linux-x64@2.1.3': + resolution: {integrity: sha512-NxlSCBhLvQtWGagEztfAZ4WcE1AkMTntZV65ZvR+J9jp06+EtOYEBPQndA70ZGhHbEDG57bR6uNvqkd1WrEYVA==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-win32-arm64@2.1.3': + resolution: {integrity: sha512-V9CUZCtWH4u0YwyCYbQ3W5F4ZGPWp2C2TYcsiWFNNyRfmOW1j/TY/jAurl33SaRjgZPO5UUhGyr9m6BN9t84NQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + + '@biomejs/cli-win32-x64@2.1.3': + resolution: {integrity: sha512-dxy599q6lgp8ANPpR8sDMscwdp9oOumEsVXuVCVT9N2vAho8uYXlCz53JhxX6LtJOXaE73qzgkGQ7QqvFlMC0g==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + + '@bufbuild/buf-darwin-arm64@1.56.0': + resolution: {integrity: sha512-9neaI9gx1sxOGl9xrL7kw6H+0WmVAFlIQTIDc3vt1qRhfgOt/8AWOHSOWppGTRjNiB0qh6Xie1LYHv/jgDVN0g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@bufbuild/buf-darwin-x64@1.56.0': + resolution: {integrity: sha512-nRHPMXV8fr/lqU+u/1GGsUg7OvNcxJuCJoJpfRoRg38b+NPzOz2FkQAs5OEJzzprQB5aftn5//cl8YXjgvTuFA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@bufbuild/buf-linux-aarch64@1.56.0': + resolution: {integrity: sha512-+td559RuKNwYDnq49NrIDGJ4F73Ra4QzVVbsC+UeveA0HMnIGRzFbchGjHtNJyaZsI57sXJ7dCHH0iFV3jcYwQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@bufbuild/buf-linux-armv7@1.56.0': + resolution: {integrity: sha512-9v3zmos6wRTBc4QeIg4rfDmPzmTgtUTRCbhr87qws/yddIT8cFtHHhy1whnozBNqtmYOdwZNBNx/QXqGGcRuKw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@bufbuild/buf-linux-x64@1.56.0': + resolution: {integrity: sha512-3jZHHBol1fuichNke7LJtHJUdw314XBj6OuJHY6IufsaaVIj1mtM2DPbGiDhYB453J7FiV/buadctKBxAAHclg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@bufbuild/buf-win32-arm64@1.56.0': + resolution: {integrity: sha512-KMGzSf9rIbT01Jb2685JovwRRYEdL7Zbs6ZrjyhIHBgKK6cBwz1AJvEaDrWMEzCdv+opQwjgM6UdtA4e9BWP1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@bufbuild/buf-win32-x64@1.56.0': + resolution: {integrity: sha512-19LFOCyFFVTaaqNGtYTpiF67fcpneWZFlm8UNU+Xs87Kh+N5i/LjDjNytnpFT6snwU4/S+UUkq7WgS6UPjqXIg==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@bufbuild/buf@1.56.0': + resolution: {integrity: sha512-1xQWOf3FCDDTi+5B/VScQ73EP6ACwQPCP4ODvCq2L6IVgFtvYX49ur6cQ2qCM8yFitIHESm/Nbff93sh+V/Iog==} + engines: {node: '>=12'} + hasBin: true + + '@bufbuild/protobuf@2.6.3': + resolution: {integrity: sha512-w/gJKME9mYN7ZoUAmSMAWXk4hkVpxRKvEJCb3dV5g9wwWdxTJJ0ayOJAVcNxtdqaxDyFuC0uz4RSGVacJ030PQ==} + + '@bufbuild/protoc-gen-es@2.6.3': + resolution: {integrity: sha512-20o4U/Th0yLK/ayQGJ8hwh+fmcI/2PWZFkTS4gv08AtOx31YA05/X/wbn+pLZLJCDP2ik4KTIWuV1j4gERs15A==} + engines: {node: '>=14'} + hasBin: true + peerDependencies: + '@bufbuild/protobuf': 2.6.3 + peerDependenciesMeta: + '@bufbuild/protobuf': + optional: true + + '@bufbuild/protoplugin@2.6.3': + resolution: {integrity: sha512-VceMuxeRukxGeABfo34SXq0VqY1MU+mzS+PBf0HAWo97ylFut8F6sQ3mV0tKiM08UQ/xQco7lxCn83BkoxrWrA==} + + '@noble/ciphers@1.3.0': + resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} + engines: {node: ^14.21.3 || >=16} + + '@noble/curves@1.9.6': + resolution: {integrity: sha512-GIKz/j99FRthB8icyJQA51E8Uk5hXmdyThjgQXRKiv9h0zeRlzSCLIzFw6K1LotZ3XuB7yzlf76qk7uBmTdFqA==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@scure/base@1.2.6': + resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} + + '@scure/bip32@1.7.0': + resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==} + + '@scure/bip39@1.6.0': + resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} + + '@standard-schema/spec@1.0.0': + resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + + '@types/bun@1.2.19': + resolution: {integrity: sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg==} + + '@types/node@24.3.0': + resolution: {integrity: sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==} + + '@types/react@19.1.10': + resolution: {integrity: sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==} + + '@typescript/vfs@1.6.1': + resolution: {integrity: sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA==} + peerDependencies: + typescript: '*' + + abitype@1.0.8: + resolution: {integrity: sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + bun-types@1.2.19: + resolution: {integrity: sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ==} + peerDependencies: + '@types/react': ^19 + + case-anything@2.1.13: + resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==} + engines: {node: '>=12.13'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + dprint-node@1.0.8: + resolution: {integrity: sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + isows@1.0.7: + resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==} + peerDependencies: + ws: '*' + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + ox@0.8.7: + resolution: {integrity: sha512-W1f0FiMf9NZqtHPEDEAEkyzZDwbIKfmH2qmQx8NNiQ/9JhxrSblmtLJsSfTtQG5YKowLOnBlLVguCyxm/7ztxw==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-poet@6.12.0: + resolution: {integrity: sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==} + + ts-proto-descriptors@2.0.0: + resolution: {integrity: sha512-wHcTH3xIv11jxgkX5OyCSFfw27agpInAd6yh89hKG6zqIXnjW9SYqSER2CVQxdPj4czeOhGagNvZBEbJPy7qkw==} + + ts-proto@2.7.5: + resolution: {integrity: sha512-FoRxSaNW+P3m+GiXIZjUjhaHXT67Ah4zMGKzn4yklbGRQTS+PqpUhKo5AJnwfUDUByjEUG7ch36byFUYWRH9Nw==} + hasBin: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@5.9.2: + resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.10.0: + resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} + + viem@2.34.0: + resolution: {integrity: sha512-HJZG9Wt0DLX042MG0PK17tpataxtdAEhpta9/Q44FqKwy3xZMI5Lx4jF+zZPuXFuYjZ68R0PXqRwlswHs6r4gA==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + +snapshots: + + '@adraffy/ens-normalize@1.11.0': {} + + '@biomejs/biome@2.1.3': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 2.1.3 + '@biomejs/cli-darwin-x64': 2.1.3 + '@biomejs/cli-linux-arm64': 2.1.3 + '@biomejs/cli-linux-arm64-musl': 2.1.3 + '@biomejs/cli-linux-x64': 2.1.3 + '@biomejs/cli-linux-x64-musl': 2.1.3 + '@biomejs/cli-win32-arm64': 2.1.3 + '@biomejs/cli-win32-x64': 2.1.3 + + '@biomejs/cli-darwin-arm64@2.1.3': + optional: true + + '@biomejs/cli-darwin-x64@2.1.3': + optional: true + + '@biomejs/cli-linux-arm64-musl@2.1.3': + optional: true + + '@biomejs/cli-linux-arm64@2.1.3': + optional: true + + '@biomejs/cli-linux-x64-musl@2.1.3': + optional: true + + '@biomejs/cli-linux-x64@2.1.3': + optional: true + + '@biomejs/cli-win32-arm64@2.1.3': + optional: true + + '@biomejs/cli-win32-x64@2.1.3': + optional: true + + '@bufbuild/buf-darwin-arm64@1.56.0': + optional: true + + '@bufbuild/buf-darwin-x64@1.56.0': + optional: true + + '@bufbuild/buf-linux-aarch64@1.56.0': + optional: true + + '@bufbuild/buf-linux-armv7@1.56.0': + optional: true + + '@bufbuild/buf-linux-x64@1.56.0': + optional: true + + '@bufbuild/buf-win32-arm64@1.56.0': + optional: true + + '@bufbuild/buf-win32-x64@1.56.0': + optional: true + + '@bufbuild/buf@1.56.0': + optionalDependencies: + '@bufbuild/buf-darwin-arm64': 1.56.0 + '@bufbuild/buf-darwin-x64': 1.56.0 + '@bufbuild/buf-linux-aarch64': 1.56.0 + '@bufbuild/buf-linux-armv7': 1.56.0 + '@bufbuild/buf-linux-x64': 1.56.0 + '@bufbuild/buf-win32-arm64': 1.56.0 + '@bufbuild/buf-win32-x64': 1.56.0 + + '@bufbuild/protobuf@2.6.3': {} + + '@bufbuild/protoc-gen-es@2.6.3(@bufbuild/protobuf@2.6.3)': + dependencies: + '@bufbuild/protoplugin': 2.6.3 + optionalDependencies: + '@bufbuild/protobuf': 2.6.3 + transitivePeerDependencies: + - supports-color + + '@bufbuild/protoplugin@2.6.3': + dependencies: + '@bufbuild/protobuf': 2.6.3 + '@typescript/vfs': 1.6.1(typescript@5.4.5) + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + + '@noble/ciphers@1.3.0': {} + + '@noble/curves@1.9.6': + dependencies: + '@noble/hashes': 1.8.0 + + '@noble/hashes@1.8.0': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@scure/base@1.2.6': {} + + '@scure/bip32@1.7.0': + dependencies: + '@noble/curves': 1.9.6 + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + + '@scure/bip39@1.6.0': + dependencies: + '@noble/hashes': 1.8.0 + '@scure/base': 1.2.6 + + '@standard-schema/spec@1.0.0': {} + + '@types/bun@1.2.19(@types/react@19.1.10)': + dependencies: + bun-types: 1.2.19(@types/react@19.1.10) + transitivePeerDependencies: + - '@types/react' + + '@types/node@24.3.0': + dependencies: + undici-types: 7.10.0 + + '@types/react@19.1.10': + dependencies: + csstype: 3.1.3 + + '@typescript/vfs@1.6.1(typescript@5.4.5)': + dependencies: + debug: 4.4.1 + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + + abitype@1.0.8(typescript@5.9.2)(zod@3.25.76): + optionalDependencies: + typescript: 5.9.2 + zod: 3.25.76 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + bun-types@1.2.19(@types/react@19.1.10): + dependencies: + '@types/node': 24.3.0 + '@types/react': 19.1.10 + + case-anything@2.1.13: {} + + csstype@3.1.3: {} + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + detect-libc@1.0.3: {} + + dprint-node@1.0.8: + dependencies: + detect-libc: 1.0.3 + + eventemitter3@5.0.1: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + isows@1.0.7(ws@8.18.3): + dependencies: + ws: 8.18.3 + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + ms@2.1.3: {} + + ox@0.8.7(typescript@5.9.2)(zod@3.25.76): + dependencies: + '@adraffy/ens-normalize': 1.11.0 + '@noble/ciphers': 1.3.0 + '@noble/curves': 1.9.6 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.0.8(typescript@5.9.2)(zod@3.25.76) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - zod + + picomatch@2.3.1: {} + + queue-microtask@1.2.3: {} + + reusify@1.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-poet@6.12.0: + dependencies: + dprint-node: 1.0.8 + + ts-proto-descriptors@2.0.0: + dependencies: + '@bufbuild/protobuf': 2.6.3 + + ts-proto@2.7.5: + dependencies: + '@bufbuild/protobuf': 2.6.3 + case-anything: 2.1.13 + ts-poet: 6.12.0 + ts-proto-descriptors: 2.0.0 + + tslib@2.8.1: {} + + typescript@5.4.5: {} + + typescript@5.9.2: {} + + undici-types@7.10.0: {} + + viem@2.34.0(typescript@5.9.2)(zod@3.25.76): + dependencies: + '@noble/curves': 1.9.6 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.0.8(typescript@5.9.2)(zod@3.25.76) + isows: 1.0.7(ws@8.18.3) + ox: 0.8.7(typescript@5.9.2)(zod@3.25.76) + ws: 8.18.3 + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + ws@8.18.3: {} + + zod@3.25.76: {} diff --git a/src/workflows/on-chain-write/abi.ts b/src/workflows/on-chain-write/abi.ts new file mode 100644 index 00000000..cebf4719 --- /dev/null +++ b/src/workflows/on-chain-write/abi.ts @@ -0,0 +1,126 @@ +export const STORAGE_ABI = [ + { + inputs: [], + name: "get", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, +] as const; + +export const CALCULATOR_CONSUMER_ABI = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { + inputs: [ + { internalType: "address", name: "received", type: "address" }, + { internalType: "address", name: "expected", type: "address" }, + ], + name: "InvalidAuthor", + type: "error", + }, + { + inputs: [ + { internalType: "bytes10", name: "received", type: "bytes10" }, + { internalType: "bytes10", name: "expected", type: "bytes10" }, + ], + name: "InvalidWorkflowName", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "resultId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "finalResult", + type: "uint256", + }, + ], + name: "ResultUpdated", + type: "event", + }, + { + inputs: [], + name: "EXPECTED_AUTHOR", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "EXPECTED_WORKFLOW_NAME", + outputs: [{ internalType: "bytes10", name: "", type: "bytes10" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "uint256", name: "offchainValue", type: "uint256" }, + { internalType: "int256", name: "onchainValue", type: "int256" }, + { internalType: "uint256", name: "finalResult", type: "uint256" }, + ], + internalType: "struct CalculatorConsumer.CalculatorResult", + name: "_prospectiveResult", + type: "tuple", + }, + ], + name: "isResultAnomalous", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "latestResult", + outputs: [ + { internalType: "uint256", name: "offchainValue", type: "uint256" }, + { internalType: "int256", name: "onchainValue", type: "int256" }, + { internalType: "uint256", name: "finalResult", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes", name: "", type: "bytes" }, + { internalType: "bytes", name: "report", type: "bytes" }, + ], + name: "onReport", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "resultCount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "", type: "uint256" }], + name: "results", + outputs: [ + { internalType: "uint256", name: "offchainValue", type: "uint256" }, + { internalType: "int256", name: "onchainValue", type: "int256" }, + { internalType: "uint256", name: "finalResult", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "pure", + type: "function", + }, +] as const; diff --git a/src/workflows/on-chain-write/on-chain-write.ts b/src/workflows/on-chain-write/on-chain-write.ts new file mode 100644 index 00000000..e1860e98 --- /dev/null +++ b/src/workflows/on-chain-write/on-chain-write.ts @@ -0,0 +1,263 @@ +import { z } from "zod"; +import { cre, type Environment } from "@cre/sdk/cre"; +import { runInNodeMode } from "@cre/sdk/runtime/run-in-node-mode"; +import { SimpleConsensusInputsSchema } from "@cre/generated/sdk/v1alpha/sdk_pb"; +import { create } from "@bufbuild/protobuf"; +import { + consensusDescriptorMedian, + observationValue, +} from "@cre/sdk/utils/values/consensus"; +import { sendResponseValue } from "@cre/sdk/utils/send-response-value"; +import { val } from "@cre/sdk/utils/values/value"; +import { + encodeFunctionData, + decodeFunctionResult, + type Hex, + toHex, + encodeAbiParameters, +} from "viem"; +import { bytesToHex } from "@cre/sdk/utils/hex-utils"; +import { CALCULATOR_CONSUMER_ABI, STORAGE_ABI } from "./abi"; +import type { Runtime } from "@cre/sdk/workflow"; +import { capability } from "@cre/generated/tools/generator/v1alpha/cre_metadata_pb"; +// Storage contract ABI - we only need the 'get' function +// TODO: In production, load ABI from external file or contract metadata +// following Go SDK patterns for ABI management + +// Config struct defines the parameters that can be passed to the workflow +const configSchema = z.object({ + schedule: z.string(), + apiUrl: z.string(), + evms: z.array( + z.object({ + storageAddress: z.string(), + calculatorConsumerAddress: z.string(), + chainSelector: z.number(), + gasLimit: z.number(), + }) + ), +}); + +type Config = z.infer; + +// // updateCalculatorResult handles the logic for writing data to the CalculatorConsumer contract. +// func updateCalculatorResult(env *sdk.Environment[*Config], runtime sdk.Runtime, evmConfig EvmConfig, offchainValue *big.Int, onchainValue *big.Int, finalResult *big.Int) (string, error) { +// env.Logger.Info("Updating calculator result", "consumerAddress", evmConfig.CalculatorConsumerAddress) +// ​ +// evmClient := &evm.Client{ +// ChainSelector: evmConfig.ChainSelector, +// } +// ​ +// // Create a contract binding instance pointed at the CalculatorConsumer address. +// consumerContract, err := calculator_consumer.NewCalculatorConsumer(evmClient, common.HexToAddress(evmConfig.CalculatorConsumerAddress).Bytes(), nil) +// if err != nil { +// return "", fmt.Errorf("failed to create consumer contract instance: %w", err) +// } +// ​ +// gasConfig := &evm.GasConfig{ +// GasLimit: evmConfig.GasLimit, +// } +// ​ +// env.Logger.Info("Writing report to consumer contract", "offchainValue", offchainValue, "onchainValue", onchainValue, "finalResult", finalResult) +// // Call the `WriteReport` method on the binding. This sends a secure report to the consumer. +// writeReportPromise, err := consumerContract.WriteReportCalculatorConsumerCalculatorResult(runtime, calculator_consumer.CalculatorConsumerCalculatorResult{ +// OffchainValue: offchainValue, +// OnchainValue: onchainValue, +// FinalResult: finalResult, +// }, gasConfig) +// ​ +// if err != nil { +// env.Logger.Error("WriteReport failed", "error", err) +// return "", fmt.Errorf("failed to write report: %w", err) +// } +// ​ +// env.Logger.Info("Waiting for write report response") +// resp, err := writeReportPromise.Await() +// if err != nil { +// env.Logger.Error("WriteReport await failed", "error", err) +// return "", fmt.Errorf("failed to await write report: %w", err) +// } +// env.Logger.Info("Write report to consumer succeeded", "response", resp) +// txHash := fmt.Sprintf("0x%x", resp.TxHash) +// env.Logger.Info("Write report transaction succeeded", "txHash", txHash) +// return txHash, nil +// } + +async function updateCalculatorResult( + env: Environment, + evmConfig: Config["evms"][number], + offchainValue: bigint, + onchainValue: bigint, + finalResult: bigint +) { + const evmClient = new cre.capabilities.EVMClient( + undefined, // use default mode + BigInt(evmConfig.chainSelector) // pass chainSelector as BigInt + ); + + // Encode the contract call data for the 'onReport' function + const callData2 = encodeFunctionData({ + abi: CALCULATOR_CONSUMER_ABI, + functionName: "isResultAnomalous", + args: [ + { + offchainValue: offchainValue, + onchainValue: onchainValue, + finalResult: finalResult, + }, + ], + }); + + // Encode the contract call data for the 'get' function + const callData = encodeFunctionData({ + abi: CALCULATOR_CONSUMER_ABI, + functionName: "onReport", + // The `metadata` (first) parameter is unused here but is required by the IReceiver interface. + args: [toHex("0x"), callData2], + }); + + // dry run the call to ensure the value is not anomalous + const dryRunCall = await evmClient.callContract({ + call: { + from: "0x0000000000000000000000000000000000000000", // zero address for view calls + to: evmConfig.calculatorConsumerAddress, + data: callData, + }, + blockNumber: { + absVal: "03", // 3 for finalized block + sign: "-1", // negative + }, + }); + + const resp = await evmClient.writeReport({ + receiver: evmConfig.calculatorConsumerAddress, + report: { + rawReport: callData, + }, + }); + + return resp.txHash; +} + +// onCronTrigger is the callback function that gets executed when the cron trigger fires +const onCronTrigger = async (env: Environment): Promise => { + env.logger?.log("Hello, Calculator! Workflow triggered."); + + if (!env.config?.evms || env.config.evms.length === 0) { + throw new Error("No EVM configuration provided"); + } + + // Step 1: Fetch offchain data using consensus (from Part 2) + const offchainValue = await runInNodeMode(async () => { + const http = new cre.capabilities.HTTPClient(); + const resp = await http.sendRequest({ + url: env.config?.apiUrl, + method: "GET", + }); + + const bodyStr = new TextDecoder().decode(resp.body); + const num = Number.parseFloat(bodyStr.trim()); + + return create(SimpleConsensusInputsSchema, { + observation: observationValue(val.float64(num)), + descriptors: consensusDescriptorMedian, + }); + }); + + env.logger?.log("Successfully fetched offchain value"); + + // Get the first EVM configuration from the list + const evmConfig = env.config.evms[0]; + + // Step 2: Read onchain data using the EVM client with chainSelector + const evmClient = new cre.capabilities.EVMClient( + undefined, // use default mode + BigInt(evmConfig.chainSelector) // pass chainSelector as BigInt + ); + + // Encode the contract call data for the 'get' function + const callData = encodeFunctionData({ + abi: STORAGE_ABI, + functionName: "get", + }); + + const contractCall = await evmClient.callContract({ + call: { + from: "0x0000000000000000000000000000000000000000", // zero address for view calls + to: evmConfig.storageAddress, + data: callData, + }, + blockNumber: { + absVal: "03", // 3 for finalized block + sign: "-1", // negative + }, + }); + + // Decode the result + const decodedResult = decodeFunctionResult({ + abi: STORAGE_ABI, + functionName: "get", + data: bytesToHex(contractCall.data) as Hex, + }); + + const onchainValue = decodedResult as bigint; + env.logger?.log("Successfully read onchain value"); + + // Step 3: Combine the results - convert offchain float to bigint and add + const offchainFloat = + offchainValue.value.case === "float64Value" ? offchainValue.value.value : 0; + + const offchainBigInt = BigInt(Math.floor(offchainFloat)); + const finalResult = onchainValue + offchainBigInt; + + env.logger?.log("Final calculated result"); + + // Step 4: Write to the calculator consumer + const writeData = encodeFunctionData({ + abi: CALCULATOR_CONSUMER_ABI, + functionName: "onReport", + args: [toHex(finalResult), toHex(finalResult)], + }); + + const txHash = await updateCalculatorResult( + env, + evmConfig, + offchainBigInt, + onchainValue, + finalResult + ); + + sendResponseValue( + val.mapValue({ + FinalResult: val.bigint(finalResult), + }) + ); +}; + +// InitWorkflow is the required entry point for a CRE workflow +// The runner calls this function to initialize the workflow and register its handlers +const initWorkflow = (env: Environment) => { + const cron = new cre.capabilities.CronCapability(); + + return [ + cre.handler( + // Use the schedule from our config file + cron.trigger({ schedule: env.config?.schedule }), + onCronTrigger + ), + ]; +}; + +// main is the entry point for the workflow +export async function main() { + try { + const runner = await cre.newRunner({ + configSchema: configSchema, + }); + await runner.run(initWorkflow); + } catch (error) { + console.log("error", JSON.stringify(error, null, 2)); + } +} + +main(); From 98dbd82c18d9083fdb519bb42d056d9cabe50bbe Mon Sep 17 00:00:00 2001 From: Fernando Montero Date: Fri, 22 Aug 2025 11:37:49 +0100 Subject: [PATCH 2/5] encode and return final aggregated values --- src/workflows/on-chain-write/on-chain-write.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/workflows/on-chain-write/on-chain-write.ts b/src/workflows/on-chain-write/on-chain-write.ts index e1860e98..9f4b1ea7 100644 --- a/src/workflows/on-chain-write/on-chain-write.ts +++ b/src/workflows/on-chain-write/on-chain-write.ts @@ -213,11 +213,6 @@ const onCronTrigger = async (env: Environment): Promise => { env.logger?.log("Final calculated result"); // Step 4: Write to the calculator consumer - const writeData = encodeFunctionData({ - abi: CALCULATOR_CONSUMER_ABI, - functionName: "onReport", - args: [toHex(finalResult), toHex(finalResult)], - }); const txHash = await updateCalculatorResult( env, @@ -227,9 +222,16 @@ const onCronTrigger = async (env: Environment): Promise => { finalResult ); + if (!txHash) { + throw new Error("Failed to write report"); + } + sendResponseValue( val.mapValue({ + OffchainValue: val.bigint(offchainBigInt), + OnchainValue: val.bigint(onchainValue), FinalResult: val.bigint(finalResult), + TxHash: val.string(txHash.toString()), }) ); }; From 316427dcc536793e9945056d4bb262467a589b63 Mon Sep 17 00:00:00 2001 From: Fernando Montero Date: Fri, 22 Aug 2025 14:57:40 +0100 Subject: [PATCH 3/5] update code to use dry run --- .../on-chain-write/on-chain-write.ts | 73 +++++-------------- 1 file changed, 20 insertions(+), 53 deletions(-) diff --git a/src/workflows/on-chain-write/on-chain-write.ts b/src/workflows/on-chain-write/on-chain-write.ts index 9f4b1ea7..cfba7918 100644 --- a/src/workflows/on-chain-write/on-chain-write.ts +++ b/src/workflows/on-chain-write/on-chain-write.ts @@ -40,49 +40,6 @@ const configSchema = z.object({ type Config = z.infer; -// // updateCalculatorResult handles the logic for writing data to the CalculatorConsumer contract. -// func updateCalculatorResult(env *sdk.Environment[*Config], runtime sdk.Runtime, evmConfig EvmConfig, offchainValue *big.Int, onchainValue *big.Int, finalResult *big.Int) (string, error) { -// env.Logger.Info("Updating calculator result", "consumerAddress", evmConfig.CalculatorConsumerAddress) -// ​ -// evmClient := &evm.Client{ -// ChainSelector: evmConfig.ChainSelector, -// } -// ​ -// // Create a contract binding instance pointed at the CalculatorConsumer address. -// consumerContract, err := calculator_consumer.NewCalculatorConsumer(evmClient, common.HexToAddress(evmConfig.CalculatorConsumerAddress).Bytes(), nil) -// if err != nil { -// return "", fmt.Errorf("failed to create consumer contract instance: %w", err) -// } -// ​ -// gasConfig := &evm.GasConfig{ -// GasLimit: evmConfig.GasLimit, -// } -// ​ -// env.Logger.Info("Writing report to consumer contract", "offchainValue", offchainValue, "onchainValue", onchainValue, "finalResult", finalResult) -// // Call the `WriteReport` method on the binding. This sends a secure report to the consumer. -// writeReportPromise, err := consumerContract.WriteReportCalculatorConsumerCalculatorResult(runtime, calculator_consumer.CalculatorConsumerCalculatorResult{ -// OffchainValue: offchainValue, -// OnchainValue: onchainValue, -// FinalResult: finalResult, -// }, gasConfig) -// ​ -// if err != nil { -// env.Logger.Error("WriteReport failed", "error", err) -// return "", fmt.Errorf("failed to write report: %w", err) -// } -// ​ -// env.Logger.Info("Waiting for write report response") -// resp, err := writeReportPromise.Await() -// if err != nil { -// env.Logger.Error("WriteReport await failed", "error", err) -// return "", fmt.Errorf("failed to await write report: %w", err) -// } -// env.Logger.Info("Write report to consumer succeeded", "response", resp) -// txHash := fmt.Sprintf("0x%x", resp.TxHash) -// env.Logger.Info("Write report transaction succeeded", "txHash", txHash) -// return txHash, nil -// } - async function updateCalculatorResult( env: Environment, evmConfig: Config["evms"][number], @@ -96,7 +53,7 @@ async function updateCalculatorResult( ); // Encode the contract call data for the 'onReport' function - const callData2 = encodeFunctionData({ + const dryRunCallData = encodeFunctionData({ abi: CALCULATOR_CONSUMER_ABI, functionName: "isResultAnomalous", args: [ @@ -108,20 +65,12 @@ async function updateCalculatorResult( ], }); - // Encode the contract call data for the 'get' function - const callData = encodeFunctionData({ - abi: CALCULATOR_CONSUMER_ABI, - functionName: "onReport", - // The `metadata` (first) parameter is unused here but is required by the IReceiver interface. - args: [toHex("0x"), callData2], - }); - // dry run the call to ensure the value is not anomalous const dryRunCall = await evmClient.callContract({ call: { from: "0x0000000000000000000000000000000000000000", // zero address for view calls to: evmConfig.calculatorConsumerAddress, - data: callData, + data: dryRunCallData, }, blockNumber: { absVal: "03", // 3 for finalized block @@ -129,6 +78,24 @@ async function updateCalculatorResult( }, }); + const dryRunResponse = decodeFunctionResult({ + abi: CALCULATOR_CONSUMER_ABI, + functionName: "isResultAnomalous", + data: bytesToHex(dryRunCall.data) as Hex, + }); + + if (dryRunResponse) { + throw new Error("Result is anomalous"); + } + + // Encode the contract call data for the 'get' function + const callData = encodeFunctionData({ + abi: CALCULATOR_CONSUMER_ABI, + functionName: "onReport", + // The `metadata` (first) parameter is unused here but is required by the IReceiver interface. + args: [toHex("0x"), dryRunCallData], + }); + const resp = await evmClient.writeReport({ receiver: evmConfig.calculatorConsumerAddress, report: { From 2245131776db75883a9c3454a9ba3549d98d1b3d Mon Sep 17 00:00:00 2001 From: Fernando Montero Date: Mon, 25 Aug 2025 10:20:32 +0100 Subject: [PATCH 4/5] ignore abi --- scripts/compile-to-wasm.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/compile-to-wasm.ts b/scripts/compile-to-wasm.ts index b40f52f1..822dbff5 100644 --- a/scripts/compile-to-wasm.ts +++ b/scripts/compile-to-wasm.ts @@ -7,6 +7,8 @@ export const main = async () => { const workflowJSFiles = fg.sync("dist/workflows/**/*.js"); for (const jsFile of workflowJSFiles) { + if (jsFile.includes("abi")) continue; + const wasmFile = jsFile.replace(/\.js$/, ".wasm"); console.log(`\n\n🔨 Building WASM for: ${jsFile}`); From e5b81e78ccc0333367f40f1631b8ed64c01c80c5 Mon Sep 17 00:00:00 2001 From: Fernando Montero Date: Mon, 25 Aug 2025 15:15:08 +0100 Subject: [PATCH 5/5] parse chain selector as string --- src/workflows/on-chain-write/on-chain-write.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/workflows/on-chain-write/on-chain-write.ts b/src/workflows/on-chain-write/on-chain-write.ts index cfba7918..0d232f4e 100644 --- a/src/workflows/on-chain-write/on-chain-write.ts +++ b/src/workflows/on-chain-write/on-chain-write.ts @@ -32,8 +32,8 @@ const configSchema = z.object({ z.object({ storageAddress: z.string(), calculatorConsumerAddress: z.string(), - chainSelector: z.number(), - gasLimit: z.number(), + chainSelector: z.string(), + gasLimit: z.string(), }) ), });