From 9c98cf7d8bdd0420ba851f09934098547b6c48c2 Mon Sep 17 00:00:00 2001 From: Zuhwa Date: Tue, 21 Oct 2025 16:10:34 +0800 Subject: [PATCH 1/4] Txn batching & optimization --- package-lock.json | 274 +++---- package.json | 6 +- src/acpClient.ts | 269 ++----- src/acpJob.ts | 712 ++++--------------- src/acpJobOffering.ts | 42 +- src/acpMemo.ts | 3 +- src/contractClients/acpContractClient.ts | 81 ++- src/contractClients/acpContractClientV2.ts | 31 +- src/contractClients/baseAcpContractClient.ts | 131 ++-- 9 files changed, 470 insertions(+), 1079 deletions(-) diff --git a/package-lock.json b/package-lock.json index c17185a..d5b96b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,9 @@ "version": "0.3.0-beta.1", "license": "ISC", "dependencies": { - "@aa-sdk/core": "^4.30.0", - "@account-kit/infra": "^4.30.0", - "@account-kit/smart-contracts": "^4.30.0", + "@aa-sdk/core": "^4.73.0", + "@account-kit/infra": "^4.73.0", + "@account-kit/smart-contracts": "^4.73.0", "ajv": "^8.17.1", "socket.io-client": "^4.8.1", "tsup": "^8.5.0", @@ -22,9 +22,9 @@ } }, "node_modules/@aa-sdk/core": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@aa-sdk/core/-/core-4.30.0.tgz", - "integrity": "sha512-eRDA5AIE8hMivDrw0gRBLKQeSnrCvfWZzhfwXkpNHEEc04aij6dkoO07uyCJIObPwglZHEuAG4RDE5nu4l/xSg==", + "version": "4.73.0", + "resolved": "https://registry.npmjs.org/@aa-sdk/core/-/core-4.73.0.tgz", + "integrity": "sha512-Fm9ko4GS6jHtDJq552pebl4Yp3zMWFnFAvhTds0eejDxEDScq7bzAajxh57kjitNPHowW+msY1xpe9lxFi6qCQ==", "license": "MIT", "dependencies": { "abitype": "^0.8.3", @@ -32,17 +32,17 @@ "zod": "^3.22.4" }, "peerDependencies": { - "viem": "^2.22.6" + "viem": "^2.29.2" } }, "node_modules/@account-kit/infra": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@account-kit/infra/-/infra-4.30.0.tgz", - "integrity": "sha512-NeIdu0Mlcb6arXAO+eZMEHOfbaoRnGzvOr5Xrho2DMctwk934yi6Iwl1OHJx0+f7XiEz+qWqim0DXp98AtN4QA==", + "version": "4.73.0", + "resolved": "https://registry.npmjs.org/@account-kit/infra/-/infra-4.73.0.tgz", + "integrity": "sha512-uX5h6MwQkj0KWeixKwTcyKAciHHC/mUNNGuLVEPAIoNSOOvrR2DdI04HDKVhFwHhQphO0iK09bNL2WcafRNDMA==", "license": "MIT", "dependencies": { - "@aa-sdk/core": "^4.30.0", - "@account-kit/logging": "^4.30.0", + "@aa-sdk/core": "^4.73.0", + "@account-kit/logging": "^4.73.0", "eventemitter3": "^5.0.1", "zod": "^3.22.4" }, @@ -50,36 +50,37 @@ "alchemy-sdk": "^3.0.0" }, "peerDependencies": { - "viem": "^2.22.6" + "viem": "^2.29.2" } }, "node_modules/@account-kit/logging": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@account-kit/logging/-/logging-4.30.0.tgz", - "integrity": "sha512-rmfrzcyUHPTciKPLn6FpcYihfhFkGGckcLZGQMIRv7hvBKkaXXYwZczLC8CR4rlRFQU7yEDWDYBmrF6IDeNagA==", + "version": "4.73.0", + "resolved": "https://registry.npmjs.org/@account-kit/logging/-/logging-4.73.0.tgz", + "integrity": "sha512-dS/C8vM9z0t3UoCI05F8yBjBTdu+alYn9Zfu3I6IiFeT1Uz7z8i5V+Tiobipa6Dx37tAx1mErgu4kG0TCqWQJw==", "license": "MIT", "dependencies": { - "@segment/analytics-next": "^1.74.0", + "@segment/analytics-next": "1.74.0", "uuid": "^11.0.2" } }, "node_modules/@account-kit/smart-contracts": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@account-kit/smart-contracts/-/smart-contracts-4.30.0.tgz", - "integrity": "sha512-74BfphJX3jmRAi7FShm6nNnkJzmvXqof9IGwcV4n/bwc7Z6sPWyxniUfmHdRWzs0/evWMd3iPv4H3JV6HnUt7Q==", + "version": "4.73.0", + "resolved": "https://registry.npmjs.org/@account-kit/smart-contracts/-/smart-contracts-4.73.0.tgz", + "integrity": "sha512-YwHvIhfEtg2i3JbxNPVznHePGGXgPNU5WBPjvtC9I2n4N6lcIRRbTV+D4RETEO5gPMM+0vU3mR+tK3RXM9lS9w==", "license": "MIT", "dependencies": { - "@aa-sdk/core": "^4.30.0", - "@account-kit/infra": "^4.30.0" + "@aa-sdk/core": "^4.73.0", + "@account-kit/infra": "^4.73.0", + "webauthn-p256": "^0.0.10" }, "peerDependencies": { - "viem": "^2.22.6" + "viem": "^2.29.2" } }, "node_modules/@adraffy/ens-normalize": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz", - "integrity": "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", + "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", "license": "MIT" }, "node_modules/@babel/runtime": { @@ -1284,10 +1285,22 @@ "node": ">=8" } }, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@noble/curves": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz", - "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", "license": "MIT", "dependencies": { "@noble/hashes": "1.8.0" @@ -1582,84 +1595,45 @@ ] }, "node_modules/@scure/base": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.5.tgz", - "integrity": "sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", - "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", "license": "MIT", "dependencies": { - "@noble/curves": "~1.8.1", - "@noble/hashes": "~1.7.1", - "@scure/base": "~1.2.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", - "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.7.2" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", - "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip39": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", - "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", "license": "MIT", "dependencies": { - "@noble/hashes": "~1.7.1", - "@scure/base": "~1.2.4" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", - "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@segment/analytics-core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@segment/analytics-core/-/analytics-core-1.8.1.tgz", - "integrity": "sha512-EYcdBdhfi1pOYRX+Sf5orpzzYYFmDHTEu6+w0hjXpW5bWkWct+Nv6UJg1hF4sGDKEQjpZIinLTpQ4eioFM4KeQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@segment/analytics-core/-/analytics-core-1.8.0.tgz", + "integrity": "sha512-6CrccsYRY33I3mONN2ZW8SdBpbLtu1Ict3xR+n0FemYF5RB/jG7pW6jOvDXULR8kuYMzMmGOP4HvlyUmf3qLpg==", "license": "MIT", "dependencies": { "@lukeed/uuid": "^2.0.0", @@ -1678,15 +1652,14 @@ } }, "node_modules/@segment/analytics-next": { - "version": "1.81.0", - "resolved": "https://registry.npmjs.org/@segment/analytics-next/-/analytics-next-1.81.0.tgz", - "integrity": "sha512-N267sNhJKGCviRAs/uQCC5TuP73WVDnd8xBDrsUHvM1J4qdDkSXT+KsoQbveQZV2fFUoLypuZ6nBP/MC5unTvg==", + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@segment/analytics-next/-/analytics-next-1.74.0.tgz", + "integrity": "sha512-dhSwm+kahwnsHZmhcInu6wTJZFCLtG1VDCw0uiQRuKL5SDRRNEMORvKErV6bycXHWLelaYQVIMRcHH2Y9lk48A==", "license": "MIT", "dependencies": { "@lukeed/uuid": "^2.0.0", - "@segment/analytics-core": "1.8.1", + "@segment/analytics-core": "1.8.0", "@segment/analytics-generic-utils": "1.2.0", - "@segment/analytics-page-tools": "1.0.0", "@segment/analytics.js-video-plugins": "^0.2.1", "@segment/facade": "^3.4.9", "dset": "^3.1.4", @@ -1696,15 +1669,6 @@ "unfetch": "^4.1.0" } }, - "node_modules/@segment/analytics-page-tools": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@segment/analytics-page-tools/-/analytics-page-tools-1.0.0.tgz", - "integrity": "sha512-o9OVB91qLB9qb0Bw1HfjmWm5AnrMNULRjx++4lBqLt8InKRX1urrRBparVlpj+yJA0sckN5ZcsfazRLuPgBYDQ==", - "license": "MIT", - "dependencies": { - "tslib": "^2.4.1" - } - }, "node_modules/@segment/analytics.js-video-plugins": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@segment/analytics.js-video-plugins/-/analytics.js-video-plugins-0.2.1.tgz", @@ -3005,9 +2969,9 @@ } }, "node_modules/isows": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", - "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", + "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", "funding": [ { "type": "github", @@ -3350,9 +3314,9 @@ } }, "node_modules/ox": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", - "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==", + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.6.tgz", + "integrity": "sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==", "funding": [ { "type": "github", @@ -3361,12 +3325,13 @@ ], "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "^1.10.1", - "@noble/curves": "^1.6.0", - "@noble/hashes": "^1.5.0", - "@scure/bip32": "^1.5.0", - "@scure/bip39": "^1.4.0", - "abitype": "^1.0.6", + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.0.9", "eventemitter3": "5.0.1" }, "peerDependencies": { @@ -3379,16 +3344,16 @@ } }, "node_modules/ox/node_modules/abitype": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", - "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.1.tgz", + "integrity": "sha512-Loe5/6tAgsBukY95eGaPSDmQHIjRZYQq8PB1MpsNccDIK8WiV+Uw6WzaIXipvaxTEL2yEB0OpEaQv3gs8pkS9Q==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" }, "peerDependencies": { "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" + "zod": "^3.22.0 || ^4.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -4183,9 +4148,9 @@ } }, "node_modules/viem": { - "version": "2.28.2", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.28.2.tgz", - "integrity": "sha512-HTdoskL1fsyabBplaY6qz59WXHY6+edt+byuKQz3M8SKPU9D9XLgu7t04JNXPHoxPOv72qB+ZNSfpN6PMdDtqw==", + "version": "2.38.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.38.3.tgz", + "integrity": "sha512-By2TutLv07iNHHtWqHHzjGipevYsfGqT7KQbGEmqLco1qTJxKnvBbSviqiu6/v/9REV6Q/FpmIxf2Z7/l5AbcQ==", "funding": [ { "type": "github", @@ -4194,14 +4159,14 @@ ], "license": "MIT", "dependencies": { - "@noble/curves": "1.8.2", - "@noble/hashes": "1.7.2", - "@scure/bip32": "1.6.2", - "@scure/bip39": "1.5.4", - "abitype": "1.0.8", - "isows": "1.0.6", - "ox": "0.6.9", - "ws": "8.18.1" + "@noble/curves": "1.9.1", + "@noble/hashes": "1.8.0", + "@scure/bip32": "1.7.0", + "@scure/bip39": "1.6.0", + "abitype": "1.1.0", + "isows": "1.0.7", + "ox": "0.9.6", + "ws": "8.18.3" }, "peerDependencies": { "typescript": ">=5.0.4" @@ -4212,44 +4177,17 @@ } } }, - "node_modules/viem/node_modules/@noble/curves": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", - "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.7.2" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/viem/node_modules/@noble/hashes": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", - "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/viem/node_modules/abitype": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", - "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz", + "integrity": "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" }, "peerDependencies": { "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" + "zod": "^3.22.0 || ^4.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -4261,9 +4199,9 @@ } }, "node_modules/viem/node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -4281,6 +4219,22 @@ } } }, + "node_modules/webauthn-p256": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.10.tgz", + "integrity": "sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "^1.4.0", + "@noble/hashes": "^1.4.0" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index d4479d8..0b6f487 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ "typescript": "^5.8.3" }, "dependencies": { - "@aa-sdk/core": "^4.30.0", - "@account-kit/infra": "^4.30.0", - "@account-kit/smart-contracts": "^4.30.0", + "@aa-sdk/core": "^4.73.0", + "@account-kit/infra": "^4.73.0", + "@account-kit/smart-contracts": "^4.73.0", "ajv": "^8.17.1", "socket.io-client": "^4.8.1", "tsup": "^8.5.0", diff --git a/src/acpClient.ts b/src/acpClient.ts index 6a9ef98..778778f 100644 --- a/src/acpClient.ts +++ b/src/acpClient.ts @@ -1,9 +1,10 @@ -import { Address } from "viem"; +import { Address, zeroAddress } from "viem"; import { io } from "socket.io-client"; import BaseAcpContractClient, { AcpJobPhases, FeeType, MemoType, + OperationPayload, } from "./contractClients/baseAcpContractClient"; import AcpJob from "./acpJob"; import AcpMemo from "./acpMemo"; @@ -312,7 +313,7 @@ class AcpClient { twitterHandle: agent.twitterHandle, walletAddress: agent.walletAddress, metrics: agent.metrics, - resource: agent.resources + resource: agent.resources, }; }); } @@ -336,14 +337,23 @@ class AcpClient { this.acpContractClient ); - const { jobId, txHash } = + const defaultEvaluatorAddress = + [ + baseSepoliaAcpConfig.contractAddress, + baseAcpConfig.contractAddress, + ].includes(this.acpContractClient.config.contractAddress) && + !evaluatorAddress + ? this.walletAddress + : zeroAddress; + + const createJobPayload = [ baseSepoliaAcpConfig.contractAddress, baseAcpConfig.contractAddress, ].includes(this.acpContractClient.config.contractAddress) || !account ? await this.acpContractClient.createJob( providerAddress, - evaluatorAddress || this.walletAddress, + evaluatorAddress || defaultEvaluatorAddress, expiredAt, fareAmount.fare.contractAddress, fareAmount.amount, @@ -352,245 +362,48 @@ class AcpClient { : await this.acpContractClient.createJobWithAccount( account.id, providerAddress, - evaluatorAddress || this.walletAddress, + evaluatorAddress || defaultEvaluatorAddress, fareAmount.amount, fareAmount.fare.contractAddress, expiredAt ); - await this.acpContractClient.createMemo( - jobId, - preparePayload(serviceRequirement), - MemoType.MESSAGE, - true, - AcpJobPhases.NEGOTIATION - ); - - return jobId; - } - - async createMemo(jobId: number, content: string, nextPhase: AcpJobPhases) { - return await this.acpContractClient.createMemo( - jobId, - content, - MemoType.MESSAGE, - false, - nextPhase - ); - } - - async createPayableMemo( - jobId: number, - content: string, - amount: FareAmountBase, - recipient: Address, - nextPhase: AcpJobPhases, - type: MemoType.PAYABLE_REQUEST | MemoType.PAYABLE_TRANSFER_ESCROW, - expiredAt: Date - ) { - if (type === MemoType.PAYABLE_TRANSFER_ESCROW) { - await this.acpContractClient.approveAllowance( - amount.amount, - amount.fare.contractAddress - ); - } - - const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare); - - return await this.acpContractClient.createPayableMemo( - jobId, - content, - amount.amount, - recipient, - feeAmount.amount, - FeeType.NO_FEE, - nextPhase, - type, - expiredAt, - amount.fare.contractAddress - ); - } - - async respondJob( - jobId: number, - memoId: number, - accept: boolean, - content?: string, - reason?: string - ) { - await this.acpContractClient.signMemo(memoId, accept, reason); - - if (!accept) { - return; - } - - return await this.acpContractClient.createMemo( - jobId, - content ?? `Job ${jobId} accepted. ${reason ?? ""}`, - MemoType.MESSAGE, - false, - AcpJobPhases.TRANSACTION - ); - } - - async payJob( - jobId: number, - amountBaseUnit: bigint, - memoId: number, - reason?: string - ) { - if (amountBaseUnit > BigInt(0)) { - await this.acpContractClient.approveAllowance(amountBaseUnit); - } - - await this.acpContractClient.signMemo(memoId, true, reason); - - return await this.acpContractClient.createMemo( - jobId, - `Payment made. ${reason ?? ""}`, - MemoType.MESSAGE, - false, - AcpJobPhases.EVALUATION - ); - } + const txHash = await this.acpContractClient.handleOperation([ + createJobPayload, + ]); - async requestFunds( - jobId: number, - transferFareAmount: FareAmountBase, - recipient: Address, - feeFareAmount: FareAmountBase, - feeType: FeeType, - reason: GenericPayload, - nextPhase: AcpJobPhases, - expiredAt: Date - ) { - return await this.acpContractClient.createPayableMemo( - jobId, - JSON.stringify(reason), - transferFareAmount.amount, - recipient, - feeFareAmount.amount, - feeType, - nextPhase, - MemoType.PAYABLE_REQUEST, - expiredAt + const jobId = await this.acpContractClient.getJobId( + txHash, + this.walletAddress, + providerAddress ); - } - - async responseFundsRequest( - memoId: number, - accept: boolean, - amountBaseUnit: bigint, - reason?: string - ) { - if (!accept) { - return await this.acpContractClient.signMemo(memoId, accept, reason); - } - - if (amountBaseUnit > BigInt(0)) { - await this.acpContractClient.approveAllowance(amountBaseUnit); - } - return await this.acpContractClient.signMemo(memoId, true, reason); - } - - async transferFunds( - jobId: number, - transferFareAmount: FareAmountBase, - recipient: Address, - feeFareAmount: FareAmountBase, - feeType: FeeType, - reason: GenericPayload, - nextPhase: AcpJobPhases, - expiredAt: Date - ) { - if (transferFareAmount.fare.contractAddress === ethFare.contractAddress) { - await this.acpContractClient.wrapEth(transferFareAmount.amount); - transferFareAmount = new FareBigInt(transferFareAmount.amount, wethFare); - } + const payloads: OperationPayload[] = []; - if ( - feeFareAmount.amount > 0 && - feeFareAmount.fare.contractAddress !== - this.acpContractClient.config.baseFare.contractAddress - ) { - throw new AcpError("Fee token address is not the same as the base fare"); - } - - const isFeeTokenDifferent = - feeFareAmount.fare.contractAddress !== - transferFareAmount.fare.contractAddress; - - if (isFeeTokenDifferent) { - await this.acpContractClient.approveAllowance( - feeFareAmount.amount, - feeFareAmount.fare.contractAddress + const setBudgetWithPaymentTokenPayload = + this.acpContractClient.setBudgetWithPaymentToken( + jobId, + fareAmount.amount, + fareAmount.fare.contractAddress ); - } - const finalAmount = isFeeTokenDifferent - ? transferFareAmount - : transferFareAmount.add(feeFareAmount); - - await this.acpContractClient.approveAllowance( - finalAmount.amount, - transferFareAmount.fare.contractAddress - ); + if (setBudgetWithPaymentTokenPayload) { + payloads.push(setBudgetWithPaymentTokenPayload); + } - return await this.acpContractClient.createPayableMemo( - jobId, - JSON.stringify(reason), - transferFareAmount.amount, - recipient, - feeFareAmount.amount, - feeType, - nextPhase, - MemoType.PAYABLE_TRANSFER_ESCROW, - expiredAt, - transferFareAmount.fare.contractAddress + payloads.push( + this.acpContractClient.createMemo( + jobId, + preparePayload(serviceRequirement), + MemoType.MESSAGE, + true, + AcpJobPhases.NEGOTIATION + ) ); - } - async sendMessage( - jobId: number, - message: GenericPayload, - nextPhase: AcpJobPhases - ) { - return await this.acpContractClient.createMemo( - jobId, - JSON.stringify(message), - MemoType.MESSAGE, - false, - nextPhase - ); - } + await this.acpContractClient.handleOperation(payloads); - async responseFundsTransfer( - memoId: number, - accept: boolean, - reason?: string - ) { - return await this.acpContractClient.signMemo(memoId, accept, reason); - } - - async rejectJob(jobId: number, reason?: string) { - return await this.acpContractClient.createMemo( - jobId, - `Job ${jobId} rejected. ${reason || ""}`, - MemoType.MESSAGE, - false, - AcpJobPhases.REJECTED - ); - } - - async deliverJob(jobId: number, deliverable: DeliverablePayload) { - return await this.acpContractClient.createMemo( - jobId, - preparePayload(deliverable), - MemoType.OBJECT_URL, - true, - AcpJobPhases.COMPLETED - ); + return jobId; } async getActiveJobs(page: number = 1, pageSize: number = 10) { diff --git a/src/acpJob.ts b/src/acpJob.ts index e5d54f6..b2a348d 100644 --- a/src/acpJob.ts +++ b/src/acpJob.ts @@ -4,23 +4,12 @@ import { AcpJobPhases, FeeType, MemoType, + OperationPayload, } from "./contractClients/baseAcpContractClient"; import AcpMemo from "./acpMemo"; -import { - CloseJobAndWithdrawPayload, - ClosePositionPayload, - GenericPayload, - DeliverablePayload, - OpenPositionPayload, - PayloadType, - PositionFulfilledPayload, - RequestClosePositionPayload, - SwapTokenPayload, - UnfulfilledPositionPayload, - AcpMemoStatus, -} from "./interfaces"; +import { DeliverablePayload, AcpMemoStatus } from "./interfaces"; import { preparePayload, tryParseJson } from "./utils"; -import { Fare, FareAmount, FareAmountBase } from "./acpFare"; +import { FareAmount, FareAmountBase } from "./acpFare"; import AcpError from "./acpError"; class AcpJob { @@ -97,12 +86,10 @@ class AcpJob { return requestMemo.signedReason; } - return this.memos.find( - (m) => m.nextPhase === AcpJobPhases.REJECTED - )?.content; + return this.memos.find((m) => m.nextPhase === AcpJobPhases.REJECTED) + ?.content; } - public get providerAgent() { return this.acpClient.getAgent(this.providerAddress); } @@ -124,13 +111,15 @@ class AcpJob { } async createRequirement(content: string) { - return await this.acpContractClient.createMemo( + const payload = this.acpContractClient.createMemo( this.id, content, MemoType.MESSAGE, true, AcpJobPhases.TRANSACTION ); + + return await this.acpContractClient.handleOperation([payload]); } async createPayableRequirement( @@ -140,27 +129,35 @@ class AcpJob { recipient: Address, expiredAt: Date = new Date(Date.now() + 1000 * 60 * 5) // 5 minutes ) { + const operations: OperationPayload[] = []; + if (type === MemoType.PAYABLE_TRANSFER_ESCROW) { - await this.acpContractClient.approveAllowance( - amount.amount, - amount.fare.contractAddress + operations.push( + this.acpContractClient.approveAllowance( + amount.amount, + amount.fare.contractAddress + ) ); } const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare); - return await this.acpContractClient.createPayableMemo( - this.id, - content, - amount.amount, - recipient, - feeAmount.amount, - FeeType.NO_FEE, - AcpJobPhases.TRANSACTION, - type, - expiredAt, - amount.fare.contractAddress + operations.push( + this.acpContractClient.createPayableMemo( + this.id, + content, + amount.amount, + recipient, + feeAmount.amount, + FeeType.NO_FEE, + AcpJobPhases.TRANSACTION, + type, + expiredAt, + amount.fare.contractAddress + ) ); + + return await this.acpContractClient.handleOperation(operations); } async payAndAcceptRequirement(reason?: string) { @@ -172,6 +169,8 @@ class AcpJob { throw new AcpError("No transaction memo found"); } + const operations: OperationPayload[] = []; + const baseFareAmount = new FareAmount(this.price, this.baseFare); const transferAmount = memo.payableDetails ? await FareAmountBase.fromContractAddress( @@ -187,34 +186,44 @@ class AcpJob { ? baseFareAmount.add(transferAmount) : baseFareAmount; - await this.acpContractClient.approveAllowance( - totalAmount.amount, - this.baseFare.contractAddress + operations.push( + this.acpContractClient.approveAllowance( + totalAmount.amount, + this.baseFare.contractAddress + ) ); if ( baseFareAmount.fare.contractAddress !== transferAmount.fare.contractAddress ) { - await this.acpContractClient.approveAllowance( - transferAmount.amount, - transferAmount.fare.contractAddress + operations.push( + this.acpContractClient.approveAllowance( + transferAmount.amount, + transferAmount.fare.contractAddress + ) ); } - await memo.sign(true, reason); + operations.push(this.acpContractClient.signMemo(memo.id, true, reason)); - return await this.acpContractClient.createMemo( - this.id, - `Payment made. ${reason ?? ""}`.trim(), - MemoType.MESSAGE, - true, - AcpJobPhases.EVALUATION + operations.push( + this.acpContractClient.createMemo( + this.id, + `Payment made. ${reason ?? ""}`.trim(), + MemoType.MESSAGE, + true, + AcpJobPhases.EVALUATION + ) ); + + return await this.acpContractClient.handleOperation(operations); } async respond(accept: boolean, reason?: string) { - const memoContent = `${reason || `Job ${this.id} ${accept ? "accepted" : "rejected"}.`}` + const memoContent = `${ + reason || `Job ${this.id} ${accept ? "accepted" : "rejected"}.` + }`; if (accept) { await this.accept(memoContent); return this.createRequirement(memoContent); @@ -231,27 +240,35 @@ class AcpJob { const memo = this.latestMemo; - await memo.sign(true, memoContent); + return memo.sign(true, memoContent); } async reject(reason?: string) { const memoContent = `Job ${this.id} rejected. ${reason || ""}`; + + const operations: OperationPayload[] = []; + if (this.phase === AcpJobPhases.REQUEST) { if (this.latestMemo?.nextPhase !== AcpJobPhases.NEGOTIATION) { throw new AcpError("No request memo found"); } const memo = this.latestMemo; - - return await this.acpContractClient.signMemo(memo.id, false, memoContent); + operations.push( + this.acpContractClient.signMemo(memo.id, false, memoContent) + ); } - return await this.acpContractClient.createMemo( - this.id, - memoContent, - MemoType.MESSAGE, - true, - AcpJobPhases.REJECTED + operations.push( + this.acpContractClient.createMemo( + this.id, + memoContent, + MemoType.MESSAGE, + true, + AcpJobPhases.REJECTED + ) ); + + return await this.acpContractClient.handleOperation(operations); } async deliver(deliverable: DeliverablePayload) { @@ -259,13 +276,19 @@ class AcpJob { throw new AcpError("No transaction memo found"); } - return await this.acpContractClient.createMemo( - this.id, - preparePayload(deliverable), - MemoType.MESSAGE, - true, - AcpJobPhases.COMPLETED + const operations: OperationPayload[] = []; + + operations.push( + this.acpContractClient.createMemo( + this.id, + preparePayload(deliverable), + MemoType.MESSAGE, + true, + AcpJobPhases.COMPLETED + ) ); + + return await this.acpContractClient.handleOperation(operations); } async deliverPayable( @@ -277,25 +300,33 @@ class AcpJob { throw new AcpError("No transaction memo found"); } - await this.acpContractClient.approveAllowance( - amount.amount, - amount.fare.contractAddress + const operations: OperationPayload[] = []; + + operations.push( + this.acpContractClient.approveAllowance( + amount.amount, + amount.fare.contractAddress + ) ); const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare); - return await this.acpContractClient.createPayableMemo( - this.id, - preparePayload(deliverable), - amount.amount, - this.clientAddress, - feeAmount.amount, - FeeType.NO_FEE, - AcpJobPhases.COMPLETED, - MemoType.PAYABLE_TRANSFER, - expiredAt, - amount.fare.contractAddress + operations.push( + this.acpContractClient.createPayableMemo( + this.id, + preparePayload(deliverable), + amount.amount, + this.clientAddress, + feeAmount.amount, + FeeType.NO_FEE, + AcpJobPhases.COMPLETED, + MemoType.PAYABLE_TRANSFER, + expiredAt, + amount.fare.contractAddress + ) ); + + return await this.acpContractClient.handleOperation(operations); } async evaluate(accept: boolean, reason?: string) { @@ -308,31 +339,20 @@ class AcpJob { await memo.sign(accept, reason); } - async pay(reason?: string) { - const memo = this.memos.find( - (m) => m.nextPhase === AcpJobPhases.TRANSACTION - ); - - if (!memo) { - throw new AcpError("No transaction memo found"); - } + async createNotification(content: string) { + const operations: OperationPayload[] = []; - return await this.acpClient.payJob( - this.id, - this.baseFare.formatAmount(this.price), - memo.id, - reason + operations.push( + this.acpContractClient.createMemo( + this.id, + content, + MemoType.NOTIFICATION, + true, + AcpJobPhases.COMPLETED + ) ); - } - async createNotification(content: string) { - return await this.acpContractClient.createMemo( - this.id, - content, - MemoType.NOTIFICATION, - true, - AcpJobPhases.COMPLETED - ); + return await this.acpContractClient.handleOperation(operations); } async createPayableNotification( @@ -340,493 +360,33 @@ class AcpJob { amount: FareAmountBase, expiredAt: Date = new Date(Date.now() + 1000 * 60 * 5) // 5 minutes ) { - await this.acpContractClient.approveAllowance( - amount.amount, - amount.fare.contractAddress - ); - - const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare); - - return await this.acpContractClient.createPayableMemo( - this.id, - content, - amount.amount, - this.clientAddress, - feeAmount.amount, - FeeType.NO_FEE, - AcpJobPhases.COMPLETED, - MemoType.PAYABLE_NOTIFICATION, - expiredAt, - amount.fare.contractAddress - ); - } - - // to be deprecated - - /** - * @deprecated The method should not be used - */ - async openPosition( - payload: OpenPositionPayload[], - feeAmount: number, - expiredAt: Date = new Date(Date.now() + 1000 * 60 * 3), // 3 minutes - walletAddress?: Address - ) { - if (payload.length === 0) { - throw new AcpError("No positions to open"); - } - - const sumAmount = payload.reduce((acc, curr) => acc + curr.amount, 0); - - return await this.acpClient.transferFunds( - this.id, - new FareAmount(sumAmount, this.baseFare), - walletAddress || this.providerAddress, - new FareAmount(feeAmount, this.baseFare), - FeeType.IMMEDIATE_FEE, - { - type: PayloadType.OPEN_POSITION, - data: payload, - }, - AcpJobPhases.TRANSACTION, - expiredAt - ); - } - - /** - * @deprecated The method should not be used - */ - async swapToken( - payload: SwapTokenPayload, - decimals: number, - feeAmount: number, - walletAddress?: Address - ) { - return await this.acpClient.transferFunds( - this.id, - new FareAmount( - payload.amount, - new Fare(payload.fromContractAddress, decimals) - ), - walletAddress || this.providerAddress, - new FareAmount(feeAmount, this.baseFare), - FeeType.IMMEDIATE_FEE, - { - type: PayloadType.SWAP_TOKEN, - data: payload, - }, - AcpJobPhases.TRANSACTION, - new Date(Date.now() + 1000 * 60 * 30) - ); - } - - /** - * @deprecated The method should not be used - */ - async responseSwapToken(memoId: number, accept: boolean, reason: string) { - const memo = this.memos.find((m) => m.id === memoId); - - if ( - memo?.nextPhase !== AcpJobPhases.TRANSACTION || - memo?.type !== MemoType.PAYABLE_TRANSFER_ESCROW - ) { - throw new AcpError("No swap token memo found"); - } - - const payload = tryParseJson>( - memo.content - ); - - if (payload?.type !== PayloadType.SWAP_TOKEN) { - throw new AcpError("Invalid swap token memo"); - } - - return await memo.sign(accept, reason); - } - - /** - * @deprecated The method should not be used - */ - async transferFunds( - payload: GenericPayload, - fareAmount: FareAmountBase, - walletAddress?: Address, - expiredAt: Date = new Date(Date.now() + 1000 * 60 * 30) - ) { - return await this.acpClient.transferFunds( - this.id, - fareAmount, - walletAddress || this.clientAddress, - new FareAmount(0, this.baseFare), - FeeType.NO_FEE, - payload, - AcpJobPhases.TRANSACTION, - expiredAt - ); - } - - /** - * @deprecated The method should not be used - */ - async responseOpenPosition(memoId: number, accept: boolean, reason: string) { - const memo = this.memos.find((m) => m.id === memoId); - - if ( - memo?.nextPhase !== AcpJobPhases.TRANSACTION || - memo?.type !== MemoType.PAYABLE_TRANSFER_ESCROW - ) { - throw new AcpError("No open position memo found"); - } - - const payload = tryParseJson>( - memo.content - ); - - if (payload?.type !== PayloadType.OPEN_POSITION) { - throw new AcpError("Invalid open position memo"); - } - - return await this.acpClient.responseFundsTransfer(memo.id, accept, reason); - } - - /** - * @deprecated The method should not be used - */ - async closePartialPosition( - payload: ClosePositionPayload, - expireAt: Date = new Date(Date.now() + 1000 * 60 * 60 * 24) // 24 hours - ) { - return await this.acpClient.requestFunds( - this.id, - new FareAmount(payload.amount, this.baseFare), - this.clientAddress, - new FareAmount(0, this.baseFare), - FeeType.NO_FEE, - { - type: PayloadType.CLOSE_PARTIAL_POSITION, - data: payload, - }, - AcpJobPhases.TRANSACTION, - expireAt - ); - } - - /** - * @deprecated The method should not be used - */ - async responseClosePartialPosition( - memoId: number, - accept: boolean, - reason: string - ) { - const memo = this.memos.find((m) => m.id === memoId); - - if ( - memo?.nextPhase !== AcpJobPhases.TRANSACTION || - memo?.type !== MemoType.PAYABLE_REQUEST - ) { - throw new AcpError("No close position memo found"); - } - - const payload = tryParseJson>( - memo.content - ); + const operations: OperationPayload[] = []; - if (payload?.type !== PayloadType.CLOSE_PARTIAL_POSITION) { - throw new AcpError("Invalid close position memo"); - } - - return await this.acpClient.responseFundsRequest( - memo.id, - accept, - this.baseFare.formatAmount(payload.data.amount), - reason - ); - } - - /** - * @deprecated The method should not be used - */ - async requestClosePosition(payload: RequestClosePositionPayload) { - return await this.acpClient.sendMessage( - this.id, - { - type: PayloadType.CLOSE_POSITION, - data: payload, - }, - AcpJobPhases.TRANSACTION + operations.push( + this.acpContractClient.approveAllowance( + amount.amount, + amount.fare.contractAddress + ) ); - } - - /** - * @deprecated The method should not be used - */ - async responseRequestClosePosition( - memoId: number, - accept: boolean, - payload: ClosePositionPayload, - reason?: string, - expiredAt: Date = new Date(Date.now() + 1000 * 60 * 60 * 24) // 24 hours - ) { - const memo = this.memos.find((m) => m.id === memoId); - - if ( - memo?.nextPhase !== AcpJobPhases.TRANSACTION || - memo?.type !== MemoType.MESSAGE - ) { - throw new AcpError("No message memo found"); - } - const messagePayload = tryParseJson< - GenericPayload - >(memo.content); - - if (messagePayload?.type !== PayloadType.CLOSE_POSITION) { - throw new AcpError("Invalid close position memo"); - } - - await memo.sign(accept, reason); + const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare); - if (accept) { - return await this.acpClient.transferFunds( + operations.push( + this.acpContractClient.createPayableMemo( this.id, - new FareAmount(payload.amount, this.baseFare), + content, + amount.amount, this.clientAddress, - new FareAmount(0, this.baseFare), + feeAmount.amount, FeeType.NO_FEE, - { - type: PayloadType.CLOSE_POSITION, - data: payload, - }, - AcpJobPhases.TRANSACTION, - expiredAt - ); - } - } - - /** - * @deprecated The method should not be used - */ - async confirmClosePosition(memoId: number, accept: boolean, reason?: string) { - const memo = this.memos.find((m) => m.id === memoId); - - if ( - memo?.nextPhase !== AcpJobPhases.TRANSACTION || - memo?.type !== MemoType.PAYABLE_TRANSFER_ESCROW - ) { - throw new AcpError("No payable transfer memo found"); - } - - const payload = tryParseJson>( - memo.content - ); - - if (payload?.type !== PayloadType.CLOSE_POSITION) { - throw new AcpError("Invalid close position memo"); - } - - await memo.sign(accept, reason); - } - - /** - * @deprecated The method should not be used - */ - async positionFulfilled( - payload: PositionFulfilledPayload, - expiredAt: Date = new Date(Date.now() + 1000 * 60 * 60 * 24) // 24 hours - ) { - return await this.acpClient.transferFunds( - this.id, - new FareAmount(payload.amount, this.baseFare), - this.clientAddress, - new FareAmount(0, this.baseFare), - FeeType.NO_FEE, - { - type: PayloadType.POSITION_FULFILLED, - data: payload, - }, - AcpJobPhases.TRANSACTION, - expiredAt - ); - } - - /** - * @deprecated The method should not be used - */ - async unfulfilledPosition( - payload: UnfulfilledPositionPayload, - expiredAt: Date = new Date(Date.now() + 1000 * 60 * 60 * 24) // 24 hours - ) { - return await this.acpClient.transferFunds( - this.id, - new FareAmount(payload.amount, this.baseFare), - this.clientAddress, - new FareAmount(0, this.baseFare), - FeeType.NO_FEE, - { - type: PayloadType.UNFULFILLED_POSITION, - data: payload, - }, - AcpJobPhases.TRANSACTION, - expiredAt - ); - } - - /** - * @deprecated The method should not be used - */ - async responseUnfulfilledPosition( - memoId: number, - accept: boolean, - reason: string - ) { - const memo = this.memos.find((m) => m.id === memoId); - - if ( - memo?.nextPhase !== AcpJobPhases.TRANSACTION || - memo?.type !== MemoType.PAYABLE_TRANSFER_ESCROW - ) { - throw new AcpError("No unfulfilled position memo found"); - } - - const payload = tryParseJson>( - memo.content - ); - - if (payload?.type !== PayloadType.UNFULFILLED_POSITION) { - throw new AcpError("Invalid unfulfilled position memo"); - } - - return await this.acpClient.responseFundsTransfer(memo.id, accept, reason); - } - - /** - * @deprecated The method should not be used - */ - async responsePositionFulfilled( - memoId: number, - accept: boolean, - reason: string - ) { - const memo = this.memos.find((m) => m.id === memoId); - - if ( - memo?.nextPhase !== AcpJobPhases.TRANSACTION || - memo?.type !== MemoType.PAYABLE_TRANSFER_ESCROW - ) { - throw new AcpError("No position fulfilled memo found"); - } - - const payload = tryParseJson>( - memo.content - ); - - if (payload?.type !== PayloadType.POSITION_FULFILLED) { - throw new AcpError("Invalid position fulfilled memo"); - } - - return await this.acpClient.responseFundsTransfer(memo.id, accept, reason); - } - - /** - * @deprecated The method should not be used - */ - async closeJob(message: string = "Close job and withdraw all") { - return await this.acpClient.sendMessage( - this.id, - { - type: PayloadType.CLOSE_JOB_AND_WITHDRAW, - data: { - message, - }, - }, - AcpJobPhases.TRANSACTION - ); - } - - /** - * @deprecated The method should not be used - */ - async responseCloseJob( - memoId: number, - accept: boolean, - fulfilledPositions: PositionFulfilledPayload[], - reason?: string, - expiredAt: Date = new Date(Date.now() + 1000 * 60 * 60 * 24) // 24 hours - ) { - const memo = this.memos.find((m) => m.id === memoId); - - if ( - memo?.nextPhase !== AcpJobPhases.TRANSACTION || - memo?.type !== MemoType.MESSAGE - ) { - throw new AcpError("No message memo found"); - } - - const payload = tryParseJson>( - memo.content - ); - - if (payload?.type !== PayloadType.CLOSE_JOB_AND_WITHDRAW) { - throw new AcpError("Invalid close job and withdraw memo"); - } - - await memo.sign(accept, reason); - - if (!accept) { - return; - } - - const totalAmount = fulfilledPositions.reduce( - (acc, curr) => acc + curr.amount, - 0 - ); - - if (totalAmount === 0) { - return await this.acpClient.sendMessage( - this.id, - { - type: PayloadType.CLOSE_JOB_AND_WITHDRAW, - data: fulfilledPositions, - }, - AcpJobPhases.COMPLETED - ); - } - - return await this.acpClient.transferFunds( - this.id, - new FareAmount(totalAmount, this.baseFare), - this.clientAddress, - new FareAmount(0, this.baseFare), - FeeType.NO_FEE, - { - type: PayloadType.CLOSE_JOB_AND_WITHDRAW, - data: fulfilledPositions, - }, - AcpJobPhases.COMPLETED, - expiredAt - ); - } - - /** - * @deprecated The method should not be used - */ - async confirmJobClosure(memoId: number, accept: boolean, reason?: string) { - const memo = this.memos.find((m) => m.id === memoId); - - if (!memo) { - throw new AcpError("Memo not found"); - } - - const payload = tryParseJson>( - memo.content + AcpJobPhases.COMPLETED, + MemoType.PAYABLE_NOTIFICATION, + expiredAt, + amount.fare.contractAddress + ) ); - if (payload?.type !== PayloadType.CLOSE_JOB_AND_WITHDRAW) { - throw new AcpError("Invalid close job and withdraw memo"); - } - - await memo.sign(accept, reason); + return await this.acpContractClient.handleOperation(operations); } } diff --git a/src/acpJobOffering.ts b/src/acpJobOffering.ts index 8a013ed..775ad68 100644 --- a/src/acpJobOffering.ts +++ b/src/acpJobOffering.ts @@ -6,6 +6,7 @@ import AcpError from "./acpError"; import BaseAcpContractClient, { AcpJobPhases, MemoType, + OperationPayload, } from "./contractClients/baseAcpContractClient"; import { baseAcpConfig, baseSepoliaAcpConfig } from "./configs/acpConfigs"; @@ -53,7 +54,7 @@ class AcpJobOffering { this.acpContractClient ); - const { jobId, txHash } = + const createJobPayload = [ baseSepoliaAcpConfig.contractAddress, baseAcpConfig.contractAddress, @@ -75,14 +76,41 @@ class AcpJobOffering { expiredAt ); - await this.acpContractClient.createMemo( - jobId, - JSON.stringify(finalServiceRequirement), - MemoType.MESSAGE, - true, - AcpJobPhases.NEGOTIATION + const createJobTxnHash = await this.acpContractClient.handleOperation([ + createJobPayload, + ]); + + const jobId = await this.acpContractClient.getJobId( + createJobTxnHash, + this.acpContractClient.walletAddress, + this.providerAddress ); + const payloads: OperationPayload[] = []; + + const setBudgetWithPaymentTokenPayload = + this.acpContractClient.setBudgetWithPaymentToken( + jobId, + fareAmount.amount, + fareAmount.fare.contractAddress + ); + + if (setBudgetWithPaymentTokenPayload) { + payloads.push(setBudgetWithPaymentTokenPayload); + } + + payloads.push( + this.acpContractClient.createMemo( + jobId, + JSON.stringify(finalServiceRequirement), + MemoType.MESSAGE, + true, + AcpJobPhases.NEGOTIATION + ) + ); + + await this.acpContractClient.handleOperation(payloads); + return jobId; } } diff --git a/src/acpMemo.ts b/src/acpMemo.ts index 3d78cd7..d748f23 100644 --- a/src/acpMemo.ts +++ b/src/acpMemo.ts @@ -54,7 +54,8 @@ class AcpMemo { } async sign(approved: boolean, reason?: string) { - return await this.contractClient.signMemo(this.id, approved, reason); + const payload = this.contractClient.signMemo(this.id, approved, reason); + return await this.contractClient.handleOperation([payload]); } } diff --git a/src/contractClients/acpContractClient.ts b/src/contractClients/acpContractClient.ts index 8c32c4b..c1ac83c 100644 --- a/src/contractClients/acpContractClient.ts +++ b/src/contractClients/acpContractClient.ts @@ -11,6 +11,7 @@ import BaseAcpContractClient, { AcpJobPhases, FeeType, MemoType, + OperationPayload, } from "./baseAcpContractClient"; class AcpContractClient extends BaseAcpContractClient { @@ -86,17 +87,13 @@ class AcpContractClient extends BaseAcpContractClient { return finalMaxFeePerGas; } - async handleOperation( - data: `0x${string}`, - contractAddress: Address = this.contractAddress, - value?: bigint - ) { + async handleOperation(operations: OperationPayload[]) { const payload: any = { - uo: { - target: contractAddress, - data: data, - value: value, - }, + uo: operations.map((op) => ({ + target: op.contractAddress, + data: op.data, + value: op.value, + })), overrides: { nonceKey: this.getRandomNonce(), }, @@ -177,14 +174,14 @@ class AcpContractClient extends BaseAcpContractClient { return Number(createdJobEvent.args.jobId); } - async createJob( + createJob( providerAddress: Address, evaluatorAddress: Address, expireAt: Date, paymentTokenAddress: Address, budgetBaseUnit: bigint, metadata: string - ): Promise<{ txHash: string; jobId: number }> { + ): OperationPayload { try { const data = encodeFunctionData({ abi: this.abi, @@ -196,27 +193,41 @@ class AcpContractClient extends BaseAcpContractClient { ], }); - const hash = await this.handleOperation(data, this.contractAddress); + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; - const jobId = await this.getJobId( - hash, - this.agentWalletAddress, - providerAddress - ); + return payload; + } catch (error) { + throw new AcpError("Failed to create job", error); + } + } - await this.setBudgetWithPaymentToken( - jobId, - budgetBaseUnit, - paymentTokenAddress - ); + setBudgetWithPaymentToken( + jobId: number, + budgetBaseUnit: bigint, + paymentTokenAddress: Address = this.config.baseFare.contractAddress + ): OperationPayload { + try { + const data = encodeFunctionData({ + abi: this.abi, + functionName: "setBudgetWithPaymentToken", + args: [jobId, budgetBaseUnit, paymentTokenAddress], + }); + + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; - return { txHash: hash, jobId: jobId }; + return payload; } catch (error) { - throw new AcpError("Failed to create job", error); + throw new AcpError("Failed to set budget", error); } } - async createPayableMemo( + createPayableMemo( jobId: number, content: string, amountBaseUnit: bigint, @@ -228,7 +239,7 @@ class AcpContractClient extends BaseAcpContractClient { expiredAt: Date, token: Address = this.config.baseFare.contractAddress, secured: boolean = true - ) { + ): OperationPayload { try { const data = encodeFunctionData({ abi: this.abi, @@ -247,27 +258,29 @@ class AcpContractClient extends BaseAcpContractClient { ], }); - return await this.handleOperation(data, this.contractAddress); + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; + + return payload; } catch (error) { throw new AcpError("Failed to create payable memo", error); } } - async createJobWithAccount( + createJobWithAccount( accountId: number, providerAddress: Address, evaluatorAddress: Address, budgetBaseUnit: bigint, paymentTokenAddress: Address, expiredAt: Date - ): Promise<{ txHash: string; jobId: number }> { + ): OperationPayload { throw new AcpError("Not Supported"); } - async updateAccountMetadata( - accountId: number, - metadata: string - ): Promise
{ + updateAccountMetadata(accountId: number, metadata: string): OperationPayload { throw new AcpError("Not Supported"); } } diff --git a/src/contractClients/acpContractClientV2.ts b/src/contractClients/acpContractClientV2.ts index 3b40d27..70ed117 100644 --- a/src/contractClients/acpContractClientV2.ts +++ b/src/contractClients/acpContractClientV2.ts @@ -7,7 +7,9 @@ import { import { createPublicClient, decodeEventLog, fromHex, http } from "viem"; import { AcpContractConfig, baseAcpConfigV2 } from "../configs/acpConfigs"; import AcpError from "../acpError"; -import BaseAcpContractClient from "./baseAcpContractClient"; +import BaseAcpContractClient, { + OperationPayload, +} from "./baseAcpContractClient"; import JOB_MANAGER_ABI from "../abis/jobManagerAbi"; class AcpContractClientV2 extends BaseAcpContractClient { @@ -126,17 +128,13 @@ class AcpContractClientV2 extends BaseAcpContractClient { return finalMaxFeePerGas; } - async handleOperation( - data: `0x${string}`, - contractAddress: Address = this.contractAddress, - value?: bigint - ) { + async handleOperation(operations: OperationPayload[]): Promise
{ const payload: any = { - uo: { - target: contractAddress, - data: data, - value: value, - }, + uo: operations.map((operation) => ({ + target: operation.contractAddress, + data: operation.data, + value: operation.value, + })), overrides: { nonceKey: this.getRandomNonce(), }, @@ -159,6 +157,12 @@ class AcpContractClientV2 extends BaseAcpContractClient { await this.sessionKeyClient.waitForUserOperationTransaction({ hash, + tag: "pending", + retries: { + intervalMs: 200, + multiplier: 1.1, + maxRetries: 10, + }, }); return hash; @@ -181,7 +185,10 @@ class AcpContractClientV2 extends BaseAcpContractClient { clientAddress: Address, providerAddress: Address ) { - const result = await this.sessionKeyClient.getUserOperationReceipt(hash); + const result = await this.sessionKeyClient.getUserOperationReceipt( + hash, + "pending" + ); if (!result) { throw new AcpError("Failed to get user operation receipt"); diff --git a/src/contractClients/baseAcpContractClient.ts b/src/contractClients/baseAcpContractClient.ts index dea9261..2888214 100644 --- a/src/contractClients/baseAcpContractClient.ts +++ b/src/contractClients/baseAcpContractClient.ts @@ -45,6 +45,12 @@ export enum FeeType { DEFERRED_FEE, } +export interface OperationPayload { + data: `0x${string}`; + contractAddress: Address; + value?: bigint; +} + abstract class BaseAcpContractClient { public contractAddress: Address; public chain: Chain; @@ -66,11 +72,7 @@ abstract class BaseAcpContractClient { this.jobCreatedSignature = keccak256(toHex(signature)); } - abstract handleOperation( - data: `0x${string}`, - contractAddress: Address, - value?: bigint - ): Promise
; + abstract handleOperation(operations: OperationPayload[]): Promise
; abstract getJobId( hash: Address, @@ -82,14 +84,14 @@ abstract class BaseAcpContractClient { return this.agentWalletAddress; } - async createJobWithAccount( + createJobWithAccount( accountId: number, providerAddress: Address, evaluatorAddress: Address, budgetBaseUnit: bigint, paymentTokenAddress: Address, expiredAt: Date - ): Promise<{ txHash: string; jobId: number }> { + ): OperationPayload { try { const data = encodeFunctionData({ abi: this.abi, @@ -103,28 +105,25 @@ abstract class BaseAcpContractClient { ], }); - const hash = await this.handleOperation(data, this.contractAddress); - - const jobId = await this.getJobId( - hash, - this.agentWalletAddress, - providerAddress - ); + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; - return { txHash: hash, jobId: jobId }; + return payload; } catch (error) { throw new AcpError("Failed to create job with account", error); } } - async createJob( + createJob( providerAddress: Address, evaluatorAddress: Address, expiredAt: Date, paymentTokenAddress: Address, budgetBaseUnit: bigint, metadata: string - ): Promise<{ txHash: string; jobId: number }> { + ): OperationPayload { try { const data = encodeFunctionData({ abi: this.abi, @@ -139,24 +138,21 @@ abstract class BaseAcpContractClient { ], }); - const hash = await this.handleOperation(data, this.contractAddress); + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; - const jobId = await this.getJobId( - hash, - this.agentWalletAddress, - providerAddress - ); - - return { txHash: hash, jobId: jobId }; + return payload; } catch (error) { throw new AcpError("Failed to create job", error); } } - async approveAllowance( + approveAllowance( amountBaseUnit: bigint, paymentTokenAddress: Address = this.config.baseFare.contractAddress - ) { + ): OperationPayload { try { const data = encodeFunctionData({ abi: erc20Abi, @@ -164,13 +160,18 @@ abstract class BaseAcpContractClient { args: [this.contractAddress, amountBaseUnit], }); - return await this.handleOperation(data, paymentTokenAddress); + const payload: OperationPayload = { + data: data, + contractAddress: paymentTokenAddress, + }; + + return payload; } catch (error) { throw new AcpError("Failed to approve allowance", error); } } - async createPayableMemo( + createPayableMemo( jobId: number, content: string, amountBaseUnit: bigint, @@ -186,7 +187,7 @@ abstract class BaseAcpContractClient { expiredAt: Date, token: Address = this.config.baseFare.contractAddress, secured: boolean = true - ) { + ): OperationPayload { try { const data = encodeFunctionData({ abi: this.abi, @@ -206,19 +207,24 @@ abstract class BaseAcpContractClient { ], }); - return await this.handleOperation(data, this.contractAddress); + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; + + return payload; } catch (error) { throw new AcpError("Failed to create payable memo", error); } } - async createMemo( + createMemo( jobId: number, content: string, type: MemoType, isSecured: boolean, nextPhase: AcpJobPhases - ): Promise
{ + ): OperationPayload { try { const data = encodeFunctionData({ abi: this.abi, @@ -226,13 +232,22 @@ abstract class BaseAcpContractClient { args: [jobId, content, type, isSecured, nextPhase], }); - return await this.handleOperation(data, this.contractAddress); + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; + + return payload; } catch (error) { throw new AcpError("Failed to create memo", error); } } - async signMemo(memoId: number, isApproved: boolean, reason?: string) { + signMemo( + memoId: number, + isApproved: boolean, + reason?: string + ): OperationPayload { try { const data = encodeFunctionData({ abi: this.abi, @@ -240,33 +255,26 @@ abstract class BaseAcpContractClient { args: [memoId, isApproved, reason], }); - const hash = await this.handleOperation(data, this.contractAddress); + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; - return hash; + return payload; } catch (error) { throw new AcpError("Failed to sign memo", error); } } - async setBudgetWithPaymentToken( + setBudgetWithPaymentToken( jobId: number, budgetBaseUnit: bigint, paymentTokenAddress: Address = this.config.baseFare.contractAddress - ) { - try { - const data = encodeFunctionData({ - abi: this.abi, - functionName: "setBudgetWithPaymentToken", - args: [jobId, budgetBaseUnit, paymentTokenAddress], - }); - - return await this.handleOperation(data, this.contractAddress); - } catch (error) { - throw new AcpError("Failed to set budget", error); - } + ): OperationPayload | undefined { + return undefined; } - async updateAccountMetadata(accountId: number, metadata: string) { + updateAccountMetadata(accountId: number, metadata: string): OperationPayload { try { const data = encodeFunctionData({ abi: this.abi, @@ -274,24 +282,31 @@ abstract class BaseAcpContractClient { args: [accountId, metadata], }); - return await this.handleOperation(data, this.contractAddress); + const payload: OperationPayload = { + data: data, + contractAddress: this.contractAddress, + }; + + return payload; } catch (error) { throw new AcpError("Failed to update account metadata", error); } } - async wrapEth(amountBaseUnit: bigint) { + wrapEth(amountBaseUnit: bigint): OperationPayload { try { const data = encodeFunctionData({ abi: WETH_ABI, functionName: "deposit", }); - return await this.handleOperation( - data, - wethFare.contractAddress, - amountBaseUnit - ); + const payload: OperationPayload = { + data: data, + contractAddress: wethFare.contractAddress, + value: amountBaseUnit, + }; + + return payload; } catch (error) { throw new AcpError("Failed to wrap eth", error); } From 9f1bfed2634681c706c412870da3b7fce3ecb4f2 Mon Sep 17 00:00:00 2001 From: Zuhwa Date: Tue, 21 Oct 2025 16:11:29 +0800 Subject: [PATCH 2/4] removed unused import --- src/acpClient.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/acpClient.ts b/src/acpClient.ts index 778778f..3395463 100644 --- a/src/acpClient.ts +++ b/src/acpClient.ts @@ -2,7 +2,6 @@ import { Address, zeroAddress } from "viem"; import { io } from "socket.io-client"; import BaseAcpContractClient, { AcpJobPhases, - FeeType, MemoType, OperationPayload, } from "./contractClients/baseAcpContractClient"; @@ -14,23 +13,15 @@ import { AcpAgentSort, AcpGraduationStatus, AcpOnlineStatus, - GenericPayload, IAcpAccount, IAcpClientOptions, IAcpJob, IAcpJobResponse, IAcpMemo, - DeliverablePayload, PayableDetails, } from "./interfaces"; import AcpError from "./acpError"; -import { - ethFare, - FareAmount, - FareAmountBase, - FareBigInt, - wethFare, -} from "./acpFare"; +import { FareAmountBase } from "./acpFare"; import { AcpAccount } from "./acpAccount"; import { baseAcpConfig, baseSepoliaAcpConfig } from "./configs/acpConfigs"; import { preparePayload, tryParseJson } from "./utils"; From d546f1bea275be805efb722510602191373b6e80 Mon Sep 17 00:00:00 2001 From: Ang Weoy Yang Date: Wed, 22 Oct 2025 09:15:49 +0800 Subject: [PATCH 3/4] refactor: fix convention and standardize handle operation usage --- src/acpJob.ts | 56 +++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/acpJob.ts b/src/acpJob.ts index b2a348d..126133d 100644 --- a/src/acpJob.ts +++ b/src/acpJob.ts @@ -111,15 +111,19 @@ class AcpJob { } async createRequirement(content: string) { - const payload = this.acpContractClient.createMemo( - this.id, - content, - MemoType.MESSAGE, - true, - AcpJobPhases.TRANSACTION + const operations: OperationPayload[] = []; + + operations.push( + this.acpContractClient.createMemo( + this.id, + content, + MemoType.MESSAGE, + true, + AcpJobPhases.TRANSACTION, + ) ); - return await this.acpContractClient.handleOperation([payload]); + return await this.acpContractClient.handleOperation(operations); } async createPayableRequirement( @@ -135,7 +139,7 @@ class AcpJob { operations.push( this.acpContractClient.approveAllowance( amount.amount, - amount.fare.contractAddress + amount.fare.contractAddress, ) ); } @@ -153,7 +157,7 @@ class AcpJob { AcpJobPhases.TRANSACTION, type, expiredAt, - amount.fare.contractAddress + amount.fare.contractAddress, ) ); @@ -166,7 +170,7 @@ class AcpJob { ); if (!memo) { - throw new AcpError("No transaction memo found"); + throw new AcpError("No notification memo found"); } const operations: OperationPayload[] = []; @@ -176,7 +180,7 @@ class AcpJob { ? await FareAmountBase.fromContractAddress( memo.payableDetails.amount, memo.payableDetails.token, - this.config + this.config, ) : new FareAmount(0, this.baseFare); @@ -189,7 +193,7 @@ class AcpJob { operations.push( this.acpContractClient.approveAllowance( totalAmount.amount, - this.baseFare.contractAddress + this.baseFare.contractAddress, ) ); @@ -200,7 +204,7 @@ class AcpJob { operations.push( this.acpContractClient.approveAllowance( transferAmount.amount, - transferAmount.fare.contractAddress + transferAmount.fare.contractAddress, ) ); } @@ -213,7 +217,7 @@ class AcpJob { `Payment made. ${reason ?? ""}`.trim(), MemoType.MESSAGE, true, - AcpJobPhases.EVALUATION + AcpJobPhases.EVALUATION, ) ); @@ -226,7 +230,7 @@ class AcpJob { }`; if (accept) { await this.accept(memoContent); - return this.createRequirement(memoContent); + return await this.createRequirement(memoContent); } return await this.reject(memoContent); @@ -234,18 +238,22 @@ class AcpJob { async accept(reason?: string) { const memoContent = `Job ${this.id} accepted. ${reason || ""}`; + const operations: OperationPayload[] = []; + if (this.latestMemo?.nextPhase !== AcpJobPhases.NEGOTIATION) { - throw new AcpError("No negotiation memo found"); + throw new AcpError("No request memo found"); } const memo = this.latestMemo; - return memo.sign(true, memoContent); + operations.push( + this.acpContractClient.signMemo(memo.id, true, memoContent) + ); + return await this.acpContractClient.handleOperation(operations); } async reject(reason?: string) { const memoContent = `Job ${this.id} rejected. ${reason || ""}`; - const operations: OperationPayload[] = []; if (this.phase === AcpJobPhases.REQUEST) { @@ -256,6 +264,7 @@ class AcpJob { operations.push( this.acpContractClient.signMemo(memo.id, false, memoContent) ); + return await this.acpContractClient.handleOperation(operations); } operations.push( @@ -264,10 +273,9 @@ class AcpJob { memoContent, MemoType.MESSAGE, true, - AcpJobPhases.REJECTED + AcpJobPhases.REJECTED, ) ); - return await this.acpContractClient.handleOperation(operations); } @@ -284,7 +292,7 @@ class AcpJob { preparePayload(deliverable), MemoType.MESSAGE, true, - AcpJobPhases.COMPLETED + AcpJobPhases.COMPLETED, ) ); @@ -348,7 +356,7 @@ class AcpJob { content, MemoType.NOTIFICATION, true, - AcpJobPhases.COMPLETED + AcpJobPhases.COMPLETED, ) ); @@ -365,7 +373,7 @@ class AcpJob { operations.push( this.acpContractClient.approveAllowance( amount.amount, - amount.fare.contractAddress + amount.fare.contractAddress, ) ); @@ -382,7 +390,7 @@ class AcpJob { AcpJobPhases.COMPLETED, MemoType.PAYABLE_NOTIFICATION, expiredAt, - amount.fare.contractAddress + amount.fare.contractAddress, ) ); From aa7aeda6e6b937e663b65193646f08dcaccba240 Mon Sep 17 00:00:00 2001 From: Celeste Ang Date: Mon, 27 Oct 2025 06:33:15 +0800 Subject: [PATCH 4/4] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f00424..0e27851 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@virtuals-protocol/acp-node", - "version": "0.3.0-beta.4", + "version": "0.3.0-beta.5", "main": "./dist/index.js", "module": "./dist/index.mjs", "types": "./dist/index.d.ts",