diff --git a/examples/sample-foundry-project/lib/forge-std b/examples/sample-foundry-project/lib/forge-std index 52715a217..1d9650e95 160000 --- a/examples/sample-foundry-project/lib/forge-std +++ b/examples/sample-foundry-project/lib/forge-std @@ -1 +1 @@ -Subproject commit 52715a217dc51d0de15877878ab8213f6cbbbab5 +Subproject commit 1d9650e951204a0ddce9ff89c32f1997984cef4d diff --git a/lerna.json b/lerna.json index da11091ac..2d2eb25e6 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "npmClient": "npm", "packages": ["packages/*"], "exact": true, - "version": "2.16.5-alpha.0" + "version": "2.16.6" } diff --git a/package-lock.json b/package-lock.json index bdc53c8e6..0ce087df4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25838,394 +25838,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/erc7412/node_modules/@usecannon/builder": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@usecannon/builder/-/builder-2.16.4.tgz", - "integrity": "sha512-kxw0pntrb6e6vFx3aDJ1Ua5jOHMF3gHNsmxLKGwgzYpLtfNLynFIBWkItW35D327MXLQzhhVe/14ZcNM/udgxw==", - "license": "MIT", - "dependencies": { - "@synthetixio/router": "^3.4.0", - "axios": "^1.7.2", - "axios-retry": "^4.4.2", - "buffer": "^6.0.3", - "chalk": "^4.1.2", - "debug": "^4.3.6", - "form-data": "^4.0.0", - "fuse.js": "^7.0.0", - "lodash": "^4.17.21", - "pako": "^2.1.0", - "promise-events": "^0.2.4", - "typestub-ipfs-only-hash": "^4.0.0", - "viem": "^2.16.5", - "zod": "^3.23.6" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/erc7412/node_modules/@usecannon/builder/node_modules/@noble/curves": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", - "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/erc7412/node_modules/@usecannon/builder/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/erc7412/node_modules/@usecannon/builder/node_modules/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/erc7412/node_modules/@usecannon/builder/node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/erc7412/node_modules/@usecannon/builder/node_modules/abitype": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.5.tgz", - "integrity": "sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/erc7412/node_modules/@usecannon/builder/node_modules/isows": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.4.tgz", - "integrity": "sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/erc7412/node_modules/@usecannon/builder/node_modules/viem": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.20.0.tgz", - "integrity": "sha512-cM4vs81HnSNbfceI1MLkx4pCVzbVjl9xiNSv5SCutYjUyFFOVSPDlEyhpg2iHinxx1NM4Qne3END5eLT8rvUdg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.4.0", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0", - "abitype": "1.0.5", - "isows": "1.0.4", - "webauthn-p256": "0.0.5", - "ws": "8.17.1" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/erc7412/node_modules/@usecannon/builder/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "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 - } - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@usecannon/cli/-/cli-2.16.4.tgz", - "integrity": "sha512-1HuIfpWGDqBHjlGB1zx5pVydPwYqQ1GT8E4hLTL/QHIqgx1c0bpAa0E2Ldc0U3pLCG5rqWC45OnZkbkElrC8Ug==", - "license": "MIT", - "dependencies": { - "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.4", - "abitype": "^1.0.5", - "chalk": "^4.1.2", - "commander": "^9.5.0", - "debug": "^4.3.6", - "eth-provider": "^0.13.6", - "fastq": "^1.17.1", - "fs-extra": "^11.2.0", - "lodash": "^4.17.21", - "prompts": "^2.4.2", - "semver": "^7.6.3", - "table": "^6.8.2", - "tildify": "3.0.0", - "untildify": "^4.0.0", - "viem": "^2.16.5", - "znv": "^0.4.0", - "zod": "^3.23.8" - }, - "bin": { - "cannon": "bin/cannon.js" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/@noble/curves": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", - "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/abitype": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.6.tgz", - "integrity": "sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/isows": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.4.tgz", - "integrity": "sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/viem": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.20.0.tgz", - "integrity": "sha512-cM4vs81HnSNbfceI1MLkx4pCVzbVjl9xiNSv5SCutYjUyFFOVSPDlEyhpg2iHinxx1NM4Qne3END5eLT8rvUdg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.4.0", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0", - "abitype": "1.0.5", - "isows": "1.0.4", - "webauthn-p256": "0.0.5", - "ws": "8.17.1" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/viem/node_modules/abitype": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.5.tgz", - "integrity": "sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/erc7412/node_modules/@usecannon/cli/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "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 - } - } - }, "node_modules/erc7412/node_modules/abitype": { "version": "0.9.8", "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.9.8.tgz", @@ -26250,18 +25862,6 @@ } } }, - "node_modules/erc7412/node_modules/axios-retry": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", - "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", - "license": "Apache-2.0", - "dependencies": { - "is-retry-allowed": "^2.2.0" - }, - "peerDependencies": { - "axios": "0.x || 1.x" - } - }, "node_modules/erc7412/node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -26333,18 +25933,6 @@ "node": ">=10" } }, - "node_modules/erc7412/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/erc7412/node_modules/typechain": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", @@ -52245,8 +51833,8 @@ "license": "MIT", "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@usecannon/builder": "^2.16.4", - "@usecannon/cli": "^2.16.4", + "@usecannon/builder": "^2.16.5", + "@usecannon/cli": "^2.16.5", "cors": "^2.8.5", "dotenv": "^16.4.5", "envalid": "^8.0.0", @@ -52281,9 +51869,9 @@ } }, "packages/api/node_modules/@usecannon/builder": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@usecannon/builder/-/builder-2.16.4.tgz", - "integrity": "sha512-kxw0pntrb6e6vFx3aDJ1Ua5jOHMF3gHNsmxLKGwgzYpLtfNLynFIBWkItW35D327MXLQzhhVe/14ZcNM/udgxw==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@usecannon/builder/-/builder-2.16.5.tgz", + "integrity": "sha512-6EYCs3OHyJQWgDlTTnHcn1AkntBeyjGRJYFWeEiFbNVNdDv+ZKHHB58TAgzslBFwrwNr3G1/2u0CFdfJCeTEew==", "license": "MIT", "dependencies": { "@synthetixio/router": "^3.4.0", @@ -52322,20 +51910,14 @@ } } }, - "packages/api/node_modules/@usecannon/builder/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "license": "MIT" - }, "packages/api/node_modules/@usecannon/cli": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@usecannon/cli/-/cli-2.16.4.tgz", - "integrity": "sha512-1HuIfpWGDqBHjlGB1zx5pVydPwYqQ1GT8E4hLTL/QHIqgx1c0bpAa0E2Ldc0U3pLCG5rqWC45OnZkbkElrC8Ug==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@usecannon/cli/-/cli-2.16.5.tgz", + "integrity": "sha512-PfdkIDjCwQs6/ZB50oF5xMX4dtbbN7/X+3hzaKf1qesho0cGAQKjoP+olVlqQciTO0d8xjs1JPeQZ2T2VCb6Ow==", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.4", + "@usecannon/builder": "2.16.5", "abitype": "^1.0.5", "chalk": "^4.1.2", "commander": "^9.5.0", @@ -52374,12 +51956,6 @@ } } }, - "packages/api/node_modules/@usecannon/cli/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "license": "MIT" - }, "packages/api/node_modules/array-flatten": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", @@ -52654,7 +52230,7 @@ }, "packages/builder": { "name": "@usecannon/builder", - "version": "2.16.5-alpha.0", + "version": "2.16.6", "license": "MIT", "dependencies": { "@synthetixio/router": "^3.4.0", @@ -52706,11 +52282,11 @@ }, "packages/cli": { "name": "@usecannon/cli", - "version": "2.16.5-alpha.0", + "version": "2.16.6", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.5-alpha.0", + "@usecannon/builder": "2.16.6", "abitype": "^1.0.5", "chalk": "^4.1.2", "commander": "^9.5.0", @@ -52766,12 +52342,12 @@ } }, "packages/hardhat-cannon": { - "version": "2.16.5-alpha.0", + "version": "2.16.6", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.5-alpha.0", - "@usecannon/cli": "2.16.5-alpha.0", + "@usecannon/builder": "2.16.6", + "@usecannon/cli": "2.16.6", "chalk": "^4.1.2", "debug": "^4.3.6", "fs-extra": "^11.2.0", @@ -52814,8 +52390,8 @@ "version": "2.12.0-alpha.0", "license": "ISC", "dependencies": { - "@usecannon/builder": "^2.16.4", - "@usecannon/cli": "^2.16.4", + "@usecannon/builder": "^2.16.5", + "@usecannon/cli": "^2.16.5", "dotenv": "^16.4.5", "envalid": "^8.0.0", "lodash": "^4.17.21", @@ -52829,9 +52405,9 @@ } }, "packages/indexer/node_modules/@usecannon/builder": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@usecannon/builder/-/builder-2.16.4.tgz", - "integrity": "sha512-kxw0pntrb6e6vFx3aDJ1Ua5jOHMF3gHNsmxLKGwgzYpLtfNLynFIBWkItW35D327MXLQzhhVe/14ZcNM/udgxw==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@usecannon/builder/-/builder-2.16.5.tgz", + "integrity": "sha512-6EYCs3OHyJQWgDlTTnHcn1AkntBeyjGRJYFWeEiFbNVNdDv+ZKHHB58TAgzslBFwrwNr3G1/2u0CFdfJCeTEew==", "license": "MIT", "dependencies": { "@synthetixio/router": "^3.4.0", @@ -52854,13 +52430,13 @@ } }, "packages/indexer/node_modules/@usecannon/cli": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@usecannon/cli/-/cli-2.16.4.tgz", - "integrity": "sha512-1HuIfpWGDqBHjlGB1zx5pVydPwYqQ1GT8E4hLTL/QHIqgx1c0bpAa0E2Ldc0U3pLCG5rqWC45OnZkbkElrC8Ug==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@usecannon/cli/-/cli-2.16.5.tgz", + "integrity": "sha512-PfdkIDjCwQs6/ZB50oF5xMX4dtbbN7/X+3hzaKf1qesho0cGAQKjoP+olVlqQciTO0d8xjs1JPeQZ2T2VCb6Ow==", "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.4", + "@usecannon/builder": "2.16.5", "abitype": "^1.0.5", "chalk": "^4.1.2", "commander": "^9.5.0", @@ -52929,14 +52505,14 @@ "@typechain/hardhat": "6.1.2", "@types/mocha": "9.1.1", "@types/node": "18.0.0", - "@usecannon/builder": "^2.16.4", - "@usecannon/cli": "^2.16.4", + "@usecannon/builder": "^2.16.5", + "@usecannon/cli": "^2.16.5", "at-least-node": "^1.0.0", "chai": "4.3.6", "dotenv": "16.0.1", "ethers": "5.7.1", "hardhat": "^2.22.3", - "hardhat-cannon": "^2.16.4", + "hardhat-cannon": "^2.16.5", "hardhat-contract-sizer": "^2.7.0", "hardhat-gas-reporter": "^1.0.9", "mocha": "10.0.0", @@ -52954,9 +52530,9 @@ "license": "MIT" }, "packages/registry/node_modules/@usecannon/builder": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@usecannon/builder/-/builder-2.16.4.tgz", - "integrity": "sha512-kxw0pntrb6e6vFx3aDJ1Ua5jOHMF3gHNsmxLKGwgzYpLtfNLynFIBWkItW35D327MXLQzhhVe/14ZcNM/udgxw==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@usecannon/builder/-/builder-2.16.5.tgz", + "integrity": "sha512-6EYCs3OHyJQWgDlTTnHcn1AkntBeyjGRJYFWeEiFbNVNdDv+ZKHHB58TAgzslBFwrwNr3G1/2u0CFdfJCeTEew==", "dev": true, "license": "MIT", "dependencies": { @@ -52980,14 +52556,14 @@ } }, "packages/registry/node_modules/@usecannon/cli": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/@usecannon/cli/-/cli-2.16.4.tgz", - "integrity": "sha512-1HuIfpWGDqBHjlGB1zx5pVydPwYqQ1GT8E4hLTL/QHIqgx1c0bpAa0E2Ldc0U3pLCG5rqWC45OnZkbkElrC8Ug==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@usecannon/cli/-/cli-2.16.5.tgz", + "integrity": "sha512-PfdkIDjCwQs6/ZB50oF5xMX4dtbbN7/X+3hzaKf1qesho0cGAQKjoP+olVlqQciTO0d8xjs1JPeQZ2T2VCb6Ow==", "dev": true, "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.4", + "@usecannon/builder": "2.16.5", "abitype": "^1.0.5", "chalk": "^4.1.2", "commander": "^9.5.0", @@ -53040,15 +52616,15 @@ } }, "packages/registry/node_modules/hardhat-cannon": { - "version": "2.16.4", - "resolved": "https://registry.npmjs.org/hardhat-cannon/-/hardhat-cannon-2.16.4.tgz", - "integrity": "sha512-81Z6Ql5LbG1IRzGi6SXR+jWx7WvXcJdo3kHyHC5laECmboLFQQfPKDMWLHpcES5KI5Qeseysebj9bxzkrrRrUQ==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/hardhat-cannon/-/hardhat-cannon-2.16.5.tgz", + "integrity": "sha512-qylHVRfCp6HXZJTOmifaeS/En3L+wzcbPq/fLxs5CnpsEwk06Vam0BCl23VMjErabxyGbGflR5CX8FX/Nol8hg==", "dev": true, "license": "MIT", "dependencies": { "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.4", - "@usecannon/cli": "2.16.4", + "@usecannon/builder": "2.16.5", + "@usecannon/cli": "2.16.5", "chalk": "^4.1.2", "debug": "^4.3.6", "fs-extra": "^11.2.0", @@ -53199,8 +52775,8 @@ "@types/node": "20.3.2", "@types/react": "18.2.37", "@types/react-dom": "18.2.6", - "@usecannon/builder": "2.16.5-alpha.0", - "@usecannon/cli": "2.16.5-alpha.0", + "@usecannon/builder": "^2.16.5", + "@usecannon/cli": "^2.16.5", "@vercel/analytics": "^1.1.1", "axios": "^1.6.7", "browser-level": "^1.0.1", @@ -53286,6 +52862,60 @@ "integrity": "sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw==", "license": "MIT" }, + "packages/website/node_modules/@usecannon/builder": { + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@usecannon/builder/-/builder-2.16.5.tgz", + "integrity": "sha512-6EYCs3OHyJQWgDlTTnHcn1AkntBeyjGRJYFWeEiFbNVNdDv+ZKHHB58TAgzslBFwrwNr3G1/2u0CFdfJCeTEew==", + "license": "MIT", + "dependencies": { + "@synthetixio/router": "^3.4.0", + "axios": "^1.7.2", + "axios-retry": "^4.4.2", + "buffer": "^6.0.3", + "chalk": "^4.1.2", + "debug": "^4.3.6", + "form-data": "^4.0.0", + "fuse.js": "^7.0.0", + "lodash": "^4.17.21", + "pako": "^2.1.0", + "promise-events": "^0.2.4", + "typestub-ipfs-only-hash": "^4.0.0", + "viem": "^2.16.5", + "zod": "^3.23.6" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "packages/website/node_modules/@usecannon/cli": { + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@usecannon/cli/-/cli-2.16.5.tgz", + "integrity": "sha512-PfdkIDjCwQs6/ZB50oF5xMX4dtbbN7/X+3hzaKf1qesho0cGAQKjoP+olVlqQciTO0d8xjs1JPeQZ2T2VCb6Ow==", + "license": "MIT", + "dependencies": { + "@iarna/toml": "^3.0.0", + "@usecannon/builder": "2.16.5", + "abitype": "^1.0.5", + "chalk": "^4.1.2", + "commander": "^9.5.0", + "debug": "^4.3.6", + "eth-provider": "^0.13.6", + "fastq": "^1.17.1", + "fs-extra": "^11.2.0", + "lodash": "^4.17.21", + "prompts": "^2.4.2", + "semver": "^7.6.3", + "table": "^6.8.2", + "tildify": "3.0.0", + "untildify": "^4.0.0", + "viem": "^2.16.5", + "znv": "^0.4.0", + "zod": "^3.23.8" + }, + "bin": { + "cannon": "bin/cannon.js" + } + }, "packages/website/node_modules/abitype": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.5.tgz", @@ -53313,6 +52943,18 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, + "packages/website/node_modules/axios-retry": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", + "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", + "license": "Apache-2.0", + "dependencies": { + "is-retry-allowed": "^2.2.0" + }, + "peerDependencies": { + "axios": "0.x || 1.x" + } + }, "packages/website/node_modules/eslint": { "version": "8.43.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", @@ -53473,6 +53115,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/website/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "packages/website/node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", diff --git a/package.json b/package.json index 262d72787..5f9ee3ec4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "lint:fix:js": "prettier --write '{packages,examples}/**/*.{js,ts}' && eslint --fix '{packages,examples}/**/*.{js,ts}'", "lint:fix:sol": "prettier --write '{packages,examples}/*/{contracts,src}/**/*.sol'", "lint:fix": "npm-run-parallel lint:fix:js lint:fix:sol", - "build": "lerna run build --ignore cannon-website --ignore @usecannon/indexer --ignore repo --ignore @usecannon/api", + "build": "lerna run build --ignore cannon-website --ignore @usecannon/indexer --ignore repo", "version-alpha": "lerna version prerelease --no-private", "version-patch": "lerna version patch --no-private", "version-minor": "lerna version minor --no-private", diff --git a/packages/api/package.json b/packages/api/package.json index bac80b3c6..c7c8efcf6 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -14,8 +14,8 @@ "license": "MIT", "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@usecannon/builder": "^2.16.4", - "@usecannon/cli": "^2.16.4", + "@usecannon/builder": "2.16.6", + "@usecannon/cli": "2.16.6", "cors": "^2.8.5", "dotenv": "^16.4.5", "envalid": "^8.0.0", diff --git a/packages/builder/package.json b/packages/builder/package.json index d657c6ef0..37c23132a 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@usecannon/builder", - "version": "2.16.5-alpha.0", + "version": "2.16.6", "description": "Assembles cannonfile.toml manifests into cannon packages.", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -30,15 +30,15 @@ "@types/lodash": "^4.17.7", "@types/pako": "^2.0.3", "jest": "^29.7.0", - "rollup": "^4.20.0", - "ts-jest": "^29.2.4", - "typedoc": "^0.26.5", - "typedoc-plugin-markdown": "^4.2.4", - "typedoc-plugin-zod": "^1.2.0" + "rollup": "^4.21.2", + "ts-jest": "^29.2.5", + "typedoc": "^0.26.6", + "typedoc-plugin-markdown": "^4.2.6", + "typedoc-plugin-zod": "^1.2.1" }, "dependencies": { "@synthetixio/router": "^3.4.0", - "axios": "^1.7.4", + "axios": "^1.7.7", "axios-retry": "^4.5.0", "buffer": "^6.0.3", "chalk": "^4.1.2", @@ -49,7 +49,7 @@ "pako": "^2.1.0", "promise-events": "^0.2.4", "typestub-ipfs-only-hash": "^4.0.0", - "viem": "^2.19.4", + "viem": "^2.21.1", "zod": "^3.23.8" }, "engines": { diff --git a/packages/builder/src/schemas.ts b/packages/builder/src/schemas.ts index f2ca9a060..2eb7d671a 100644 --- a/packages/builder/src/schemas.ts +++ b/packages/builder/src/schemas.ts @@ -10,7 +10,7 @@ const argtype: z.ZodLazy = z.lazy(() => // Different regular expressions used to validate formats like // <%= string interpolation %>, step.names or property.names, packages:versions -const interpolatedRegex = RegExp(/^<%=\s\w+.+[\w()[\]-]+\s%>$/, 'i'); +const interpolatedRegex = RegExp(/\w*<%= [^%]* %>\w*|[^<%=]*<%= [^%]* %>[^<%=]*/, 'i'); const stepRegex = RegExp(/^[\w-]+\.[.\w-]+$/, 'i'); const packageRegex = RegExp(/^(?@?[a-z0-9][a-z0-9-]{1,}[a-z0-9])(?::(?[^@]+))?(@(?[^\s]+))?$/, 'i'); const jsonAbiPathRegex = RegExp(/^(?!.*\.d?$).*\.json?$/, 'i'); diff --git a/packages/builder/src/steps/__snapshots__/deploy.test.ts.snap b/packages/builder/src/steps/__snapshots__/deploy.test.ts.snap deleted file mode 100644 index bd39c2273..000000000 --- a/packages/builder/src/steps/__snapshots__/deploy.test.ts.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`steps/deploy.ts exec() when create2 = true fails if contract already deployed 1`] = `"The CREATE2 contract seems to be failing in the constructor. However, we were not able to get a stack trace."`; diff --git a/packages/builder/src/steps/clone.ts b/packages/builder/src/steps/clone.ts index c2159d685..7c0699c73 100644 --- a/packages/builder/src/steps/clone.ts +++ b/packages/builder/src/steps/clone.ts @@ -133,7 +133,7 @@ const cloneSpec = { runtime.emit( Events.Notice, packageState.currentLabel, - 'To prevent unexpected upgrades, it is strongly reccomended to lock the version of the source package by specifying a version in the `source` field.' + 'To prevent unexpected upgrades, it is strongly recommended to lock the version of the source package by specifying a version in the `source` field.' ); } diff --git a/packages/builder/src/steps/deploy.test.ts b/packages/builder/src/steps/deploy.test.ts index 57a7da8cf..9e612f59a 100644 --- a/packages/builder/src/steps/deploy.test.ts +++ b/packages/builder/src/steps/deploy.test.ts @@ -177,23 +177,45 @@ describe('steps/deploy.ts', () => { describe('exec()', () => { describe('when create2 = true', () => { - it('fails if contract already deployed', async () => { + it('works if contract already deployed', async () => { jest.mocked(fakeRuntime.provider.getCode).mockResolvedValue('0xabcdef'); - expect( - action.exec( - fakeRuntime, - fakeCtx, - { - artifact: 'hello', - create2: true, - args: [viem.stringToHex('one', { size: 32 }), viem.stringToHex('two', { size: 32 }), { three: 'four' }], - salt: 'wohoo', - value: '1234', + const result = await action.exec( + fakeRuntime, + fakeCtx, + { + artifact: 'hello', + create2: true, + args: [viem.stringToHex('one', { size: 32 }), viem.stringToHex('two', { size: 32 }), { three: 'four' }], + salt: 'wohoo', + value: '1234', + }, + { ref: new PackageReference('hello:1.0.0'), currentLabel: 'contract.Woot' } + ); + + expect(result).toStrictEqual({ + contracts: { + Woot: { + abi: fakeAbi, + address: '0x3F9270CE7b8704E7BE0BfcA0EA8836f2B135a4ef', + constructorArgs: [ + viem.stringToHex('one', { size: 32 }), + viem.stringToHex('two', { size: 32 }), + { three: 'four' }, + ], + contractName: undefined, + deployTxnHash: '', + deployTxnBlockNumber: '', + deployTimestamp: '', + deployedOn: 'contract.Woot', + gasCost: '0', + gasUsed: 0, + linkedLibraries: {}, + sourceName: undefined, + highlight: undefined, }, - { ref: new PackageReference('hello:1.0.0'), currentLabel: 'contract.Woot' } - ) - ).rejects.toThrowErrorMatchingSnapshot(); + }, + }); }); it('works if contract needs to be deployed', async () => { diff --git a/packages/builder/src/steps/deploy.ts b/packages/builder/src/steps/deploy.ts index 2618520e3..3115800b7 100644 --- a/packages/builder/src/steps/deploy.ts +++ b/packages/builder/src/steps/deploy.ts @@ -289,12 +289,7 @@ const deploySpec = { if (bytecode && bytecode !== '0x') { debug('create2 contract already completed'); - - // the cannon state does not think a contract should be deployed, but the on-chain state says a contract - // is deployed. this could be a mistake. alert the user and explain how to override - throw new Error( - `The contract at the create2 destination ${addr} is already deployed, but the Cannon state does not recognize that this contract has already been deployed. This typically indicates incorrect upgrade configuration. Please confirm if this contract should already be deployed or not, and if you want to continue the build as-is, run 'cannon alter ${packageState.ref} set-contract-address ${packageState.currentLabel} ${addr}'` - ); + // our work is done for us. unfortunately, its not easy to figure out what the transaction hash was } else { const signer = config.from ? await runtime.getSigner(config.from as viem.Address) diff --git a/packages/builder/src/steps/pull.ts b/packages/builder/src/steps/pull.ts index 479fae7a4..41e4e6730 100644 --- a/packages/builder/src/steps/pull.ts +++ b/packages/builder/src/steps/pull.ts @@ -87,7 +87,7 @@ const pullSpec = { runtime.emit( Events.Notice, packageState.currentLabel, - 'To prevent unexpected upgrades, it is strongly reccomended to lock the version of the source package by specifying a version in the `source` field.' + 'To prevent unexpected upgrades, it is strongly recommended to lock the version of the source package by specifying a version in the `source` field.' ); } diff --git a/packages/cli/package.json b/packages/cli/package.json index 0608d0fa6..5a4ed2511 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@usecannon/cli", - "version": "2.16.5-alpha.0", + "version": "2.16.6", "description": "Utility for instantly loading cannon packages in standalone contexts", "main": "dist/src/index.js", "scripts": { @@ -40,15 +40,15 @@ "@types/prompts": "^2.4.9", "@types/semver": "^7.5.8", "@types/sinon": "^17.0.3", - "axios": "^1.7.4", + "axios": "^1.7.7", "jest": "^29.7.0", "mock-fs": "^5.2.0", "tmp-promise": "^3.0.3", - "ts-jest": "^29.2.4", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", - "typedoc": "^0.26.5", - "typedoc-plugin-markdown": "^4.2.4", - "typedoc-plugin-zod": "^1.2.0", + "typedoc": "^0.26.6", + "typedoc-plugin-markdown": "^4.2.6", + "typedoc-plugin-zod": "^1.2.1", "typescript": "^5.5.4" }, "bin": { @@ -56,12 +56,12 @@ }, "dependencies": { "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.5-alpha.0", + "@usecannon/builder": "2.16.6", "abitype": "^1.0.6", "chalk": "^4.1.2", "commander": "^9.5.0", "debug": "^4.3.6", - "eth-provider": "^0.13.6", + "eth-provider": "^0.13.7", "fastq": "^1.17.1", "fs-extra": "^11.2.0", "lodash": "^4.17.21", @@ -70,7 +70,7 @@ "table": "^6.8.2", "tildify": "3.0.0", "untildify": "^4.0.0", - "viem": "^2.19.4", + "viem": "^2.21.1", "znv": "^0.4.0", "zod": "^3.23.8" }, diff --git a/packages/cli/src/commands/decode.ts b/packages/cli/src/commands/decode.ts index 6e33b406d..b5b2301c9 100644 --- a/packages/cli/src/commands/decode.ts +++ b/packages/cli/src/commands/decode.ts @@ -5,24 +5,31 @@ import { ContractData, DeploymentInfo, decodeTxError } from '@usecannon/builder' import { log, error, warn } from '../util/console'; import { readDeployRecursive } from '../package'; -import { formatAbiFunction, getSighash } from '../helpers'; +import { ensureChainIdConsistency, formatAbiFunction, getSighash } from '../helpers'; import { resolveCliSettings } from '../../src/settings'; +import { isTxHash } from '../util/is-tx-hash'; +import { getChainIdFromRpcUrl, isURL, ProviderAction, resolveProvider } from '../util/provider'; export async function decode({ packageRef, data, chainId, + rpcUrl, presetArg, json = false, }: { packageRef: string; - data: viem.Hash[]; - chainId: number; + data: viem.Hash; + chainId?: number; + rpcUrl?: string; presetArg: string; json: boolean; }) { - if (!data[0].startsWith('0x')) { - data[0] = ('0x' + data[0]) as viem.Hash; + const cliSettings = resolveCliSettings(); + + // Add 0x prefix to data or transaction hash if missing + if (!data.startsWith('0x')) { + data = ('0x' + data) as viem.Hash; } // Handle deprecated preset specification @@ -37,13 +44,33 @@ export async function decode({ packageRef = packageRef.split('@')[0] + `@${presetArg}`; } - const deployInfos = await readDeployRecursive(packageRef, chainId); + let inputData = data; + + if (isTxHash(data)) { + if (!chainId && rpcUrl && isURL(rpcUrl)) { + chainId = await getChainIdFromRpcUrl(rpcUrl); + } else { + if (!chainId) throw new Error('--chain-id or --rpc-url is required to decode transaction data'); + } + + await ensureChainIdConsistency(rpcUrl, chainId); + + const { provider } = await resolveProvider({ action: ProviderAction.ReadProvider, quiet: true, cliSettings, chainId }); + + const transaction = await provider.getTransaction({ + hash: data, + }); + + inputData = transaction.input; + } + + const deployInfos = await readDeployRecursive(packageRef, chainId!); const abis = deployInfos.flatMap((deployData) => _getAbis(deployData)); - const parsed = _parseData(abis, data); + const parsed = _parseData(abis, inputData); if (!parsed) { - const errorMessage = decodeTxError(data[0], abis); + const errorMessage = decodeTxError(inputData, abis); if (errorMessage) { log(errorMessage); return; @@ -67,11 +94,10 @@ export async function decode({ const sighash = getSighash(fragment as AbiFunction | AbiEvent); - log(); log(green(`${formatAbiFunction(fragment as any)}`), `${sighash ? italic(gray(sighash)) : ''}`); if ((parsed.result as viem.DecodeErrorResultReturnType).errorName) { - const errorMessage = decodeTxError(data[0], abis); + const errorMessage = decodeTxError(inputData, abis); if (errorMessage) { log(errorMessage); return; @@ -99,7 +125,6 @@ export async function decode({ offset.repeat(2) ); } - log(); } break; } @@ -132,8 +157,6 @@ export async function decode({ renderArgs((fragment as viem.AbiFunction).inputs[index], parsed.result.args[index]); } } - - log(); } function _getAbis(deployData: DeploymentInfo) { @@ -176,20 +199,21 @@ function _renderValue(type: viem.AbiParameter, value: string | bigint) { } } -function _parseData(abis: ContractData['abi'][], data: viem.Hash[]) { - if (data.length === 0) return null; +function _parseData(abis: ContractData['abi'][], data: viem.Hash) { + if (!data) return null; for (const abi of abis) { const result = - _try(() => viem.decodeErrorResult({ abi, data: data[0] })) || - _try(() => viem.decodeFunctionData({ abi, data: data[0] })) || + _try(() => viem.decodeErrorResult({ abi, data: data })) || + _try(() => viem.decodeFunctionData({ abi, data: data })) || _try(() => viem.decodeEventLog({ abi, - topics: (data.length > 1 ? data.slice(0, -1) : data) as [viem.Hex], - data: data.length > 1 ? data[data.length - 1] : '0x', + topics: [data] as [viem.Hex], + data, }) ); + if (result) return { abi, result }; } diff --git a/packages/cli/src/commandsConfig.ts b/packages/cli/src/commandsConfig.ts index 9fa4090df..859ec23d4 100644 --- a/packages/cli/src/commandsConfig.ts +++ b/packages/cli/src/commandsConfig.ts @@ -784,7 +784,7 @@ const commandsConfig = { }, { flags: '', - description: 'base 16 encoded transaction data to input to a function call, or transaction hash', + description: 'bytes32 encoded transaction data to input to a function call, or transaction hash', }, ], options: [ @@ -835,15 +835,22 @@ const commandsConfig = { description: 'Name, version and preset of the package to decode from (name:version@preset)', }, { - flags: '', - description: 'bytes32 encoded transaction data to decode', + flags: '', + description: 'bytes32 encoded transaction data, or transaction hash', }, ], options: [ { flags: '-c --chain-id ', description: 'Chain ID of the variant to inspect', - defaultValue: '13370', + }, + { + flags: '-n --rpc-url [url]', + description: 'RPC endpoint to decode on', + }, + { + flags: '-n --provider-url [url]', + description: '(DEPRECATED) RPC endpoint to decode on', }, { flags: '-p --preset ', diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 5f3c216f6..8e44838c6 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,7 +1,6 @@ import { spawn } from 'node:child_process'; import path from 'node:path'; import { - CANNON_CHAIN_ID, CannonStorage, ChainBuilderRuntime, ChainDefinition, @@ -674,10 +673,13 @@ applyCommandsConfig(program.command('trace'), commandsConfig.trace).action(async applyCommandsConfig(program.command('decode'), commandsConfig.decode).action(async function (packageRef, data, options) { const { decode } = await import('./commands/decode'); + const cliSettings = resolveCliSettings(options); + await decode({ packageRef, data, - chainId: parseInt(options.chainId || CANNON_CHAIN_ID), + chainId: options.chainId ? parseInt(options.chainId) : undefined, + rpcUrl: cliSettings.rpcUrl, presetArg: options.preset, json: options.json, }); diff --git a/packages/cli/src/util/is-tx-hash.ts b/packages/cli/src/util/is-tx-hash.ts new file mode 100644 index 000000000..94901f68d --- /dev/null +++ b/packages/cli/src/util/is-tx-hash.ts @@ -0,0 +1,18 @@ +import { isHash } from 'viem'; + +/** + * Checks if a string is a valid Ethereum transaction hash. + * + * An Ethereum transaction hash should be a 32-byte (64 characters) hexadecimal string + * prefixed with '0x', totaling 66 characters. + * + * @param {string} hash - The string to be checked. + * @returns {boolean} True if the string is a valid Ethereum transaction hash, false otherwise. + * + */ +export const isTxHash = (hash: string): boolean => { + // Check for exact 66-character length (including '0x' prefix) + const is66CharHex = /^0x[a-fA-F0-9]{64}$/.test(hash); + + return is66CharHex && isHash(hash); +}; diff --git a/packages/cli/src/util/provider.ts b/packages/cli/src/util/provider.ts index f2c06e2aa..0c924ce6e 100644 --- a/packages/cli/src/util/provider.ts +++ b/packages/cli/src/util/provider.ts @@ -76,7 +76,7 @@ export const hideApiKey = (rpcUrl: string) => { }; export const getChainIdFromRpcUrl = async (rpcUrl: string) => { - if (!isURL(rpcUrl)) throw new Error('Provider URL has not a valid format'); + if (!isURL(rpcUrl)) throw new Error('RPC URL has not a valid format'); const provider = viem.createPublicClient({ transport: viem.http(rpcUrl, { timeout: 180000 }) }); return provider.getChainId(); @@ -162,14 +162,14 @@ export async function resolveProviderAndSigners({ privateKey?: string; action: ProviderAction; }): Promise<{ provider: viem.PublicClient & viem.WalletClient; signers: CannonSigner[] }> { - const providerDisplayName = (providerUrl: string) => { - switch (providerUrl) { + const providerDisplayName = (rpcUrl: string) => { + switch (rpcUrl) { case 'frame': return 'Frame (frame.sh) if running'; case 'direct': return 'default IPC paths, ws://127.0.0.1:8546, or http://127.0.0.1:8545'; default: - return hideApiKey(providerUrl); + return hideApiKey(rpcUrl); } }; diff --git a/packages/cli/test/e2e/e2e-tests.bats b/packages/cli/test/e2e/e2e-tests.bats index 7689683e7..998e2670b 100644 --- a/packages/cli/test/e2e/e2e-tests.bats +++ b/packages/cli/test/e2e/e2e-tests.bats @@ -103,6 +103,22 @@ teardown() { assert_success } +@test "Decode - Synthetix configureCollateral function (Transaction Hash)" { + run decode.sh 6 + echo $output + assert_output --partial 'function configureCollateral(tuple config)' + assert_output --partial '0x644cb0f3' + assert_output --partial 'tuple config' + assert_output --partial 'bool depositingEnabled true' + assert_output --partial 'uint256 issuanceRatioD18 4000000000000000000' + assert_output --partial 'uint256 liquidationRatioD18 1500000000000000000' + assert_output --partial 'uint256 liquidationRewardD18 10000000000000000000' + assert_output --partial 'bytes32 oracleNodeId 0x050be821f7e92c7ca8366e2fe01eee313272231d436c5deaed75b978d78f7116' + assert_output --partial 'address tokenAddress 0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F' + assert_output --partial 'uint256 minDelegationD18 10000000000000000000' + assert_success +} + @test "Alter - Import contract " { run alter-import-contract.sh echo $output diff --git a/packages/cli/test/e2e/scripts/non-interactive/decode.sh b/packages/cli/test/e2e/scripts/non-interactive/decode.sh index 0718e5d00..02f496b00 100755 --- a/packages/cli/test/e2e/scripts/non-interactive/decode.sh +++ b/packages/cli/test/e2e/scripts/non-interactive/decode.sh @@ -14,5 +14,9 @@ case $1 in ;; 5) # stress test tuple bonanza - $CANNON decode trusted-multicall-forwarder 0x174dea710000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000066465706c6f7900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d584b63586e3658395562415142754a4b686d65415359476d434a6f3465616567355a666435617a6f4e47737800000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d556743474252476a576f32337879676f37416b3279456b5066637547504e486f7550767168724b527838476f0000000000000000000000000000000000000000000000000000000000000000000000000000000000004d68747470733a2f2f6769746875622e636f6d2f75736563616e6e6f6e2f63616e6e6f6e3a7061636b616765732f72656769737472792f63616e6e6f6e66696c652e6d61696e6e65742e746f6d6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002836623039306465356332653162303539633631326230613164306364343066393531643536393164000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014570ce88f490a80342cc156a6a0ebc173609f5e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000084aac438c0e4081025d866ae5c47f7f03e3e53aa94c5a9bd46173b8182424024f5d5337838000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000146b090de5c2e1b059c612b0a1d0cd40f951d5691d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014570ce88f490a80342cc156a6a0ebc173609f5e00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a4aac438c0a1a7b3a8a9c4099451d93943c003e197d52f41d92ed974a4b32a38732748902a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d584b63586e3658395562415142754a4b686d65415359476d434a6f3465616567355a666435617a6f4e4773780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e5c7efc9636a6a0408a46bb7f617094b81e5dba00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000243659cfe6000000000000000000000000dfc9ce9de4076acb7ca504ad74e4ecb57838f1eb00000000000000000000000000000000000000000000000000000000 + $CANNON decode trusted-multicall-forwarder 0x174dea710000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000066465706c6f7900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d584b63586e3658395562415142754a4b686d65415359476d434a6f3465616567355a666435617a6f4e47737800000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d556743474252476a576f32337879676f37416b3279456b5066637547504e486f7550767168724b527838476f0000000000000000000000000000000000000000000000000000000000000000000000000000000000004d68747470733a2f2f6769746875622e636f6d2f75736563616e6e6f6e2f63616e6e6f6e3a7061636b616765732f72656769737472792f63616e6e6f6e66696c652e6d61696e6e65742e746f6d6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002836623039306465356332653162303539633631326230613164306364343066393531643536393164000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014570ce88f490a80342cc156a6a0ebc173609f5e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000084aac438c0e4081025d866ae5c47f7f03e3e53aa94c5a9bd46173b8182424024f5d5337838000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000146b090de5c2e1b059c612b0a1d0cd40f951d5691d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014570ce88f490a80342cc156a6a0ebc173609f5e00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a4aac438c0a1a7b3a8a9c4099451d93943c003e197d52f41d92ed974a4b32a38732748902a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d584b63586e3658395562415142754a4b686d65415359476d434a6f3465616567355a666435617a6f4e4773780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e5c7efc9636a6a0408a46bb7f617094b81e5dba00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000243659cfe6000000000000000000000000dfc9ce9de4076acb7ca504ad74e4ecb57838f1eb00000000000000000000000000000000000000000000000000000000 --chain-id 13370 + ;; + 6) + $CANNON decode synthetix-omnibus 0x243fc3d98160ae6ec9f764dd688cbc4c99d29f30d5e28ebefdc4968a45371ce3 --rpc-url https://eth.llamarpc.com + esac diff --git a/packages/hardhat-cannon/package.json b/packages/hardhat-cannon/package.json index 72bdbfd51..a64dfd218 100644 --- a/packages/hardhat-cannon/package.json +++ b/packages/hardhat-cannon/package.json @@ -1,6 +1,6 @@ { "name": "hardhat-cannon", - "version": "2.16.5-alpha.0", + "version": "2.16.6", "description": "Agnostic chain construction. Select the protocols and configuration you need to quickly and easily verify your project", "repository": "github:usecannon/cannon", "author": "Synthetix", @@ -32,9 +32,9 @@ "@nomiclabs/hardhat-ethers": "^2.2.3", "@types/debug": "^4.1.12", "@types/mocha": "^10.0.7", - "@types/node": "^22.3.0", + "@types/node": "^22.5.1", "bn.js": "^5.2.1", - "hardhat": "^2.22.8", + "hardhat": "^2.22.9", "ts-node": "^10.9.2", "typescript": "^5.5.4" }, @@ -43,12 +43,12 @@ }, "dependencies": { "@iarna/toml": "^3.0.0", - "@usecannon/builder": "2.16.5-alpha.0", - "@usecannon/cli": "2.16.5-alpha.0", + "@usecannon/builder": "2.16.6", + "@usecannon/cli": "2.16.6", "chalk": "^4.1.2", "debug": "^4.3.6", "fs-extra": "^11.2.0", - "viem": "^2.19.4" + "viem": "^2.21.1" }, "gitHead": "81979336c4cfe5f1f8ee7677b2b968f886a20a87" } diff --git a/packages/hardhat-cannon/src/type-extensions.ts b/packages/hardhat-cannon/src/type-extensions.ts index 6f83542ab..e7e448dd4 100644 --- a/packages/hardhat-cannon/src/type-extensions.ts +++ b/packages/hardhat-cannon/src/type-extensions.ts @@ -15,7 +15,7 @@ declare module 'hardhat/types/config' { //export type NetworkConfig = NetworkConfig | HttpNetworkConfig; // TODO: this is a known (and apparently decided to be unsolved) issue with ts https://github.com/microsoft/TypeScript/issues/28078 - // therefore, in the future it would be best to update hardhat upstream to use the reccomended workaround and + // therefore, in the future it would be best to update hardhat upstream to use the recommended workaround and // remove the hardhatntework extension export interface CannonNetworkConfig extends HardhatNetworkConfig { // nothing for now diff --git a/packages/indexer/package.json b/packages/indexer/package.json index b0b7ce2ca..13bbf0775 100644 --- a/packages/indexer/package.json +++ b/packages/indexer/package.json @@ -11,8 +11,8 @@ "author": "", "license": "ISC", "dependencies": { - "@usecannon/builder": "^2.16.4", - "@usecannon/cli": "^2.16.4", + "@usecannon/builder": "2.16.6", + "@usecannon/cli": "2.16.6", "dotenv": "^16.4.5", "envalid": "^8.0.0", "lodash": "^4.17.21", diff --git a/packages/registry/package.json b/packages/registry/package.json index 40824928e..1f49d669a 100644 --- a/packages/registry/package.json +++ b/packages/registry/package.json @@ -24,14 +24,14 @@ "@typechain/hardhat": "6.1.2", "@types/mocha": "9.1.1", "@types/node": "18.0.0", - "@usecannon/builder": "^2.16.4", - "@usecannon/cli": "^2.16.4", + "@usecannon/builder": "2.16.6", + "@usecannon/cli": "2.16.6", "at-least-node": "^1.0.0", "chai": "4.3.6", "dotenv": "16.0.1", "ethers": "5.7.1", "hardhat": "^2.22.3", - "hardhat-cannon": "^2.16.4", + "hardhat-cannon": "2.16.6", "hardhat-contract-sizer": "^2.7.0", "hardhat-gas-reporter": "^1.0.9", "mocha": "10.0.0", diff --git a/packages/website/package.json b/packages/website/package.json index ae8f6198c..6577b922d 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -38,8 +38,8 @@ "@types/node": "20.3.2", "@types/react": "18.2.37", "@types/react-dom": "18.2.6", - "@usecannon/builder": "2.16.5-alpha.0", - "@usecannon/cli": "2.16.5-alpha.0", + "@usecannon/builder": "2.16.6", + "@usecannon/cli": "2.16.6", "@vercel/analytics": "^1.1.1", "axios": "^1.6.7", "browser-level": "^1.0.1", diff --git a/packages/website/src/components/Accordion.tsx b/packages/website/src/components/Accordion.tsx new file mode 100644 index 000000000..fb13dd39b --- /dev/null +++ b/packages/website/src/components/Accordion.tsx @@ -0,0 +1,61 @@ +import { + Accordion as AccordionChakra, + AccordionProps, + AccordionButton, + AccordionIcon, + AccordionItem as AccordionItemChakra, + AccordionItemProps, + AccordionPanel, + AccordionPanelProps, + Box, + Text, +} from '@chakra-ui/react'; +import { FC, PropsWithChildren } from 'react'; + +export const CustomAccordion: FC = ({ + children, + ...rest +}) => { + return ( + + {children} + + ); +}; + +export const CustomAccordionItem: FC< + PropsWithChildren & { + itemProps?: AccordionItemProps; + accordionPanelProps: AccordionPanelProps; + title: string; + } +> = ({ title, children, itemProps, accordionPanelProps }) => { + return ( + +

