From fced040ee35bcb9faaa2c4dd3012aeea6920482e Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:42:42 +0200 Subject: [PATCH 1/9] feat: default Arbitrum Sepolia, drop Bellecour SGX/sconify and vouchers - DEFAULT_CHAIN_ID 421614; remove bellecour chain config; default host arbitrum-sepolia-testnet - Remove useVoucher and voucher helpers from sendTelegram and filterWorkerpoolOrders - deployApp: TDX-only mrenclave; deploy workflow removes sconify and bellecour envs - Test stack: anvil fork + SMS/result-proxy/market/compass/graph for Arbitrum Sepolia; no voucher subgraph - test-utils: fork RPC 8555, RLC balance via anvil_setStorageAt, tee+tdx orders, compass mock Made-with: Cursor --- .github/workflows/dapp-deploy.yml | 111 ----- dapp/tests/e2e/app.test.js | 2 +- dapp/tests/unit/decryptContent.test.js | 5 +- deployment-dapp/src/deployScript.ts | 13 +- deployment-dapp/src/revokeSellOrderScript.ts | 2 +- .../src/singleFunction/deployApp.ts | 25 +- deployment-dapp/src/utils/utils.ts | 2 +- package.json | 2 +- src/config/config.ts | 12 +- src/utils/getChainId.ts | 4 +- src/utils/getWeb3Provider.ts | 4 +- src/utils/sendTelegram.models.ts | 64 +-- src/web3telegram/IExecWeb3telegram.ts | 2 +- src/web3telegram/sendTelegram.ts | 53 +-- src/web3telegram/types.ts | 1 - tests/docker-compose.yml | 117 +++-- tests/e2e/sendTelegram.test.ts | 256 +---------- tests/mock/compass/data.json | 24 + ...repare-arbitrum-sepolia-fork-for-tests.js} | 154 ++----- tests/scripts/prepare-test-env.js | 42 +- tests/test-utils.ts | 421 +++++------------- tests/unit/fetchMyContacts.test.ts | 29 +- tests/unit/sendTelegram.models.test.ts | 279 +++--------- tests/unit/sendTelegram.test.ts | 19 +- .../unit/utils/filterWorkerpoolOrders.test.ts | 6 - 25 files changed, 375 insertions(+), 1274 deletions(-) create mode 100644 tests/mock/compass/data.json rename tests/scripts/{prepare-bellecour-fork-for-tests.js => prepare-arbitrum-sepolia-fork-for-tests.js} (51%) diff --git a/.github/workflows/dapp-deploy.yml b/.github/workflows/dapp-deploy.yml index 9e7e9b3..50e0357 100644 --- a/.github/workflows/dapp-deploy.yml +++ b/.github/workflows/dapp-deploy.yml @@ -8,11 +8,7 @@ on: required: true type: choice options: - # dev environments - - bellecour-dev - arbitrum-sepolia-dev - # prod environments (requires a tag starting with dapp-v) - - bellecour-prod - arbitrum-sepolia-prod - arbitrum-prod @@ -24,10 +20,6 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - # ref should be a tag beginning with dapp-v if not exit error - # use unique clean-tag: - - # else - # use rolling clean-tag: dev - name: Check and extract tag id: tag run: | @@ -71,36 +63,7 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PAT }} - sconify: - if: startsWith(github.event.inputs.environment, 'bellecour-') - uses: iExecBlockchainComputing/github-actions-workflows/.github/workflows/sconify.yml@sconify-v2.0.0 - needs: [docker-publish, extract-tag] - with: - image-name: 'iexechub/web3telegram-dapp' - image-tag: ${{ needs.extract-tag.outputs.clean_tag }} - sconify-debug: false - sconify-prod: true - docker-registry: docker.io - sconify-version: ${{ vars.SCONIFY_VERSION }} - binary: /usr/local/bin/node - command: node - host-path: | - /etc/hosts - /etc/resolv.conf - binary-fs: true - fs-dir: /app - heap: 1G - dlopen: 1 - mprotect: 0 - secrets: - docker-username: ${{ secrets.DOCKERHUB_USERNAME }} - docker-password: ${{ secrets.DOCKERHUB_PAT }} - scontain-username: ${{ secrets.SCONTAIN_REGISTRY_USERNAME }} - scontain-password: ${{ secrets.SCONTAIN_REGISTRY_PAT }} - scone-signing-key: ${{ secrets.SCONIFY_SIGNING_PRIVATE_KEY }} - deploy-tdx-dapp: - if: startsWith(github.event.inputs.environment, 'arbitrum-') needs: [extract-tag, docker-publish] runs-on: ubuntu-latest environment: ${{ inputs.environment }} @@ -161,77 +124,3 @@ jobs: cd node_modules/whitelist-smart-contract export ADDRESS_TO_ADD=$(cat ../../deployment-dapp/.app-address) npm run addResourceToWhitelist -- --network ${{ vars.WHITELIST_NETWORK_NAME }} - - deploy-scone-dapp: - if: startsWith(github.event.inputs.environment, 'bellecour-') - needs: [extract-tag, sconify] - runs-on: ubuntu-latest - environment: ${{ inputs.environment }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - - name: Install dependencies - run: | - npm ci - cd node_modules/whitelist-smart-contract - npm install --save-dev ts-node - cd ../../deployment-dapp - npm ci - - - name: Deploy SCONE dapp contract - env: - WALLET_PRIVATE_KEY: ${{ secrets.WEB3TELEGRAM_APP_OWNER_PRIVATEKEY }} - DOCKER_IMAGE_TAG: ${{ needs.sconify.outputs.prod-image-tag }} - CHECKSUM: ${{ needs.sconify.outputs.prod-checksum }} - FINGERPRINT: ${{ needs.sconify.outputs.prod-mrenclave }} - RPC_URL: ${{ secrets.RPC_URL }} - SCONIFY_VERSION: ${{ vars.SCONIFY_VERSION }} - run: | - cd deployment-dapp - npm run deploy-dapp - - - name: Push dapp secret - env: - WALLET_PRIVATE_KEY: ${{ secrets.WEB3TELEGRAM_APP_OWNER_PRIVATEKEY }} - TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} - RPC_URL: ${{ secrets.RPC_URL }} - run: | - cd deployment-dapp - npm run push-dapp-secret - - - name: Publish free sell order - env: - WALLET_PRIVATE_KEY: ${{ secrets.WEB3TELEGRAM_APP_OWNER_PRIVATEKEY }} - PRICE: ${{ vars.SELL_ORDER_PRICE }} - VOLUME: ${{ vars.SELL_ORDER_VOLUME }} - RPC_URL: ${{ secrets.RPC_URL }} - TEE_FRAMEWORK: ${{ vars.TEE_FRAMEWORK }} - run: | - cd deployment-dapp - npm run publish-sell-order - - - name: Add resource to whitelist - env: - CONTRACT_ADDRESS: ${{ vars.WEB3TELEGRAM_WHITELIST_CONTRACT_ADDRESS }} - PRIVATE_KEY: ${{ secrets.WEB3TELEGRAM_APP_OWNER_PRIVATEKEY }} - RPC_URL: ${{ secrets.RPC_URL }} - run: | - cd node_modules/whitelist-smart-contract - export ADDRESS_TO_ADD=$(cat ../../deployment-dapp/.app-address) - npm run addResourceToWhitelist -- --network ${{ vars.WHITELIST_NETWORK_NAME }} - - - name: Configure ENS - if: ${{ vars.DAPP_ENS_NAME }} - env: - WALLET_PRIVATE_KEY: ${{ secrets.WEB3TELEGRAM_APP_OWNER_PRIVATEKEY }} - DAPP_ENS_NAME: ${{ vars.DAPP_ENS_NAME }} - run: | - cd deployment-dapp - npm run configure-ens diff --git a/dapp/tests/e2e/app.test.js b/dapp/tests/e2e/app.test.js index 646fd09..1424c64 100644 --- a/dapp/tests/e2e/app.test.js +++ b/dapp/tests/e2e/app.test.js @@ -38,7 +38,7 @@ describe('sendTelegram', () => { process.env.IEXEC_DATASET_FILENAME = 'data-chatId.zip'; process.env.WEB3TELEGRAM_IPFS_GATEWAY = process.env.WEB3TELEGRAM_IPFS_GATEWAY || - 'https://ipfs-gateway.v8-bellecour.iex.ec'; + 'https://ipfs-gateway.arbitrum-sepolia-testnet.iex.ec'; // developer secret setup process.env.IEXEC_APP_DEVELOPER_SECRET = JSON.stringify({ TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_BOT_TOKEN, diff --git a/dapp/tests/unit/decryptContent.test.js b/dapp/tests/unit/decryptContent.test.js index 47a8f75..383aab6 100644 --- a/dapp/tests/unit/decryptContent.test.js +++ b/dapp/tests/unit/decryptContent.test.js @@ -8,12 +8,13 @@ import { resolveIpfsGatewayUrl, } from '../../src/decryptContent'; -const TEST_IPFS_GATEWAY = 'https://ipfs-gateway.v8-bellecour.iex.ec'; +const TEST_IPFS_GATEWAY = + 'https://ipfs-gateway.arbitrum-sepolia-testnet.iex.ec'; describe('decryptContent', () => { it('should decrypt message correctly', async () => { const iexec = new IExec({ - ethProvider: 'bellecour', + ethProvider: 'arbitrum-sepolia-testnet', }); const encryptionKey = iexec.dataset.generateEncryptionKey(); diff --git a/deployment-dapp/src/deployScript.ts b/deployment-dapp/src/deployScript.ts index 8393281..7104ae1 100644 --- a/deployment-dapp/src/deployScript.ts +++ b/deployment-dapp/src/deployScript.ts @@ -2,15 +2,8 @@ import { deployApp } from './singleFunction/deployApp.js'; import { getIExec, saveAppAddress } from './utils/utils.js'; const main = async () => { - // get env variables from GitHub Actions - const { - RPC_URL, - WALLET_PRIVATE_KEY, - DOCKER_IMAGE_TAG, - CHECKSUM, - FINGERPRINT, - SCONIFY_VERSION, - } = process.env; + const { RPC_URL, WALLET_PRIVATE_KEY, DOCKER_IMAGE_TAG, CHECKSUM } = + process.env; if (!WALLET_PRIVATE_KEY) throw Error(`Missing WALLET_PRIVATE_KEY environment variable`); @@ -25,8 +18,6 @@ const main = async () => { iexec, dockerTag: DOCKER_IMAGE_TAG, checksum: CHECKSUM, - fingerprint: FINGERPRINT, - sconifyVersion: SCONIFY_VERSION, }); await saveAppAddress(address); }; diff --git a/deployment-dapp/src/revokeSellOrderScript.ts b/deployment-dapp/src/revokeSellOrderScript.ts index b3e97c8..123f684 100644 --- a/deployment-dapp/src/revokeSellOrderScript.ts +++ b/deployment-dapp/src/revokeSellOrderScript.ts @@ -17,7 +17,7 @@ const main = async () => { // validate params const orderHash = await orderHashSchema().validate(ORDER_HASH); - //revoke sell order for Tee app (scone) + // revoke sell order for TEE app (TDX) const txHash = await revokeSellOrder(iexec, orderHash); if (!txHash) throw Error(`Failed to revoke app sell order: ${orderHash}`); }; diff --git a/deployment-dapp/src/singleFunction/deployApp.ts b/deployment-dapp/src/singleFunction/deployApp.ts index 7e9e6ae..387f03f 100644 --- a/deployment-dapp/src/singleFunction/deployApp.ts +++ b/deployment-dapp/src/singleFunction/deployApp.ts @@ -12,37 +12,19 @@ export const deployApp = async ({ dockerRepository = DOCKER_IMAGE_REPOSITORY, dockerTag, checksum, - // TODO: to be deleted after migration to TDX - fingerprint, - sconifyVersion, }: { iexec: IExec; dockerNamespace?: string; dockerRepository?: string; dockerTag: string; checksum?: string; - // TODO: to be deleted after migration to TDX - fingerprint?: string; - sconifyVersion?: string; }): Promise => { const name = APP_NAME; const type = APP_TYPE; - let mrenclave; - - // TODO: to be deleted after migration to TDX - if (sconifyVersion) { - console.log( - `Using SCONE framework with SCONIFY version: ${sconifyVersion}` - ); - mrenclave = { - framework: 'SCONE', // workaround framework not auto capitalized - version: `v${sconifyVersion.split('.').slice(0, 2).join('.')}`, // extracts "vX.Y" from "X.Y.Z-vN" format (e.g., "5.9.1-v16" → "v5.9") - entrypoint: 'node --disable-wasm-trap-handler /app/app.js', - heapSize: 1073741824, // 1GB - fingerprint, - }; - } + const mrenclave = { + framework: 'TDX', + }; const app = { owner: await iexec.wallet.getAddress(), @@ -50,7 +32,6 @@ export const deployApp = async ({ type, multiaddr: `${dockerNamespace}/${dockerRepository}:${dockerTag}`, checksum, - // TODO: to be deleted after migration to TDX mrenclave, }; console.log(`Deploying app:\n${JSON.stringify(app, undefined, 2)}`); diff --git a/deployment-dapp/src/utils/utils.ts b/deployment-dapp/src/utils/utils.ts index 6e8e533..dbc1448 100644 --- a/deployment-dapp/src/utils/utils.ts +++ b/deployment-dapp/src/utils/utils.ts @@ -3,7 +3,7 @@ import { IExec, utils } from 'iexec'; export const getIExec = ( privateKey: string, - host: string = 'bellecour' + host: string = 'arbitrum-sepolia-testnet' ): IExec => { const ethProvider = utils.getSignerFromPrivateKey(host, privateKey, { providers: {}, diff --git a/package.json b/package.json index b50f99f..d7976a8 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "scripts": { "build": "rm -rf dist && tsc --project tsconfig.build.json", "check-types": "tsc --noEmit", - "test:prepare": "node tests/scripts/prepare-bellecour-fork-for-tests.js && node tests/scripts/prepare-iexec.js", + "test:prepare": "node tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js && node tests/scripts/prepare-iexec.js", "test": "NODE_OPTIONS=--experimental-vm-modules jest --testMatch \"**/tests/**/*.test.ts\" --forceExit -b", "test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --testMatch \"**/tests/**/*.test.ts\" --forceExit --coverage", "test:unit": "NODE_OPTIONS=--experimental-vm-modules jest --testMatch \"**/tests/unit/**/*.test.ts\" -b", diff --git a/src/config/config.ts b/src/config/config.ts index 4c12def..62b915e 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -3,7 +3,7 @@ export const MAX_DESIRED_APP_ORDER_PRICE = 0; export const MAX_DESIRED_WORKERPOOL_ORDER_PRICE = 0; export const ANY_DATASET_ADDRESS = 'any'; -export const DEFAULT_CHAIN_ID = 134; +export const DEFAULT_CHAIN_ID = 421614; interface ChainConfig { name: string; @@ -17,16 +17,6 @@ interface ChainConfig { } export const CHAIN_CONFIG: Record = { - 134: { - name: 'bellecour', - dappAddress: 'web3telegram.apps.iexec.eth', - prodWorkerpoolAddress: 'prod-v8-bellecour.main.pools.iexec.eth', - dataProtectorSubgraph: - 'https://thegraph.iex.ec/subgraphs/name/bellecour/dataprotector-v2', - ipfsUploadUrl: '/dns4/ipfs-upload.v8-bellecour.iex.ec/https', - ipfsGateway: 'https://ipfs-gateway.v8-bellecour.iex.ec', - whitelistSmartContract: '0x192C6f5AccE52c81Fcc2670f10611a3665AAA98F', - }, 421614: { name: 'arbitrum-sepolia-testnet', dappAddress: undefined, // ENS not supported on this network, address will be resolved from Compass diff --git a/src/utils/getChainId.ts b/src/utils/getChainId.ts index c958eeb..20e448f 100644 --- a/src/utils/getChainId.ts +++ b/src/utils/getChainId.ts @@ -18,9 +18,7 @@ export async function getChainIdFromProvider( ): Promise { try { if (typeof ethProvider === 'string') { - // Handle network string - if (ethProvider === 'bellecour') return 134; - // TODO add arbitrum & avalanche + if (ethProvider === 'arbitrum-sepolia-testnet') return 421614; const provider = new JsonRpcProvider(ethProvider); const network = await provider.getNetwork(); return Number(network.chainId); diff --git a/src/utils/getWeb3Provider.ts b/src/utils/getWeb3Provider.ts index d9c6eb7..f1cd6e3 100644 --- a/src/utils/getWeb3Provider.ts +++ b/src/utils/getWeb3Provider.ts @@ -5,7 +5,9 @@ export const getWeb3Provider = ( privateKey: string, options: { allowExperimentalNetworks?: boolean; host?: number | string } = {} ): Web3SignerProvider => { - const chainHost = options?.host ? `${options.host}` : 'bellecour'; + const chainHost = options?.host + ? `${options.host}` + : 'arbitrum-sepolia-testnet'; return getSignerFromPrivateKey(chainHost, privateKey, { allowExperimentalNetworks: options?.allowExperimentalNetworks, providers: {}, diff --git a/src/utils/sendTelegram.models.ts b/src/utils/sendTelegram.models.ts index f478d1b..ba18ef6 100644 --- a/src/utils/sendTelegram.models.ts +++ b/src/utils/sendTelegram.models.ts @@ -1,76 +1,17 @@ -import { Address, BN } from 'iexec'; import { PublishedWorkerpoolorder } from 'iexec/IExecOrderbookModule'; -type VoucherInfo = { - owner: Address; - address: Address; - type: BN; - balance: BN; - expirationTimestamp: BN; - sponsoredApps: Address[]; - sponsoredDatasets: Address[]; - sponsoredWorkerpools: Address[]; - allowanceAmount: BN; - authorizedAccounts: Address[]; -}; - -function bnToNumber(bn: BN) { - return Number(bn.toString()); -} - -export function checkUserVoucher({ - userVoucher, -}: { - userVoucher: VoucherInfo; -}) { - if (bnToNumber(userVoucher.expirationTimestamp) < Date.now() / 1000) { - throw new Error( - 'Oops, it seems your voucher has expired. You might want to ask for a top up. Check on https://builder.iex.ec/' - ); - } - - if (bnToNumber(userVoucher.balance) === 0) { - throw new Error( - 'Oops, it seems your voucher is empty. You might want to ask for a top up. Check on https://builder.iex.ec/' - ); - } -} - export function filterWorkerpoolOrders({ workerpoolOrders, workerpoolMaxPrice, - useVoucher, - userVoucher, }: { workerpoolOrders: PublishedWorkerpoolorder[]; workerpoolMaxPrice: number; - useVoucher: boolean; - userVoucher?: VoucherInfo; }) { if (workerpoolOrders.length === 0) { return null; } - let eligibleWorkerpoolOrders = [...workerpoolOrders]; - let maxVoucherSponsoredAmount = 0; // may be safer to use bigint - - if (useVoucher) { - if (!userVoucher) { - throw new Error( - 'useVoucher === true but userVoucher is undefined? Hum...' - ); - } - // only voucher sponsored workerpoolorders - eligibleWorkerpoolOrders = eligibleWorkerpoolOrders.filter(({ order }) => - userVoucher.sponsoredWorkerpools.includes(order.workerpool) - ); - if (eligibleWorkerpoolOrders.length === 0) { - throw new Error( - 'Found some workerpool orders but none can be sponsored by your voucher.' - ); - } - maxVoucherSponsoredAmount = bnToNumber(userVoucher.balance); - } + const eligibleWorkerpoolOrders = [...workerpoolOrders]; const [cheapestOrder] = eligibleWorkerpoolOrders.sort( (order1, order2) => @@ -79,8 +20,7 @@ export function filterWorkerpoolOrders({ if ( !cheapestOrder || - cheapestOrder.order.workerpoolprice > - workerpoolMaxPrice + maxVoucherSponsoredAmount + cheapestOrder.order.workerpoolprice > workerpoolMaxPrice ) { return null; } diff --git a/src/web3telegram/IExecWeb3telegram.ts b/src/web3telegram/IExecWeb3telegram.ts index 05d1121..de2779a 100644 --- a/src/web3telegram/IExecWeb3telegram.ts +++ b/src/web3telegram/IExecWeb3telegram.ts @@ -71,7 +71,7 @@ export class IExecWeb3telegram { ethProvider?: EthersCompatibleProvider, options?: Web3TelegramConfigOptions ) { - this.ethProvider = ethProvider || 'bellecour'; + this.ethProvider = ethProvider || 'arbitrum-sepolia-testnet'; this.options = options || {}; } diff --git a/src/web3telegram/sendTelegram.ts b/src/web3telegram/sendTelegram.ts index ab1ab7c..9343a94 100644 --- a/src/web3telegram/sendTelegram.ts +++ b/src/web3telegram/sendTelegram.ts @@ -16,13 +16,9 @@ import { throwIfMissing, addressSchema, senderNameSchema, - booleanSchema, } from '../utils/validators.js'; import { SendTelegramParams, SendTelegramResponse } from './types.js'; -import { - checkUserVoucher, - filterWorkerpoolOrders, -} from '../utils/sendTelegram.models.js'; +import { filterWorkerpoolOrders } from '../utils/sendTelegram.models.js'; import { DappAddressConsumer, DappWhitelistAddressConsumer, @@ -49,7 +45,6 @@ export const sendTelegram = async ({ appMaxPrice = MAX_DESIRED_APP_ORDER_PRICE, workerpoolMaxPrice = MAX_DESIRED_WORKERPOOL_ORDER_PRICE, protectedData, - useVoucher = false, }: IExecConsumer & SubgraphConsumer & DappAddressConsumer & @@ -91,9 +86,6 @@ export const sendTelegram = async ({ const vWorkerpoolMaxPrice = positiveNumberSchema() .label('workerpoolMaxPrice') .validateSync(workerpoolMaxPrice); - const vUseVoucher = booleanSchema() - .label('useVoucher') - .validateSync(useVoucher); // Check protected data validity through subgraph const isValidProtectedData = await checkProtectedDataValidity( @@ -107,20 +99,6 @@ export const sendTelegram = async ({ } const requesterAddress = await iexec.wallet.getAddress(); - let userVoucher; - if (vUseVoucher) { - try { - userVoucher = await iexec.voucher.showUserVoucher(requesterAddress); - checkUserVoucher({ userVoucher }); - } catch (err) { - if (err?.message?.startsWith('No Voucher found for address')) { - throw new Error( - 'Oops, it seems your wallet is not associated with any voucher. Check on https://builder.iex.ec/' - ); - } - throw err; - } - } // Fetch app order const apporder = await iexec.orderbook .fetchAppOrderbook({ @@ -173,23 +151,21 @@ export const sendTelegram = async ({ // Fetch workerpool order for App or AppWhitelist Promise.all([ - // for app iexec.orderbook.fetchWorkerpoolOrderbook({ workerpool: workerpoolAddressOrEns, app: vDappAddressOrENS, dataset: vDatasetAddress, - requester: requesterAddress, // public orders + user specific orders - isRequesterStrict: useVoucher, // If voucher, we only want user specific orders + requester: requesterAddress, + isRequesterStrict: false, minTag: workerpoolMinTag, category: 0, }), - // for app whitelist iexec.orderbook.fetchWorkerpoolOrderbook({ workerpool: workerpoolAddressOrEns, app: vDappWhitelistAddress, dataset: vDatasetAddress, - requester: requesterAddress, // public orders + user specific orders - isRequesterStrict: useVoucher, // If voucher, we only want user specific orders + requester: requesterAddress, + isRequesterStrict: false, minTag: workerpoolMinTag, category: 0, }), @@ -201,8 +177,6 @@ export const sendTelegram = async ({ ...workerpoolOrderbookForAppWhitelist.orders, ], workerpoolMaxPrice: vWorkerpoolMaxPrice, - useVoucher: vUseVoucher, - userVoucher, }); if (!desiredPriceWorkerpoolOrder) { throw new Error( @@ -264,7 +238,7 @@ export const sendTelegram = async ({ datasetmaxprice: datasetorder.datasetprice, appmaxprice: apporder.appprice, workerpoolmaxprice: workerpoolorder.workerpoolprice, - tag: ['tee'], + tag: workerpoolMinTag, workerpool: vWorkerpoolAddressOrEns, params: { iexec_secrets: { @@ -276,15 +250,12 @@ export const sendTelegram = async ({ const requestorder = await iexec.order.signRequestorder(requestorderToSign); // Match orders and compute task ID - const { dealid: dealId } = await iexec.order.matchOrders( - { - apporder: apporder, - datasetorder: datasetorder, - workerpoolorder: workerpoolorder, - requestorder: requestorder, - }, - { useVoucher: vUseVoucher } - ); + const { dealid: dealId } = await iexec.order.matchOrders({ + apporder: apporder, + datasetorder: datasetorder, + workerpoolorder: workerpoolorder, + requestorder: requestorder, + }); const taskId = await iexec.deal.computeTaskId(dealId, 0); return { dealId, diff --git a/src/web3telegram/types.ts b/src/web3telegram/types.ts index 39adbfb..15a5a6f 100644 --- a/src/web3telegram/types.ts +++ b/src/web3telegram/types.ts @@ -76,7 +76,6 @@ export type SendTelegramParams = { dataMaxPrice?: number; appMaxPrice?: number; workerpoolMaxPrice?: number; - useVoucher?: boolean; }; export type SendTelegramResponse = { diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index cfd6117..d06f63b 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -1,15 +1,14 @@ services: - bellecour-fork: + arbitrum-sepolia-fork: restart: 'no' image: ghcr.io/foundry-rs/foundry:v1.0.0 entrypoint: anvil - command: '--host 0.0.0.0 --port 8545 --block-time 1 --hardfork berlin --fork-url $BELLECOUR_FORK_URL --fork-block-number $BELLECOUR_FORK_BLOCK --chain-id 134 --gas-limit 6700000 --gas-price 0' + command: '--host 0.0.0.0 --port 8545 --block-time 1 --fork-url $ARBITRUM_SEPOLIA_FORK_URL --fork-block-number $ARBITRUM_SEPOLIA_FORK_BLOCK --chain-id 421614' expose: - 8545 ports: - - 8545:8545 + - 8555:8545 healthcheck: - # check port 8545 is open without nc test: (echo >/dev/tcp/$(hostname)/8545) &>/dev/null interval: 30s timeout: 5s @@ -21,36 +20,36 @@ services: restart: unless-stopped environment: JAVA_TOOL_OPTIONS: '-Xmx256M' - IEXEC_SMS_BLOCKCHAIN_NODE_ADDRESS: http://bellecour-fork:8545 - IEXEC_HUB_ADDRESS: '0x3eca1B216A7DF1C7689aEb259fFB83ADFB894E7f' - IEXEC_SMS_TEE_RUNTIME_FRAMEWORK: scone + IEXEC_SMS_BLOCKCHAIN_NODE_ADDRESS: http://arbitrum-sepolia-fork:8545 + IEXEC_HUB_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' + IEXEC_SMS_TEE_RUNTIME_FRAMEWORK: tdx IEXEC_SMS_IMAGE_LAS_IMAGE: 'las-image' IEXEC_TEE_WORKER_PRE_COMPUTE_IMAGE: 'pre-compute-image' IEXEC_TEE_WORKER_PRE_COMPUTE_FINGERPRINT: 'pre-compute-fingerprint' IEXEC_TEE_WORKER_POST_COMPUTE_IMAGE: 'post-compute-image' IEXEC_TEE_WORKER_POST_COMPUTE_FINGERPRINT: 'post-compute-fingerprint' ports: - - 13300:13300 + - 13350:13300 healthcheck: test: curl -f localhost:13300/actuator/health || exit 1 depends_on: - bellecour-fork: + arbitrum-sepolia-fork: condition: service_healthy result-proxy: image: iexechub/iexec-result-proxy:7.1.0 restart: unless-stopped environment: - IEXEC_PRIVATE_CHAIN_ADDRESS: http://bellecour-fork:8545 - IEXEC_PUBLIC_CHAIN_ADDRESS: http://bellecour-fork:8545 - IEXEC_HUB_ADDRESS: '0x3eca1B216A7DF1C7689aEb259fFB83ADFB894E7f' + IEXEC_PRIVATE_CHAIN_ADDRESS: http://arbitrum-sepolia-fork:8545 + IEXEC_PUBLIC_CHAIN_ADDRESS: http://arbitrum-sepolia-fork:8545 + IEXEC_HUB_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' MONGO_HOST: result-proxy-mongo MONGO_PORT: 13202 IEXEC_IPFS_HOST: ipfs ports: - - 13200:13200 + - 13250:13200 depends_on: - bellecour-fork: + arbitrum-sepolia-fork: condition: service_healthy result-proxy-mongo: condition: service_started @@ -82,7 +81,7 @@ services: start_period: 30s market-mongo: - image: mongo:7.0.6 + image: mongo:6.0.3 restart: unless-stopped expose: - 27017 @@ -97,51 +96,72 @@ services: - 6379 ports: - 6379:6379 + healthcheck: + test: nc -z 0.0.0.0 6379 + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s market-watcher: image: iexechub/iexec-market-watcher:7.0.1 restart: unless-stopped environment: - CHAIN: BELLECOUR - START_BLOCK: $BELLECOUR_FORK_BLOCK - ETH_WS_HOST: ws://bellecour-fork:8545 - ETH_RPC_HOST: http://bellecour-fork:8545 + CHAIN: ARBITRUM_SEPOLIA + START_BLOCK: $ARBITRUM_SEPOLIA_FORK_BLOCK + CHAIN_ID: 421614 + IEXEC_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' + IS_NATIVE: 'false' + ETH_WS_HOST: ws://arbitrum-sepolia-fork:8545 + ETH_RPC_HOST: http://arbitrum-sepolia-fork:8545 MONGO_HOST: market-mongo REDIS_HOST: market-redis depends_on: - bellecour-fork: + arbitrum-sepolia-fork: condition: service_healthy market-redis: - condition: service_started + condition: service_healthy market-mongo: condition: service_started market-api: - image: iexechub/iexec-market-api:7.1.1 + image: iexechub/iexec-market-api:7.1.2 restart: unless-stopped ports: - - 3000:3000 + - 3050:3000 expose: - 3000 environment: - CHAINS: BELLECOUR_FORK - BELLECOUR_FORK_ETH_RPC_HOST: http://bellecour-fork:8545 - BELLECOUR_FORK_CHAIN_ID: 134 - BELLECOUR_FORK_IS_NATIVE: 'true' - BELLECOUR_FORK_IEXEC_ADDRESS: '0x3eca1B216A7DF1C7689aEb259fFB83ADFB894E7f' + CHAINS: ARBITRUM_SEPOLIA_FORK + ARBITRUM_SEPOLIA_FORK_ETH_RPC_HOST: http://arbitrum-sepolia-fork:8545 + ARBITRUM_SEPOLIA_FORK_CHAIN_ID: 421614 + ARBITRUM_SEPOLIA_FORK_IS_NATIVE: 'false' + ARBITRUM_SEPOLIA_FORK_IEXEC_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' MONGO_HOST: market-mongo REDIS_HOST: market-redis RATE_LIMIT_MAX: 10000 RATE_LIMIT_PERIOD: 60000 MAX_OPEN_ORDERS_PER_WALLET: 1000 depends_on: - bellecour-fork: + arbitrum-sepolia-fork: condition: service_healthy market-redis: - condition: service_started + condition: service_healthy market-mongo: condition: service_started + compass-arbitrum-sepolia: + image: iexechub/compass:v0.1.1 + restart: unless-stopped + environment: + DATA_FILE_PATH: /app/data.json + volumes: + - $PWD/mock/compass/data.json:/app/data.json:ro + ports: + - 8069:3000 + healthcheck: + test: nc -w 1 0.0.0.0 3000 + graphnode-postgres: image: postgres:12 restart: unless-stopped @@ -169,13 +189,8 @@ services: - 8000 - 8020 ports: - # GraphQL HTTP - 8000:8000 - # GraphQL WS - # - 8001:8001 - # admin RPC - 8020:8020 - # # metrics - 8040:8040 environment: postgres_host: graphnode-postgres @@ -184,10 +199,10 @@ services: postgres_pass: password postgres_db: graphnode-db ipfs: ipfs:5001 - ethereum: bellecour:http://bellecour-fork:8545 - GRAPH_ETHEREUM_GENESIS_BLOCK_NUMBER: $BELLECOUR_FORK_BLOCK + ethereum: 'arbitrum-sepolia:http://arbitrum-sepolia-fork:8545' + GRAPH_ETHEREUM_GENESIS_BLOCK_NUMBER: $ARBITRUM_SEPOLIA_FORK_BLOCK depends_on: - bellecour-fork: + arbitrum-sepolia-fork: condition: service_healthy graphnode-postgres: condition: service_healthy @@ -210,34 +225,16 @@ services: condition: service_started environment: ENV: prod - START_BLOCK: $BELLECOUR_FORK_BLOCK + START_BLOCK: $ARBITRUM_SEPOLIA_FORK_BLOCK GRAPHNODE_URL: http://graphnode:8020 IPFS_URL: http://ipfs:5001 - voucher-subgraph-deployer: - restart: 'no' - # https://github.com/iExecBlockchainComputing/iexec-voucher-subgraph - image: iexechub/voucher-subgraph-deployer:1.0.0 - environment: - RPC_URL: http://bellecour-fork:8545 - GRAPHNODE_URL: http://graphnode:8020 - IPFS_URL: http://ipfs:5001 - VOUCHER_HUB_ADDRESS: '0x3137B6DF4f36D338b82260eDBB2E7bab034AFEda' - VOUCHER_HUB_START_BLOCK: $BELLECOUR_FORK_BLOCK - depends_on: - bellecour-fork: - condition: service_healthy - graphnode: - condition: service_healthy - ipfs: - condition: service_healthy - stack-ready: image: bash command: - echo "all services ready" depends_on: - bellecour-fork: + arbitrum-sepolia-fork: condition: service_healthy graphnode: condition: service_healthy @@ -251,5 +248,5 @@ services: condition: service_started dataprotector-subgraph-deployer: condition: service_completed_successfully - voucher-subgraph-deployer: - condition: service_completed_successfully + compass-arbitrum-sepolia: + condition: service_healthy diff --git a/tests/e2e/sendTelegram.test.ts b/tests/e2e/sendTelegram.test.ts index 7001667..bbafe6f 100644 --- a/tests/e2e/sendTelegram.test.ts +++ b/tests/e2e/sendTelegram.test.ts @@ -5,24 +5,17 @@ import { } from '@iexec/dataprotector'; import { beforeAll, describe, expect, it } from '@jest/globals'; import { HDNodeWallet } from 'ethers'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; import { IExecWeb3telegram, WorkflowError as Web3TelegramWorkflowError, } from '../../src/index.js'; import { MAX_EXPECTED_BLOCKTIME, - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, MAX_EXPECTED_WEB2_SERVICES_TIME, TEST_CHAIN, - addVoucherEligibleAsset, + TEST_WEB3TELEGRAM_DAPP_ADDRESS, createAndPublishAppOrders, createAndPublishWorkerpoolOrder, - createVoucher, - createVoucherType, ensureSufficientStake, getRandomWallet, getTestConfig, @@ -41,14 +34,11 @@ describe('web3telegram.sendTelegram()', () => { let validProtectedData: ProtectedDataWithSecretProps; let invalidProtectedData: ProtectedDataWithSecretProps; let consumerIExecInstance: IExec; - let prodWorkerpoolAddress: string; let learnProdWorkerpoolAddress: string; const iexecOptions = getTestIExecOption(); const prodWorkerpoolPublicPrice = 1000; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); beforeAll(async () => { - // (default) prod workerpool (not free) always available await createAndPublishWorkerpoolOrder( TEST_CHAIN.prodWorkerpool, TEST_CHAIN.prodWorkerpoolOwnerWallet, @@ -56,15 +46,13 @@ describe('web3telegram.sendTelegram()', () => { 1_000, prodWorkerpoolPublicPrice ); - // learn prod pool (free) assumed always available await createAndPublishWorkerpoolOrder( - TEST_CHAIN.learnProdWorkerpool, - TEST_CHAIN.learnProdWorkerpoolOwnerWallet, + TEST_CHAIN.prodWorkerpool, + TEST_CHAIN.prodWorkerpoolOwnerWallet, NULL_ADDRESS, 0, 10_000 ); - // apporder always available providerWallet = getRandomWallet(); const ethProvider = getTestWeb3SignerProvider( TEST_CHAIN.appOwnerWallet.privateKey @@ -72,17 +60,11 @@ describe('web3telegram.sendTelegram()', () => { const resourceProvider = new IExec({ ethProvider }, iexecOptions); await createAndPublishAppOrders( resourceProvider, - defaultConfig!.dappAddress + TEST_WEB3TELEGRAM_DAPP_ADDRESS ); - learnProdWorkerpoolAddress = await resourceProvider.ens.resolveName( - TEST_CHAIN.learnProdWorkerpool - ); - prodWorkerpoolAddress = await resourceProvider.ens.resolveName( - TEST_CHAIN.prodWorkerpool - ); + learnProdWorkerpoolAddress = TEST_CHAIN.prodWorkerpool; - //create valid protected data dataProtector = new IExecDataProtectorCore( ...getTestConfig(providerWallet.privateKey) ); @@ -90,7 +72,6 @@ describe('web3telegram.sendTelegram()', () => { data: { telegram_chatId: '12345' }, name: 'test do not use', }); - //create invalid protected data invalidProtectedData = await dataProtector.protectData({ data: { foo: 'bar' }, name: 'test do not use', @@ -99,7 +80,6 @@ describe('web3telegram.sendTelegram()', () => { }, 4 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME + 5_000); beforeEach(async () => { - // use a fresh wallet for calling sendTelegram consumerWallet = getRandomWallet(); const consumerEthProvider = getTestWeb3SignerProvider( consumerWallet.privateKey @@ -109,9 +89,9 @@ describe('web3telegram.sendTelegram()', () => { iexecOptions ); await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: validProtectedData.address, - authorizedUser: consumerWallet.address, // consumer wallet + authorizedUser: consumerWallet.address, numberOfAccess: 1000, }); web3telegram = new IExecWeb3telegram( @@ -218,7 +198,6 @@ describe('web3telegram.sendTelegram()', () => { it( 'should fail if there is no Dataset order found', async () => { - //create valid protected data with blank order to not have: datasetorder is fully consumed error from iexec sdk const protectedData = await dataProtector.protectData({ data: { telegram_chatId: '12345' }, name: 'test do not use', @@ -244,7 +223,6 @@ describe('web3telegram.sendTelegram()', () => { it( 'should throw a protocol error id a service is not available', async () => { - // Call getTestConfig to get the default configuration const [ethProvider, defaultOptions] = getTestConfig( providerWallet.privateKey ); @@ -257,7 +235,6 @@ describe('web3telegram.sendTelegram()', () => { }, }; - // Pass the modified options to IExecWeb3telegram const invalidWeb3telegram = new IExecWeb3telegram(ethProvider, options); let error: Web3TelegramWorkflowError | undefined; @@ -299,17 +276,15 @@ describe('web3telegram.sendTelegram()', () => { it( 'should successfully send telegram with granted access to whitelist address', async () => { - //create valid protected data const protectedDataForWhitelist = await dataProtector.protectData({ data: { telegram_chatId: '1461320872' }, name: 'test do not use', }); await waitSubgraphIndexing(); - //grant access to whitelist await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedDataForWhitelist.address, - authorizedUser: consumerWallet.address, // consumer wallet + authorizedUser: consumerWallet.address, numberOfAccess: 1000, }); @@ -327,7 +302,6 @@ describe('web3telegram.sendTelegram()', () => { 2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME ); - // TODO impliment this feature in dapp it( 'should successfully send telegram with content type html', async () => { @@ -335,7 +309,6 @@ describe('web3telegram.sendTelegram()', () => { telegramContent: '