+ + + + {title} + + + + +

+ {children} +
+ ); +}; diff --git a/packages/website/src/components/CodePreview.tsx b/packages/website/src/components/CodePreview.tsx index 3b5392d18..c431e915b 100644 --- a/packages/website/src/components/CodePreview.tsx +++ b/packages/website/src/components/CodePreview.tsx @@ -1,11 +1,12 @@ import { FC, useRef } from 'react'; -import Editor from '@monaco-editor/react'; +import Editor, { type EditorProps } from '@monaco-editor/react'; interface ICodePreviewProps { code: string; language?: string; height?: string | number | undefined; line?: number; // The line to highlight + editorProps?: EditorProps; } export const CodePreview: FC = ({ @@ -13,6 +14,7 @@ export const CodePreview: FC = ({ language, height = '190px', line, + editorProps, }) => { const editorRef = useRef(null); @@ -53,6 +55,7 @@ export const CodePreview: FC = ({ value={code} options={{ readOnly: true }} onMount={handleEditorDidMount} + {...editorProps} /> ); }; diff --git a/packages/website/src/components/IconText.tsx b/packages/website/src/components/IconText.tsx new file mode 100644 index 000000000..6b7ff5b47 --- /dev/null +++ b/packages/website/src/components/IconText.tsx @@ -0,0 +1,30 @@ +import { FC, ComponentType } from 'react'; +import { FlexProps, IconProps } from '@chakra-ui/react'; +import { Flex } from '@chakra-ui/react'; + +interface IconLinkProps extends FlexProps { + icon: ComponentType; + label: string; + iconProps?: IconProps; +} + +const IconText: FC = ({ + icon: IconComponent, + label, + iconProps, + ...flexProps +}) => { + return ( + + + {label} + + ); +}; + +export default IconText; diff --git a/packages/website/src/components/buttons/Outlined.tsx b/packages/website/src/components/buttons/Outlined.tsx new file mode 100644 index 000000000..cea865e94 --- /dev/null +++ b/packages/website/src/components/buttons/Outlined.tsx @@ -0,0 +1,25 @@ +import { Button, type ButtonProps } from '@chakra-ui/react'; +import { PropsWithChildren } from 'react'; + +type Props = PropsWithChildren<{ buttonProps: ButtonProps & { href: string } }>; +export default function ButtonOutlined({ children, buttonProps }: Props) { + return ( + + ); +} diff --git a/packages/website/src/constants/externalLinks.ts b/packages/website/src/constants/externalLinks.ts index 4c03726a8..59649c63d 100644 --- a/packages/website/src/constants/externalLinks.ts +++ b/packages/website/src/constants/externalLinks.ts @@ -11,7 +11,8 @@ export const externalLinks = { PINATA_IPFS: 'https://www.pinata.cloud/', FOUNDRY_EXAMPLE: github + 'usecannon/cannon/tree/main/examples/sample-foundry-project', HARDHAT_EXAMPLE: github + 'usecannon/cannon/tree/main/examples/sample-hardhat-project', - ETHERSCAN: 'https://www.etherscan.io/', + ETHERSCAN: 'https://etherscan.io/', IPFS_CLUSTER: 'https://cluster.ipfs.io/', IPFS_CANNON: 'https://repo.usecannon.com/', + API_CANNON: process.env.NEXT_PUBLIC_API_URL || 'https://api.usecannon.com', }; diff --git a/packages/website/src/features/Deploy/DisplayedTransaction.tsx b/packages/website/src/features/Deploy/DisplayedTransaction.tsx index 3ed586efb..8396dfaff 100644 --- a/packages/website/src/features/Deploy/DisplayedTransaction.tsx +++ b/packages/website/src/features/Deploy/DisplayedTransaction.tsx @@ -100,7 +100,7 @@ export function DisplayedTransaction(props: { for (const n of parsedContractNames) { try { decodedFunctionData = decodeFunctionData({ - abi: contracts[n].abi, + abi: contracts[n]?.abi, data: props.txn?.data || '0x', }); contractName = n; @@ -117,7 +117,7 @@ export function DisplayedTransaction(props: { const functionArgs = decodedFunctionData?.args?.map((v) => v) || [ rawFunctionArgs, ]; - const functionFragmentsFromAbi = contracts?.[contractName].abi.filter( + const functionFragmentsFromAbi = contracts?.[contractName]?.abi.filter( (f) => 'name' in f && f.name === functionName ); const functionFragmentFromAbi = functionFragmentsFromAbi?.find( diff --git a/packages/website/src/features/Packages/CannonfileExplorer.tsx b/packages/website/src/features/Packages/CannonfileExplorer.tsx index a8ad0eec8..aa653ea34 100644 --- a/packages/website/src/features/Packages/CannonfileExplorer.tsx +++ b/packages/website/src/features/Packages/CannonfileExplorer.tsx @@ -34,6 +34,7 @@ import { CannonfileGraph } from './CannonfileGraph'; import { StepModalProvider } from '@/providers/stepModalProvider'; import { stringify } from '@iarna/toml'; import { PiGraphLight, PiCodeLight, PiListBullets } from 'react-icons/pi'; +import { ApiPackage } from '@usecannon/api/dist/src/types'; function omitEmptyObjects(config: { [x: string]: any }) { for (const key in config) { @@ -54,7 +55,7 @@ function omitEmptyObjects(config: { [x: string]: any }) { } export const CannonfileExplorer: FC<{ - pkg: any; + pkg: ApiPackage; }> = ({ pkg }) => { const deploymentData = useQueryIpfsDataParsed( pkg?.deployUrl, diff --git a/packages/website/src/features/Packages/CodeExplorer.tsx b/packages/website/src/features/Packages/CodeExplorer.tsx index 8e980da8b..a90eca3cc 100644 --- a/packages/website/src/features/Packages/CodeExplorer.tsx +++ b/packages/website/src/features/Packages/CodeExplorer.tsx @@ -19,6 +19,7 @@ import { DownloadIcon, InfoOutlineIcon } from '@chakra-ui/icons'; import { CustomSpinner } from '@/components/CustomSpinner'; import { isEmpty } from 'lodash'; import { DeploymentInfo } from '@usecannon/builder'; +import { ApiPackage } from '@usecannon/api/dist/src/types'; const handleDownload = (content: Record, filename: string) => { const blob = new Blob([JSON.stringify(content, null, 2)], { @@ -81,7 +82,7 @@ const PackageButton: FC<{ }; export const CodeExplorer: FC<{ - pkg: any; + pkg: ApiPackage; name: string; moduleName?: string; source: string; @@ -107,12 +108,9 @@ export const CodeExplorer: FC<{ }); const { data: metadata } = useQueryIpfsDataParsed<{ cannonfile: string; - }>(pkg?.metaUrl, !!pkg?.metaUrl); + }>(pkg.metaUrl); - const deploymentData = useQueryIpfsDataParsed( - pkg?.deployUrl, - !!pkg?.deployUrl - ); + const deploymentData = useQueryIpfsDataParsed(pkg.deployUrl); // Provisioned packages could be inside the "provision" (old) or "clone" (current) key // So we check both in order to keep backwards compatibility diff --git a/packages/website/src/features/Packages/CodePage.tsx b/packages/website/src/features/Packages/CodePage.tsx index d8df24400..7ef279782 100644 --- a/packages/website/src/features/Packages/CodePage.tsx +++ b/packages/website/src/features/Packages/CodePage.tsx @@ -6,9 +6,8 @@ import { CodeExplorer } from '@/features/Packages/CodeExplorer'; import { CustomSpinner } from '@/components/CustomSpinner'; import { Address } from 'viem'; import { useRouter } from 'next/router'; -import { useQuery } from '@tanstack/react-query'; -import { getPackage } from '@/helpers/api'; import { PackageReference } from '@usecannon/builder'; +import { usePackageByRef } from '@/hooks/api/usePackage'; export const CodePage: FC<{ name: string; @@ -19,10 +18,7 @@ export const CodePage: FC<{ }> = ({ name, tag, variant, moduleName }) => { const [chainId, preset] = PackageReference.parseVariant(variant); - const packagesQuery = useQuery({ - queryKey: ['package', [`${name}:${tag}@${preset}/${chainId}`]], - queryFn: getPackage, - }); + const packagesQuery = usePackageByRef({ name, tag, preset, chainId }); const searchParams = useRouter().query; const source = (searchParams.source as string) || ''; @@ -32,11 +28,15 @@ export const CodePage: FC<{ return ; } + if (packagesQuery.isError) { + throw new Error('Failed to fetch package'); + } + return ( = ({ pkg }) => { const deploymentData = useQueryIpfsDataParsed( pkg?.deployUrl, @@ -95,23 +88,6 @@ export const DeploymentExplorer: FC<{ ? mergeInvoke(deploymentInfo.state) : {}; - function extractAddressesAbis(obj: any, result: any = {}) { - for (const key in obj) { - if (obj[key] && typeof obj[key] === 'object') { - // If the current object has both address and abi keys - if (obj[key].address && obj[key].abi) { - result[key] = { - address: obj[key].address, - abi: obj[key].abi, - }; - } - // Recursively search through nested objects - extractAddressesAbis(obj[key], result); - } - } - return result; - } - const addressesAbis = deploymentInfo?.state ? extractAddressesAbis(deploymentInfo.state) : {}; @@ -145,22 +121,6 @@ export const DeploymentExplorer: FC<{ const mergedExtras = mergeExtras(deploymentInfo?.state || {}); - const handleDownload = () => { - const blob = new Blob([JSON.stringify(addressesAbis, null, 2)], { - type: 'application/json', - }); - const url = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = 'deployments.json'; - document.body.appendChild(a); - a.click(); - a.remove(); - URL.revokeObjectURL(url); - }; - - const pkgDef = deploymentData?.data?.def; - return pkg?.deployUrl ? ( {deploymentData.isLoading ? ( @@ -184,61 +144,10 @@ export const DeploymentExplorer: FC<{ ) : deploymentInfo ? ( - { - - - - - Run Package - - - - Install the CLI - {' '} - and then run a local node for development with this package - {pkg.chainId != 13370 && ' on a fork'}: - - - - - - } {(!isEmpty(addressesAbis) || !isEmpty(contractState)) && ( Contract Deployments - - - { const { variant, tag, name, moduleName, contractName, contractAddress } = @@ -35,17 +34,14 @@ const Interact: FC = () => { const [chainId, preset] = PackageReference.parseVariant(variant); - const packagesQuery = useQuery({ - queryKey: ['package', [`${name}:${tag}@${preset}/${chainId}`]], - queryFn: getPackage, - }); + const packagesQuery = usePackageByRef({ name, tag, preset, chainId }); const [cannonOutputs, setCannonOutputs] = useState({}); const [contract, setContract] = useState(); const deploymentData = useQueryIpfsDataParsed( - packagesQuery?.data?.data.deployUrl, - !!packagesQuery?.data?.data.deployUrl + packagesQuery?.data?.deployUrl, + !!packagesQuery?.data?.deployUrl ); useEffect(() => { @@ -95,14 +91,14 @@ const Interact: FC = () => { const deployUrl = `${ externalLinks.IPFS_CANNON - }${packagesQuery.data?.data.deployUrl.replace('ipfs://', '')}`; + }${packagesQuery.data?.deployUrl.replace('ipfs://', '')}`; const etherscanUrl = ( Object.values(chains).find( - (chain) => chain.id === packagesQuery.data?.data?.chainId + (chain) => chain.id === packagesQuery.data?.chainId ) as any - )?.blockExplorers?.default?.url ?? 'https://etherscan.io'; + )?.blockExplorers?.default?.url ?? externalLinks.ETHERSCAN; const isMobile = useBreakpointValue([true, true, false]); @@ -110,6 +106,10 @@ const Interact: FC = () => { const isLoadingData = packagesQuery.isPending || deploymentData.isPending; + if (!packagesQuery.isLoading && !packagesQuery.data) { + throw new Error('Failed to fetch package'); + } + return ( <> {/* Header */} @@ -172,11 +172,11 @@ const Interact: FC = () => { href={deployUrl} > {isMobile - ? `${packagesQuery.data?.data.deployUrl.substring( + ? `${packagesQuery.data?.deployUrl.substring( 0, 13 - )}...${packagesQuery.data?.data?.deployUrl.slice(-4)}` - : packagesQuery.data?.data?.deployUrl} + )}...${packagesQuery.data?.deployUrl.slice(-4)}` + : packagesQuery.data?.deployUrl} @@ -189,9 +189,9 @@ const Interact: FC = () => { contractSource={contract?.sourceName} address={contractAddress!} cannonOutputs={cannonOutputs} - chainId={packagesQuery.data?.data?.chainId} + chainId={packagesQuery.data!.chainId} onDrawerOpen={onOpen} - packageUrl={packagesQuery.data?.data.deployUrl} + packageUrl={packagesQuery.data?.deployUrl} /> diff --git a/packages/website/src/features/Packages/IpfsLinks.tsx b/packages/website/src/features/Packages/IpfsLinks.tsx index c908bdd9d..c0afcacb0 100644 --- a/packages/website/src/features/Packages/IpfsLinks.tsx +++ b/packages/website/src/features/Packages/IpfsLinks.tsx @@ -11,9 +11,10 @@ import { import { useQueryIpfsDataParsed } from '@/hooks/ipfs'; import { DeploymentInfo } from '@usecannon/builder/src/types'; import { PiCheckCircleFill, PiMinusCircleFill } from 'react-icons/pi'; +import { ApiPackage } from '@usecannon/api/dist/src/types'; export const IpfsLinks: FC<{ - pkg: any; + pkg: ApiPackage; }> = ({ pkg }) => { const theme = useTheme(); const green500Hex = theme.colors.green[500]; diff --git a/packages/website/src/features/Packages/PackageAccordionHelper/IntegrateWithPackage.tsx b/packages/website/src/features/Packages/PackageAccordionHelper/IntegrateWithPackage.tsx new file mode 100644 index 000000000..2e60f2018 --- /dev/null +++ b/packages/website/src/features/Packages/PackageAccordionHelper/IntegrateWithPackage.tsx @@ -0,0 +1,113 @@ +import CodePreview from '@/components/CodePreview'; +import { ItemBodyWrapper } from '@/features/Packages/PackageAccordionHelper/utils'; +import { InfoOutlineIcon } from '@chakra-ui/icons'; +import { Flex, Text, Tooltip } from '@chakra-ui/react'; +import Link from 'next/link'; +import camelCase from 'lodash/camelCase'; +import { ChainDefinition, getArtifacts } from '@usecannon/builder'; +import { DeploymentState } from '@usecannon/builder/src'; +import ButtonOutlined from '@/components/buttons/Outlined'; + +function generateSettingsText(settings?: Record) { + let text = ''; + for (const key in settings) { + text += `options.${key} = "${settings[key]}"\n`; + } + return text.trim(); +} + +type Props = { + name: string; + chainId: number; + preset: string; + version: string; + chainDefinition: ChainDefinition; + deploymentState: DeploymentState; +}; + +export default function IntegrateWithPackage({ + name, + chainId, + preset, + version, + chainDefinition, + deploymentState, +}: Props) { + const contextDataCode = getArtifacts(chainDefinition, deploymentState); + + const _preset = preset !== 'main' ? `@${preset}` : ''; + const _version = version !== 'latest' ? `:${version}` : ''; + const _source = `"${name.toLowerCase()}${_version}${_preset}"`; + + const pullCode = `[pull.${camelCase(name)}] +source = ${_source} +`; + + const cloneCode = `[clone.${camelCase(name)}] +source = ${_source} +target = "PACKAGE_NAME@${camelCase( + name + )}${_preset}" # Replace with a name:version@preset for your cloned instance. +${generateSettingsText(contextDataCode.settings)} +`.trim(); + + const interactCode = chainId == 13370 ? cloneCode : pullCode; + + return ( + + Build a cannonfile + + } + > + + + Add to Cannonfile + + + + + + + + + + Cannonfile Context Data + + + + + + + + + ); +} diff --git a/packages/website/src/features/Packages/PackageAccordionHelper/RetrieveAddressAbi.tsx b/packages/website/src/features/Packages/PackageAccordionHelper/RetrieveAddressAbi.tsx new file mode 100644 index 000000000..38770f7a2 --- /dev/null +++ b/packages/website/src/features/Packages/PackageAccordionHelper/RetrieveAddressAbi.tsx @@ -0,0 +1,70 @@ +import { CommandPreview } from '@/components/CommandPreview'; +import { ItemBodyWrapper } from '@/features/Packages/PackageAccordionHelper/utils'; +import { Button } from '@chakra-ui/react'; +import { FC } from 'react'; + +type Props = { + name: string; + chainId: number; + version: string; + preset: string; + addressesAbis: Record; +}; + +const DownloadButton: FC<{ onClick: () => void }> = ({ onClick }) => ( + +); + +const handleDownload = (addressesAbis: Record) => { + const blob = new Blob([JSON.stringify(addressesAbis, null, 2)], { + type: 'application/json', + }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'deployments.json'; + document.body.appendChild(a); + a.click(); + a.remove(); + URL.revokeObjectURL(url); +}; + +export default function RetrieveAddressAbi({ + name, + chainId, + version, + preset, + addressesAbis, +}: Props) { + const _version = version !== 'latest' ? `:${version}` : ''; + const _preset = preset !== 'main' ? `@${preset}` : ''; + const _chainId = chainId != 13370 ? ` --chain-id ${chainId}` : ''; + return ( + handleDownload(addressesAbis)} /> + } + > + + + ); +} diff --git a/packages/website/src/features/Packages/PackageAccordionHelper/RunPackageLocally.tsx b/packages/website/src/features/Packages/PackageAccordionHelper/RunPackageLocally.tsx new file mode 100644 index 000000000..a84579e2e --- /dev/null +++ b/packages/website/src/features/Packages/PackageAccordionHelper/RunPackageLocally.tsx @@ -0,0 +1,39 @@ +import ButtonOutlined from '@/components/buttons/Outlined'; +import { CommandPreview } from '@/components/CommandPreview'; +import { ItemBodyWrapper } from '@/features/Packages/PackageAccordionHelper/utils'; +import Link from 'next/link'; + +type Props = { + name: string; + chainId: number; + version: string; + preset: string; +}; + +export default function RunPackageLocally({ + name, + chainId, + version, + preset, +}: Props) { + const _version = version !== 'latest' ? `:${version}` : ''; + const _preset = preset !== 'main' ? `@${preset}` : ''; + const _chainId = chainId != 13370 ? ` --chain-id ${chainId}` : ''; + + return ( + + Install CLI + + } + > + + + ); +} diff --git a/packages/website/src/features/Packages/PackageAccordionHelper/index.tsx b/packages/website/src/features/Packages/PackageAccordionHelper/index.tsx new file mode 100644 index 000000000..554137b2a --- /dev/null +++ b/packages/website/src/features/Packages/PackageAccordionHelper/index.tsx @@ -0,0 +1,104 @@ +import { CustomAccordion, CustomAccordionItem } from '@/components/Accordion'; +import RunPackageLocally from '@/features/Packages/PackageAccordionHelper/RunPackageLocally'; +import { useQueryIpfsDataParsed } from '@/hooks/ipfs'; +import { ChainDefinition, DeploymentInfo } from '@usecannon/builder'; +import RetrieveAddressAbi from '@/features/Packages/PackageAccordionHelper/RetrieveAddressAbi'; +import IntegrateWithPackage from '@/features/Packages/PackageAccordionHelper/IntegrateWithPackage'; +import { extractAddressesAbis } from '@/features/Packages/utils/extractAddressesAndABIs'; +import { Skeleton, Stack, Text } from '@chakra-ui/react'; +import { usePackageByRef } from '@/hooks/api/usePackage'; + +type Props = { + name: string; + chainId: number; + tag: string; + preset: string; +}; + +export default function PackageAccordionHelper({ + name, + tag, + preset, + chainId, +}: Props) { + const packagesQuery = usePackageByRef({ name, tag, preset, chainId }); + + const deploymentData = useQueryIpfsDataParsed( + packagesQuery?.data?.deployUrl, + !!packagesQuery?.data?.deployUrl + ); + + const isLoading = packagesQuery.isLoading || deploymentData.isLoading; + + if (isLoading) { + return ( + + + + + + ); + } + + if (!packagesQuery.data || !deploymentData.data) { + throw new Error('Failed to fetch package'); + } + + const state = deploymentData.data.state; + const deploymentInfo = deploymentData.data; + + if (!state || !deploymentInfo) { + return null; + } + + return ( + + + + + + + + + + + {state && deploymentInfo ? ( + + ) : ( + Error retrieving deployment data + )} + + + ); +} diff --git a/packages/website/src/features/Packages/PackageAccordionHelper/utils.tsx b/packages/website/src/features/Packages/PackageAccordionHelper/utils.tsx new file mode 100644 index 000000000..5a9724dbf --- /dev/null +++ b/packages/website/src/features/Packages/PackageAccordionHelper/utils.tsx @@ -0,0 +1,29 @@ +import { Box, Flex, Heading } from '@chakra-ui/react'; +import { PropsWithChildren, FC, JSX } from 'react'; + +export const ItemBodyWrapper: FC< + PropsWithChildren & { titleText: string; titleAction: JSX.Element } +> = ({ children, titleAction, titleText }) => ( + + + + {titleText} + + + {titleAction} + + + {children} + +); diff --git a/packages/website/src/features/Packages/PackagePage.tsx b/packages/website/src/features/Packages/PackagePage.tsx index ed77ab750..ecf87fed4 100644 --- a/packages/website/src/features/Packages/PackagePage.tsx +++ b/packages/website/src/features/Packages/PackagePage.tsx @@ -4,18 +4,21 @@ import { FC } from 'react'; import { Flex, Container } from '@chakra-ui/react'; import { PackageCard } from '../Search/PackageCard/PackageCard'; import { CustomSpinner } from '@/components/CustomSpinner'; -import { useQuery } from '@tanstack/react-query'; -import { getPackage } from '@/helpers/api'; import Custom404 from '@/pages/404'; +import { usePackageByName } from '@/hooks/api/usePackage'; export const PackagePage: FC<{ name: string; }> = ({ name }) => { - // TODO: Handle pagination - const packagesQuery = useQuery({ - queryKey: ['package', name], - queryFn: getPackage, - }); + const packagesQuery = usePackageByName({ name }); + + if (packagesQuery.isLoading) { + return ; + } + + if (packagesQuery.isError) { + throw new Error('Failed to fetch package'); + } return ( diff --git a/packages/website/src/features/Packages/Tabs/CannonfileTab.tsx b/packages/website/src/features/Packages/Tabs/CannonfileTab.tsx index 9679f25a9..4a3240d33 100644 --- a/packages/website/src/features/Packages/Tabs/CannonfileTab.tsx +++ b/packages/website/src/features/Packages/Tabs/CannonfileTab.tsx @@ -4,9 +4,8 @@ import { FC } from 'react'; import { Flex } from '@chakra-ui/react'; import { CannonfileExplorer } from '@/features/Packages/CannonfileExplorer'; import { CustomSpinner } from '@/components/CustomSpinner'; -import { useQuery } from '@tanstack/react-query'; -import { getPackage } from '@/helpers/api'; import { PackageReference } from '@usecannon/builder'; +import { usePackageByRef } from '@/hooks/api/usePackage'; export const CannonfileTab: FC<{ name: string; @@ -15,18 +14,19 @@ export const CannonfileTab: FC<{ }> = ({ name, tag, variant }) => { const [chainId, preset] = PackageReference.parseVariant(variant); - const packagesQuery = useQuery({ - queryKey: ['package', [`${name}:${tag}@${preset}/${chainId}`]], - queryFn: getPackage, - }); + const packagesQuery = usePackageByRef({ name, tag, preset, chainId }); if (packagesQuery.isPending) { return ; } + if (packagesQuery.isError) { + throw new Error('Failed to fetch package'); + } + return ( - + ); }; diff --git a/packages/website/src/features/Packages/Tabs/DeploymentTab.tsx b/packages/website/src/features/Packages/Tabs/DeploymentTab.tsx index 62557de4d..03d897ddf 100644 --- a/packages/website/src/features/Packages/Tabs/DeploymentTab.tsx +++ b/packages/website/src/features/Packages/Tabs/DeploymentTab.tsx @@ -1,12 +1,11 @@ 'use client'; import { FC } from 'react'; -import { useQuery } from '@tanstack/react-query'; import { Flex } from '@chakra-ui/react'; import { PackageReference } from '@usecannon/builder'; import { DeploymentExplorer } from '@/features/Packages/DeploymentExplorer'; import { CustomSpinner } from '@/components/CustomSpinner'; -import { getPackage } from '@/helpers/api'; +import { usePackageByRef } from '@/hooks/api/usePackage'; export const DeploymentTab: FC<{ name: string; @@ -17,18 +16,24 @@ export const DeploymentTab: FC<{ decodeURIComponent(variant) ); - const packagesQuery = useQuery({ - queryKey: ['package', [`${name}:${tag}@${preset}/${chainId}`]], - queryFn: getPackage, + const packagesQuery = usePackageByRef({ + name, + tag, + preset, + chainId, }); if (packagesQuery.isPending) { return ; } + if (packagesQuery.isError) { + throw new Error('Failed to fetch package'); + } + return ( - + ); }; diff --git a/packages/website/src/features/Packages/Tabs/InteractTab.tsx b/packages/website/src/features/Packages/Tabs/InteractTab.tsx index 2f185da13..53fd84f35 100644 --- a/packages/website/src/features/Packages/Tabs/InteractTab.tsx +++ b/packages/website/src/features/Packages/Tabs/InteractTab.tsx @@ -18,10 +18,9 @@ import { import { ChainArtifacts, DeploymentInfo } from '@usecannon/builder'; import { getOutput } from '@/lib/builder'; import { useRouter } from 'next/router'; -import { useQuery } from '@tanstack/react-query'; -import { getPackage } from '@/helpers/api'; import { usePackageVersionUrlParams } from '@/hooks/routing/usePackageVersionUrlParams'; import { CustomSpinner } from '@/components/CustomSpinner'; +import { usePackageByRef } from '@/hooks/api/usePackage'; type Option = { moduleName: string; @@ -58,18 +57,16 @@ export const InteractTab: FC<{ }> = ({ children }) => { const router = useRouter(); const { name, tag, preset, chainId, variant } = usePackageVersionUrlParams(); - const packagesQuery = useQuery({ - queryKey: ['package', [`${name}:${tag}@${preset}/${chainId}`]], - queryFn: getPackage, - }); + const packagesQuery = usePackageByRef({ name, tag, preset, chainId }); + const activeContractOption = useActiveContract(); const [highlightedOptions, setHighlightedOptions] = useState([]); const [otherOptions, setOtherOptions] = useState([]); const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [routing, setRouting] = useState(false); const deploymentData = useQueryIpfsDataParsed( - packagesQuery?.data?.data.deployUrl, - !!packagesQuery?.data?.data.deployUrl + packagesQuery?.data?.deployUrl, + !!packagesQuery?.data?.deployUrl ); const hasSubnav = otherOptions.length > 0 || highlightedOptions.length > 1; diff --git a/packages/website/src/features/Packages/VersionSelect.tsx b/packages/website/src/features/Packages/VersionSelect.tsx index 6c9a44410..ae31d8474 100644 --- a/packages/website/src/features/Packages/VersionSelect.tsx +++ b/packages/website/src/features/Packages/VersionSelect.tsx @@ -11,24 +11,24 @@ import { import { ArrowUpDownIcon } from '@chakra-ui/icons'; import { PackageCard } from '@/features/Search/PackageCard/PackageCard'; import Chain from '@/features/Search/PackageCard/Chain'; -import { useQuery } from '@tanstack/react-query'; -import { getPackage } from '@/helpers/api'; import { CustomSpinner } from '@/components/CustomSpinner'; +import { usePackageByName } from '@/hooks/api/usePackage'; export const VersionSelect: FC<{ pkg: any; }> = ({ pkg }) => { const { isOpen, onOpen, onClose } = useDisclosure(); - const packagesQuery = useQuery({ - queryKey: ['package', pkg.name], - queryFn: getPackage, - }); + const packagesQuery = usePackageByName({ name: pkg.name }); if (packagesQuery.isPending) { return ; } + if (packagesQuery.isError) { + throw new Error('Failed to fetch package'); + } + return ( <>