Test html

test paragraph

', protectedData: validProtectedData.address, - // contentType: 'text/html', workerpoolAddressOrEns: learnProdWorkerpoolAddress, }); expect('taskId' in sendTelegramResponse).toBe(true); @@ -370,7 +343,7 @@ describe('web3telegram.sendTelegram()', () => { it( 'should successfully send telegram with message content size < 512 kilo-bytes', async () => { - const desiredSizeInBytes = 500000; // 500 kilo-bytes + const desiredSizeInBytes = 500000; const characterToRepeat = 'A'; const LARGE_CONTENT = characterToRepeat.repeat(desiredSizeInBytes); @@ -401,216 +374,7 @@ describe('web3telegram.sendTelegram()', () => { dealId: expect.any(String), taskId: expect.any(String), }); - // TODO check label in created deal }, 2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME ); - - describe('when useVoucher:true', () => { - it( - 'should throw error if no voucher available for the requester', - async () => { - let error; - try { - await web3telegram.sendTelegram({ - telegramContent: 'e2e telegram content for test', - protectedData: validProtectedData.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, - workerpoolMaxPrice: 1000, - useVoucher: true, - }); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - expect(error.message).toBe('Failed to sendTelegram'); - expect(error.cause).toStrictEqual( - Error( - 'Oops, it seems your wallet is not associated with any voucher. Check on https://builder.iex.ec/' - ) - ); - }, - 2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME - ); - it( - 'should throw error if workerpool is not sponsored by the voucher', - async () => { - const voucherType = await createVoucherType({ - description: 'test voucher type', - duration: 60 * 60, - }); - await createVoucher({ - owner: consumerWallet.address, - voucherType, - value: 1000, - }); - - let error; - try { - await web3telegram.sendTelegram({ - telegramContent: 'e2e telegram content for test', - protectedData: validProtectedData.address, - // workerpoolAddressOrEns: prodWorkerpoolAddress, // default - workerpoolMaxPrice: 1000, - useVoucher: true, - }); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - expect(error.message).toBe('Failed to sendTelegram'); - expect(error.cause.message).toBe( - 'Found some workerpool orders but none can be sponsored by your voucher.' - ); - }, - 2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME - ); - describe('when voucher balance covers the full workerpool price', () => { - it( - 'should create a deal for send telegram message', - async () => { - // payable workerpool - const voucherType = await createVoucherType({ - description: 'test voucher type', - duration: 60 * 60, - }); - await addVoucherEligibleAsset(prodWorkerpoolAddress, voucherType); - const voucherValue = 1000; - await createVoucher({ - owner: consumerWallet.address, - voucherType, - value: voucherValue, - }); - await waitSubgraphIndexing(); - - const sendTelegramResponse = await web3telegram.sendTelegram({ - telegramContent: 'e2e telegram content for test', - protectedData: validProtectedData.address, - // workerpoolAddressOrEns: prodWorkerpoolAddress, // default - useVoucher: true, - }); - expect(sendTelegramResponse).toStrictEqual({ - dealId: expect.any(String), - taskId: expect.any(String), - }); - }, - 2 * MAX_EXPECTED_BLOCKTIME + - MAX_EXPECTED_WEB2_SERVICES_TIME + - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME - ); - }); - - describe('when voucher balance does not cover the full workerpool price', () => { - describe('but workerpoolMaxPrice covers the non sponsored amount', () => { - it( - 'should create task if user approves the non sponsored amount', - async () => { - const voucherType = await createVoucherType({ - description: 'test voucher type', - duration: 60 * 60, - }); - await addVoucherEligibleAsset(prodWorkerpoolAddress, voucherType); - - const voucherRemainingValue = 500; - const workerpoolOrderPrice = 600; - const nonSponsoredAmount = - workerpoolOrderPrice - voucherRemainingValue; - - // voucher with balance insufficient to cover workerpool price - const [voucherAddress] = await Promise.all([ - createVoucher({ - owner: consumerWallet.address, - voucherType, - value: voucherRemainingValue, - skipOrders: true, - }), - createAndPublishWorkerpoolOrder( - TEST_CHAIN.prodWorkerpool, - TEST_CHAIN.prodWorkerpoolOwnerWallet, - consumerWallet.address, - workerpoolOrderPrice - ), - ]); - await waitSubgraphIndexing(); - await ensureSufficientStake( - consumerIExecInstance, - nonSponsoredAmount - ); - await consumerIExecInstance.account.approve( - nonSponsoredAmount, - voucherAddress - ); - - const sendTelegramResponse = await web3telegram.sendTelegram({ - telegramContent: 'e2e telegram content for test', - protectedData: validProtectedData.address, - // workerpoolAddressOrEns: prodWorkerpoolAddress, // default - workerpoolMaxPrice: nonSponsoredAmount, - useVoucher: true, - }); - expect(sendTelegramResponse).toStrictEqual({ - dealId: expect.any(String), - taskId: expect.any(String), - }); - }, - 2 * MAX_EXPECTED_BLOCKTIME + - MAX_EXPECTED_WEB2_SERVICES_TIME + - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME - ); - }); - describe('and workerpoolMaxPrice does NOT covers the non sponsored amount', () => { - it( - 'should throws an error No Workerpool order found for the desired price', - async () => { - const voucherType = await createVoucherType({ - description: 'test voucher type', - duration: 60 * 60, - }); - await addVoucherEligibleAsset(prodWorkerpoolAddress, voucherType); - - const voucherRemainingValue = 500; - const workerpoolOrderPrice = 600; - - // voucher with balance insufficient to cover workerpool price - await Promise.all([ - createVoucher({ - owner: consumerWallet.address, - voucherType, - value: voucherRemainingValue, - skipOrders: true, - }), - createAndPublishWorkerpoolOrder( - TEST_CHAIN.prodWorkerpool, - TEST_CHAIN.prodWorkerpoolOwnerWallet, - consumerWallet.address, - workerpoolOrderPrice - ), - ]); - await waitSubgraphIndexing(); - - let error; - try { - await web3telegram.sendTelegram({ - telegramContent: 'e2e telegram content for test', - protectedData: validProtectedData.address, - // workerpoolAddressOrEns: prodWorkerpoolAddress, // default - // workerpoolMaxPrice: 0, // default - useVoucher: true, - }); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - expect(error.message).toBe('Failed to sendTelegram'); - expect(error.cause.message).toBe( - `No Workerpool order found for the desired price` - ); - }, - 2 * MAX_EXPECTED_BLOCKTIME + - MAX_EXPECTED_WEB2_SERVICES_TIME + - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME - ); - }); - }); - }); }); diff --git a/tests/mock/compass/data.json b/tests/mock/compass/data.json new file mode 100644 index 0000000..cc0014d --- /dev/null +++ b/tests/mock/compass/data.json @@ -0,0 +1,24 @@ +[ + { + "chainId": "421614", + "description": "arbitrum-sepolia-fork", + "iapps": [ + { + "name": "web3telegram-tdx", + "address": "0x7f67e78a4b0A98c50333B8b72851952c396601a1" + } + ], + "workerpools": [ + { + "name": "unreachable-workerpool", + "apiUrl": "https://unreachable-workerpool.iex.ec", + "address": "0xB967057a21dc6A66A29721d96b8Aa7454B7c383F" + }, + { + "name": "workerpool-http-500", + "apiUrl": "http://localhost:5500", + "address": "0x2956f0cb779904795a5f30d3b3ea88b714c3123f" + } + ] + } +] diff --git a/tests/scripts/prepare-bellecour-fork-for-tests.js b/tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js similarity index 51% rename from tests/scripts/prepare-bellecour-fork-for-tests.js rename to tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js index 95801d9..3e445e9 100644 --- a/tests/scripts/prepare-bellecour-fork-for-tests.js +++ b/tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js @@ -1,44 +1,24 @@ import { Contract, - EnsPlugin, JsonRpcProvider, JsonRpcSigner, - Network, formatEther, - keccak256, toBeHex, } from 'ethers'; -const VOUCHER_HUB_ADDRESS = '0x3137B6DF4f36D338b82260eDBB2E7bab034AFEda'; -const TARGET_VOUCHER_MANAGER_WALLET = - '0x44cA21A3c4efE9B1A0268e2e9B2547E7d9C8f19C'; // Should be same wallet as TEST_CHAIN.voucherManagerWallet -const LEARN_WORKERPOOL_OWNER_WALLET = - '0x02D0e61355e963210d0DE382e6BA09781181bB94'; +const TARGET_POCO_ADMIN_WALLET = '0x7bd4783FDCAD405A28052a0d1f11236A741da593'; const PROD_WORKERPOOL_OWNER_WALLET = '0x1Ff6AfF580e8Ca738F76485E0914C2aCaDa7B462'; const APP_OWNER_WALLET = '0x626D65C778fB98f813C25F84249E3012B80e8d91'; -const LEARN_WORKERPOOL_ENS = 'prod-v8-learn.main.pools.iexec.eth'; -const PROD_WORKERPOOL_ENS = 'prod-v8-bellecour.main.pools.iexec.eth'; -// TODO change to prod ens when it's available -const WEB3_TELEGRAM_DAPP_ADDRESS_ENS = 'web3telegram.apps.iexec.eth'; +const PROD_WORKERPOOL = '0x2956f0cb779904795a5f30d3b3ea88b714c3123f'; +const WEB3_TELEGRAM_DAPP_ADDRESS = '0x7f67e78a4b0A98c50333B8b72851952c396601a1'; +const IEXEC_HUB_ADDRESS = '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E'; -const rpcURL = 'http://localhost:8545'; +const rpcURL = 'http://localhost:8555'; -const provider = new JsonRpcProvider( - rpcURL, - new Network('bellecour-fork', 134).attachPlugin( - new EnsPlugin('0x5f5B93fca68c9C79318d1F3868A354EE67D8c006', 134) - ), - { - pollingInterval: 1000, // speed up tests - } -); - -const LEARN_WORKERPOOL = await provider.resolveName(LEARN_WORKERPOOL_ENS); -const PROD_WORKERPOOL = await provider.resolveName(PROD_WORKERPOOL_ENS); -const WEB3_TELEGRAM_DAPP_ADDRESS = await provider.resolveName( - WEB3_TELEGRAM_DAPP_ADDRESS_ENS -); +const provider = new JsonRpcProvider(rpcURL, undefined, { + pollingInterval: 1000, +}); const setBalance = async (address, weiAmount) => { await fetch(rpcURL, { @@ -54,7 +34,7 @@ const setBalance = async (address, weiAmount) => { }, }); const balance = await provider.getBalance(address); - console.log(`${address} wallet balance is now ${formatEther(balance)} RLC`); + console.log(`${address} wallet balance is now ${formatEther(balance)} ETH`); }; const impersonate = async (address) => { @@ -89,106 +69,40 @@ const stopImpersonate = async (address) => { console.log(`stop impersonating ${address}`); }; -const getVoucherManagementRoles = async (targetManager) => { - const voucherHubContract = new Contract( - VOUCHER_HUB_ADDRESS, +const getIExecHubOwnership = async (hubAddress, targetOwner) => { + const iexecContract = new Contract( + hubAddress, [ { inputs: [], - name: 'defaultAdmin', - outputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], + name: 'owner', + outputs: [{ internalType: 'address', name: '', type: 'address' }], stateMutability: 'view', type: 'function', }, { inputs: [ - { - internalType: 'bytes32', - name: 'role', - type: 'bytes32', - }, - { - internalType: 'address', - name: 'account', - type: 'address', - }, + { internalType: 'address', name: 'newOwner', type: 'address' }, ], - name: 'grantRole', + name: 'transferOwnership', outputs: [], stateMutability: 'nonpayable', type: 'function', }, - { - inputs: [ - { - internalType: 'bytes32', - name: 'role', - type: 'bytes32', - }, - { - internalType: 'address', - name: 'account', - type: 'address', - }, - ], - name: 'hasRole', - outputs: [ - { - internalType: 'bool', - name: '', - type: 'bool', - }, - ], - stateMutability: 'view', - type: 'function', - }, ], provider ); - - const defaultAdmin = await voucherHubContract.defaultAdmin(); - - console.log('VoucherHub defaultAdmin:', defaultAdmin); - - await impersonate(defaultAdmin); - - const MINTER_ROLE = keccak256(Buffer.from('MINTER_ROLE')); - - const MANAGER_ROLE = keccak256(Buffer.from('MANAGER_ROLE')); - - await voucherHubContract - .connect(new JsonRpcSigner(provider, defaultAdmin)) - .grantRole(MINTER_ROLE, targetManager, { gasPrice: 0 }) + const iexecOwner = await iexecContract.owner(); + await setBalance(iexecOwner, 1n * 10n ** 18n); + await impersonate(iexecOwner); + await iexecContract + .connect(new JsonRpcSigner(provider, iexecOwner)) + .transferOwnership(targetOwner) .then((tx) => tx.wait()); + await stopImpersonate(iexecOwner); - await voucherHubContract - .connect(new JsonRpcSigner(provider, defaultAdmin)) - .grantRole(MANAGER_ROLE, targetManager, { - gasPrice: 0, - }) - .then((tx) => tx.wait()); - - await stopImpersonate(defaultAdmin); - - console.log( - `${targetManager} has role MINTER_ROLE: ${await voucherHubContract.hasRole( - MINTER_ROLE, - targetManager - )}` - ); - - console.log( - `${targetManager} has role MANAGER_ROLE: ${await voucherHubContract.hasRole( - MANAGER_ROLE, - targetManager - )}` - ); + const newOwner = await iexecContract.owner(); + console.log(`IExecHub proxy at ${hubAddress} is now owned by ${newOwner}`); }; const getIExecResourceOwnership = async (resourceAddress, targetOwner) => { @@ -263,9 +177,7 @@ const getIExecResourceOwnership = async (resourceAddress, targetOwner) => { await impersonate(resourceOwner); await resourceRegistryContract .connect(new JsonRpcSigner(provider, resourceOwner)) - .safeTransferFrom(resourceOwner, targetOwner, resourceAddress, { - gasPrice: 0, - }) + .safeTransferFrom(resourceOwner, targetOwner, resourceAddress) .then((tx) => tx.wait()); await stopImpersonate(resourceOwner); @@ -274,23 +186,15 @@ const getIExecResourceOwnership = async (resourceAddress, targetOwner) => { }; const main = async () => { - console.log(`preparing bellecour-fork at ${rpcURL}`); + console.log(`preparing arbitrum-sepolia-fork at ${rpcURL}`); - // prepare Voucher - await setBalance(TARGET_VOUCHER_MANAGER_WALLET, 1000000n * 10n ** 18n); - await getVoucherManagementRoles(TARGET_VOUCHER_MANAGER_WALLET); + await setBalance(TARGET_POCO_ADMIN_WALLET, 1000000n * 10n ** 18n); + await getIExecHubOwnership(IEXEC_HUB_ADDRESS, TARGET_POCO_ADMIN_WALLET); - // prepare workerpools - await getIExecResourceOwnership( - LEARN_WORKERPOOL, - LEARN_WORKERPOOL_OWNER_WALLET - ); await getIExecResourceOwnership( PROD_WORKERPOOL, PROD_WORKERPOOL_OWNER_WALLET ); - - // prepare web3telegram app for tests await getIExecResourceOwnership(WEB3_TELEGRAM_DAPP_ADDRESS, APP_OWNER_WALLET); }; diff --git a/tests/scripts/prepare-test-env.js b/tests/scripts/prepare-test-env.js index 7cdb445..199cc84 100644 --- a/tests/scripts/prepare-test-env.js +++ b/tests/scripts/prepare-test-env.js @@ -1,33 +1,41 @@ import { writeFileSync } from 'fs'; -const forkUrl = 'https://bellecour.iex.ec'; +const arbitrumSepoliaForkUrl = + process.env.ARBITRUM_SEPOLIA_FORK_URL || + 'https://sepolia-rollup.arbitrum.io/rpc'; -fetch(forkUrl, { +const forkBlockNumber = await fetch(arbitrumSepoliaForkUrl, { method: 'POST', body: JSON.stringify({ - jsonrpc: 2.0, + jsonrpc: '2.0', method: 'eth_blockNumber', params: [], id: 1, }), + headers: { + 'Content-Type': 'application/json', + }, }) .then((res) => res.json()) .then((jsonRes) => { - const forkBlockNumber = parseInt(jsonRes.result.substring(2), 16); - - console.log('Creating .env file for docker-compose test-stack'); - writeFileSync( - '.env', - `############ THIS FILE IS GENERATED ############ -# run "node prepare-test-env.js" to regenerate # -################################################ - -# blockchain node to use as the reference for the local fork -BELLECOUR_FORK_URL=${forkUrl} -# block number to fork from -BELLECOUR_FORK_BLOCK=${forkBlockNumber}` + console.log( + `Current block number of ${arbitrumSepoliaForkUrl} is ${JSON.stringify(jsonRes)}` ); + return parseInt(jsonRes.result.substring(2), 16); }) .catch((e) => { - throw Error(`Failed to get current block number from ${forkUrl}: ${e}`); + throw Error( + `Failed to get current block number from ${arbitrumSepoliaForkUrl}: ${e}` + ); }); + +console.log('Creating .env file for docker-compose test-stack'); +writeFileSync( + '.env', + `############ THIS FILE IS GENERATED ############ +# run "node prepare-test-env.js" to regenerate # +################################################ + +ARBITRUM_SEPOLIA_FORK_URL=${arbitrumSepoliaForkUrl} +ARBITRUM_SEPOLIA_FORK_BLOCK=${forkBlockNumber}` +); diff --git a/tests/test-utils.ts b/tests/test-utils.ts index c6d0806..9700c40 100644 --- a/tests/test-utils.ts +++ b/tests/test-utils.ts @@ -1,42 +1,45 @@ -import { Wallet, JsonRpcProvider, ethers, Contract } from 'ethers'; +import { + Wallet, + JsonRpcProvider, + ethers, + Contract, + keccak256, + AbiCoder, + toBeHex, +} from 'ethers'; import { type Web3TelegramConfigOptions, type Web3SignerProvider, } from '../src/web3telegram/types.js'; import { IExec, utils } from 'iexec'; import { randomInt } from 'crypto'; -import { getSignerFromPrivateKey } from 'iexec/utils'; + +/** Production web3telegram TDX app on Arbitrum Sepolia (fork inherits deployment). */ +export const TEST_WEB3TELEGRAM_DAPP_ADDRESS = + '0x7f67e78a4b0A98c50333B8b72851952c396601a1'; export const TEST_CHAIN = { ipfsGateway: 'http://127.0.0.1:8080', ipfsNode: 'http://127.0.0.1:5001', - rpcURL: 'http://localhost:8545', - chainId: '134', - smsURL: 'http://127.0.0.1:13300', - smsDebugURL: 'http://127.0.0.1:13301', - resultProxyURL: 'http://127.0.0.1:13200', - iexecGatewayURL: 'http://127.0.0.1:3000', - voucherHubAddress: '0x3137B6DF4f36D338b82260eDBB2E7bab034AFEda', - voucherManagerWallet: new Wallet( - '0x2c906d4022cace2b3ee6c8b596564c26c4dcadddf1e949b769bcb0ad75c40c33' - ), - voucherSubgraphURL: - 'http://127.0.0.1:8000/subgraphs/name/bellecour/iexec-voucher', - learnProdWorkerpool: 'prod-v8-learn.main.pools.iexec.eth', - learnProdWorkerpoolOwnerWallet: new Wallet( - '0x800e01919eadf36f110f733decb1cc0f82e7941a748e89d7a3f76157f6654bb3' - ), - prodWorkerpool: 'prod-v8-bellecour.main.pools.iexec.eth', + rpcURL: 'http://localhost:8555', + chainId: '421614', + smsURL: 'http://127.0.0.1:13350', + smsDebugURL: 'http://127.0.0.1:13351', + resultProxyURL: 'http://127.0.0.1:13250', + iexecGatewayURL: 'http://127.0.0.1:3050', + compassURL: 'http://127.0.0.1:8069', + prodWorkerpool: '0x2956f0cb779904795a5f30d3b3ea88b714c3123f', prodWorkerpoolOwnerWallet: new Wallet( '0x6a12f56d7686e85ab0f46eb3c19cb0c75bfabf8fb04e595654fc93ad652fa7bc' ), appOwnerWallet: new Wallet( '0xa911b93e50f57c156da0b8bff2277d241bcdb9345221a3e246a99c6e7cedcde5' ), - provider: new JsonRpcProvider('http://localhost:8545', undefined, { - pollingInterval: 1000, // speed up tests + provider: new JsonRpcProvider('http://localhost:8555', 421614, { + pollingInterval: 1000, }), - hubAddress: '0x3eca1B216A7DF1C7689aEb259fFB83ADFB894E7f', + hubAddress: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E', + isNative: false, }; export const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms)); @@ -59,12 +62,6 @@ export const MAX_EXPECTED_WEB2_SERVICES_TIME = 80_000; export const MARKET_API_CALL_TIMEOUT = 2_000; -export const timeouts = { - // utils - createVoucherType: MAX_EXPECTED_BLOCKTIME * 2, - createVoucher: MAX_EXPECTED_BLOCKTIME * 4 + MARKET_API_CALL_TIMEOUT * 2, -}; - export const getTestWeb3SignerProvider = ( privateKey: string = Wallet.createRandom().privateKey ): Web3SignerProvider => @@ -72,15 +69,96 @@ export const getTestWeb3SignerProvider = ( export const getTestRpcProvider = () => new JsonRpcProvider(TEST_CHAIN.rpcURL); +const anvilSetBalance = async (address: string, targetWeiBalance: bigint) => { + await fetch(TEST_CHAIN.rpcURL, { + method: 'POST', + body: JSON.stringify({ + method: 'anvil_setBalance', + params: [address, toBeHex(targetWeiBalance)], + id: 1, + jsonrpc: '2.0', + }), + headers: { + 'Content-Type': 'application/json', + }, + }); +}; + +const anvilSetNRlcTokenBalance = async ( + address: string, + targetNRlcBalance: ethers.BigNumberish +) => { + const hubContract = new Contract( + TEST_CHAIN.hubAddress, + [ + { + inputs: [], + name: 'token', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + ], + TEST_CHAIN.provider + ); + const rlcAddress = await hubContract.token(); + + const erc20StorageLocation = + '0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00'; + + const balanceSlot = keccak256( + AbiCoder.defaultAbiCoder().encode( + ['address', 'uint256'], + [address, erc20StorageLocation] + ) + ); + + await fetch(TEST_CHAIN.rpcURL, { + method: 'POST', + body: JSON.stringify({ + method: 'anvil_setStorageAt', + params: [ + rlcAddress, + balanceSlot, + toBeHex(BigInt(`${targetNRlcBalance}`), 32), + ], + id: 1, + jsonrpc: '2.0', + }), + headers: { + 'Content-Type': 'application/json', + }, + }); +}; + +export const setBalance = async ( + address: string, + targetWeiBalance: ethers.BigNumberish +) => { + await anvilSetBalance(address, BigInt(`${targetWeiBalance}`)); +}; + +export const setNRlcBalance = async ( + address: string, + nRlcTargetBalance: ethers.BigNumberish +) => { + if (TEST_CHAIN.isNative) { + const weiAmount = BigInt(`${nRlcTargetBalance}`) * 10n ** 9n; + await anvilSetBalance(address, weiAmount); + return; + } + await anvilSetNRlcTokenBalance(address, nRlcTargetBalance); +}; + export const getTestIExecOption = () => ({ smsURL: TEST_CHAIN.smsURL, smsDebugURL: TEST_CHAIN.smsDebugURL, resultProxyURL: TEST_CHAIN.resultProxyURL, iexecGatewayURL: TEST_CHAIN.iexecGatewayURL, - voucherHubAddress: TEST_CHAIN.voucherHubAddress, - voucherSubgraphURL: TEST_CHAIN.voucherSubgraphURL, ipfsGatewayURL: TEST_CHAIN.ipfsGateway, ipfsNodeURL: TEST_CHAIN.ipfsNode, + compassURL: TEST_CHAIN.compassURL, + hubAddress: TEST_CHAIN.hubAddress, }); export const getTestConfig = ( @@ -90,6 +168,7 @@ export const getTestConfig = ( ? getTestWeb3SignerProvider(privateKey) : undefined; const options = { + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, iexecOptions: getTestIExecOption(), ipfsGateway: 'http://127.0.0.1:8080', ipfsNode: 'http://127.0.0.1:5001', @@ -135,7 +214,6 @@ export const createAndPublishAppOrders = async ( resourceProvider, appAddressOrEns ) => { - // Resolve ENS name to address if needed let appAddress = appAddressOrEns; if (appAddressOrEns && appAddressOrEns.includes('.eth')) { appAddress = await resourceProvider.ens.resolveName(appAddressOrEns); @@ -147,7 +225,7 @@ export const createAndPublishAppOrders = async ( await resourceProvider.order .createApporder({ app: appAddress, - tag: ['tee', 'scone'], + tag: ['tee', 'tdx'], volume: 100, appprice: 0, }) @@ -155,98 +233,6 @@ export const createAndPublishAppOrders = async ( .then(resourceProvider.order.publishApporder); }; -export const setBalance = async ( - address: string, - targetWeiBalance: ethers.BigNumberish -) => { - await fetch(TEST_CHAIN.rpcURL, { - method: 'POST', - body: JSON.stringify({ - method: 'anvil_setBalance', - params: [address, ethers.toBeHex(targetWeiBalance)], - id: 1, - jsonrpc: '2.0', - }), - headers: { - 'Content-Type': 'application/json', - }, - }); -}; - -export const setNRlcBalance = async ( - address: string, - nRlcTargetBalance: ethers.BigNumberish -) => { - const weiAmount = BigInt(`${nRlcTargetBalance}`) * 10n ** 9n; // 1 nRLC is 10^9 wei - await setBalance(address, weiAmount); -}; - -export const createVoucherType = async ({ - description = 'test', - duration = 1000, -} = {}) => { - const VOUCHER_HUB_ABI = [ - { - inputs: [ - { - internalType: 'string', - name: 'description', - type: 'string', - }, - { - internalType: 'uint256', - name: 'duration', - type: 'uint256', - }, - ], - name: 'createVoucherType', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: 'uint256', - name: 'id', - type: 'uint256', - }, - { - indexed: false, - internalType: 'string', - name: 'description', - type: 'string', - }, - { - indexed: false, - internalType: 'uint256', - name: 'duration', - type: 'uint256', - }, - ], - name: 'VoucherTypeCreated', - type: 'event', - }, - ]; - const voucherHubContract = new Contract( - TEST_CHAIN.voucherHubAddress, - VOUCHER_HUB_ABI, - TEST_CHAIN.provider - ) as any; - const signer = TEST_CHAIN.voucherManagerWallet.connect(TEST_CHAIN.provider); - const createVoucherTypeTxHash = await voucherHubContract - .connect(signer) - .createVoucherType(description, duration); - const txReceipt = await createVoucherTypeTxHash.wait(); - const { id } = getEventFromLogs('VoucherTypeCreated', txReceipt.logs, { - strict: true, - }).args; - - return id as bigint; -}; - export const ensureSufficientStake = async ( iexec: IExec, requiredStake: ethers.BigNumberish @@ -282,199 +268,14 @@ export const createAndPublishWorkerpoolOrder = async ( requesterrestrict, volume, workerpoolprice, - tag: ['tee', 'scone'], + tag: ['tee', 'tdx'], }); await iexec.order .signWorkerpoolorder(workerpoolorder) .then((o) => iexec.order.publishWorkerpoolorder(o)); } catch (error) { - // In test environment, workerpools might not exist, so we skip the order creation console.warn( `Skipping workerpool order creation for ${workerpool}: ${error.message}` ); } }; - -export const WORKERPOOL_ORDER_PER_VOUCHER = 1000; - -export const createVoucher = async ({ - owner, - voucherType, - value, - skipOrders = false, -}: { - owner: string; - voucherType: ethers.BigNumberish; - value: ethers.BigNumberish; - skipOrders?: boolean; -}) => { - const VOUCHER_HUB_ABI = [ - { - inputs: [ - { - internalType: 'address', - name: 'owner', - type: 'address', - }, - { - internalType: 'uint256', - name: 'voucherType', - type: 'uint256', - }, - { - internalType: 'uint256', - name: 'value', - type: 'uint256', - }, - ], - name: 'createVoucher', - outputs: [ - { - internalType: 'address', - name: 'voucherAddress', - type: 'address', - }, - ], - stateMutability: 'nonpayable', - type: 'function', - }, - { - inputs: [ - { - internalType: 'address', - name: 'account', - type: 'address', - }, - ], - name: 'getVoucher', - outputs: [ - { - internalType: 'address', - name: '', - type: 'address', - }, - ], - stateMutability: 'view', - type: 'function', - }, - ]; - - const iexec = new IExec( - { - ethProvider: getSignerFromPrivateKey( - TEST_CHAIN.rpcURL, - TEST_CHAIN.voucherManagerWallet.privateKey - ), - }, - { hubAddress: TEST_CHAIN.hubAddress } - ); - - // ensure RLC balance - await setNRlcBalance(await iexec.wallet.getAddress(), value); - - // deposit RLC to voucherHub - const contractClient = await iexec.config.resolveContractsClient(); - const iexecContract = contractClient.getIExecContract(); - - try { - await iexecContract.depositFor(TEST_CHAIN.voucherHubAddress, { - value: BigInt(value) * 10n ** 9n, - gasPrice: 0, - }); - } catch (error) { - console.error('Error depositing RLC:', error); - throw error; - } - - const voucherHubContract = new Contract( - TEST_CHAIN.voucherHubAddress, - VOUCHER_HUB_ABI, - TEST_CHAIN.provider - ) as any; - - const signer = TEST_CHAIN.voucherManagerWallet.connect(TEST_CHAIN.provider); - - try { - const createVoucherTxHash = await voucherHubContract - .connect(signer) - .createVoucher(owner, voucherType, value); - - await createVoucherTxHash.wait(); - } catch (error) { - console.error('Error creating voucher:', error); - throw error; - } - - if (!skipOrders) { - try { - const workerpoolprice = Math.floor( - Number(value) / WORKERPOOL_ORDER_PER_VOUCHER - ); - await createAndPublishWorkerpoolOrder( - TEST_CHAIN.prodWorkerpool, - TEST_CHAIN.prodWorkerpoolOwnerWallet, - owner, - workerpoolprice, - WORKERPOOL_ORDER_PER_VOUCHER - ); - } catch (error) { - // In test environment, workerpool orders might fail, but we don't want to fail the voucher creation - console.warn('Error publishing workerpoolorder:', error.message); - } - } - - try { - return voucherHubContract.getVoucher(owner); - } catch (error) { - console.error('Error getting voucher:', error); - throw error; - } -}; - -export const addVoucherEligibleAsset = async (assetAddress, voucherTypeId) => { - const voucherHubContract = new Contract(TEST_CHAIN.voucherHubAddress, [ - { - inputs: [ - { - internalType: 'uint256', - name: 'voucherTypeId', - type: 'uint256', - }, - { - internalType: 'address', - name: 'asset', - type: 'address', - }, - ], - name: 'addEligibleAsset', - outputs: [], - stateMutability: 'nonpayable', - type: 'function', - }, - ]) as any; - - const signer = TEST_CHAIN.voucherManagerWallet.connect(TEST_CHAIN.provider); - - const retryableAddEligibleAsset = async (tryCount = 1) => { - try { - const tx = await voucherHubContract - .connect(signer) - .addEligibleAsset(voucherTypeId, assetAddress); - await tx.wait(); - } catch (error) { - console.warn( - `Error adding eligible asset to voucher (try count ${tryCount}):`, - error - ); - if (tryCount < 3) { - await sleep(3000 * tryCount); - await retryableAddEligibleAsset(tryCount + 1); - } else { - throw new Error( - `Failed to add eligible asset to voucher after ${tryCount} attempts` - ); - } - } - }; - await retryableAddEligibleAsset(); -}; diff --git a/tests/unit/fetchMyContacts.test.ts b/tests/unit/fetchMyContacts.test.ts index 3fa88ca..18d177c 100644 --- a/tests/unit/fetchMyContacts.test.ts +++ b/tests/unit/fetchMyContacts.test.ts @@ -5,7 +5,10 @@ import { getChainDefaultConfig, } from '../../src/config/config.js'; import { type FetchMyContacts } from '../../src/web3telegram/fetchMyContacts.js'; -import { getRandomAddress } from '../test-utils.js'; +import { + getRandomAddress, + TEST_WEB3TELEGRAM_DAPP_ADDRESS, +} from '../test-utils.js'; jest.unstable_mockModule('../../src/utils/subgraphQuery.js', () => ({ getValidContact: jest.fn(), @@ -36,7 +39,7 @@ describe('fetchMyContacts', () => { }, orderHash: '0x396392835c2cbe933023dd28a3d6eedceb21c52b1dba199835a6f24cc75e7685', - chainId: 134, + chainId: 421614, publicationTimestamp: '2023-06-15T16:39:22.713Z', signer: '0xD52C27CC2c7D3fb5BA4440ffa825c12EA5658D60', status: 'open', @@ -79,13 +82,13 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, }); const userAddress = (await iexec.wallet.getAddress()).toLowerCase(); expect(iexec.orderbook.fetchDatasetOrderbook).toHaveBeenNthCalledWith(1, { dataset: 'any', - app: defaultConfig.dappAddress.toLowerCase(), + app: TEST_WEB3TELEGRAM_DAPP_ADDRESS.toLowerCase(), requester: userAddress, isAppStrict: true, isRequesterStrict: false, @@ -140,14 +143,14 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, isUserStrict: true, }); const userAddress = (await iexec.wallet.getAddress()).toLowerCase(); expect(iexec.orderbook.fetchDatasetOrderbook).toHaveBeenNthCalledWith(1, { dataset: 'any', - app: defaultConfig.dappAddress.toLowerCase(), + app: TEST_WEB3TELEGRAM_DAPP_ADDRESS.toLowerCase(), requester: userAddress, isAppStrict: true, isRequesterStrict: true, @@ -215,7 +218,7 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, }); @@ -262,14 +265,14 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, bulkOnly: true, }); const userAddress = (await iexec.wallet.getAddress()).toLowerCase(); expect(iexec.orderbook.fetchDatasetOrderbook).toHaveBeenNthCalledWith(1, { dataset: 'any', - app: defaultConfig.dappAddress.toLowerCase(), + app: TEST_WEB3TELEGRAM_DAPP_ADDRESS.toLowerCase(), requester: userAddress, isAppStrict: true, isRequesterStrict: false, @@ -324,14 +327,14 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, bulkOnly: false, }); const userAddress = (await iexec.wallet.getAddress()).toLowerCase(); expect(iexec.orderbook.fetchDatasetOrderbook).toHaveBeenNthCalledWith(1, { dataset: 'any', - app: defaultConfig.dappAddress.toLowerCase(), + app: TEST_WEB3TELEGRAM_DAPP_ADDRESS.toLowerCase(), requester: userAddress, isAppStrict: true, isRequesterStrict: false, @@ -386,7 +389,7 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, isUserStrict: true, bulkOnly: true, @@ -394,7 +397,7 @@ describe('fetchMyContacts', () => { const userAddress = (await iexec.wallet.getAddress()).toLowerCase(); expect(iexec.orderbook.fetchDatasetOrderbook).toHaveBeenNthCalledWith(1, { dataset: 'any', - app: defaultConfig.dappAddress.toLowerCase(), + app: TEST_WEB3TELEGRAM_DAPP_ADDRESS.toLowerCase(), requester: userAddress, isAppStrict: true, isRequesterStrict: true, diff --git a/tests/unit/sendTelegram.models.test.ts b/tests/unit/sendTelegram.models.test.ts index 5e17e04..37f8bec 100644 --- a/tests/unit/sendTelegram.models.test.ts +++ b/tests/unit/sendTelegram.models.test.ts @@ -1,260 +1,101 @@ -import { Address, BN } from 'iexec'; import { PublishedWorkerpoolorder } from 'iexec/IExecOrderbookModule'; -// import { VoucherInfo } from 'iexec/IExecVoucherModule'; - import { getRandomAddress } from '../test-utils.js'; -import { - checkUserVoucher, - filterWorkerpoolOrders, -} from '../../src/utils/sendTelegram.models.js'; - -// To import from 'iexec' once exported -type VoucherInfo = { - owner: Address; - address: Address; - type: BN; - balance: BN; - expirationTimestamp: BN; - sponsoredApps: Address[]; - sponsoredDatasets: Address[]; - sponsoredWorkerpools: Address[]; - allowanceAmount: BN; - authorizedAccounts: Address[]; -}; +import { filterWorkerpoolOrders } from '../../src/utils/sendTelegram.models.js'; describe('sendTelegram.models', () => { - describe('checkUserVoucher', () => { - describe('When voucher is expired', () => { - it('should throw an Error with the correct message', async () => { - // --- GIVEN - const userVoucher = { - expirationTimestamp: Date.now() / 1000 - 60, // Expired 1min ago - } as unknown as VoucherInfo; - - expect(() => - checkUserVoucher({ - userVoucher, - }) - ).toThrow( - new Error( - 'Oops, it seems your voucher has expired. You might want to ask for a top up. Check on https://builder.iex.ec/' - ) - ); - }); - }); - - describe('When voucher has a balance equals to 0', () => { - it('should throw an Error with the correct message', async () => { - // --- GIVEN - const userVoucher = { - expirationTimestamp: Date.now() / 1000 + 3600, // Will expire in 1h - balance: 0, - } as unknown as VoucherInfo; - - expect(() => - checkUserVoucher({ - userVoucher, - }) - ).toThrow( - new Error( - 'Oops, it seems your voucher is empty. You might want to ask for a top up. Check on https://builder.iex.ec/' - ) - ); - }); - }); - }); - describe('filterWorkerpoolOrders()', () => { describe('When workerpool orders is an empty array', () => { it('should answer with null', () => { - // --- GIVEN const workerpoolOrders = []; - // --- WHEN const foundOrder = filterWorkerpoolOrders({ workerpoolOrders, workerpoolMaxPrice: 0, - useVoucher: false, - userVoucher: undefined, }); - // --- THEN expect(foundOrder).toBeNull(); }); }); - describe('useVoucher === false', () => { - describe('When all orders are too expensive', () => { - it('should answer with null', () => { - // --- GIVEN - const workerpoolOrders = [ - { - order: { - workerpoolprice: 1, - }, + describe('When all orders are too expensive', () => { + it('should answer with null', () => { + const workerpoolOrders = [ + { + order: { + workerpoolprice: 1, }, - { - order: { - workerpoolprice: 2, - }, + }, + { + order: { + workerpoolprice: 2, }, - ] as PublishedWorkerpoolorder[]; + }, + ] as PublishedWorkerpoolorder[]; - // --- WHEN - const foundOrder = filterWorkerpoolOrders({ - workerpoolOrders, - workerpoolMaxPrice: 0, // <-- I want a free workerpool order - useVoucher: false, - userVoucher: undefined, - }); - - // --- THEN - expect(foundOrder).toBeNull(); + const foundOrder = filterWorkerpoolOrders({ + workerpoolOrders, + workerpoolMaxPrice: 0, }); - }); - describe('When one order is cheap enough', () => { - it('should answer with it', () => { - // --- GIVEN - const workerpoolOrders = [ - { - order: { - workerpoolprice: 1, - }, - }, - { - order: { - workerpoolprice: 2, - }, - }, - ] as PublishedWorkerpoolorder[]; - - // --- WHEN - const foundOrder = filterWorkerpoolOrders({ - workerpoolOrders, - workerpoolMaxPrice: 1, - useVoucher: false, - }); - - // --- THEN - expect(foundOrder).toBeTruthy(); - expect(foundOrder.workerpoolprice).toBe(1); - }); + expect(foundOrder).toBeNull(); }); }); - describe('useVoucher === true', () => { - describe('When there are workerpool orders but workerpool is NOT included in the voucher sponsored workerpools', () => { - it('should answer with null', () => { - // --- GIVEN - const userVoucher = { - balance: 4, // Technically it should be a BN - sponsoredWorkerpools: [getRandomAddress()], - } as unknown as VoucherInfo; - const workerpoolOrders = [ - { - order: { - workerpoolprice: 3, - workerpool: getRandomAddress(), - }, + describe('When one order is cheap enough', () => { + it('should answer with it', () => { + const workerpoolOrders = [ + { + order: { + workerpoolprice: 1, }, - { - order: { - workerpoolprice: 1, - workerpool: getRandomAddress(), - }, + }, + { + order: { + workerpoolprice: 2, }, - ] as PublishedWorkerpoolorder[]; + }, + ] as PublishedWorkerpoolorder[]; - expect(() => - filterWorkerpoolOrders({ - workerpoolOrders, - workerpoolMaxPrice: 0, - useVoucher: true, - userVoucher, - }) - ).toThrow( - new Error( - 'Found some workerpool orders but none can be sponsored by your voucher.' - ) - ); + const foundOrder = filterWorkerpoolOrders({ + workerpoolOrders, + workerpoolMaxPrice: 1, }); + + expect(foundOrder).toBeTruthy(); + expect(foundOrder!.workerpoolprice).toBe(1); }); + }); - describe('When voucher balance is greater than asked maxPrice', () => { - it('should answer with the cheapest sponsored order', () => { - // --- GIVEN - const userVoucher = { - balance: 4, // Technically it should be a BN - sponsoredWorkerpools: [ - '0x3779Da315D935D3E3957561667236BF6859C1b0E', - ], - } as unknown as VoucherInfo; - const workerpoolOrders = [ - { - order: { - workerpoolprice: 3, - workerpool: '0x3779Da315D935D3E3957561667236BF6859C1b0E', - }, + describe('When multiple sponsored pools exist', () => { + it('should pick the cheapest eligible order', () => { + const workerpoolOrders = [ + { + order: { + workerpoolprice: 3, + workerpool: '0x3779Da315D935D3E3957561667236BF6859C1b0E', }, - { - order: { - workerpoolprice: 1, - workerpool: '0x3779Da315D935D3E3957561667236BF6859C1b0E', - }, + }, + { + order: { + workerpoolprice: 1, + workerpool: '0x3779Da315D935D3E3957561667236BF6859C1b0E', }, - { - order: { - workerpoolprice: 0, - workerpool: getRandomAddress(), - }, + }, + { + order: { + workerpoolprice: 0, + workerpool: getRandomAddress(), }, - ] as PublishedWorkerpoolorder[]; + }, + ] as PublishedWorkerpoolorder[]; - // --- WHEN - const foundOrder = filterWorkerpoolOrders({ - workerpoolOrders, - workerpoolMaxPrice: 0, - useVoucher: true, - userVoucher, - }); - - // --- THEN - expect(foundOrder).toBeTruthy(); - expect(foundOrder.workerpoolprice).toBe(1); + const foundOrder = filterWorkerpoolOrders({ + workerpoolOrders, + workerpoolMaxPrice: 2, }); - }); - describe('When voucher balance is not enough but user wants to pay the rest (workerpoolMaxPrice)', () => { - it('should answer with the cheapest order', () => { - // --- GIVEN - const userVoucher = { - balance: 2, // Technically it should be a BN - sponsoredWorkerpools: [ - '0x3779Da315D935D3E3957561667236BF6859C1b0E', - ], - } as unknown as VoucherInfo; - const workerpoolOrders = [ - { - order: { - workerpoolprice: 3, - workerpool: '0x3779Da315D935D3E3957561667236BF6859C1b0E', - }, - }, - ] as PublishedWorkerpoolorder[]; - - // --- WHEN - const foundOrder = filterWorkerpoolOrders({ - workerpoolOrders, - workerpoolMaxPrice: 1, - useVoucher: true, - userVoucher, - }); - - // --- THEN - expect(foundOrder).toBeTruthy(); - expect(foundOrder.workerpoolprice).toBe(3); - }); + expect(foundOrder).toBeTruthy(); + expect(foundOrder!.workerpoolprice).toBe(0); }); }); }); diff --git a/tests/unit/sendTelegram.test.ts b/tests/unit/sendTelegram.test.ts index c12f62f..87054ba 100644 --- a/tests/unit/sendTelegram.test.ts +++ b/tests/unit/sendTelegram.test.ts @@ -1,6 +1,9 @@ import { expect, it, jest } from '@jest/globals'; import { type SendTelegram } from '../../src/web3telegram/sendTelegram.js'; -import { getRandomAddress } from '../test-utils.js'; +import { + getRandomAddress, + TEST_WEB3TELEGRAM_DAPP_ADDRESS, +} from '../test-utils.js'; import { DEFAULT_CHAIN_ID, getChainDefaultConfig, @@ -44,7 +47,7 @@ describe('sendTelegram', () => { graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -77,7 +80,7 @@ describe('sendTelegram', () => { graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -110,7 +113,7 @@ describe('sendTelegram', () => { graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -142,7 +145,7 @@ describe('sendTelegram', () => { graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -176,7 +179,7 @@ describe('sendTelegram', () => { graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -215,7 +218,7 @@ describe('sendTelegram', () => { graphQLClient: { request: jest.fn() } as any, iexec, workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: defaultConfig.dappAddress, + dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -229,7 +232,7 @@ describe('sendTelegram', () => { 1, { workerpool: defaultConfig.prodWorkerpoolAddress, - app: defaultConfig.dappAddress.toLowerCase(), + app: TEST_WEB3TELEGRAM_DAPP_ADDRESS.toLowerCase(), dataset: protectedData, requester: userAddress, isRequesterStrict: false, diff --git a/tests/unit/utils/filterWorkerpoolOrders.test.ts b/tests/unit/utils/filterWorkerpoolOrders.test.ts index 5e55001..dc7aa48 100644 --- a/tests/unit/utils/filterWorkerpoolOrders.test.ts +++ b/tests/unit/utils/filterWorkerpoolOrders.test.ts @@ -7,7 +7,6 @@ describe('filterWorkerpoolOrders', () => { filterWorkerpoolOrders({ workerpoolOrders: [], workerpoolMaxPrice: 100, - useVoucher: false, }) ).toBeNull(); }); @@ -41,7 +40,6 @@ describe('filterWorkerpoolOrders', () => { filterWorkerpoolOrders({ workerpoolOrders: orders, workerpoolMaxPrice: 100, - useVoucher: false, }) ).toEqual(orders[0].order); }); @@ -75,7 +73,6 @@ describe('filterWorkerpoolOrders', () => { filterWorkerpoolOrders({ workerpoolOrders: orders, workerpoolMaxPrice: 100, - useVoucher: false, }) ).toBeNull(); }); @@ -151,7 +148,6 @@ describe('filterWorkerpoolOrders', () => { filterWorkerpoolOrders({ workerpoolOrders: orders, workerpoolMaxPrice: 100, - useVoucher: false, }) ).toEqual(orders[1].order); // the cheapest }); @@ -227,7 +223,6 @@ describe('filterWorkerpoolOrders', () => { filterWorkerpoolOrders({ workerpoolOrders: orders, workerpoolMaxPrice: 100, - useVoucher: false, }) ).toBeNull(); }); @@ -303,7 +298,6 @@ describe('filterWorkerpoolOrders', () => { filterWorkerpoolOrders({ workerpoolOrders: orders, workerpoolMaxPrice: 100, - useVoucher: false, }) ).toEqual(orders[1].order); }); From 7b5638aba7778f57b964a6f2954a648300d92b75 Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:08:27 +0200 Subject: [PATCH 2/9] test: align test docker-compose with web3mail and fix e2e suite --- tests/docker-compose.yml | 559 ++++++++++-------- tests/e2e/fetchMyContacts.test.ts | 29 +- tests/e2e/fetchUserContacts.test.ts | 31 +- tests/e2e/prepareTelegramCampaign.test.ts | 49 +- tests/e2e/sendTelegram.test.ts | 57 +- tests/e2e/sendTelegramCampaign.test.ts | 18 +- tests/mock/compass/data.json | 2 +- tests/mock/server/http500.nginx.conf | 6 + ...prepare-arbitrum-sepolia-fork-for-tests.js | 17 +- tests/scripts/prepare-test-env.js | 5 +- tests/test-utils.ts | 82 ++- 11 files changed, 507 insertions(+), 348 deletions(-) create mode 100644 tests/mock/server/http500.nginx.conf diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index d06f63b..ed688c6 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -1,252 +1,307 @@ -services: - arbitrum-sepolia-fork: - restart: 'no' - image: ghcr.io/foundry-rs/foundry:v1.0.0 - entrypoint: anvil - command: '--host 0.0.0.0 --port 8545 --block-time 1 --fork-url $ARBITRUM_SEPOLIA_FORK_URL --fork-block-number $ARBITRUM_SEPOLIA_FORK_BLOCK --chain-id 421614' - expose: - - 8545 - ports: - - 8555:8545 - healthcheck: - test: (echo >/dev/tcp/$(hostname)/8545) &>/dev/null - interval: 30s - timeout: 5s - retries: 3 - start_period: 90s - - sms: - image: iexechub/iexec-sms:8.7.0 - restart: unless-stopped - environment: - JAVA_TOOL_OPTIONS: '-Xmx256M' - IEXEC_SMS_BLOCKCHAIN_NODE_ADDRESS: http://arbitrum-sepolia-fork:8545 - IEXEC_HUB_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' - IEXEC_SMS_TEE_RUNTIME_FRAMEWORK: tdx - IEXEC_SMS_IMAGE_LAS_IMAGE: 'las-image' - IEXEC_TEE_WORKER_PRE_COMPUTE_IMAGE: 'pre-compute-image' - IEXEC_TEE_WORKER_PRE_COMPUTE_FINGERPRINT: 'pre-compute-fingerprint' - IEXEC_TEE_WORKER_POST_COMPUTE_IMAGE: 'post-compute-image' - IEXEC_TEE_WORKER_POST_COMPUTE_FINGERPRINT: 'post-compute-fingerprint' - ports: - - 13350:13300 - healthcheck: - test: curl -f localhost:13300/actuator/health || exit 1 - depends_on: - arbitrum-sepolia-fork: - condition: service_healthy - - result-proxy: - image: iexechub/iexec-result-proxy:7.1.0 - restart: unless-stopped - environment: - IEXEC_PRIVATE_CHAIN_ADDRESS: http://arbitrum-sepolia-fork:8545 - IEXEC_PUBLIC_CHAIN_ADDRESS: http://arbitrum-sepolia-fork:8545 - IEXEC_HUB_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' - MONGO_HOST: result-proxy-mongo - MONGO_PORT: 13202 - IEXEC_IPFS_HOST: ipfs - ports: - - 13250:13200 - depends_on: - arbitrum-sepolia-fork: - condition: service_healthy - result-proxy-mongo: - condition: service_started - ipfs: - condition: service_started - - result-proxy-mongo: - restart: unless-stopped - image: library/mongo:4.2 - entrypoint: '/bin/bash' - command: -c "mongod --bind_ip_all --port 13202" - expose: - - 13202 - - ipfs: - restart: unless-stopped - image: ipfs/go-ipfs:v0.9.1 - expose: - - 8080 - - 5001 - ports: - - 8080:8080 - - 5001:5001 - healthcheck: - test: nc -z 0.0.0.0 8080 && nc -z 0.0.0.0 5001 - interval: 10s - timeout: 5s - retries: 3 - start_period: 30s - - market-mongo: - image: mongo:6.0.3 - restart: unless-stopped - expose: - - 27017 - ports: - - 27017:27017 - - market-redis: - image: redis:7.0.7-alpine - restart: unless-stopped - command: redis-server --appendonly yes - expose: - - 6379 - ports: - - 6379:6379 - healthcheck: - test: nc -z 0.0.0.0 6379 - interval: 10s - timeout: 5s - retries: 3 - start_period: 30s - - market-watcher: - image: iexechub/iexec-market-watcher:7.0.1 - restart: unless-stopped - environment: - CHAIN: ARBITRUM_SEPOLIA - START_BLOCK: $ARBITRUM_SEPOLIA_FORK_BLOCK - CHAIN_ID: 421614 - IEXEC_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' - IS_NATIVE: 'false' - ETH_WS_HOST: ws://arbitrum-sepolia-fork:8545 - ETH_RPC_HOST: http://arbitrum-sepolia-fork:8545 - MONGO_HOST: market-mongo - REDIS_HOST: market-redis - depends_on: - arbitrum-sepolia-fork: - condition: service_healthy - market-redis: - condition: service_healthy - market-mongo: - condition: service_started - - market-api: - image: iexechub/iexec-market-api:7.1.2 - restart: unless-stopped - ports: - - 3050:3000 - expose: - - 3000 - environment: - CHAINS: ARBITRUM_SEPOLIA_FORK - ARBITRUM_SEPOLIA_FORK_ETH_RPC_HOST: http://arbitrum-sepolia-fork:8545 - ARBITRUM_SEPOLIA_FORK_CHAIN_ID: 421614 - ARBITRUM_SEPOLIA_FORK_IS_NATIVE: 'false' - ARBITRUM_SEPOLIA_FORK_IEXEC_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' - MONGO_HOST: market-mongo - REDIS_HOST: market-redis - RATE_LIMIT_MAX: 10000 - RATE_LIMIT_PERIOD: 60000 - MAX_OPEN_ORDERS_PER_WALLET: 1000 - depends_on: - arbitrum-sepolia-fork: - condition: service_healthy - market-redis: - condition: service_healthy - market-mongo: - condition: service_started - - compass-arbitrum-sepolia: - image: iexechub/compass:v0.1.1 - restart: unless-stopped - environment: - DATA_FILE_PATH: /app/data.json - volumes: - - $PWD/mock/compass/data.json:/app/data.json:ro - ports: - - 8069:3000 - healthcheck: - test: nc -w 1 0.0.0.0 3000 - - graphnode-postgres: - image: postgres:12 - restart: unless-stopped - command: - - 'postgres' - - '-cshared_preload_libraries=pg_stat_statements' - expose: - - 5432 - environment: - POSTGRES_USER: graphnode - POSTGRES_PASSWORD: password - POSTGRES_DB: graphnode-db - POSTGRES_INITDB_ARGS: '-E UTF8 --locale=C' - healthcheck: - test: pg_isready -U graphnode -d graphnode-db - interval: 10s - timeout: 5s - retries: 3 - start_period: 30s - - graphnode: - image: graphprotocol/graph-node:v0.34.1 - restart: unless-stopped - expose: - - 8000 - - 8020 - ports: - - 8000:8000 - - 8020:8020 - - 8040:8040 - environment: - postgres_host: graphnode-postgres - postgres_port: 5432 - postgres_user: graphnode - postgres_pass: password - postgres_db: graphnode-db - ipfs: ipfs:5001 - ethereum: 'arbitrum-sepolia:http://arbitrum-sepolia-fork:8545' - GRAPH_ETHEREUM_GENESIS_BLOCK_NUMBER: $ARBITRUM_SEPOLIA_FORK_BLOCK - depends_on: - arbitrum-sepolia-fork: - condition: service_healthy - graphnode-postgres: - condition: service_healthy - ipfs: - condition: service_started - healthcheck: - test: netcat -w 1 0.0.0.0 8020 - interval: 10s - timeout: 5s - retries: 5 - start_period: 30s - - dataprotector-subgraph-deployer: - image: iexechub/dataprotector-subgraph-deployer:3.0.0 - restart: 'no' - depends_on: - graphnode: - condition: service_healthy - ipfs: - condition: service_started - environment: - ENV: prod - START_BLOCK: $ARBITRUM_SEPOLIA_FORK_BLOCK - GRAPHNODE_URL: http://graphnode:8020 - IPFS_URL: http://ipfs:5001 - - stack-ready: - image: bash - command: - - echo "all services ready" - depends_on: - arbitrum-sepolia-fork: - condition: service_healthy - graphnode: - condition: service_healthy - sms: - condition: service_healthy - market-watcher: - condition: service_started - market-api: - condition: service_started - result-proxy: - condition: service_started - dataprotector-subgraph-deployer: - condition: service_completed_successfully - compass-arbitrum-sepolia: - condition: service_healthy +services: + arbitrum-sepolia-fork: + restart: 'no' + platform: linux/amd64 + image: ghcr.io/foundry-rs/foundry:v1.0.0 + entrypoint: anvil + command: '--host 0.0.0.0 --port 8545 --block-time 1 --fork-url $ARBITRUM_SEPOLIA_FORK_URL --fork-block-number $ARBITRUM_SEPOLIA_FORK_BLOCK --chain-id 421614' + expose: + - 8545 + ports: + - 8555:8545 + healthcheck: + # check port 8545 is open without nc + test: (echo >/dev/tcp/$(hostname)/8545) &>/dev/null + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s + + unknown-chain-fork: + restart: 'no' + platform: linux/amd64 + image: ghcr.io/foundry-rs/foundry:v1.0.0 + entrypoint: anvil + command: '--host 0.0.0.0 --port 8545 --block-time 1 --fork-url $ARBITRUM_SEPOLIA_FORK_URL --fork-block-number $ARBITRUM_SEPOLIA_FORK_BLOCK --chain-id 421615' + expose: + - 8545 + ports: + - 8565:8545 + healthcheck: + # check port 8545 is open without nc + test: (echo >/dev/tcp/$(hostname)/8545) &>/dev/null + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s + + service-internal-error: + image: nginx:alpine + platform: linux/amd64 + volumes: + - $PWD/mock/server/http500.nginx.conf:/etc/nginx/conf.d/default.conf:ro + expose: + - 80 + ports: + - 5500:80 + + sms-arbitrum-sepolia: + platform: linux/amd64 + image: iexechub/iexec-sms:8.7.0 + restart: unless-stopped + environment: + JAVA_TOOL_OPTIONS: '-Xmx256M' + IEXEC_SMS_BLOCKCHAIN_NODE_ADDRESS: http://arbitrum-sepolia-fork:8545 + IEXEC_HUB_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' + IEXEC_SMS_TEE_RUNTIME_FRAMEWORK: scone + IEXEC_SMS_IMAGE_LAS_IMAGE: 'las-image' + IEXEC_TEE_WORKER_PRE_COMPUTE_IMAGE: 'pre-compute-image' + IEXEC_TEE_WORKER_PRE_COMPUTE_FINGERPRINT: 'pre-compute-fingerprint' + IEXEC_TEE_WORKER_POST_COMPUTE_IMAGE: 'post-compute-image' + IEXEC_TEE_WORKER_POST_COMPUTE_FINGERPRINT: 'post-compute-fingerprint' + ports: + - 13350:13300 + healthcheck: + test: curl -f localhost:13300/actuator/health || exit 1 + interval: 10s + timeout: 10s + retries: 10 + start_period: 120s + depends_on: + arbitrum-sepolia-fork: + condition: service_healthy + + result-proxy-arbitrum-sepolia: + platform: linux/amd64 + image: iexechub/iexec-result-proxy:7.1.0 + restart: unless-stopped + environment: + IEXEC_PRIVATE_CHAIN_ADDRESS: http://arbitrum-sepolia-fork:8545 + IEXEC_PUBLIC_CHAIN_ADDRESS: http://arbitrum-sepolia-fork:8545 + IEXEC_HUB_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' + MONGO_HOST: result-proxy-mongo + MONGO_PORT: 13202 + IEXEC_IPFS_HOST: ipfs + ports: + - 13250:13200 + depends_on: + arbitrum-sepolia-fork: + condition: service_healthy + result-proxy-mongo: + condition: service_started + ipfs: + condition: service_healthy + + result-proxy-mongo: + restart: unless-stopped + image: library/mongo:4.2 + platform: linux/amd64 + entrypoint: '/bin/bash' + command: -c "mongod --bind_ip_all --port 13202" + expose: + - 13202 + ports: + - 13202:13202 + + ipfs: + restart: unless-stopped + image: ipfs/go-ipfs:v0.9.1 + platform: linux/amd64 + expose: + - 8080 + - 5001 + ports: + - 8080:8080 + - 5001:5001 + healthcheck: + test: nc -z 0.0.0.0 8080 && nc -z 0.0.0.0 5001 + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s + + market-mongo: + image: mongo:6.0.3 + restart: unless-stopped + platform: linux/amd64 + expose: + - 27017 + ports: + - 27017:27017 + + market-redis: + image: redis:7.0.7-alpine + platform: linux/amd64 + restart: unless-stopped + command: redis-server --appendonly yes + expose: + - 6379 + ports: + - 6379:6379 + healthcheck: + test: nc -z 0.0.0.0 6379 + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s + + market-watcher-arbitrum-sepolia: + platform: linux/amd64 + image: iexechub/iexec-market-watcher:7.0.1 + restart: unless-stopped + environment: + CHAIN: ARBITRUM_SEPOLIA + START_BLOCK: $ARBITRUM_SEPOLIA_FORK_BLOCK + CHAIN_ID: 421614 + IEXEC_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' + IS_NATIVE: 'false' + ETH_WS_HOST: ws://arbitrum-sepolia-fork:8545 + ETH_RPC_HOST: http://arbitrum-sepolia-fork:8545 + MONGO_HOST: market-mongo + REDIS_HOST: market-redis + depends_on: + arbitrum-sepolia-fork: + condition: service_healthy + market-redis: + condition: service_healthy + market-mongo: + condition: service_started + + market-api-arbitrum-sepolia: + platform: linux/amd64 + image: iexechub/iexec-market-api:7.1.2 + restart: unless-stopped + ports: + - 3050:3000 + expose: + - 3000 + environment: + CHAINS: ARBITRUM_SEPOLIA_FORK + ARBITRUM_SEPOLIA_FORK_ETH_RPC_HOST: http://arbitrum-sepolia-fork:8545 + ARBITRUM_SEPOLIA_FORK_CHAIN_ID: 421614 + ARBITRUM_SEPOLIA_FORK_IS_NATIVE: 'false' + ARBITRUM_SEPOLIA_FORK_IEXEC_ADDRESS: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E' + MONGO_HOST: market-mongo + REDIS_HOST: market-redis + RATE_LIMIT_MAX: 10000 + RATE_LIMIT_PERIOD: 60000 + MAX_OPEN_ORDERS_PER_WALLET: 1000 + depends_on: + arbitrum-sepolia-fork: + condition: service_healthy + market-redis: + condition: service_healthy + market-mongo: + condition: service_started + + compass-arbitrum-sepolia: + platform: linux/amd64 + image: iexechub/compass:v0.1.1 + restart: unless-stopped + environment: + DATA_FILE_PATH: /app/data.json + volumes: + - $PWD/mock/compass/data.json:/app/data.json:ro + ports: + - 8069:3000 + healthcheck: + test: nc -w 1 0.0.0.0 3000 + + graphnode-postgres: + image: postgres:12 + platform: linux/amd64 + restart: unless-stopped + command: + - 'postgres' + - '-cshared_preload_libraries=pg_stat_statements' + expose: + - 5432 + environment: + POSTGRES_USER: graphnode + POSTGRES_PASSWORD: password + POSTGRES_DB: graphnode-db + POSTGRES_INITDB_ARGS: '-E UTF8 --locale=C' + healthcheck: + test: pg_isready -U graphnode -d graphnode-db + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s + + graphnode: + platform: linux/amd64 + image: graphprotocol/graph-node:v0.34.1 + restart: unless-stopped + expose: + - 8000 + - 8020 + ports: + - 8000:8000 + - 8020:8020 + - 8040:8040 + environment: + postgres_host: graphnode-postgres + postgres_port: 5432 + postgres_user: graphnode + postgres_pass: password + postgres_db: graphnode-db + ipfs: ipfs:5001 + # Alias arbitrum-sepolia-fork as "bellecour" so the subgraph template (hardcoded network name) works + ethereum: 'bellecour:http://arbitrum-sepolia-fork:8545' + GRAPH_ETHEREUM_GENESIS_BLOCK_NUMBER: $ARBITRUM_SEPOLIA_FORK_BLOCK + depends_on: + arbitrum-sepolia-fork: + condition: service_healthy + graphnode-postgres: + condition: service_healthy + ipfs: + condition: service_started + healthcheck: + test: netcat -w 1 0.0.0.0 8020 + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + + dataprotector-subgraph-deployer: + platform: linux/amd64 + image: iexechub/dataprotector-subgraph-deployer:3.0.0 + restart: 'no' + depends_on: + graphnode: + condition: service_healthy + ipfs: + condition: service_started + environment: + ENV: prod + START_BLOCK: $ARBITRUM_SEPOLIA_INDEX_BLOCK + DATAPROTECTOR_ADDRESS: '0x168eAF6C33a77E3caD9db892452f51a5D91df621' + APP_REGISTRY_ADDRESS: '0x9950D94FB074182eE93fF79a50CD698C4983281F' + DATASET_REGISTRY_ADDRESS: '0x07cc4E1Ea30dD02796795876509a3bfC5053128d' + GRAPHNODE_URL: http://graphnode:8020 + IPFS_URL: http://ipfs:5001 + + stack-ready: + image: bash + platform: linux/amd64 + command: + - echo "all services ready" + depends_on: + arbitrum-sepolia-fork: + condition: service_healthy + sms-arbitrum-sepolia: + condition: service_healthy + market-watcher-arbitrum-sepolia: + condition: service_started + market-api-arbitrum-sepolia: + condition: service_started + result-proxy-arbitrum-sepolia: + condition: service_started + compass-arbitrum-sepolia: + condition: service_healthy + graphnode: + condition: service_healthy + dataprotector-subgraph-deployer: + condition: service_completed_successfully + unknown-chain-fork: + condition: service_healthy diff --git a/tests/e2e/fetchMyContacts.test.ts b/tests/e2e/fetchMyContacts.test.ts index 79b33f0..4f90e19 100644 --- a/tests/e2e/fetchMyContacts.test.ts +++ b/tests/e2e/fetchMyContacts.test.ts @@ -1,21 +1,20 @@ import { describe, expect, it } from '@jest/globals'; import { IExecDataProtector } from '@iexec/dataprotector'; import { IExecWeb3telegram } from '../../src/index.js'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; -import { getTestConfig, waitSubgraphIndexing } from '../test-utils.js'; -import { HDNodeWallet, Wallet } from 'ethers'; -import { NULL_ADDRESS } from 'iexec/utils'; import { MAX_EXPECTED_BLOCKTIME, MAX_EXPECTED_WEB2_SERVICES_TIME, MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, + TEST_WEB3TELEGRAM_DAPP_ADDRESS, deployRandomDataset, - getTestWeb3SignerProvider, + getTestConfig, getTestIExecOption, + getTestWeb3SignerProvider, + setBalance, + waitSubgraphIndexing, } from '../test-utils.js'; +import { HDNodeWallet, Wallet } from 'ethers'; +import { NULL_ADDRESS } from 'iexec/utils'; import IExec from 'iexec/IExec'; describe('web3telegram.fetchMyContacts()', () => { @@ -23,10 +22,10 @@ describe('web3telegram.fetchMyContacts()', () => { let web3telegram: IExecWeb3telegram; let dataProtector: IExecDataProtector; let protectedData: any; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); beforeAll(async () => { wallet = Wallet.createRandom(); + await setBalance(wallet.address, 10n ** 18n); dataProtector = new IExecDataProtector(...getTestConfig(wallet.privateKey)); web3telegram = new IExecWeb3telegram(...getTestConfig(wallet.privateKey)); protectedData = await dataProtector.core.protectData({ @@ -40,7 +39,7 @@ describe('web3telegram.fetchMyContacts()', () => { 'pass with a granted access for a specific requester', async () => { await dataProtector.core.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedData.address, authorizedUser: wallet.address, }); @@ -65,7 +64,7 @@ describe('web3telegram.fetchMyContacts()', () => { async () => { const grantedAccessForAnyRequester = await dataProtector.core.grantAccess( { - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedData.address, authorizedUser: NULL_ADDRESS, } @@ -105,7 +104,7 @@ describe('web3telegram.fetchMyContacts()', () => { const encryptionKey = await iexec.dataset.generateEncryptionKey(); await iexec.dataset.pushDatasetSecret(dataset.address, encryptionKey); await dataProtector.core.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: dataset.address, authorizedUser: wallet.address, }); @@ -127,7 +126,7 @@ describe('web3telegram.fetchMyContacts()', () => { await waitSubgraphIndexing(); await dataProtector.core.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: notValidProtectedData.address, authorizedUser: wallet.address, }); @@ -164,7 +163,7 @@ describe('web3telegram.fetchMyContacts()', () => { async () => { // Grant access with allowBulk: true await dataProtector.core.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedDataWithBulk.address, authorizedUser: wallet.address, allowBulk: true, @@ -172,7 +171,7 @@ describe('web3telegram.fetchMyContacts()', () => { // Grant access with allowBulk: false (or default) await dataProtector.core.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedDataWithoutBulk.address, authorizedUser: wallet.address, allowBulk: false, diff --git a/tests/e2e/fetchUserContacts.test.ts b/tests/e2e/fetchUserContacts.test.ts index 99d0657..a5edbf0 100644 --- a/tests/e2e/fetchUserContacts.test.ts +++ b/tests/e2e/fetchUserContacts.test.ts @@ -13,7 +13,9 @@ import { MAX_EXPECTED_BLOCKTIME, MAX_EXPECTED_WEB2_SERVICES_TIME, MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, + TEST_WEB3TELEGRAM_DAPP_ADDRESS, getTestConfig, + setBalance, waitSubgraphIndexing, } from '../test-utils.js'; @@ -26,6 +28,7 @@ describe('web3telegram.fetchMyContacts()', () => { beforeAll(async () => { wallet = Wallet.createRandom(); + await setBalance(wallet.address, 10n ** 18n); dataProtector = new IExecDataProtectorCore( ...getTestConfig(wallet.privateKey) ); @@ -92,10 +95,10 @@ describe('web3telegram.fetchMyContacts()', () => { 'should return the user contacts for both app and whitelist', async () => { const userWithAccess = Wallet.createRandom().address; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); - expect(defaultConfig).not.toBeNull(); - const authorizedApp = defaultConfig!.dappAddress; - const authorizedWhitelist = defaultConfig!.whitelistSmartContract; + const chainConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); + expect(chainConfig).not.toBeNull(); + const authorizedApp = TEST_WEB3TELEGRAM_DAPP_ADDRESS; + const authorizedWhitelist = chainConfig!.whitelistSmartContract; await dataProtector.grantAccess({ authorizedApp: authorizedApp, @@ -123,15 +126,14 @@ describe('web3telegram.fetchMyContacts()', () => { async () => { const user1 = Wallet.createRandom().address; const user2 = Wallet.createRandom().address; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedData1.address, authorizedUser: user1, }); await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedData2.address, authorizedUser: user2, }); @@ -151,9 +153,8 @@ describe('web3telegram.fetchMyContacts()', () => { 'Test that the protected data can be accessed by authorized user', async () => { const userWithAccess = Wallet.createRandom().address; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedData1.address, authorizedUser: userWithAccess, }); @@ -212,9 +213,7 @@ describe('web3telegram.fetchMyContacts()', () => { // Call getTestConfig to get the default configuration const [ethProvider, defaultOptions] = getTestConfig(wallet.privateKey); - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); - expect(defaultConfig).not.toBeNull(); - const authorizedApp = defaultConfig!.dappAddress; + const authorizedApp = TEST_WEB3TELEGRAM_DAPP_ADDRESS; await dataProtector.grantAccess({ authorizedApp: authorizedApp, @@ -266,12 +265,8 @@ describe('web3telegram.fetchMyContacts()', () => { it( 'should return only contacts with bulk access when bulkOnly is true', async () => { - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); - expect(defaultConfig).not.toBeNull(); - - // Grant access with allowBulk: true await dataProtector.grantAccess({ - authorizedApp: defaultConfig!.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedDataWithBulk.address, authorizedUser: userWithAccess, allowBulk: true, @@ -279,7 +274,7 @@ describe('web3telegram.fetchMyContacts()', () => { // Grant access with allowBulk: false (or default) await dataProtector.grantAccess({ - authorizedApp: defaultConfig!.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: protectedDataWithoutBulk.address, authorizedUser: userWithAccess, allowBulk: false, diff --git a/tests/e2e/prepareTelegramCampaign.test.ts b/tests/e2e/prepareTelegramCampaign.test.ts index 499ffd4..6f88ea5 100644 --- a/tests/e2e/prepareTelegramCampaign.test.ts +++ b/tests/e2e/prepareTelegramCampaign.test.ts @@ -4,19 +4,25 @@ import { } from '@iexec/dataprotector'; import { beforeAll, describe, expect, it } from '@jest/globals'; import { HDNodeWallet } from 'ethers'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; import { Contact, IExecWeb3telegram } from '../../src/index.js'; import { MAX_EXPECTED_BLOCKTIME, MAX_EXPECTED_WEB2_SERVICES_TIME, MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, + TEST_CHAIN, + TEST_WEB3TELEGRAM_DAPP_ADDRESS, + createAndPublishAppOrders, + createAndPublishWorkerpoolOrder, getRandomWallet, getTestConfig, + getTestIExecOption, + getTestWeb3SignerProvider, + setBalance, + setEthForGas, waitSubgraphIndexing, } from '../test-utils.js'; +import { IExec } from 'iexec'; +import { NULL_ADDRESS } from 'iexec/utils'; describe('web3telegram.prepareTelegramCampaign()', () => { let consumerWallet: HDNodeWallet; @@ -26,17 +32,39 @@ describe('web3telegram.prepareTelegramCampaign()', () => { let validProtectedData1: ProtectedDataWithSecretProps; let validProtectedData2: ProtectedDataWithSecretProps; let validProtectedData3: ProtectedDataWithSecretProps; + const iexecOptions = getTestIExecOption(); const prodWorkerpoolPublicPrice = 1000; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); beforeAll(async () => { - // Create app orders + await createAndPublishWorkerpoolOrder( + TEST_CHAIN.prodWorkerpool, + TEST_CHAIN.prodWorkerpoolOwnerWallet, + NULL_ADDRESS, + 1_000, + prodWorkerpoolPublicPrice + ); + providerWallet = getRandomWallet(); + const resourceProvider = new IExec( + { + ethProvider: getTestWeb3SignerProvider( + TEST_CHAIN.appOwnerWallet.privateKey + ), + }, + iexecOptions + ); + await createAndPublishAppOrders( + resourceProvider, + TEST_WEB3TELEGRAM_DAPP_ADDRESS + ); + dataProtector = new IExecDataProtectorCore( ...getTestConfig(providerWallet.privateKey) ); + await setBalance(providerWallet.address, 10n ** 18n); + // create valid protected data validProtectedData1 = await dataProtector.protectData({ data: { telegram_chatId: '12345' }, @@ -54,28 +82,29 @@ describe('web3telegram.prepareTelegramCampaign()', () => { }); await waitSubgraphIndexing(); - }, 5 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME + 5_000); + }, 5 * (MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME) + MAX_EXPECTED_SUBGRAPH_INDEXING_TIME + 5_000); beforeEach(async () => { consumerWallet = getRandomWallet(); + await setEthForGas(consumerWallet.address); // Grant access with allowBulk for bulk processing await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: validProtectedData1.address, authorizedUser: consumerWallet.address, allowBulk: true, }); await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: validProtectedData2.address, authorizedUser: consumerWallet.address, allowBulk: true, }); await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: validProtectedData3.address, authorizedUser: consumerWallet.address, allowBulk: true, diff --git a/tests/e2e/sendTelegram.test.ts b/tests/e2e/sendTelegram.test.ts index bbafe6f..c7bad21 100644 --- a/tests/e2e/sendTelegram.test.ts +++ b/tests/e2e/sendTelegram.test.ts @@ -3,7 +3,7 @@ import { ProtectedDataWithSecretProps, WorkflowError, } from '@iexec/dataprotector'; -import { beforeAll, describe, expect, it } from '@jest/globals'; +import { beforeAll, beforeEach, describe, expect, it } from '@jest/globals'; import { HDNodeWallet } from 'ethers'; import { IExecWeb3telegram, @@ -17,10 +17,13 @@ import { createAndPublishAppOrders, createAndPublishWorkerpoolOrder, ensureSufficientStake, + getId, getRandomWallet, getTestConfig, getTestIExecOption, getTestWeb3SignerProvider, + setBalance, + setEthForGas, waitSubgraphIndexing, } from '../test-utils.js'; import { IExec } from 'iexec'; @@ -36,16 +39,8 @@ describe('web3telegram.sendTelegram()', () => { let consumerIExecInstance: IExec; let learnProdWorkerpoolAddress: string; const iexecOptions = getTestIExecOption(); - const prodWorkerpoolPublicPrice = 1000; beforeAll(async () => { - await createAndPublishWorkerpoolOrder( - TEST_CHAIN.prodWorkerpool, - TEST_CHAIN.prodWorkerpoolOwnerWallet, - NULL_ADDRESS, - 1_000, - prodWorkerpoolPublicPrice - ); await createAndPublishWorkerpoolOrder( TEST_CHAIN.prodWorkerpool, TEST_CHAIN.prodWorkerpoolOwnerWallet, @@ -54,6 +49,7 @@ describe('web3telegram.sendTelegram()', () => { 10_000 ); providerWallet = getRandomWallet(); + await setBalance(providerWallet.address, 10n ** 18n); const ethProvider = getTestWeb3SignerProvider( TEST_CHAIN.appOwnerWallet.privateKey ); @@ -81,6 +77,7 @@ describe('web3telegram.sendTelegram()', () => { beforeEach(async () => { consumerWallet = getRandomWallet(); + await setEthForGas(consumerWallet.address); const consumerEthProvider = getTestWeb3SignerProvider( consumerWallet.privateKey ); @@ -100,21 +97,50 @@ describe('web3telegram.sendTelegram()', () => { }); describe('when using the default (not free) prod workerpool', () => { + let paidWorkerpoolAddress: string; + const prodWorkerpoolPublicPrice = 1000; + + beforeAll(async () => { + // Deploy a fresh workerpool so it has no pre-existing free orders from the fork + await setEthForGas(TEST_CHAIN.prodWorkerpoolOwnerWallet.address); + const workerpoolOwnerEthProvider = getTestWeb3SignerProvider( + TEST_CHAIN.prodWorkerpoolOwnerWallet.privateKey + ); + const workerpoolOwnerIexec = new IExec( + { ethProvider: workerpoolOwnerEthProvider }, + iexecOptions + ); + const { address } = + await workerpoolOwnerIexec.workerpool.deployWorkerpool({ + owner: TEST_CHAIN.prodWorkerpoolOwnerWallet.address, + description: `paid test workerpool ${getId()}`, + }); + paidWorkerpoolAddress = address; + await createAndPublishWorkerpoolOrder( + paidWorkerpoolAddress, + TEST_CHAIN.prodWorkerpoolOwnerWallet, + NULL_ADDRESS, + prodWorkerpoolPublicPrice, + 10 + ); + }, 3 * MAX_EXPECTED_BLOCKTIME); + describe('when using the user does not set the workerpoolMaxPrice', () => { it( 'should throw an error No Workerpool order found for the desired price', async () => { - let error: Error; + let error!: Error; await web3telegram .sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, + workerpoolAddressOrEns: paidWorkerpoolAddress, }) .catch((e) => (error = e)); expect(error).toBeDefined(); expect(error.message).toBe('Failed to sendTelegram'); expect(error.cause).toStrictEqual( - Error(`No Workerpool order found for the desired price`) + new Error(`No Workerpool order found for the desired price`) ); }, 2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME @@ -124,18 +150,19 @@ describe('web3telegram.sendTelegram()', () => { it( `should throw an error if the user can't pay with its account`, async () => { - let error: Error; + let error!: Web3TelegramWorkflowError; await web3telegram .sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, + workerpoolAddressOrEns: paidWorkerpoolAddress, workerpoolMaxPrice: prodWorkerpoolPublicPrice, }) .catch((e) => (error = e)); expect(error).toBeInstanceOf(Web3TelegramWorkflowError); expect(error.message).toBe('Failed to sendTelegram'); expect(error.cause).toStrictEqual( - Error( + new Error( `Cost per task (${prodWorkerpoolPublicPrice}) is greater than requester account stake (0). Orders can't be matched. If you are the requester, you should deposit to top up your account` ) ); @@ -152,6 +179,7 @@ describe('web3telegram.sendTelegram()', () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, + workerpoolAddressOrEns: paidWorkerpoolAddress, workerpoolMaxPrice: prodWorkerpoolPublicPrice, }); expect(sendTelegramResponse).toStrictEqual({ @@ -213,7 +241,7 @@ describe('web3telegram.sendTelegram()', () => { ).rejects.toThrow( new WorkflowError({ message: 'Failed to sendTelegram', - errorCause: Error('No Dataset order found for the desired price'), + errorCause: new Error('No Dataset order found for the desired price'), }) ); }, @@ -322,7 +350,6 @@ describe('web3telegram.sendTelegram()', () => { it( 'should successfully send telegram with a valid senderName', - async () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', diff --git a/tests/e2e/sendTelegramCampaign.test.ts b/tests/e2e/sendTelegramCampaign.test.ts index e1fda46..09f2420 100644 --- a/tests/e2e/sendTelegramCampaign.test.ts +++ b/tests/e2e/sendTelegramCampaign.test.ts @@ -4,16 +4,13 @@ import { } from '@iexec/dataprotector'; import { beforeAll, describe, expect, it } from '@jest/globals'; import { HDNodeWallet } from 'ethers'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; import { Contact, IExecWeb3telegram } from '../../src/index.js'; import { MAX_EXPECTED_BLOCKTIME, MAX_EXPECTED_WEB2_SERVICES_TIME, MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, TEST_CHAIN, + TEST_WEB3TELEGRAM_DAPP_ADDRESS, createAndPublishAppOrders, createAndPublishWorkerpoolOrder, ensureSufficientStake, @@ -21,6 +18,8 @@ import { getTestConfig, getTestIExecOption, getTestWeb3SignerProvider, + setBalance, + setEthForGas, waitSubgraphIndexing, } from '../test-utils.js'; import { IExec } from 'iexec'; @@ -37,7 +36,6 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { let consumerIExecInstance: IExec; const iexecOptions = getTestIExecOption(); const prodWorkerpoolPublicPrice = 1000; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); beforeAll(async () => { // Create workerpool orders @@ -51,6 +49,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { // Create app orders providerWallet = getRandomWallet(); + await setBalance(providerWallet.address, 10n ** 18n); const resourceProvider = new IExec( { @@ -62,7 +61,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { ); await createAndPublishAppOrders( resourceProvider, - defaultConfig!.dappAddress + TEST_WEB3TELEGRAM_DAPP_ADDRESS ); dataProtector = new IExecDataProtectorCore( @@ -90,6 +89,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { beforeEach(async () => { consumerWallet = getRandomWallet(); + await setEthForGas(consumerWallet.address); const consumerEthProvider = getTestWeb3SignerProvider( consumerWallet.privateKey ); @@ -100,21 +100,21 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { // Grant access with allowBulk for bulk processing await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: validProtectedData1.address, authorizedUser: consumerWallet.address, allowBulk: true, }); await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: validProtectedData2.address, authorizedUser: consumerWallet.address, allowBulk: true, }); await dataProtector.grantAccess({ - authorizedApp: defaultConfig.dappAddress, + authorizedApp: TEST_WEB3TELEGRAM_DAPP_ADDRESS, protectedData: validProtectedData3.address, authorizedUser: consumerWallet.address, allowBulk: true, diff --git a/tests/mock/compass/data.json b/tests/mock/compass/data.json index cc0014d..a0f427d 100644 --- a/tests/mock/compass/data.json +++ b/tests/mock/compass/data.json @@ -4,7 +4,7 @@ "description": "arbitrum-sepolia-fork", "iapps": [ { - "name": "web3telegram-tdx", + "key": "web3telegram-tdx", "address": "0x7f67e78a4b0A98c50333B8b72851952c396601a1" } ], diff --git a/tests/mock/server/http500.nginx.conf b/tests/mock/server/http500.nginx.conf new file mode 100644 index 0000000..54751ad --- /dev/null +++ b/tests/mock/server/http500.nginx.conf @@ -0,0 +1,6 @@ +server { + listen 80; + location / { + return 500; + } +} diff --git a/tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js b/tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js index 3e445e9..87b81e3 100644 --- a/tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js +++ b/tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js @@ -2,14 +2,22 @@ import { Contract, JsonRpcProvider, JsonRpcSigner, + Wallet, formatEther, toBeHex, } from 'ethers'; +/** Must match tests/test-utils.ts prodWorkerpoolOwnerWallet / appOwnerWallet private keys. */ +const PROD_WORKERPOOL_OWNER_PK = + '0x6a12f56d7686e85ab0f46eb3c19cb0c75bfabf8fb04e595654fc93ad652fa7bc'; +const APP_OWNER_PK = + '0xa911b93e50f57c156da0b8bff2277d241bcdb9345221a3e246a99c6e7cedcde5'; + +const PROD_WORKERPOOL_OWNER_WALLET = new Wallet( + PROD_WORKERPOOL_OWNER_PK +).address; +const APP_OWNER_WALLET = new Wallet(APP_OWNER_PK).address; const TARGET_POCO_ADMIN_WALLET = '0x7bd4783FDCAD405A28052a0d1f11236A741da593'; -const PROD_WORKERPOOL_OWNER_WALLET = - '0x1Ff6AfF580e8Ca738F76485E0914C2aCaDa7B462'; -const APP_OWNER_WALLET = '0x626D65C778fB98f813C25F84249E3012B80e8d91'; const PROD_WORKERPOOL = '0x2956f0cb779904795a5f30d3b3ea88b714c3123f'; const WEB3_TELEGRAM_DAPP_ADDRESS = '0x7f67e78a4b0A98c50333B8b72851952c396601a1'; const IEXEC_HUB_ADDRESS = '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E'; @@ -196,6 +204,9 @@ const main = async () => { PROD_WORKERPOOL_OWNER_WALLET ); await getIExecResourceOwnership(WEB3_TELEGRAM_DAPP_ADDRESS, APP_OWNER_WALLET); + + await setBalance(PROD_WORKERPOOL_OWNER_WALLET, 100n * 10n ** 18n); + await setBalance(APP_OWNER_WALLET, 100n * 10n ** 18n); }; main(); diff --git a/tests/scripts/prepare-test-env.js b/tests/scripts/prepare-test-env.js index 199cc84..eafd471 100644 --- a/tests/scripts/prepare-test-env.js +++ b/tests/scripts/prepare-test-env.js @@ -37,5 +37,8 @@ writeFileSync( ################################################ ARBITRUM_SEPOLIA_FORK_URL=${arbitrumSepoliaForkUrl} -ARBITRUM_SEPOLIA_FORK_BLOCK=${forkBlockNumber}` +# block number to fork from +ARBITRUM_SEPOLIA_FORK_BLOCK=${forkBlockNumber} +# block number to index from (should be fork block + 1 to skip all existing ArbitrumInternalTxType which is not supported by a graphnode connected to anvil) +ARBITRUM_SEPOLIA_INDEX_BLOCK=${forkBlockNumber + 1}` ); diff --git a/tests/test-utils.ts b/tests/test-utils.ts index 9700c40..4f00d19 100644 --- a/tests/test-utils.ts +++ b/tests/test-utils.ts @@ -46,8 +46,64 @@ export const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms)); export const MAX_EXPECTED_SUBGRAPH_INDEXING_TIME = 5_000; -export const waitSubgraphIndexing = () => - sleep(MAX_EXPECTED_SUBGRAPH_INDEXING_TIME); +const DATAPROTECTOR_SUBGRAPH_URL = + 'http://127.0.0.1:8000/subgraphs/name/DataProtector-v2'; + +export const waitSubgraphIndexing = async ( + timeoutMs = 60_000 +): Promise => { + const provider = new JsonRpcProvider(TEST_CHAIN.rpcURL); + const targetBlock = await provider.getBlockNumber(); + + const deadline = Date.now() + timeoutMs; + while (Date.now() < deadline) { + try { + const res = await fetch(DATAPROTECTOR_SUBGRAPH_URL, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query: '{ _meta { block { number } } }' }), + }); + const json = await res.json(); + const indexedBlock: number = json?.data?._meta?.block?.number ?? 0; + if (indexedBlock >= targetBlock) return; + } catch { + // subgraph not ready yet, keep polling + } + await sleep(1_000); + } + throw new Error( + `waitSubgraphIndexing: subgraph did not index block ${targetBlock} within ${timeoutMs}ms` + ); +}; + +const anvilSetBalance = async (address: string, targetWeiBalance: bigint) => { + await fetch(TEST_CHAIN.rpcURL, { + method: 'POST', + body: JSON.stringify({ + method: 'anvil_setBalance', + params: [address, toBeHex(targetWeiBalance)], + id: 1, + jsonrpc: '2.0', + }), + headers: { + 'Content-Type': 'application/json', + }, + }); +}; + +export const setBalance = async ( + address: string, + targetWeiBalance: ethers.BigNumberish +) => { + await anvilSetBalance(address, BigInt(`${targetWeiBalance}`)); +}; + +export const setEthForGas = async ( + address: string, + wei: bigint = 10n ** 18n +) => { + await setBalance(address, wei); +}; export const getRequiredFieldMessage = (field: string = 'this') => `${field} is a required field`; @@ -69,21 +125,6 @@ export const getTestWeb3SignerProvider = ( export const getTestRpcProvider = () => new JsonRpcProvider(TEST_CHAIN.rpcURL); -const anvilSetBalance = async (address: string, targetWeiBalance: bigint) => { - await fetch(TEST_CHAIN.rpcURL, { - method: 'POST', - body: JSON.stringify({ - method: 'anvil_setBalance', - params: [address, toBeHex(targetWeiBalance)], - id: 1, - jsonrpc: '2.0', - }), - headers: { - 'Content-Type': 'application/json', - }, - }); -}; - const anvilSetNRlcTokenBalance = async ( address: string, targetNRlcBalance: ethers.BigNumberish @@ -131,13 +172,6 @@ const anvilSetNRlcTokenBalance = async ( }); }; -export const setBalance = async ( - address: string, - targetWeiBalance: ethers.BigNumberish -) => { - await anvilSetBalance(address, BigInt(`${targetWeiBalance}`)); -}; - export const setNRlcBalance = async ( address: string, nRlcTargetBalance: ethers.BigNumberish From 7898a943f2940f33e37c131eb7d4e920dde8c3c7 Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Wed, 29 Apr 2026 11:59:42 +0200 Subject: [PATCH 3/9] chore: update iexec deps --- package-lock.json | 65 ++++++++++++++++++++++++++++++++++++++++++++--- package.json | 2 +- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5c28e18..28d454e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "buffer": "^6.0.3", "ethers": "^6.15.0", "graphql-request": "^6.1.0", - "iexec": "^8.24.0", + "iexec": "^9.0.0", "kubo-rpc-client": "^5.4.1", "yup": "^1.1.1" }, @@ -823,6 +823,63 @@ "yup": "^1.0.2" } }, + "node_modules/@iexec/dataprotector/node_modules/iexec": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/iexec/-/iexec-8.24.0.tgz", + "integrity": "sha512-XMi+kZlRHPB5prubA7PQvhEmKxENN/5P0+gfe96eKKUWZSb3qllzi14btRE/MEmUXwsQok9kpIOq9IajUY8VQQ==", + "license": "Apache-2.0", + "dependencies": { + "@multiformats/multiaddr": "^13.0.1", + "@types/bn.js": "^5.2.0", + "bn.js": "^5.2.2", + "buffer": "^6.0.3", + "commander": "^13.1.0", + "debug": "^4.4.3", + "ethers": "^6.13.5", + "fs-extra": "^11.3.0", + "graphql-request": "^7.3.5", + "inquirer": "^13.1.0", + "is-docker": "^3.0.0", + "jszip": "^3.10.1", + "kubo-rpc-client": "^5.3.0", + "multiformats": "^13.4.2", + "node-forge": "^1.3.2", + "ora": "^9.0.0", + "prettyjson": "^1.2.5", + "query-string": "^9.1.1", + "rlc-faucet-contract": "^1.0.10", + "semver": "^7.7.3", + "update-check": "^1.5.4", + "yup": "^1.6.1" + }, + "bin": { + "iexec": "dist/esm/cli/cmd/iexec.js" + } + }, + "node_modules/@iexec/dataprotector/node_modules/iexec/node_modules/@multiformats/multiaddr": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-13.0.1.tgz", + "integrity": "sha512-XToN915cnfr6Lr9EdGWakGJbPT0ghpg/850HvdC+zFX8XvpLZElwa8synCiwa8TuvKNnny6m8j8NVBNCxhIO3g==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "multiformats": "^13.0.0", + "uint8-varint": "^2.0.1", + "uint8arrays": "^5.0.0" + } + }, + "node_modules/@iexec/dataprotector/node_modules/iexec/node_modules/graphql-request": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-7.4.0.tgz", + "integrity": "sha512-xfr+zFb/QYbs4l4ty0dltqiXIp07U6sl+tOKAb0t50/EnQek6CVVBLjETXi+FghElytvgaAWtIOt3EV7zLzIAQ==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, "node_modules/@inquirer/ansi": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.5.tgz", @@ -5600,9 +5657,9 @@ "license": "BSD-3-Clause" }, "node_modules/iexec": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/iexec/-/iexec-8.24.0.tgz", - "integrity": "sha512-XMi+kZlRHPB5prubA7PQvhEmKxENN/5P0+gfe96eKKUWZSb3qllzi14btRE/MEmUXwsQok9kpIOq9IajUY8VQQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/iexec/-/iexec-9.0.0.tgz", + "integrity": "sha512-6Rh8GvxBUxuElBFUatn55RG0PdoQBLxYW73hB1LrBA4kycea526qJK5ut7Qi2xF2K5xXXYLwH8QdeioYEC6SuQ==", "license": "Apache-2.0", "dependencies": { "@multiformats/multiaddr": "^13.0.1", diff --git a/package.json b/package.json index d7976a8..6088fd8 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "buffer": "^6.0.3", "ethers": "^6.15.0", "graphql-request": "^6.1.0", - "iexec": "^8.24.0", + "iexec": "^9.0.0", "kubo-rpc-client": "^5.4.1", "yup": "^1.1.1" }, From eb2c21603a8bc7b3f55ec806fa430803e2860e39 Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:29:50 +0200 Subject: [PATCH 4/9] refactor!: remove ENS support and rename address options (iexec v9) --- src/utils/getWeb3Provider.ts | 1 - src/utils/resolveDappAddressFromCompass.ts | 4 +- src/utils/validators.ts | 11 ------ src/web3telegram/IExecWeb3telegram.ts | 34 ++++++++-------- src/web3telegram/fetchMyContacts.ts | 4 +- src/web3telegram/fetchUserContacts.ts | 21 ++++------ src/web3telegram/internalTypes.ts | 4 +- src/web3telegram/prepareTelegramCampaign.ts | 24 +++++------ src/web3telegram/sendTelegram.ts | 44 +++++++++------------ src/web3telegram/sendTelegramCampaign.ts | 16 ++++---- src/web3telegram/types.ts | 20 ++++------ tests/e2e/constructor.test.ts | 22 +++++------ tests/e2e/fetchUserContacts.test.ts | 4 +- tests/e2e/sendTelegram.test.ts | 26 ++++++------ tests/e2e/sendTelegramCampaign.test.ts | 24 +++++------ tests/test-utils.ts | 2 +- tests/unit/fetchMyContacts.test.ts | 12 +++--- tests/unit/sendTelegram.test.ts | 24 +++++------ tests/unit/sendTelegramCampaign.test.ts | 35 ++++++++-------- tests/unit/utils/validators.test.ts | 41 ++++++++----------- 20 files changed, 165 insertions(+), 208 deletions(-) diff --git a/src/utils/getWeb3Provider.ts b/src/utils/getWeb3Provider.ts index f1cd6e3..118a969 100644 --- a/src/utils/getWeb3Provider.ts +++ b/src/utils/getWeb3Provider.ts @@ -10,6 +10,5 @@ export const getWeb3Provider = ( : 'arbitrum-sepolia-testnet'; return getSignerFromPrivateKey(chainHost, privateKey, { allowExperimentalNetworks: options?.allowExperimentalNetworks, - providers: {}, }); }; diff --git a/src/utils/resolveDappAddressFromCompass.ts b/src/utils/resolveDappAddressFromCompass.ts index 6439017..5ca9ec9 100644 --- a/src/utils/resolveDappAddressFromCompass.ts +++ b/src/utils/resolveDappAddressFromCompass.ts @@ -1,10 +1,10 @@ import { CompassCallError } from 'iexec/errors'; -import { AddressOrENS } from '../web3telegram/types.js'; +import { Address } from '../web3telegram/types.js'; export async function resolveDappAddressFromCompass( compassUrl: string, chainId: number -): Promise { +): Promise
{ if (!compassUrl) { return undefined; } diff --git a/src/utils/validators.ts b/src/utils/validators.ts index 964af5c..b448310 100644 --- a/src/utils/validators.ts +++ b/src/utils/validators.ts @@ -18,17 +18,6 @@ export const throwIfMissing = (): never => { const isUndefined = (value: unknown) => value === undefined; const isAddressTest = (value: string) => isAddress(value); -export const isEnsTest = (value: string) => - value.endsWith('.eth') && value.length > 6; - -export const addressOrEnsSchema = () => - string() - .transform((value: string) => value?.toLowerCase() || value) - .test( - 'is-address-or-ens', - '${path} should be an ethereum address or a ENS name', - (value) => isUndefined(value) || isAddressTest(value) || isEnsTest(value) - ); export const addressSchema = () => string() diff --git a/src/web3telegram/IExecWeb3telegram.ts b/src/web3telegram/IExecWeb3telegram.ts index de2779a..a541a6a 100644 --- a/src/web3telegram/IExecWeb3telegram.ts +++ b/src/web3telegram/IExecWeb3telegram.ts @@ -10,7 +10,7 @@ import { Contact, FetchUserContactsParams, SendTelegramParams, - AddressOrENS, + Address, Web3TelegramConfigOptions, Web3SignerProvider, FetchMyContactsParams, @@ -34,8 +34,8 @@ type EthersCompatibleProvider = | string; interface Web3telegramResolvedConfig { - dappAddressOrENS: AddressOrENS; - dappWhitelistAddress: AddressOrENS; + dappAddress: Address; + dappWhitelistAddress: Address; graphQLClient: GraphQLClient; ipfsNode: string; ipfsGateway: string; @@ -45,9 +45,9 @@ interface Web3telegramResolvedConfig { } export class IExecWeb3telegram { - private dappAddressOrENS!: AddressOrENS; + private dappAddress!: Address; - private dappWhitelistAddress!: AddressOrENS; + private dappWhitelistAddress!: Address; private graphQLClient!: GraphQLClient; @@ -78,7 +78,7 @@ export class IExecWeb3telegram { async init(): Promise { if (!this.initPromise) { this.initPromise = this.resolveConfig().then((config) => { - this.dappAddressOrENS = config.dappAddressOrENS; + this.dappAddress = config.dappAddress; this.dappWhitelistAddress = config.dappWhitelistAddress; this.graphQLClient = config.graphQLClient; this.ipfsNode = config.ipfsNode; @@ -99,7 +99,7 @@ export class IExecWeb3telegram { ...args, iexec: this.iexec, graphQLClient: this.graphQLClient, - dappAddressOrENS: this.dappAddressOrENS, + dappAddress: this.dappAddress, dappWhitelistAddress: this.dappWhitelistAddress, }); } @@ -111,7 +111,7 @@ export class IExecWeb3telegram { ...args, iexec: this.iexec, graphQLClient: this.graphQLClient, - dappAddressOrENS: this.dappAddressOrENS, + dappAddress: this.dappAddress, dappWhitelistAddress: this.dappWhitelistAddress, }); } @@ -121,12 +121,11 @@ export class IExecWeb3telegram { await isValidProvider(this.iexec); return sendTelegram({ ...args, - workerpoolAddressOrEns: - args.workerpoolAddressOrEns || this.defaultWorkerpool, + workerpoolAddress: args.workerpoolAddress || this.defaultWorkerpool, iexec: this.iexec, ipfsNode: this.ipfsNode, ipfsGateway: this.ipfsGateway, - dappAddressOrENS: this.dappAddressOrENS, + dappAddress: this.dappAddress, dappWhitelistAddress: this.dappWhitelistAddress, graphQLClient: this.graphQLClient, }); @@ -139,8 +138,7 @@ export class IExecWeb3telegram { await isValidProvider(this.iexec); return sendTelegramCampaign({ ...args, - workerpoolAddressOrEns: - args.workerpoolAddressOrEns || this.defaultWorkerpool, + workerpoolAddress: args.workerpoolAddress || this.defaultWorkerpool, dataProtector: this.dataProtector, }); } @@ -156,7 +154,7 @@ export class IExecWeb3telegram { dataProtector: this.dataProtector, ipfsNode: this.ipfsNode, ipfsGateway: this.ipfsGateway, - dappAddressOrENS: this.dappAddressOrENS, + dappAddress: this.dappAddress, }); } @@ -187,8 +185,8 @@ export class IExecWeb3telegram { const subgraphUrl = this.options?.dataProtectorSubgraph || chainDefaultConfig?.dataProtectorSubgraph; - const dappAddressOrENS = - this.options?.dappAddressOrENS || + const dappAddress = + this.options?.dappAddress || chainDefaultConfig?.dappAddress || (await resolveDappAddressFromCompass( await iexec.config.resolveCompassURL(), @@ -204,7 +202,7 @@ export class IExecWeb3telegram { const missing = []; if (!subgraphUrl) missing.push('dataProtectorSubgraph'); - if (!dappAddressOrENS) missing.push('dappAddress'); + if (!dappAddress) missing.push('dappAddress'); if (!dappWhitelistAddress) missing.push('whitelistSmartContract'); if (!ipfsGateway) missing.push('ipfsGateway'); if (!defaultWorkerpool) missing.push('prodWorkerpoolAddress'); @@ -236,7 +234,7 @@ export class IExecWeb3telegram { }); return { - dappAddressOrENS, + dappAddress, dappWhitelistAddress: dappWhitelistAddress.toLowerCase(), defaultWorkerpool, graphQLClient, diff --git a/src/web3telegram/fetchMyContacts.ts b/src/web3telegram/fetchMyContacts.ts index 7fcabaa..ffb800d 100644 --- a/src/web3telegram/fetchMyContacts.ts +++ b/src/web3telegram/fetchMyContacts.ts @@ -13,7 +13,7 @@ export type FetchMyContacts = typeof fetchMyContacts; export const fetchMyContacts = async ({ graphQLClient = throwIfMissing(), iexec = throwIfMissing(), - dappAddressOrENS = throwIfMissing(), + dappAddress = throwIfMissing(), dappWhitelistAddress = throwIfMissing(), isUserStrict = false, bulkOnly = false, @@ -30,7 +30,7 @@ export const fetchMyContacts = async ({ return fetchUserContacts({ iexec, graphQLClient, - dappAddressOrENS, + dappAddress, dappWhitelistAddress, userAddress, isUserStrict: vIsUserStrict, diff --git a/src/web3telegram/fetchUserContacts.ts b/src/web3telegram/fetchUserContacts.ts index 8ab7778..84ee67d 100644 --- a/src/web3telegram/fetchUserContacts.ts +++ b/src/web3telegram/fetchUserContacts.ts @@ -4,10 +4,8 @@ import { handleIfProtocolError, WorkflowError } from '../utils/errors.js'; import { autoPaginateRequest } from '../utils/paginate.js'; import { getValidContact } from '../utils/subgraphQuery.js'; import { - addressOrEnsSchema, addressSchema, booleanSchema, - isEnsTest, throwIfMissing, } from '../utils/validators.js'; import { Contact, FetchUserContactsParams, GrantedAccess } from './types.js'; @@ -23,7 +21,7 @@ import { export const fetchUserContacts = async ({ graphQLClient = throwIfMissing(), iexec = throwIfMissing(), - dappAddressOrENS = throwIfMissing(), + dappAddress = throwIfMissing(), dappWhitelistAddress = throwIfMissing(), userAddress, isUserStrict = false, @@ -34,15 +32,15 @@ export const fetchUserContacts = async ({ DappWhitelistAddressConsumer & FetchUserContactsParams): Promise => { try { - const vDappAddressOrENS = addressOrEnsSchema() + const address = addressSchema() .required() - .label('dappAddressOrENS') - .validateSync(dappAddressOrENS); + .label('dappAddress') + .validateSync(dappAddress); const vDappWhitelistAddress = addressSchema() .required() .label('dappWhitelistAddress') .validateSync(dappWhitelistAddress); - const vUserAddress = addressOrEnsSchema() + const vUserAddress = addressSchema() .required() .label('userAddress') .validateSync(userAddress); @@ -55,7 +53,7 @@ export const fetchUserContacts = async ({ fetchAllOrdersByApp({ iexec, userAddress: vUserAddress, - appAddress: vDappAddressOrENS, + appAddress: address, isUserStrict: vIsUserStrict, bulkOnly: vBulkOnly, }), @@ -69,14 +67,9 @@ export const fetchUserContacts = async ({ ]); const orders = dappOrders.concat(whitelistOrders); const myContacts: Omit[] = []; - let web3DappResolvedAddress = vDappAddressOrENS; - if (isEnsTest(vDappAddressOrENS)) { - web3DappResolvedAddress = await iexec.ens.resolveName(vDappAddressOrENS); - } orders.forEach((order) => { if ( - order.order.apprestrict.toLowerCase() === - web3DappResolvedAddress.toLowerCase() || + order.order.apprestrict.toLowerCase() === address.toLowerCase() || order.order.apprestrict.toLowerCase() === vDappWhitelistAddress.toLowerCase() ) { diff --git a/src/web3telegram/internalTypes.ts b/src/web3telegram/internalTypes.ts index 7cd2947..626dfb0 100644 --- a/src/web3telegram/internalTypes.ts +++ b/src/web3telegram/internalTypes.ts @@ -1,5 +1,5 @@ import { IExec } from 'iexec'; -import { AddressOrENS } from './types.js'; +import { Address } from './types.js'; import { GraphQLClient } from 'graphql-request'; import { IExecDataProtectorCore } from '@iexec/dataprotector'; @@ -13,7 +13,7 @@ export type GraphQLResponse = { }; export type DappAddressConsumer = { - dappAddressOrENS: AddressOrENS; + dappAddress: Address; }; export type IpfsNodeConfigConsumer = { diff --git a/src/web3telegram/prepareTelegramCampaign.ts b/src/web3telegram/prepareTelegramCampaign.ts index 7d58e90..6770f88 100644 --- a/src/web3telegram/prepareTelegramCampaign.ts +++ b/src/web3telegram/prepareTelegramCampaign.ts @@ -6,7 +6,7 @@ import { import { handleIfProtocolError, WorkflowError } from '../utils/errors.js'; import * as ipfs from '../utils/ipfs-service.js'; import { - addressOrEnsSchema, + addressSchema, telegramContentSchema, positiveNumberSchema, labelSchema, @@ -30,8 +30,8 @@ export type PrepareTelegramCampaign = typeof prepareTelegramCampaign; export const prepareTelegramCampaign = async ({ iexec = throwIfMissing(), dataProtector = throwIfMissing(), - workerpoolAddressOrEns, - dappAddressOrENS, + workerpoolAddress, + dappAddress, ipfsNode, ipfsGateway, senderName, @@ -48,9 +48,9 @@ export const prepareTelegramCampaign = async ({ DataProtectorConsumer & PrepareTelegramCampaignParams): Promise => { try { - const vWorkerpoolAddressOrEns = addressOrEnsSchema() - .label('WorkerpoolAddressOrEns') - .validateSync(workerpoolAddressOrEns); + const vWorkerpoolAddress = addressSchema() + .label('workerpoolAddress') + .validateSync(workerpoolAddress); const vSenderName = senderNameSchema() .label('senderName') .validateSync(senderName); @@ -59,10 +59,10 @@ export const prepareTelegramCampaign = async ({ .label('telegramContent') .validateSync(telegramContent); const vLabel = labelSchema().label('label').validateSync(label); - const vDappAddressOrENS = addressOrEnsSchema() + const vDappAddress = addressSchema() .required() - .label('dappAddressOrENS') - .validateSync(dappAddressOrENS); + .label('dappAddress') + .validateSync(dappAddress); const vAppMaxPrice = positiveNumberSchema() .label('appMaxPrice') .validateSync(appMaxPrice); @@ -115,10 +115,10 @@ export const prepareTelegramCampaign = async ({ const { bulkRequest: campaignRequest } = await dataProtector.prepareBulkRequest({ - app: vDappAddressOrENS, + app: vDappAddress, appMaxPrice: vAppMaxPrice, workerpoolMaxPrice: vWorkerpoolMaxPrice, - workerpool: vWorkerpoolAddressOrEns, + workerpool: vWorkerpoolAddress, args: vLabel, inputFiles: [], secrets, @@ -132,7 +132,7 @@ export const prepareTelegramCampaign = async ({ throw error; } // Handle protocol errors - this will throw if it's an ApiCallError - // handleIfProtocolError transforms ApiCallError into a WorkflowError with isProtocolError=true + // handleIfProtocolError transforms ApiCallError into WorkflowError with isProtocolError=true handleIfProtocolError(error); // For all other errors throw new WorkflowError({ diff --git a/src/web3telegram/sendTelegram.ts b/src/web3telegram/sendTelegram.ts index 9343a94..5e348e8 100644 --- a/src/web3telegram/sendTelegram.ts +++ b/src/web3telegram/sendTelegram.ts @@ -9,7 +9,6 @@ import { generateSecureUniqueId } from '../utils/generateUniqueId.js'; import * as ipfs from '../utils/ipfs-service.js'; import { checkProtectedDataValidity } from '../utils/subgraphQuery.js'; import { - addressOrEnsSchema, telegramContentSchema, positiveNumberSchema, labelSchema, @@ -33,8 +32,8 @@ export type SendTelegram = typeof sendTelegram; export const sendTelegram = async ({ graphQLClient = throwIfMissing(), iexec = throwIfMissing(), - workerpoolAddressOrEns = throwIfMissing(), - dappAddressOrENS, + workerpoolAddress = throwIfMissing(), + dappAddress, dappWhitelistAddress, ipfsNode, ipfsGateway, @@ -53,7 +52,7 @@ export const sendTelegram = async ({ IpfsGatewayConfigConsumer & SendTelegramParams): Promise => { try { - const vDatasetAddress = addressOrEnsSchema() + const vDatasetAddress = addressSchema() .required() .label('protectedData') .validateSync(protectedData); @@ -65,14 +64,14 @@ export const sendTelegram = async ({ .label('telegramContent') .validateSync(telegramContent); const vLabel = labelSchema().label('label').validateSync(label); - const vWorkerpoolAddressOrEns = addressOrEnsSchema() + const vWorkerpoolAddress = addressSchema() .required() - .label('WorkerpoolAddressOrEns') - .validateSync(workerpoolAddressOrEns); - const vDappAddressOrENS = addressOrEnsSchema() + .label('workerpoolAddress') + .validateSync(workerpoolAddress); + const vDappAddress = addressSchema() .required() - .label('dappAddressOrENS') - .validateSync(dappAddressOrENS); + .label('dappAddress') + .validateSync(dappAddress); const vDappWhitelistAddress = addressSchema() .required() .label('dappWhitelistAddress') @@ -102,9 +101,9 @@ export const sendTelegram = async ({ // Fetch app order const apporder = await iexec.orderbook .fetchAppOrderbook({ - app: dappAddressOrENS, + app: vDappAddress, minTag: ['tee'], - workerpool: workerpoolAddressOrEns, + workerpool: vWorkerpoolAddress, }) .then((appOrderbook) => { const desiredPriceAppOrderbook = appOrderbook.orders.filter( @@ -125,7 +124,7 @@ export const sendTelegram = async ({ iexec.orderbook .fetchDatasetOrderbook({ dataset: vDatasetAddress, - app: dappAddressOrENS, + app: vDappAddress, requester: requesterAddress, }) .then((datasetOrderbook) => { @@ -152,8 +151,8 @@ export const sendTelegram = async ({ // Fetch workerpool order for App or AppWhitelist Promise.all([ iexec.orderbook.fetchWorkerpoolOrderbook({ - workerpool: workerpoolAddressOrEns, - app: vDappAddressOrENS, + workerpool: vWorkerpoolAddress, + app: vDappAddress, dataset: vDatasetAddress, requester: requesterAddress, isRequesterStrict: false, @@ -161,7 +160,7 @@ export const sendTelegram = async ({ category: 0, }), iexec.orderbook.fetchWorkerpoolOrderbook({ - workerpool: workerpoolAddressOrEns, + workerpool: vWorkerpoolAddress, app: vDappWhitelistAddress, dataset: vDatasetAddress, requester: requesterAddress, @@ -232,14 +231,14 @@ export const sendTelegram = async ({ ); const requestorderToSign = await iexec.order.createRequestorder({ - app: vDappAddressOrENS, + app: vDappAddress, category: workerpoolorder.category, dataset: vDatasetAddress, datasetmaxprice: datasetorder.datasetprice, appmaxprice: apporder.appprice, workerpoolmaxprice: workerpoolorder.workerpoolprice, tag: workerpoolMinTag, - workerpool: vWorkerpoolAddressOrEns, + workerpool: vWorkerpoolAddress, params: { iexec_secrets: { 1: requesterSecretId, @@ -258,18 +257,11 @@ export const sendTelegram = async ({ }); const taskId = await iexec.deal.computeTaskId(dealId, 0); return { - dealId, taskId, + dealId, }; } catch (error) { - // Protocol error detected, re-throwing as-is - if ((error as any)?.isProtocolError === true) { - throw error; - } - // Handle protocol errors - this will throw if it's an ApiCallError - // handleIfProtocolError transforms ApiCallError into a WorkflowError with isProtocolError=true handleIfProtocolError(error); - // For all other errors throw new WorkflowError({ message: 'Failed to sendTelegram', errorCause: error, diff --git a/src/web3telegram/sendTelegramCampaign.ts b/src/web3telegram/sendTelegramCampaign.ts index 14dbae0..5ec81fb 100644 --- a/src/web3telegram/sendTelegramCampaign.ts +++ b/src/web3telegram/sendTelegramCampaign.ts @@ -1,7 +1,7 @@ import { NULL_ADDRESS } from 'iexec/utils'; import { handleIfProtocolError, WorkflowError } from '../utils/errors.js'; import { - addressOrEnsSchema, + addressSchema, throwIfMissing, campaignRequestSchema, } from '../utils/validators.js'; @@ -21,7 +21,7 @@ export type SendTelegramCampaign = typeof sendTelegramCampaign; export const sendTelegramCampaign = async ({ dataProtector = throwIfMissing(), - workerpoolAddressOrEns = throwIfMissing(), + workerpoolAddress = throwIfMissing(), campaignRequest, }: DataProtectorConsumer & SendTelegramCampaignParams): Promise => { @@ -31,18 +31,18 @@ export const sendTelegramCampaign = async ({ .label('campaignRequest') .validateSync(campaignRequest) as CampaignRequest; - const vWorkerpoolAddressOrEns = addressOrEnsSchema() + const vWorkerpoolAddress = addressSchema() .required() - .label('WorkerpoolAddressOrEns') - .validateSync(workerpoolAddressOrEns); + .label('workerpoolAddress') + .validateSync(workerpoolAddress); if ( vCampaignRequest.workerpool !== NULL_ADDRESS && vCampaignRequest.workerpool.toLowerCase() !== - vWorkerpoolAddressOrEns.toLowerCase() + vWorkerpoolAddress.toLowerCase() ) { throw new ValidationError( - "workerpoolAddressOrEns doesn't match campaignRequest workerpool" + "workerpoolAddress doesn't match campaignRequest workerpool" ); } @@ -50,7 +50,7 @@ export const sendTelegramCampaign = async ({ const processBulkRequestResponse: ProcessBulkRequestResponse = await dataProtector.processBulkRequest({ bulkRequest: vCampaignRequest, - workerpool: vWorkerpoolAddressOrEns, + workerpool: vWorkerpoolAddress, }); return processBulkRequestResponse; diff --git a/src/web3telegram/types.ts b/src/web3telegram/types.ts index 15a5a6f..6d92f4b 100644 --- a/src/web3telegram/types.ts +++ b/src/web3telegram/types.ts @@ -1,12 +1,8 @@ +import type { AbstractSigner } from 'ethers'; import { BulkRequest } from '@iexec/dataprotector'; -import { EnhancedWallet } from 'iexec'; import { IExecConfigOptions } from 'iexec/IExecConfig'; -export type Web3SignerProvider = EnhancedWallet; - -export type ENS = string; - -export type AddressOrENS = Address | ENS; +export type Web3SignerProvider = AbstractSigner; export type Address = string; @@ -72,7 +68,7 @@ export type SendTelegramParams = { telegramContent: string; protectedData: Address; label?: string; - workerpoolAddressOrEns?: AddressOrENS; + workerpoolAddress?: Address; dataMaxPrice?: number; appMaxPrice?: number; workerpoolMaxPrice?: number; @@ -94,7 +90,7 @@ export type PrepareTelegramCampaignParams = { senderName?: string; telegramContent: string; label?: string; - workerpoolAddressOrEns?: AddressOrENS; + workerpoolAddress?: Address; dataMaxPrice?: number; appMaxPrice?: number; workerpoolMaxPrice?: number; @@ -115,9 +111,9 @@ export type SendTelegramCampaignParams = { */ campaignRequest: CampaignRequest; /** - * Workerpool address or ENS to use for processing + * Workerpool contract address used for processing */ - workerpoolAddressOrEns?: string; + workerpoolAddress?: string; }; export type SendTelegramCampaignResponse = { @@ -133,10 +129,10 @@ export type SendTelegramCampaignResponse = { */ export type Web3TelegramConfigOptions = { /** - * The Ethereum contract address or ENS (Ethereum Name Service) for the telegram sender dapp. + * Ethereum contract address for the telegram sender dapp. * If not provided, the default web3telegram address for the detected chain will be used. */ - dappAddressOrENS?: AddressOrENS; + dappAddress?: Address; /** * The Ethereum contract address for the whitelist. diff --git a/tests/e2e/constructor.test.ts b/tests/e2e/constructor.test.ts index bd4f6b0..e79a429 100644 --- a/tests/e2e/constructor.test.ts +++ b/tests/e2e/constructor.test.ts @@ -77,7 +77,7 @@ describe('IExecWeb3telegram()', () => { const wallet = Wallet.createRandom(); const customSubgraphUrl = 'https://example.com/custom-subgraph'; const customIpfsGateway = 'https://example.com/ipfs_gateway'; - const customDapp = 'web3telegramstg.apps.iexec.eth'; + const customDapp = '0x1111111111111111111111111111111111111111'; const customIpfsNode = 'https://example.com/node'; const smsURL = 'https://custom-sms-url.com'; const iexecGatewayURL = 'https://custom-market-api-url.com'; @@ -93,7 +93,7 @@ describe('IExecWeb3telegram()', () => { ipfsNode: customIpfsNode, ipfsGateway: customIpfsGateway, dataProtectorSubgraph: customSubgraphUrl, - dappAddressOrENS: customDapp, + dappAddress: customDapp, dappWhitelistAddress: customDappWhitelistAddress, } ); @@ -101,14 +101,14 @@ describe('IExecWeb3telegram()', () => { const graphQLClient = web3telegram['graphQLClient']; const ipfsNode = web3telegram['ipfsNode']; const ipfsGateway = web3telegram['ipfsGateway']; - const dappAddressOrENS = web3telegram['dappAddressOrENS']; + const dappAddress = web3telegram['dappAddress']; const iexec = web3telegram['iexec']; const whitelistAddress = web3telegram['dappWhitelistAddress']; expect(graphQLClient['url']).toBe(customSubgraphUrl); expect(ipfsNode).toStrictEqual(customIpfsNode); expect(ipfsGateway).toStrictEqual(customIpfsGateway); - expect(dappAddressOrENS).toStrictEqual(customDapp); + expect(dappAddress).toStrictEqual(customDapp); expect(whitelistAddress).toStrictEqual( customDappWhitelistAddress.toLowerCase() ); @@ -175,7 +175,7 @@ describe('IExecWeb3telegram()', () => { expect(web3telegram['ipfsNode']).toBe( arbitrumSepoliaConfig!.ipfsUploadUrl ); - expect(web3telegram['dappAddressOrENS']).toMatch(/^0x[a-fA-F0-9]{40}$/); // resolved from Compass + expect(web3telegram['dappAddress']).toMatch(/^0x[a-fA-F0-9]{40}$/); // resolved from Compass expect(web3telegram['dappWhitelistAddress']).toBe( arbitrumSepoliaConfig!.whitelistSmartContract.toLowerCase() ); @@ -189,17 +189,17 @@ describe('IExecWeb3telegram()', () => { it('should allow custom configuration override for Arbitrum Sepolia', async () => { const customIpfsGateway = 'https://custom-arbitrum-ipfs.com'; - const customDappAddress = 'custom.arbitrum.app.eth'; + const customDappAddress = '0x2222222222222222222222222222222222222222'; const web3telegram = new IExecWeb3telegram(experimentalNetworkSigner, { allowExperimentalNetworks: true, ipfsGateway: customIpfsGateway, - dappAddressOrENS: customDappAddress, + dappAddress: customDappAddress, }); await web3telegram.init(); expect(web3telegram['ipfsGateway']).toBe(customIpfsGateway); - expect(web3telegram['dappAddressOrENS']).toBe(customDappAddress); + expect(web3telegram['dappAddress']).toBe(customDappAddress); const arbitrumSepoliaConfig = getChainDefaultConfig(421614, { allowExperimentalNetworks: true, @@ -238,9 +238,9 @@ describe('IExecWeb3telegram()', () => { ); await web3telegram.init(); - const dappAddressOrENS = web3telegram['dappAddressOrENS']; - expect(typeof dappAddressOrENS).toBe('string'); - expect(dappAddressOrENS).toMatch(/^0x[a-fA-F0-9]{40}$/); + const dappAddress = web3telegram['dappAddress']; + expect(typeof dappAddress).toBe('string'); + expect(dappAddress).toMatch(/^0x[a-fA-F0-9]{40}$/); }); }); }); diff --git a/tests/e2e/fetchUserContacts.test.ts b/tests/e2e/fetchUserContacts.test.ts index a5edbf0..fd11dea 100644 --- a/tests/e2e/fetchUserContacts.test.ts +++ b/tests/e2e/fetchUserContacts.test.ts @@ -69,7 +69,7 @@ describe('web3telegram.fetchMyContacts()', () => { await web3telegram.init(); // eslint-disable-next-line @typescript-eslint/dot-notation - const authorizedApp = web3telegram['dappAddressOrENS']; + const authorizedApp = web3telegram['dappAddress']; await dataProtector.grantAccess({ authorizedApp: authorizedApp, @@ -218,7 +218,7 @@ describe('web3telegram.fetchMyContacts()', () => { await dataProtector.grantAccess({ authorizedApp: authorizedApp, protectedData: protectedData1.address, - authorizedUser: ethProvider.address, + authorizedUser: await ethProvider.getAddress(), }); const options = { diff --git a/tests/e2e/sendTelegram.test.ts b/tests/e2e/sendTelegram.test.ts index c7bad21..56f6d7a 100644 --- a/tests/e2e/sendTelegram.test.ts +++ b/tests/e2e/sendTelegram.test.ts @@ -134,7 +134,7 @@ describe('web3telegram.sendTelegram()', () => { .sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, - workerpoolAddressOrEns: paidWorkerpoolAddress, + workerpoolAddress: paidWorkerpoolAddress, }) .catch((e) => (error = e)); expect(error).toBeDefined(); @@ -155,7 +155,7 @@ describe('web3telegram.sendTelegram()', () => { .sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, - workerpoolAddressOrEns: paidWorkerpoolAddress, + workerpoolAddress: paidWorkerpoolAddress, workerpoolMaxPrice: prodWorkerpoolPublicPrice, }) .catch((e) => (error = e)); @@ -179,7 +179,7 @@ describe('web3telegram.sendTelegram()', () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, - workerpoolAddressOrEns: paidWorkerpoolAddress, + workerpoolAddress: paidWorkerpoolAddress, workerpoolMaxPrice: prodWorkerpoolPublicPrice, }); expect(sendTelegramResponse).toStrictEqual({ @@ -199,7 +199,7 @@ describe('web3telegram.sendTelegram()', () => { web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: invalidProtectedData.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, }) ).rejects.toThrow('Failed to sendTelegram'); @@ -208,7 +208,7 @@ describe('web3telegram.sendTelegram()', () => { await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: invalidProtectedData.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, }); } catch (err) { error = err as Web3TelegramWorkflowError; @@ -236,7 +236,7 @@ describe('web3telegram.sendTelegram()', () => { web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: protectedData.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, }) ).rejects.toThrow( new WorkflowError({ @@ -269,7 +269,7 @@ describe('web3telegram.sendTelegram()', () => { try { await invalidWeb3telegram.sendTelegram({ protectedData: validProtectedData.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, telegramContent: 'e2e telegram content for test', }); } catch (err) { @@ -291,7 +291,7 @@ describe('web3telegram.sendTelegram()', () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, }); expect(sendTelegramResponse).toStrictEqual({ dealId: expect.any(String), @@ -319,7 +319,7 @@ describe('web3telegram.sendTelegram()', () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: protectedDataForWhitelist.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, }); expect('taskId' in sendTelegramResponse).toBe(true); expect(sendTelegramResponse).toStrictEqual({ @@ -337,7 +337,7 @@ describe('web3telegram.sendTelegram()', () => { telegramContent: '

Test html

test paragraph

', protectedData: validProtectedData.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, }); expect('taskId' in sendTelegramResponse).toBe(true); expect(sendTelegramResponse).toStrictEqual({ @@ -355,7 +355,7 @@ describe('web3telegram.sendTelegram()', () => { telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, senderName: 'Product Team', - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, }); expect(sendTelegramResponse).toBeDefined(); expect('taskId' in sendTelegramResponse).toBe(true); @@ -378,7 +378,7 @@ describe('web3telegram.sendTelegram()', () => { telegramContent: LARGE_CONTENT, protectedData: validProtectedData.address, senderName: 'Product Team', - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, }); expect(sendTelegramResponse).toStrictEqual({ dealId: expect.any(String), @@ -394,7 +394,7 @@ describe('web3telegram.sendTelegram()', () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, - workerpoolAddressOrEns: learnProdWorkerpoolAddress, + workerpoolAddress: learnProdWorkerpoolAddress, label: 'ID1234678', }); expect(sendTelegramResponse).toStrictEqual({ diff --git a/tests/e2e/sendTelegramCampaign.test.ts b/tests/e2e/sendTelegramCampaign.test.ts index 09f2420..4b3a11a 100644 --- a/tests/e2e/sendTelegramCampaign.test.ts +++ b/tests/e2e/sendTelegramCampaign.test.ts @@ -149,7 +149,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { maxProtectedDataPerTask: 3, appMaxPrice: 1000, workerpoolMaxPrice: 1000, - workerpoolAddressOrEns: TEST_CHAIN.prodWorkerpool, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, senderName: 'Bulk Test Sender', }); const campaignRequest = prepareResult.campaignRequest; @@ -158,7 +158,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { // Use the workerpool from campaignRequest (already resolved to address) const result = await web3telegram.sendTelegramCampaign({ campaignRequest, - workerpoolAddressOrEns: campaignRequest.workerpool, + workerpoolAddress: campaignRequest.workerpool, }); // Verify the result @@ -200,7 +200,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { maxProtectedDataPerTask: 1, appMaxPrice: 1000, workerpoolMaxPrice: 1000, - workerpoolAddressOrEns: TEST_CHAIN.prodWorkerpool, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, senderName: 'Single Contact Test', }); const campaignRequest = prepareResult.campaignRequest; @@ -209,7 +209,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { // Use the workerpool from campaignRequest (already resolved to address) const result = await web3telegram.sendTelegramCampaign({ campaignRequest, - workerpoolAddressOrEns: campaignRequest.workerpool, + workerpoolAddress: campaignRequest.workerpool, }); // Verify the result @@ -248,7 +248,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { maxProtectedDataPerTask: 1, // Force one protected data per task appMaxPrice: 1000, workerpoolMaxPrice: 1000, - workerpoolAddressOrEns: TEST_CHAIN.prodWorkerpool, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, senderName: 'Max Data Test', label: 'MAXDATA', }); @@ -258,7 +258,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { // Use the workerpool from campaignRequest (already resolved to address) const result = await web3telegram.sendTelegramCampaign({ campaignRequest, - workerpoolAddressOrEns: campaignRequest.workerpool, + workerpoolAddress: campaignRequest.workerpool, }); // Verify the result @@ -295,7 +295,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { maxProtectedDataPerTask: 3, appMaxPrice: 1000, workerpoolMaxPrice: 1000, - workerpoolAddressOrEns: TEST_CHAIN.prodWorkerpool, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, senderName: 'CustomSender', label: 'CUSTOM123', }); @@ -305,7 +305,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { // Use the workerpool from campaignRequest (already resolved to address) const result = await web3telegram.sendTelegramCampaign({ campaignRequest, - workerpoolAddressOrEns: campaignRequest.workerpool, + workerpoolAddress: campaignRequest.workerpool, }); // Verify the result @@ -319,7 +319,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { ); it( - 'should throw error when workerpoolAddressOrEns does not match campaignRequest.workerpool', + 'should throw error when workerpoolAddress does not match campaignRequest.workerpool', async () => { // Fetch contacts with allowBulk access const contacts: Contact[] = await web3telegram.fetchMyContacts({ @@ -335,7 +335,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { maxProtectedDataPerTask: 3, appMaxPrice: 1000, workerpoolMaxPrice: 1000, - workerpoolAddressOrEns: TEST_CHAIN.prodWorkerpool, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, senderName: 'Mismatch Test', }); const campaignRequest = prepareResult.campaignRequest; @@ -346,14 +346,14 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { await expect( web3telegram.sendTelegramCampaign({ campaignRequest, - workerpoolAddressOrEns: differentWorkerpool, + workerpoolAddress: differentWorkerpool, }) ).rejects.toMatchObject({ message: 'Failed to sendTelegramCampaign', cause: expect.objectContaining({ name: 'ValidationError', message: - "workerpoolAddressOrEns doesn't match campaignRequest workerpool", + "workerpoolAddress doesn't match campaignRequest workerpool", }), }); }, diff --git a/tests/test-utils.ts b/tests/test-utils.ts index 4f00d19..5d60168 100644 --- a/tests/test-utils.ts +++ b/tests/test-utils.ts @@ -202,7 +202,7 @@ export const getTestConfig = ( ? getTestWeb3SignerProvider(privateKey) : undefined; const options = { - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, iexecOptions: getTestIExecOption(), ipfsGateway: 'http://127.0.0.1:8080', ipfsNode: 'http://127.0.0.1:5001', diff --git a/tests/unit/fetchMyContacts.test.ts b/tests/unit/fetchMyContacts.test.ts index 18d177c..5955074 100644 --- a/tests/unit/fetchMyContacts.test.ts +++ b/tests/unit/fetchMyContacts.test.ts @@ -82,7 +82,7 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, }); const userAddress = (await iexec.wallet.getAddress()).toLowerCase(); @@ -143,7 +143,7 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, isUserStrict: true, }); @@ -218,7 +218,7 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, }); @@ -265,7 +265,7 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, bulkOnly: true, }); @@ -327,7 +327,7 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, bulkOnly: false, }); @@ -389,7 +389,7 @@ describe('fetchMyContacts', () => { iexec: iexec, // @ts-expect-error No need for graphQLClient here graphQLClient: {}, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, isUserStrict: true, bulkOnly: true, diff --git a/tests/unit/sendTelegram.test.ts b/tests/unit/sendTelegram.test.ts index 87054ba..5611bdf 100644 --- a/tests/unit/sendTelegram.test.ts +++ b/tests/unit/sendTelegram.test.ts @@ -46,8 +46,8 @@ describe('sendTelegram', () => { sendTelegram({ graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -79,8 +79,8 @@ describe('sendTelegram', () => { sendTelegram({ graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -112,8 +112,8 @@ describe('sendTelegram', () => { sendTelegram({ graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -144,8 +144,8 @@ describe('sendTelegram', () => { sendTelegram({ graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -178,8 +178,8 @@ describe('sendTelegram', () => { sendTelegram({ graphQLClient: { request: jest.fn() } as any, iexec: mockAllForSendTelegram() as any, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, @@ -217,8 +217,8 @@ describe('sendTelegram', () => { await sendTelegram({ graphQLClient: { request: jest.fn() } as any, iexec, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, - dappAddressOrENS: TEST_WEB3TELEGRAM_DAPP_ADDRESS, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, + dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, dappWhitelistAddress: defaultConfig.whitelistSmartContract, ipfsNode: defaultConfig.ipfsUploadUrl, ipfsGateway: defaultConfig.ipfsGateway, diff --git a/tests/unit/sendTelegramCampaign.test.ts b/tests/unit/sendTelegramCampaign.test.ts index 8362b5e..f798661 100644 --- a/tests/unit/sendTelegramCampaign.test.ts +++ b/tests/unit/sendTelegramCampaign.test.ts @@ -58,7 +58,7 @@ describe('sendTelegramCampaign', () => { // --- WHEN const result = await sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, campaignRequest: mockCampaignRequest, }); @@ -113,7 +113,7 @@ describe('sendTelegramCampaign', () => { // --- WHEN const result = await sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, campaignRequest: mockCampaignRequest, }); @@ -163,7 +163,7 @@ describe('sendTelegramCampaign', () => { // --- WHEN await sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, campaignRequest: mockCampaignRequest, }); @@ -185,7 +185,7 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, // campaignRequest is not provided } as any) ).rejects.toThrow(); @@ -194,7 +194,7 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, } as any) ).rejects.toMatchObject({ message: expect.stringMatching( @@ -237,7 +237,7 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, campaignRequest: mockCampaignRequest, }) ).rejects.toMatchObject({ @@ -245,7 +245,7 @@ describe('sendTelegramCampaign', () => { }); }); - it('should throw error when workerpoolAddressOrEns is not provided', async () => { + it('should throw error when workerpoolAddress is not provided', async () => { // --- GIVEN const mockCampaignRequest: BulkRequest = { app: '0x0000000000000000000000000000000000000000', @@ -275,7 +275,7 @@ describe('sendTelegramCampaign', () => { sendTelegramCampaign({ dataProtector: mockDataprotector, campaignRequest: mockCampaignRequest, - // workerpoolAddressOrEns is not provided + // workerpoolAddress is not provided } as any) ).rejects.toMatchObject({ message: expect.stringMatching( @@ -311,7 +311,7 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ // dataProtector is not provided - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, campaignRequest: mockCampaignRequest, } as any) ).rejects.toMatchObject({ @@ -321,7 +321,7 @@ describe('sendTelegramCampaign', () => { }); }); - it('should throw error when workerpoolAddressOrEns is invalid', async () => { + it('should throw error when workerpoolAddress is invalid', async () => { // --- GIVEN const mockCampaignRequest: BulkRequest = { app: '0x0000000000000000000000000000000000000000', @@ -350,7 +350,7 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: 'invalid-address', + workerpoolAddress: 'invalid-address', campaignRequest: mockCampaignRequest, }) ).rejects.toMatchObject({ @@ -373,7 +373,7 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, campaignRequest: null as any, // Invalid campaignRequest }) ).rejects.toMatchObject({ @@ -420,7 +420,7 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, campaignRequest: mockCampaignRequest, }) ).rejects.toBe(protocolError); @@ -458,7 +458,7 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: defaultConfig.prodWorkerpoolAddress, + workerpoolAddress: defaultConfig.prodWorkerpoolAddress, campaignRequest: mockCampaignRequest, }) ).rejects.toMatchObject({ @@ -466,7 +466,7 @@ describe('sendTelegramCampaign', () => { }); }); - it('should throw error when workerpoolAddressOrEns does not match campaignRequest.workerpool', async () => { + it('should throw error when workerpoolAddress does not match campaignRequest.workerpool', async () => { // --- GIVEN const mockCampaignRequest: BulkRequest = { app: '0x0000000000000000000000000000000000000000', @@ -497,15 +497,14 @@ describe('sendTelegramCampaign', () => { await expect( sendTelegramCampaign({ dataProtector: mockDataprotector, - workerpoolAddressOrEns: differentWorkerpool, + workerpoolAddress: differentWorkerpool, campaignRequest: mockCampaignRequest, }) ).rejects.toMatchObject({ message: 'Failed to sendTelegramCampaign', cause: expect.objectContaining({ name: 'ValidationError', - message: - "workerpoolAddressOrEns doesn't match campaignRequest workerpool", + message: "workerpoolAddress doesn't match campaignRequest workerpool", }), }); diff --git a/tests/unit/utils/validators.test.ts b/tests/unit/utils/validators.test.ts index a78d9a5..2eff8f4 100644 --- a/tests/unit/utils/validators.test.ts +++ b/tests/unit/utils/validators.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from '@jest/globals'; import { ValidationError } from 'yup'; import { - addressOrEnsSchema, + addressSchema, senderNameSchema, telegramContentSchema, labelSchema, @@ -11,50 +11,41 @@ import { getRandomAddress, getRequiredFieldMessage } from '../../test-utils.js'; const CANNOT_BE_NULL_ERROR = new ValidationError('this cannot be null'); const IS_REQUIRED_ERROR = new ValidationError(getRequiredFieldMessage()); -describe('addressOrEnsSchema()', () => { +describe('addressSchema()', () => { describe('validateSync()', () => { const address = getRandomAddress(); const EXPECTED_ERROR = new ValidationError( - 'this should be an ethereum address or a ENS name' + 'this should be an ethereum address' ); it('transforms to lowercase', () => { - const res = addressOrEnsSchema().validateSync(address); + const res = addressSchema().validateSync(address); expect(res).toBe(address.toLowerCase()); }); it('accepts undefined (is not required by default)', () => { - const res = addressOrEnsSchema().validateSync(undefined); + const res = addressSchema().validateSync(undefined); expect(res).toBeUndefined(); }); it('accepts case insensitive ethereum address', () => { - expect(addressOrEnsSchema().validateSync(address)).toBeDefined(); - expect( - addressOrEnsSchema().validateSync(address.toUpperCase()) - ).toBeDefined(); - expect( - addressOrEnsSchema().validateSync(address.toLowerCase()) - ).toBeDefined(); + expect(addressSchema().validateSync(address)).toBeDefined(); + expect(addressSchema().validateSync(address.toUpperCase())).toBeDefined(); + expect(addressSchema().validateSync(address.toLowerCase())).toBeDefined(); }); - it('accepts string ending with ".eth"', () => { - expect(addressOrEnsSchema().validateSync('FOO.eth')).toBe('foo.eth'); + it('does not accept string ending with ".eth"', () => { + expect(() => addressSchema().validateSync('FOO.eth')).toThrow( + EXPECTED_ERROR + ); }); it('does not accept null', () => { - expect(() => addressOrEnsSchema().validateSync(null)).toThrow( + expect(() => addressSchema().validateSync(null)).toThrow( CANNOT_BE_NULL_ERROR ); }); it('does not accept empty string', () => { - expect(() => addressOrEnsSchema().validateSync('')).toThrow( - EXPECTED_ERROR - ); + expect(() => addressSchema().validateSync('')).toThrow(EXPECTED_ERROR); }); it('does not accept non address string', () => { - expect(() => addressOrEnsSchema().validateSync('test')).toThrow( - EXPECTED_ERROR - ); - }); - it('does not accept ENS name with label < 3 char', () => { - expect(() => addressOrEnsSchema().validateSync('ab.eth')).toThrow( + expect(() => addressSchema().validateSync('test')).toThrow( EXPECTED_ERROR ); }); @@ -63,7 +54,7 @@ describe('addressOrEnsSchema()', () => { describe('validateSync()', () => { it('does not accept undefined', () => { expect(() => - addressOrEnsSchema().required().validateSync(undefined) + addressSchema().required().validateSync(undefined) ).toThrow(IS_REQUIRED_ERROR); }); }); From ddbd7fd08d0fdd545c1a4d8749a20ba219532eb0 Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:43:26 +0200 Subject: [PATCH 5/9] chore(dapp): bump iexec SDK in dapp and deployment-dapp --- dapp/package-lock.json | 8 ++++---- dapp/package.json | 2 +- deployment-dapp/package-lock.json | 8 ++++---- deployment-dapp/package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dapp/package-lock.json b/dapp/package-lock.json index 9e99661..70f9ac3 100644 --- a/dapp/package-lock.json +++ b/dapp/package-lock.json @@ -22,7 +22,7 @@ "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.28.1", "eslint-plugin-sonarjs": "^0.21.0", - "iexec": "^8.24.0", + "iexec": "^9.0.0", "jest": "^29.7.0", "prettier": "^2.8.8" }, @@ -4215,9 +4215,9 @@ "license": "BSD-3-Clause" }, "node_modules/iexec": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/iexec/-/iexec-8.24.0.tgz", - "integrity": "sha512-XMi+kZlRHPB5prubA7PQvhEmKxENN/5P0+gfe96eKKUWZSb3qllzi14btRE/MEmUXwsQok9kpIOq9IajUY8VQQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/iexec/-/iexec-9.0.0.tgz", + "integrity": "sha512-6Rh8GvxBUxuElBFUatn55RG0PdoQBLxYW73hB1LrBA4kycea526qJK5ut7Qi2xF2K5xXXYLwH8QdeioYEC6SuQ==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/dapp/package.json b/dapp/package.json index 5d95353..d108c1e 100644 --- a/dapp/package.json +++ b/dapp/package.json @@ -33,7 +33,7 @@ "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.28.1", "eslint-plugin-sonarjs": "^0.21.0", - "iexec": "^8.24.0", + "iexec": "^9.0.0", "jest": "^29.7.0", "prettier": "^2.8.8" } diff --git a/deployment-dapp/package-lock.json b/deployment-dapp/package-lock.json index 93bad15..55bf020 100644 --- a/deployment-dapp/package-lock.json +++ b/deployment-dapp/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "iexec": "^8.24.0", + "iexec": "^9.0.0", "typescript": "^5.0.4", "yup": "^1.2.0" }, @@ -3605,9 +3605,9 @@ "license": "BSD-3-Clause" }, "node_modules/iexec": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/iexec/-/iexec-8.24.0.tgz", - "integrity": "sha512-XMi+kZlRHPB5prubA7PQvhEmKxENN/5P0+gfe96eKKUWZSb3qllzi14btRE/MEmUXwsQok9kpIOq9IajUY8VQQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/iexec/-/iexec-9.0.0.tgz", + "integrity": "sha512-6Rh8GvxBUxuElBFUatn55RG0PdoQBLxYW73hB1LrBA4kycea526qJK5ut7Qi2xF2K5xXXYLwH8QdeioYEC6SuQ==", "license": "Apache-2.0", "dependencies": { "@multiformats/multiaddr": "^13.0.1", diff --git a/deployment-dapp/package.json b/deployment-dapp/package.json index 49fc4f1..e978f7d 100644 --- a/deployment-dapp/package.json +++ b/deployment-dapp/package.json @@ -18,7 +18,7 @@ "author": "", "license": "ISC", "dependencies": { - "iexec": "^8.24.0", + "iexec": "^9.0.0", "typescript": "^5.0.4", "yup": "^1.2.0" }, From 6d7740d7bb405253669ab1ba7a3871e8f3787518 Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:59:53 +0200 Subject: [PATCH 6/9] chore(sdk): bump dataprotector SDK --- deployment-dapp/package-lock.json | 591 +++++++++++++++++++++++++++++- deployment-dapp/package.json | 1 + 2 files changed, 579 insertions(+), 13 deletions(-) diff --git a/deployment-dapp/package-lock.json b/deployment-dapp/package-lock.json index 55bf020..a6bd841 100644 --- a/deployment-dapp/package-lock.json +++ b/deployment-dapp/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@iexec/dataprotector": "^2.0.0-beta.27", "iexec": "^9.0.0", "typescript": "^5.0.4", "yup": "^1.2.0" @@ -588,6 +589,61 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@ethersproject/bytes": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz", + "integrity": "sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", + "integrity": "sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "node_modules/@ethersproject/random": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.8.0.tgz", + "integrity": "sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0" + } + }, "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", @@ -659,6 +715,57 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@iexec/dataprotector": { + "version": "2.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@iexec/dataprotector/-/dataprotector-2.0.0-beta.27.tgz", + "integrity": "sha512-t5+e/XBCq7L7ztMkRb2I5WYqo6pWuXKqMeilQb+SGPPgk7rFTIMhex6d/MJl7peTTAvWKeLU+WNVPY5aXjc+BA==", + "license": "Apache-2.0", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@multiformats/multiaddr": "^12.1.3", + "@typechain/ethers-v6": "^0.5.1", + "@types/bn.js": "^5.1.6", + "borsh": "^2.0.0", + "debug": "^4.3.4", + "ethers": "^6.13.2", + "graphql-request": "^6.0.0", + "iexec": "^9.0.0", + "jszip": "^3.7.1", + "kubo-rpc-client": "^5.4.1", + "magic-bytes.js": "^1.0.15", + "typechain": "^8.3.2", + "yup": "^1.0.2" + } + }, + "node_modules/@iexec/dataprotector/node_modules/@multiformats/multiaddr": { + "version": "12.5.1", + "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.5.1.tgz", + "integrity": "sha512-+DDlr9LIRUS8KncI1TX/FfUn8F2dl6BIxJgshS/yFQCNB5IAF0OGzcwB39g5NLE22s4qqDePv0Qof6HdpJ/4aQ==", + "license": "Apache-2.0 OR MIT", + "dependencies": { + "@chainsafe/is-ip": "^2.0.1", + "@chainsafe/netmask": "^2.0.0", + "@multiformats/dns": "^1.0.3", + "abort-error": "^1.0.1", + "multiformats": "^13.0.0", + "uint8-varint": "^2.0.1", + "uint8arrays": "^5.0.0" + } + }, + "node_modules/@iexec/dataprotector/node_modules/graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, "node_modules/@inquirer/ansi": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.5.tgz", @@ -1291,6 +1398,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@typechain/ethers-v6": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", + "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "ethers": "6.x", + "typechain": "^8.3.2", + "typescript": ">=4.7.0" + } + }, "node_modules/@types/bn.js": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.2.0.tgz", @@ -1323,6 +1445,12 @@ "undici-types": "~7.19.0" } }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "license": "MIT" + }, "node_modules/@types/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", @@ -1601,7 +1729,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -1630,6 +1757,15 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", @@ -1792,7 +1928,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, "node_modules/base64-js": { @@ -1830,6 +1965,12 @@ "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", "license": "MIT" }, + "node_modules/borsh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-2.0.0.tgz", + "integrity": "sha512-kc9+BgR3zz9+cjbwM8ODoUB4fs3X3I5A/HtX7LZKxCLaMrEeDFoBpnhZY//DTS1VZBSs6S5v46RZRbZjRFspEg==", + "license": "Apache-2.0" + }, "node_modules/brace-expansion": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", @@ -1955,7 +2096,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -2014,7 +2154,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2027,7 +2166,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/colors": { @@ -2039,6 +2177,125 @@ "node": ">=0.1.90" } }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "license": "MIT", + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", + "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", + "license": "MIT", + "dependencies": { + "array-back": "^4.0.2", + "chalk": "^2.4.2", + "table-layout": "^1.0.2", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/command-line-usage/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-usage/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/command-line-usage/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/command-line-usage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/command-line-usage/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/commander": { "version": "13.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", @@ -2052,7 +2309,6 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/confusing-browser-globals": { @@ -2068,6 +2324,15 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -3077,6 +3342,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "license": "MIT", + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3150,7 +3427,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -3485,7 +3761,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3685,7 +3960,6 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -4351,6 +4625,12 @@ "node": ">= 6" } }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", @@ -4527,6 +4807,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4550,6 +4842,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/magic-bytes.js": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.13.0.tgz", + "integrity": "sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg==", + "license": "MIT" + }, "node_modules/main-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/main-event/-/main-event-1.0.4.tgz", @@ -4637,6 +4935,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4721,6 +5031,26 @@ "semver": "bin/semver.js" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-forge": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", @@ -4847,7 +5177,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -5068,7 +5397,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5295,6 +5623,15 @@ "util-deprecate": "~1.0.1" } }, + "node_modules/reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -5820,6 +6157,12 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/string-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", + "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", + "license": "WTFPL OR MIT" + }, "node_modules/string-width": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", @@ -5962,7 +6305,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -5984,6 +6326,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/table-layout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", + "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", + "license": "MIT", + "dependencies": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/table-layout/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -6015,6 +6390,12 @@ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", "license": "MIT" }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", @@ -6028,6 +6409,30 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-command-line-args": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", + "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", + "license": "ISC", + "dependencies": { + "chalk": "^4.1.0", + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "string-format": "^2.0.0" + }, + "bin": { + "write-markdown": "dist/write-markdown.js" + } + }, + "node_modules/ts-essentials": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", + "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", + "license": "MIT", + "peerDependencies": { + "typescript": ">=3.7.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -6093,6 +6498,120 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typechain": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", + "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", + "license": "MIT", + "dependencies": { + "@types/prettier": "^2.1.1", + "debug": "^4.3.1", + "fs-extra": "^7.0.0", + "glob": "7.1.7", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "mkdirp": "^1.0.4", + "prettier": "^2.3.1", + "ts-command-line-args": "^2.2.0", + "ts-essentials": "^7.0.1" + }, + "bin": { + "typechain": "dist/cli/cli.js" + }, + "peerDependencies": { + "typescript": ">=4.3.0" + } + }, + "node_modules/typechain/node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/typechain/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/typechain/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typechain/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/typechain/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typechain/node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/typechain/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -6184,6 +6703,15 @@ "node": ">=14.17" } }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/uint8-varint": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/uint8-varint/-/uint8-varint-2.0.4.tgz", @@ -6319,6 +6847,22 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/wherearewe": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wherearewe/-/wherearewe-2.0.1.tgz", @@ -6454,11 +6998,32 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrapjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", + "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", + "license": "MIT", + "dependencies": { + "reduce-flatten": "^2.0.0", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, "license": "ISC" }, "node_modules/ws": { diff --git a/deployment-dapp/package.json b/deployment-dapp/package.json index e978f7d..67ff380 100644 --- a/deployment-dapp/package.json +++ b/deployment-dapp/package.json @@ -18,6 +18,7 @@ "author": "", "license": "ISC", "dependencies": { + "@iexec/dataprotector": "^2.0.0-beta.27", "iexec": "^9.0.0", "typescript": "^5.0.4", "yup": "^1.2.0" From b3e5116d76ebb4c0780a2ca5d8b92ff9996e93d8 Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Thu, 30 Apr 2026 08:37:35 +0200 Subject: [PATCH 7/9] fix!(sdk,deployment): require explicit chain and host; drop ENS test helpers --- README.md | 2 +- .../src/singleFunction/resolveName.ts | 8 ---- deployment-dapp/src/utils/utils.ts | 6 +-- examples/node-ts/index.ts | 5 ++- examples/node/index.js | 5 ++- src/config/config.ts | 26 ++++++++++- src/utils/getChainId.ts | 14 ++++-- src/utils/getWeb3Provider.ts | 11 ++--- src/web3telegram/IExecWeb3telegram.ts | 4 +- tests/e2e/constructor.test.ts | 22 ++++----- tests/e2e/fetchMyContacts.test.ts | 4 +- tests/e2e/fetchUserContacts.test.ts | 11 ++--- tests/e2e/prepareTelegramCampaign.test.ts | 5 +-- tests/e2e/sendTelegram.test.ts | 23 +++++----- tests/e2e/sendTelegramCampaign.test.ts | 3 +- tests/test-utils.ts | 45 +++++++++---------- tests/unit/constructor.test.ts | 6 +-- tests/unit/fetchMyContacts.test.ts | 37 +-------------- tests/unit/sendTelegram.test.ts | 7 +-- tests/unit/sendTelegramCampaign.test.ts | 7 +-- tests/utils/mockAllForSendTelegram.ts | 5 --- 21 files changed, 108 insertions(+), 148 deletions(-) delete mode 100644 deployment-dapp/src/singleFunction/resolveName.ts diff --git a/README.md b/README.md index e2b302f..597eced 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ import { IExecWeb3telegram, getWeb3Provider } from '@iexec/web3telegram'; const { PRIVATE_KEY } = process.env; -const web3Provider = getWeb3Provider(PRIVATE_KEY); +const web3Provider = getWeb3Provider(PRIVATE_KEY, 421614); const web3telegram = new IExecWeb3telegram(web3Provider); ``` diff --git a/deployment-dapp/src/singleFunction/resolveName.ts b/deployment-dapp/src/singleFunction/resolveName.ts deleted file mode 100644 index 07404a0..0000000 --- a/deployment-dapp/src/singleFunction/resolveName.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ENS, IExec } from 'iexec'; - -export const resolveName = async ( - iexec: IExec, - name: ENS -): Promise => { - return iexec.ens.resolveName(name); -}; diff --git a/deployment-dapp/src/utils/utils.ts b/deployment-dapp/src/utils/utils.ts index dbc1448..14b84bc 100644 --- a/deployment-dapp/src/utils/utils.ts +++ b/deployment-dapp/src/utils/utils.ts @@ -1,12 +1,8 @@ import fs from 'fs/promises'; import { IExec, utils } from 'iexec'; -export const getIExec = ( - privateKey: string, - host: string = 'arbitrum-sepolia-testnet' -): IExec => { +export const getIExec = (privateKey: string, host: string): IExec => { const ethProvider = utils.getSignerFromPrivateKey(host, privateKey, { - providers: {}, allowExperimentalNetworks: true, }); return new IExec( diff --git a/examples/node-ts/index.ts b/examples/node-ts/index.ts index 8f5b316..863a504 100644 --- a/examples/node-ts/index.ts +++ b/examples/node-ts/index.ts @@ -2,7 +2,10 @@ import { IExecWeb3telegram, getWeb3Provider } from '@iexec/web3telegram'; import { Wallet } from 'ethers'; const test = async () => { - const ethProvider = getWeb3Provider(Wallet.createRandom().privateKey); + const ethProvider = getWeb3Provider( + Wallet.createRandom().privateKey, + 421614 + ); const web3telegram = new IExecWeb3telegram(ethProvider); diff --git a/examples/node/index.js b/examples/node/index.js index 8f5b316..863a504 100644 --- a/examples/node/index.js +++ b/examples/node/index.js @@ -2,7 +2,10 @@ import { IExecWeb3telegram, getWeb3Provider } from '@iexec/web3telegram'; import { Wallet } from 'ethers'; const test = async () => { - const ethProvider = getWeb3Provider(Wallet.createRandom().privateKey); + const ethProvider = getWeb3Provider( + Wallet.createRandom().privateKey, + 421614 + ); const web3telegram = new IExecWeb3telegram(ethProvider); diff --git a/src/config/config.ts b/src/config/config.ts index 62b915e..ae3e465 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -3,8 +3,6 @@ export const MAX_DESIRED_APP_ORDER_PRICE = 0; export const MAX_DESIRED_WORKERPOOL_ORDER_PRICE = 0; export const ANY_DATASET_ADDRESS = 'any'; -export const DEFAULT_CHAIN_ID = 421614; - interface ChainConfig { name: string; dappAddress?: string; @@ -52,3 +50,27 @@ export const getChainDefaultConfig = ( } return config; }; + +/** + * When `ethProvider` is a string, it may be an RPC URL, a decimal chain id, or an + * iExec chain host name (see each chain's `name` in CHAIN_CONFIG). RPC URLs are not + * resolved here (returns undefined); JsonRpcProvider handles those. + */ +export function tryResolveChainIdFromProviderString( + hint: string +): number | undefined { + const trimmed = hint.trim(); + if (/^https?:\/\//i.test(trimmed)) { + return undefined; + } + if (/^\d+$/.test(trimmed)) { + return Number(trimmed); + } + const lower = trimmed.toLowerCase(); + for (const [id, cfg] of Object.entries(CHAIN_CONFIG)) { + if (cfg.name.toLowerCase() === lower) { + return Number(id); + } + } + return undefined; +} diff --git a/src/utils/getChainId.ts b/src/utils/getChainId.ts index 20e448f..0f7529e 100644 --- a/src/utils/getChainId.ts +++ b/src/utils/getChainId.ts @@ -5,7 +5,7 @@ import { AbstractSigner, Eip1193Provider, } from 'ethers'; -import { DEFAULT_CHAIN_ID } from '../config/config.js'; +import { tryResolveChainIdFromProviderString } from '../config/config.js'; type EthersCompatibleProvider = | string @@ -18,7 +18,10 @@ export async function getChainIdFromProvider( ): Promise { try { if (typeof ethProvider === 'string') { - if (ethProvider === 'arbitrum-sepolia-testnet') return 421614; + const resolved = tryResolveChainIdFromProviderString(ethProvider); + if (resolved !== undefined) { + return resolved; + } const provider = new JsonRpcProvider(ethProvider); const network = await provider.getNetwork(); return Number(network.chainId); @@ -39,6 +42,11 @@ export async function getChainIdFromProvider( } } catch (e) { console.warn('Failed to detect chainId:', e); + throw new Error( + `Failed to detect chainId from ethProvider: ${ + e instanceof Error ? e.message : String(e) + }` + ); } - return DEFAULT_CHAIN_ID; + throw new Error('Unsupported ethProvider for chain ID detection'); } diff --git a/src/utils/getWeb3Provider.ts b/src/utils/getWeb3Provider.ts index 118a969..2f3d1f3 100644 --- a/src/utils/getWeb3Provider.ts +++ b/src/utils/getWeb3Provider.ts @@ -3,12 +3,9 @@ import { Web3SignerProvider } from '../web3telegram/types.js'; export const getWeb3Provider = ( privateKey: string, - options: { allowExperimentalNetworks?: boolean; host?: number | string } = {} -): Web3SignerProvider => { - const chainHost = options?.host - ? `${options.host}` - : 'arbitrum-sepolia-testnet'; - return getSignerFromPrivateKey(chainHost, privateKey, { + host: number | string, + options: { allowExperimentalNetworks?: boolean } = {} +): Web3SignerProvider => + getSignerFromPrivateKey(`${host}`, privateKey, { allowExperimentalNetworks: options?.allowExperimentalNetworks, }); -}; diff --git a/src/web3telegram/IExecWeb3telegram.ts b/src/web3telegram/IExecWeb3telegram.ts index a541a6a..cf10942 100644 --- a/src/web3telegram/IExecWeb3telegram.ts +++ b/src/web3telegram/IExecWeb3telegram.ts @@ -68,10 +68,10 @@ export class IExecWeb3telegram { private options: Web3TelegramConfigOptions; constructor( - ethProvider?: EthersCompatibleProvider, + ethProvider: EthersCompatibleProvider, options?: Web3TelegramConfigOptions ) { - this.ethProvider = ethProvider || 'arbitrum-sepolia-testnet'; + this.ethProvider = ethProvider; this.options = options || {}; } diff --git a/tests/e2e/constructor.test.ts b/tests/e2e/constructor.test.ts index e79a429..5ca262f 100644 --- a/tests/e2e/constructor.test.ts +++ b/tests/e2e/constructor.test.ts @@ -7,10 +7,7 @@ import { getTestWeb3SignerProvider, MAX_EXPECTED_WEB2_SERVICES_TIME, } from '../test-utils.js'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; +import { getChainDefaultConfig } from '../../src/config/config.js'; describe('IExecWeb3telegram()', () => { it('instantiates with a valid ethProvider', async () => { @@ -28,7 +25,7 @@ describe('IExecWeb3telegram()', () => { ); await web3telegram.init(); const ipfsGateway = web3telegram['ipfsGateway']; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); + const defaultConfig = getChainDefaultConfig(421614); expect(defaultConfig).not.toBeNull(); expect(ipfsGateway).toStrictEqual(defaultConfig!.ipfsGateway); }); @@ -54,7 +51,7 @@ describe('IExecWeb3telegram()', () => { ); await web3telegram.init(); const graphQLClient = web3telegram['graphQLClient']; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); + const defaultConfig = getChainDefaultConfig(421614); expect(defaultConfig).not.toBeNull(); expect(graphQLClient['url']).toBe(defaultConfig!.dataProtectorSubgraph); }); @@ -120,7 +117,9 @@ describe('IExecWeb3telegram()', () => { 'When calling a read method should work as expected', async () => { // --- GIVEN - const web3telegram = new IExecWeb3telegram(); + const web3telegram = new IExecWeb3telegram('421614', { + allowExperimentalNetworks: true, + }); const wallet = Wallet.createRandom(); // --- WHEN/THEN @@ -134,10 +133,8 @@ describe('IExecWeb3telegram()', () => { describe.skip('When instantiating SDK with an experimental network', () => { const experimentalNetworkSigner = getWeb3Provider( Wallet.createRandom().privateKey, - { - host: 421614, - allowExperimentalNetworks: true, - } + 421614, + { allowExperimentalNetworks: true } ); describe('Without allowExperimentalNetworks', () => { @@ -230,8 +227,7 @@ describe('IExecWeb3telegram()', () => { expect(chainConfig.dappAddress).toBeUndefined(); // ENS not supported on this network const web3telegram = new IExecWeb3telegram( - getWeb3Provider(Wallet.createRandom().privateKey, { - host: chainId, + getWeb3Provider(Wallet.createRandom().privateKey, chainId, { allowExperimentalNetworks: true, }), { allowExperimentalNetworks: true } diff --git a/tests/e2e/fetchMyContacts.test.ts b/tests/e2e/fetchMyContacts.test.ts index 4f90e19..6de397c 100644 --- a/tests/e2e/fetchMyContacts.test.ts +++ b/tests/e2e/fetchMyContacts.test.ts @@ -4,7 +4,7 @@ import { IExecWeb3telegram } from '../../src/index.js'; import { MAX_EXPECTED_BLOCKTIME, MAX_EXPECTED_WEB2_SERVICES_TIME, - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, + TEST_CHAIN, TEST_WEB3TELEGRAM_DAPP_ADDRESS, deployRandomDataset, getTestConfig, @@ -198,7 +198,7 @@ describe('web3telegram.fetchMyContacts()', () => { expect(noBulkContact).toBeUndefined(); }, MAX_EXPECTED_BLOCKTIME + - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME + + TEST_CHAIN.maxExpectedSubgraphIndexingTime + MAX_EXPECTED_WEB2_SERVICES_TIME ); diff --git a/tests/e2e/fetchUserContacts.test.ts b/tests/e2e/fetchUserContacts.test.ts index fd11dea..a2772b0 100644 --- a/tests/e2e/fetchUserContacts.test.ts +++ b/tests/e2e/fetchUserContacts.test.ts @@ -4,15 +4,12 @@ import { } from '@iexec/dataprotector'; import { beforeAll, describe, expect, it } from '@jest/globals'; import { HDNodeWallet, Wallet } from 'ethers'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; +import { getChainDefaultConfig } from '../../src/config/config.js'; import { IExecWeb3telegram, WorkflowError } from '../../src/index.js'; import { MAX_EXPECTED_BLOCKTIME, MAX_EXPECTED_WEB2_SERVICES_TIME, - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, + TEST_CHAIN, TEST_WEB3TELEGRAM_DAPP_ADDRESS, getTestConfig, setBalance, @@ -95,7 +92,7 @@ describe('web3telegram.fetchMyContacts()', () => { 'should return the user contacts for both app and whitelist', async () => { const userWithAccess = Wallet.createRandom().address; - const chainConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); + const chainConfig = getChainDefaultConfig(421614); expect(chainConfig).not.toBeNull(); const authorizedApp = TEST_WEB3TELEGRAM_DAPP_ADDRESS; const authorizedWhitelist = chainConfig!.whitelistSmartContract; @@ -302,7 +299,7 @@ describe('web3telegram.fetchMyContacts()', () => { expect(noBulkContact).toBeUndefined(); }, MAX_EXPECTED_BLOCKTIME + - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME + + TEST_CHAIN.maxExpectedSubgraphIndexingTime + MAX_EXPECTED_WEB2_SERVICES_TIME ); diff --git a/tests/e2e/prepareTelegramCampaign.test.ts b/tests/e2e/prepareTelegramCampaign.test.ts index 6f88ea5..9d19236 100644 --- a/tests/e2e/prepareTelegramCampaign.test.ts +++ b/tests/e2e/prepareTelegramCampaign.test.ts @@ -8,7 +8,6 @@ import { Contact, IExecWeb3telegram } from '../../src/index.js'; import { MAX_EXPECTED_BLOCKTIME, MAX_EXPECTED_WEB2_SERVICES_TIME, - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, TEST_CHAIN, TEST_WEB3TELEGRAM_DAPP_ADDRESS, createAndPublishAppOrders, @@ -82,7 +81,7 @@ describe('web3telegram.prepareTelegramCampaign()', () => { }); await waitSubgraphIndexing(); - }, 5 * (MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME) + MAX_EXPECTED_SUBGRAPH_INDEXING_TIME + 5_000); + }, 5 * (MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME) + TEST_CHAIN.maxExpectedSubgraphIndexingTime + 5_000); beforeEach(async () => { consumerWallet = getRandomWallet(); @@ -114,7 +113,7 @@ describe('web3telegram.prepareTelegramCampaign()', () => { web3telegram = new IExecWeb3telegram( ...getTestConfig(consumerWallet.privateKey) ); - }, MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_SUBGRAPH_INDEXING_TIME); + }, MAX_EXPECTED_BLOCKTIME + TEST_CHAIN.maxExpectedSubgraphIndexingTime); it( 'should prepare a telegram campaignRequest', diff --git a/tests/e2e/sendTelegram.test.ts b/tests/e2e/sendTelegram.test.ts index 56f6d7a..a05b06c 100644 --- a/tests/e2e/sendTelegram.test.ts +++ b/tests/e2e/sendTelegram.test.ts @@ -37,7 +37,6 @@ describe('web3telegram.sendTelegram()', () => { let validProtectedData: ProtectedDataWithSecretProps; let invalidProtectedData: ProtectedDataWithSecretProps; let consumerIExecInstance: IExec; - let learnProdWorkerpoolAddress: string; const iexecOptions = getTestIExecOption(); beforeAll(async () => { @@ -59,8 +58,6 @@ describe('web3telegram.sendTelegram()', () => { TEST_WEB3TELEGRAM_DAPP_ADDRESS ); - learnProdWorkerpoolAddress = TEST_CHAIN.prodWorkerpool; - dataProtector = new IExecDataProtectorCore( ...getTestConfig(providerWallet.privateKey) ); @@ -199,7 +196,7 @@ describe('web3telegram.sendTelegram()', () => { web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: invalidProtectedData.address, - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, }) ).rejects.toThrow('Failed to sendTelegram'); @@ -208,7 +205,7 @@ describe('web3telegram.sendTelegram()', () => { await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: invalidProtectedData.address, - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, }); } catch (err) { error = err as Web3TelegramWorkflowError; @@ -236,7 +233,7 @@ describe('web3telegram.sendTelegram()', () => { web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: protectedData.address, - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, }) ).rejects.toThrow( new WorkflowError({ @@ -269,7 +266,7 @@ describe('web3telegram.sendTelegram()', () => { try { await invalidWeb3telegram.sendTelegram({ protectedData: validProtectedData.address, - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, telegramContent: 'e2e telegram content for test', }); } catch (err) { @@ -291,7 +288,7 @@ describe('web3telegram.sendTelegram()', () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, }); expect(sendTelegramResponse).toStrictEqual({ dealId: expect.any(String), @@ -319,7 +316,7 @@ describe('web3telegram.sendTelegram()', () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: protectedDataForWhitelist.address, - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, }); expect('taskId' in sendTelegramResponse).toBe(true); expect(sendTelegramResponse).toStrictEqual({ @@ -337,7 +334,7 @@ describe('web3telegram.sendTelegram()', () => { telegramContent: '

Test html

test paragraph

', protectedData: validProtectedData.address, - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, }); expect('taskId' in sendTelegramResponse).toBe(true); expect(sendTelegramResponse).toStrictEqual({ @@ -355,7 +352,7 @@ describe('web3telegram.sendTelegram()', () => { telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, senderName: 'Product Team', - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, }); expect(sendTelegramResponse).toBeDefined(); expect('taskId' in sendTelegramResponse).toBe(true); @@ -378,7 +375,7 @@ describe('web3telegram.sendTelegram()', () => { telegramContent: LARGE_CONTENT, protectedData: validProtectedData.address, senderName: 'Product Team', - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, }); expect(sendTelegramResponse).toStrictEqual({ dealId: expect.any(String), @@ -394,7 +391,7 @@ describe('web3telegram.sendTelegram()', () => { const sendTelegramResponse = await web3telegram.sendTelegram({ telegramContent: 'e2e telegram content for test', protectedData: validProtectedData.address, - workerpoolAddress: learnProdWorkerpoolAddress, + workerpoolAddress: TEST_CHAIN.prodWorkerpool, label: 'ID1234678', }); expect(sendTelegramResponse).toStrictEqual({ diff --git a/tests/e2e/sendTelegramCampaign.test.ts b/tests/e2e/sendTelegramCampaign.test.ts index 4b3a11a..f32af5d 100644 --- a/tests/e2e/sendTelegramCampaign.test.ts +++ b/tests/e2e/sendTelegramCampaign.test.ts @@ -8,7 +8,6 @@ import { Contact, IExecWeb3telegram } from '../../src/index.js'; import { MAX_EXPECTED_BLOCKTIME, MAX_EXPECTED_WEB2_SERVICES_TIME, - MAX_EXPECTED_SUBGRAPH_INDEXING_TIME, TEST_CHAIN, TEST_WEB3TELEGRAM_DAPP_ADDRESS, createAndPublishAppOrders, @@ -85,7 +84,7 @@ describe('web3telegram.sendTelegramCampaign() - Bulk Processing', () => { }); await waitSubgraphIndexing(); - }, 5 * (MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME) + MAX_EXPECTED_SUBGRAPH_INDEXING_TIME + 5_000); + }, 5 * (MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME) + TEST_CHAIN.maxExpectedSubgraphIndexingTime + 5_000); beforeEach(async () => { consumerWallet = getRandomWallet(); diff --git a/tests/test-utils.ts b/tests/test-utils.ts index 5d60168..903059c 100644 --- a/tests/test-utils.ts +++ b/tests/test-utils.ts @@ -40,15 +40,24 @@ export const TEST_CHAIN = { }), hubAddress: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E', isNative: false, + subgraphUrl: 'http://127.0.0.1:8000/subgraphs/name/DataProtector-v2', + maxExpectedSubgraphIndexingTime: 5_000, + /** + * [rlc-multichain](https://github.com/iExecBlockchainComputing/rlc-multichain/tree/v0.1.0) is an openzeppelin ERC20Upgradeable contract + * + * ERC20Upgradeable contract use a specific storage slot, which is: + * ``` + * // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff)) + * bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00; + * ``` + * sources: https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v5.3.0/contracts/token/ERC20/ERC20Upgradeable.sol#L43-L44 + */ + erc20BalanceSlot: + '0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00' as const, }; export const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms)); -export const MAX_EXPECTED_SUBGRAPH_INDEXING_TIME = 5_000; - -const DATAPROTECTOR_SUBGRAPH_URL = - 'http://127.0.0.1:8000/subgraphs/name/DataProtector-v2'; - export const waitSubgraphIndexing = async ( timeoutMs = 60_000 ): Promise => { @@ -58,7 +67,7 @@ export const waitSubgraphIndexing = async ( const deadline = Date.now() + timeoutMs; while (Date.now() < deadline) { try { - const res = await fetch(DATAPROTECTOR_SUBGRAPH_URL, { + const res = await fetch(TEST_CHAIN.subgraphUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: '{ _meta { block { number } } }' }), @@ -144,13 +153,10 @@ const anvilSetNRlcTokenBalance = async ( ); const rlcAddress = await hubContract.token(); - const erc20StorageLocation = - '0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00'; - const balanceSlot = keccak256( AbiCoder.defaultAbiCoder().encode( ['address', 'uint256'], - [address, erc20StorageLocation] + [address, TEST_CHAIN.erc20BalanceSlot] ) ); @@ -196,18 +202,15 @@ export const getTestIExecOption = () => ({ }); export const getTestConfig = ( - privateKey?: string + privateKey: string ): [Web3SignerProvider, Web3TelegramConfigOptions] => { - const ethProvider = privateKey - ? getTestWeb3SignerProvider(privateKey) - : undefined; + const ethProvider = getTestWeb3SignerProvider(privateKey); const options = { dappAddress: TEST_WEB3TELEGRAM_DAPP_ADDRESS, iexecOptions: getTestIExecOption(), ipfsGateway: 'http://127.0.0.1:8080', ipfsNode: 'http://127.0.0.1:5001', - dataProtectorSubgraph: - 'http://127.0.0.1:8000/subgraphs/name/DataProtector-v2', + dataProtectorSubgraph: TEST_CHAIN.subgraphUrl, }; return [ethProvider, options]; }; @@ -246,16 +249,8 @@ export const getRandomTxHash = () => { export const createAndPublishAppOrders = async ( resourceProvider, - appAddressOrEns + appAddress: string ) => { - let appAddress = appAddressOrEns; - if (appAddressOrEns && appAddressOrEns.includes('.eth')) { - appAddress = await resourceProvider.ens.resolveName(appAddressOrEns); - if (!appAddress) { - throw new Error(`Failed to resolve ENS name: ${appAddressOrEns}`); - } - } - await resourceProvider.order .createApporder({ app: appAddress, diff --git a/tests/unit/constructor.test.ts b/tests/unit/constructor.test.ts index 4d939ca..69ef598 100644 --- a/tests/unit/constructor.test.ts +++ b/tests/unit/constructor.test.ts @@ -3,10 +3,10 @@ import { IExecWeb3telegram } from '../../src/index.js'; describe('When instantiating SDK without a signer', () => { describe('When calling a write method', () => { it('should throw an error for unauthorized method', async () => { - // --- GIVEN - const web3telegram = new IExecWeb3telegram(); + const web3telegram = new IExecWeb3telegram('421614', { + allowExperimentalNetworks: true, + }); - // --- WHEN/THEN await expect(web3telegram.fetchMyContacts()).rejects.toThrow( 'Unauthorized method. Please log in with your wallet, you must set a valid provider with a signer.' ); diff --git a/tests/unit/fetchMyContacts.test.ts b/tests/unit/fetchMyContacts.test.ts index 5955074..ec48b74 100644 --- a/tests/unit/fetchMyContacts.test.ts +++ b/tests/unit/fetchMyContacts.test.ts @@ -1,9 +1,6 @@ import { describe, expect, it, jest } from '@jest/globals'; import { Address } from 'iexec'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; +import { getChainDefaultConfig } from '../../src/config/config.js'; import { type FetchMyContacts } from '../../src/web3telegram/fetchMyContacts.js'; import { getRandomAddress, @@ -17,7 +14,7 @@ jest.unstable_mockModule('../../src/utils/subgraphQuery.js', () => ({ describe('fetchMyContacts', () => { let testedModule: any; let fetchMyContacts: FetchMyContacts; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); + const defaultConfig = getChainDefaultConfig(421614); beforeAll(async () => { // import tested module after all mocked modules @@ -67,11 +64,6 @@ describe('fetchMyContacts', () => { .fn<() => Promise
>() .mockResolvedValue(getRandomAddress()), }, - ens: { - resolveName: jest - .fn<() => Promise
>() - .mockResolvedValue(getRandomAddress()), - }, orderbook: { fetchDatasetOrderbook: mockFetchDatasetOrderbook, }, @@ -128,11 +120,6 @@ describe('fetchMyContacts', () => { .fn<() => Promise
>() .mockResolvedValue(getRandomAddress()), }, - ens: { - resolveName: jest - .fn<() => Promise
>() - .mockResolvedValue(getRandomAddress()), - }, orderbook: { fetchDatasetOrderbook: mockFetchDatasetOrderbook, }, @@ -202,11 +189,6 @@ describe('fetchMyContacts', () => { .fn<() => Promise
>() .mockResolvedValue(getRandomAddress()), }, - ens: { - resolveName: jest - .fn<() => Promise
>() - .mockResolvedValue(getRandomAddress()), - }, orderbook: { fetchDatasetOrderbook: mockFetchDatasetOrderbook, }, @@ -250,11 +232,6 @@ describe('fetchMyContacts', () => { .fn<() => Promise
>() .mockResolvedValue(getRandomAddress()), }, - ens: { - resolveName: jest - .fn<() => Promise
>() - .mockResolvedValue(getRandomAddress()), - }, orderbook: { fetchDatasetOrderbook: mockFetchDatasetOrderbook, }, @@ -312,11 +289,6 @@ describe('fetchMyContacts', () => { .fn<() => Promise
>() .mockResolvedValue(getRandomAddress()), }, - ens: { - resolveName: jest - .fn<() => Promise
>() - .mockResolvedValue(getRandomAddress()), - }, orderbook: { fetchDatasetOrderbook: mockFetchDatasetOrderbook, }, @@ -374,11 +346,6 @@ describe('fetchMyContacts', () => { .fn<() => Promise
>() .mockResolvedValue(getRandomAddress()), }, - ens: { - resolveName: jest - .fn<() => Promise
>() - .mockResolvedValue(getRandomAddress()), - }, orderbook: { fetchDatasetOrderbook: mockFetchDatasetOrderbook, }, diff --git a/tests/unit/sendTelegram.test.ts b/tests/unit/sendTelegram.test.ts index 5611bdf..aab5cfd 100644 --- a/tests/unit/sendTelegram.test.ts +++ b/tests/unit/sendTelegram.test.ts @@ -4,10 +4,7 @@ import { getRandomAddress, TEST_WEB3TELEGRAM_DAPP_ADDRESS, } from '../test-utils.js'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; +import { getChainDefaultConfig } from '../../src/config/config.js'; import { mockAllForSendTelegram } from '../utils/mockAllForSendTelegram.js'; jest.unstable_mockModule('../../src/utils/subgraphQuery.js', () => ({ @@ -24,7 +21,7 @@ jest.unstable_mockModule('../../src/utils/ipfs-service.js', () => ({ describe('sendTelegram', () => { let testedModule: any; let sendTelegram: SendTelegram; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); + const defaultConfig = getChainDefaultConfig(421614); beforeAll(async () => { // import tested module after all mocked modules diff --git a/tests/unit/sendTelegramCampaign.test.ts b/tests/unit/sendTelegramCampaign.test.ts index f798661..caea349 100644 --- a/tests/unit/sendTelegramCampaign.test.ts +++ b/tests/unit/sendTelegramCampaign.test.ts @@ -1,16 +1,13 @@ import { expect, it, jest, describe, beforeAll } from '@jest/globals'; import { type SendTelegramCampaign } from '../../src/web3telegram/sendTelegramCampaign.js'; import { getRandomAddress } from '../test-utils.js'; -import { - DEFAULT_CHAIN_ID, - getChainDefaultConfig, -} from '../../src/config/config.js'; +import { getChainDefaultConfig } from '../../src/config/config.js'; import { BulkRequest } from '@iexec/dataprotector'; describe('sendTelegramCampaign', () => { let testedModule: any; let sendTelegramCampaign: SendTelegramCampaign; - const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID); + const defaultConfig = getChainDefaultConfig(421614); beforeAll(async () => { // import tested module after all mocked modules diff --git a/tests/utils/mockAllForSendTelegram.ts b/tests/utils/mockAllForSendTelegram.ts index 5fa86a6..8ba7559 100644 --- a/tests/utils/mockAllForSendTelegram.ts +++ b/tests/utils/mockAllForSendTelegram.ts @@ -11,11 +11,6 @@ export function mockAllForSendTelegram() { .fn<() => Promise
>() .mockResolvedValue(getRandomAddress()), }, - ens: { - resolveName: jest - .fn<() => Promise
>() - .mockResolvedValue(getRandomAddress()), - }, orderbook: { fetchDatasetOrderbook: jest .fn<() => Promise<{ orders: any[] }>>() From c94b020a8c55a4d5f635315656689df208d6617b Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:56:09 +0200 Subject: [PATCH 8/9] test: fix subgraph deployer --- tests/docker-compose.yml | 13 +++++-------- tests/test-utils.ts | 3 ++- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index ed688c6..c341fd4 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -246,9 +246,8 @@ services: postgres_pass: password postgres_db: graphnode-db ipfs: ipfs:5001 - # Alias arbitrum-sepolia-fork as "bellecour" so the subgraph template (hardcoded network name) works - ethereum: 'bellecour:http://arbitrum-sepolia-fork:8545' - GRAPH_ETHEREUM_GENESIS_BLOCK_NUMBER: $ARBITRUM_SEPOLIA_FORK_BLOCK + ethereum: 'arbitrum-sepolia:http://arbitrum-sepolia-fork:8545' + GRAPH_ETHEREUM_GENESIS_BLOCK_NUMBER: $ARBITRUM_SEPOLIA_INDEX_BLOCK depends_on: arbitrum-sepolia-fork: condition: service_healthy @@ -265,7 +264,7 @@ services: dataprotector-subgraph-deployer: platform: linux/amd64 - image: iexechub/dataprotector-subgraph-deployer:3.0.0 + image: iexechub/dataprotector-subgraph-deployer:3.1.1-main-4df5c2d restart: 'no' depends_on: graphnode: @@ -273,13 +272,11 @@ services: ipfs: condition: service_started environment: - ENV: prod START_BLOCK: $ARBITRUM_SEPOLIA_INDEX_BLOCK - DATAPROTECTOR_ADDRESS: '0x168eAF6C33a77E3caD9db892452f51a5D91df621' - APP_REGISTRY_ADDRESS: '0x9950D94FB074182eE93fF79a50CD698C4983281F' - DATASET_REGISTRY_ADDRESS: '0x07cc4E1Ea30dD02796795876509a3bfC5053128d' + NETWORK_NAME: arbitrum-sepolia GRAPHNODE_URL: http://graphnode:8020 IPFS_URL: http://ipfs:5001 + ENV: prod stack-ready: image: bash diff --git a/tests/test-utils.ts b/tests/test-utils.ts index 903059c..f06e0d8 100644 --- a/tests/test-utils.ts +++ b/tests/test-utils.ts @@ -40,7 +40,8 @@ export const TEST_CHAIN = { }), hubAddress: '0xB2157BF2fAb286b2A4170E3491Ac39770111Da3E', isNative: false, - subgraphUrl: 'http://127.0.0.1:8000/subgraphs/name/DataProtector-v2', + subgraphUrl: + 'http://127.0.0.1:8000/subgraphs/name/arbitrum-sepolia/dataprotector-v2', maxExpectedSubgraphIndexingTime: 5_000, /** * [rlc-multichain](https://github.com/iExecBlockchainComputing/rlc-multichain/tree/v0.1.0) is an openzeppelin ERC20Upgradeable contract From f5b8b79d6e4badebc33aa19bc25375d19f5b3746 Mon Sep 17 00:00:00 2001 From: Pierre Jeanjacquot <26487010+PierreJeanjacquot@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:56:21 +0200 Subject: [PATCH 9/9] chore: cleanup scripts --- package.json | 2 +- tests/scripts/prepare-iexec.js | 24 ------------------------ 2 files changed, 1 insertion(+), 25 deletions(-) delete mode 100644 tests/scripts/prepare-iexec.js diff --git a/package.json b/package.json index 6088fd8..0d2dbe4 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "scripts": { "build": "rm -rf dist && tsc --project tsconfig.build.json", "check-types": "tsc --noEmit", - "test:prepare": "node tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js && node tests/scripts/prepare-iexec.js", + "test:prepare": "node tests/scripts/prepare-arbitrum-sepolia-fork-for-tests.js", "test": "NODE_OPTIONS=--experimental-vm-modules jest --testMatch \"**/tests/**/*.test.ts\" --forceExit -b", "test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --testMatch \"**/tests/**/*.test.ts\" --forceExit --coverage", "test:unit": "NODE_OPTIONS=--experimental-vm-modules jest --testMatch \"**/tests/unit/**/*.test.ts\" -b", diff --git a/tests/scripts/prepare-iexec.js b/tests/scripts/prepare-iexec.js deleted file mode 100644 index c2dd4ff..0000000 --- a/tests/scripts/prepare-iexec.js +++ /dev/null @@ -1,24 +0,0 @@ -import { readFile, writeFile } from 'fs/promises'; -import { resolve } from 'path'; - -const disableCheckImplementedOnChain = async () => { - const configModulePath = resolve( - 'node_modules/iexec/dist/esm/common/utils/config.js' - ); - const configModule = await readFile(configModulePath, 'utf8'); - const OG_CODE_SNIPPET = - 'export const checkImplementedOnChain = (chainId, featureName) => {'; - const REPLACEMENT_CODE_SNIPPET = - 'export const checkImplementedOnChain = (chainId, featureName) => { return;'; - - if (!configModule.includes(REPLACEMENT_CODE_SNIPPET)) { - console.log('disabling checkImplementedOnChain implementation...'); - const patchedConfigModule = configModule.replace( - OG_CODE_SNIPPET, - REPLACEMENT_CODE_SNIPPET - ); - await writeFile(configModulePath, patchedConfigModule, 'utf8'); - } -}; - -disableCheckImplementedOnChain();