From 6bd8b1988e7c131f7daf5716eb01f291ef6be917 Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:10:37 +0200 Subject: [PATCH 1/2] fix(dapp): resolve IPFS gateway from WEB3TELEGRAM_IPFS_GATEWAY Inject gateway at image build via Dockerfile ARG/ENV and GitHub Environment (read-ipfs-gateway + docker build-args), aligned with web3mail. --- .github/workflows/dapp-deploy.yml | 14 ++++- dapp/.env.override | 1 + dapp/Dockerfile | 2 + dapp/README.md | 7 ++- dapp/src/decryptContent.js | 12 +++- .../_test_outputs_/iexec_out/result.json | 58 +------------------ dapp/tests/e2e/app.test.js | 3 + dapp/tests/unit/decryptContent.test.js | 32 ++++++++-- 8 files changed, 65 insertions(+), 64 deletions(-) diff --git a/.github/workflows/dapp-deploy.yml b/.github/workflows/dapp-deploy.yml index ab32d75..9e7e9b3 100644 --- a/.github/workflows/dapp-deploy.yml +++ b/.github/workflows/dapp-deploy.yml @@ -41,14 +41,26 @@ jobs: else echo "clean_tag=dev" | tee -a $GITHUB_OUTPUT fi + read-ipfs-gateway: + runs-on: ubuntu-latest + environment: ${{ github.event.inputs.environment }} + outputs: + web3telegram_ipfs_gateway: ${{ vars.WEB3TELEGRAM_IPFS_GATEWAY }} + steps: + - name: WEB3TELEGRAM_IPFS_GATEWAY + run: echo "WEB3TELEGRAM_IPFS_GATEWAY=$WEB3TELEGRAM_IPFS_GATEWAY" + env: + WEB3TELEGRAM_IPFS_GATEWAY: ${{ vars.WEB3TELEGRAM_IPFS_GATEWAY }} + docker-publish: uses: iExecBlockchainComputing/github-actions-workflows/.github/workflows/docker-build.yml@docker-build-v3.3.0 - needs: [extract-tag] + needs: [extract-tag, read-ipfs-gateway] with: image-name: 'iexechub/web3telegram-dapp' registry: 'docker.io' dockerfile: 'dapp/Dockerfile' context: 'dapp' + build-args: WEB3TELEGRAM_IPFS_GATEWAY=${{ needs.read-ipfs-gateway.outputs.web3telegram_ipfs_gateway }} security-scan: false hadolint: true push: true diff --git a/dapp/.env.override b/dapp/.env.override index 7e45e38..8760214 100644 --- a/dapp/.env.override +++ b/dapp/.env.override @@ -1,3 +1,4 @@ +WEB3TELEGRAM_IPFS_GATEWAY=https://ipfs-gateway.v8-bellecour.iex.ec IEXEC_IN=/path/to/input/directory IEXEC_OUT=/path/to/output/directory IEXEC_DATASET_FILENAME="protectedData.zip" diff --git a/dapp/Dockerfile b/dapp/Dockerfile index 2f0040a..369ede6 100644 --- a/dapp/Dockerfile +++ b/dapp/Dockerfile @@ -1,4 +1,6 @@ FROM node:22-alpine3.22 +ARG WEB3TELEGRAM_IPFS_GATEWAY +ENV WEB3TELEGRAM_IPFS_GATEWAY=$WEB3TELEGRAM_IPFS_GATEWAY WORKDIR /app COPY package*.json ./ RUN npm ci --production diff --git a/dapp/README.md b/dapp/README.md index 01c13de..9511bef 100644 --- a/dapp/README.md +++ b/dapp/README.md @@ -19,6 +19,7 @@ fill in the environment variables: - **IEXEC_DATASET\_\\_FILENAME**: The name of the data file for dataset at index (starting from 1) that you place in the **IEXEC_IN** directory. - **IEXEC_APP_DEVELOPER_SECRET**: A JSON string with the following keys: - **TELEGRAM_BOT_TOKEN**: The API key of the telegram bot used to send the message. +- **WEB3TELEGRAM_IPFS_GATEWAY**: Base URL of the iExec IPFS gateway used to download encrypted message content (must match the chain where content was pinned, e.g. `https://ipfs-gateway.v8-bellecour.iex.ec` or `https://ipfs-gateway.arbitrum-mainnet.iex.ec`). Baked into release images via the deploy workflow; required for local runs. - **IEXEC_REQUESTER_SECRET_1**: A JSON string with the following keys: - **telegramContentMultiAddr**: Multiaddress pointing to the encrypted message content to send. - **telegramContentEncryptionKey**: The encryption key used to encrypt the content. @@ -43,9 +44,12 @@ The Dapp will send a telegram message using the object and content specified in 1. **Build the Docker image**: Navigate to the `/web3telegram/dapp` directory of the project and run the following command to build the Docker image: ```sh - docker build . --tag web3telegram-dapp + docker build . --tag web3telegram-dapp \ + --build-arg WEB3TELEGRAM_IPFS_GATEWAY=https://ipfs-gateway.v8-bellecour.iex.ec ``` + Use the gateway URL for the same chain as your pinned content (see `src/config/config.ts` `ipfsGateway` per chain). + 2. **Create local directories**: In your terminal, execute the following commands to create two local directories on your machine: ```sh @@ -69,6 +73,7 @@ The Dapp will send a telegram message using the object and content specified in -e IEXEC_IN=/iexec_in \ -e IEXEC_OUT=/iexec_out \ -e IEXEC_DATASET_FILENAME=data.zip \ + -e WEB3TELEGRAM_IPFS_GATEWAY=https://ipfs-gateway.v8-bellecour.iex.ec \ IEXEC_REQUESTER_SECRET_1='{"telegramContentEncryptionKey":"telegram_content_encryption_key","telegramContentMultiAddr":"encrypted_telegram_content_multiaddress","senderName":"sender_name","contentType":"text/plain"}' \ web3telegram-dapp ``` diff --git a/dapp/src/decryptContent.js b/dapp/src/decryptContent.js index 8f588a6..390a7a5 100644 --- a/dapp/src/decryptContent.js +++ b/dapp/src/decryptContent.js @@ -2,11 +2,19 @@ import { Buffer } from 'buffer'; import fetch from 'node-fetch'; import forge from 'node-forge'; -const DEFAULT_IPFS_GATEWAY = 'https://ipfs-gateway.v8-bellecour.iex.ec'; +export const resolveIpfsGatewayUrl = () => { + const url = process.env.WEB3TELEGRAM_IPFS_GATEWAY; + if (url == null || String(url).trim() === '') { + throw new Error( + 'WEB3TELEGRAM_IPFS_GATEWAY environment variable is not set.' + ); + } + return String(url).trim(); +}; export const downloadEncryptedContent = async ( multiaddr, - { ipfsGateway = DEFAULT_IPFS_GATEWAY } = {} + { ipfsGateway = resolveIpfsGatewayUrl() } = {} ) => { try { const publicUrl = `${ipfsGateway}${multiaddr.replace('/p2p/', '/ipfs/')}`; diff --git a/dapp/tests/_test_outputs_/iexec_out/result.json b/dapp/tests/_test_outputs_/iexec_out/result.json index 31cb693..680203c 100644 --- a/dapp/tests/_test_outputs_/iexec_out/result.json +++ b/dapp/tests/_test_outputs_/iexec_out/result.json @@ -1,58 +1,4 @@ { - "success": true, - "totalCount": 10, - "successCount": 10, - "errorCount": 0, - "results": [ - { - "index": 1, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 2, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 3, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 4, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 5, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 6, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 7, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 8, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 9, - "protectedData": "data-chatId.zip", - "success": true - }, - { - "index": 10, - "protectedData": "data-chatId.zip", - "success": true - } - ] + "success": false, + "error": "App secret error: \"TELEGRAM_BOT_TOKEN\" is required" } \ No newline at end of file diff --git a/dapp/tests/e2e/app.test.js b/dapp/tests/e2e/app.test.js index 4a63d4d..646fd09 100644 --- a/dapp/tests/e2e/app.test.js +++ b/dapp/tests/e2e/app.test.js @@ -36,6 +36,9 @@ describe('sendTelegram', () => { beforeEach(() => { // protected data setup 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'; // 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 0aead62..47a8f75 100644 --- a/dapp/tests/unit/decryptContent.test.js +++ b/dapp/tests/unit/decryptContent.test.js @@ -5,8 +5,11 @@ import { IExec } from 'iexec'; import { decryptContent, downloadEncryptedContent, + resolveIpfsGatewayUrl, } from '../../src/decryptContent'; +const TEST_IPFS_GATEWAY = 'https://ipfs-gateway.v8-bellecour.iex.ec'; + describe('decryptContent', () => { it('should decrypt message correctly', async () => { const iexec = new IExec({ @@ -33,21 +36,42 @@ describe('decryptContent', () => { }); }); +describe('resolveIpfsGatewayUrl', () => { + const prev = process.env.WEB3TELEGRAM_IPFS_GATEWAY; + + afterAll(() => { + if (prev === undefined) { + delete process.env.WEB3TELEGRAM_IPFS_GATEWAY; + } else { + process.env.WEB3TELEGRAM_IPFS_GATEWAY = prev; + } + }); + + it('should throw if WEB3TELEGRAM_IPFS_GATEWAY is not set', () => { + delete process.env.WEB3TELEGRAM_IPFS_GATEWAY; + expect(() => resolveIpfsGatewayUrl()).toThrow( + Error('WEB3TELEGRAM_IPFS_GATEWAY environment variable is not set.') + ); + }); +}); + describe('downloadEncryptedContent', () => { it('should return the encrypted content', async () => { const content = `{"JSONPath":"$['rates']['GBP']","body":"","dataType":"number","dataset":"0x0000000000000000000000000000000000000000","headers":{},"method":"GET","url":"https://api.exchangerate.host/latest?base=USD&symbols=GBP"}`; const textEncoder = new TextEncoder(); const actualContent = await textEncoder.encode(content); const multiaddr = '/ipfs/Qmb1JLTVp4zfRMPaori9htzzM9D3B1tG8pGbZYTRC1favA'; - const expectedContent = await downloadEncryptedContent(multiaddr); + const expectedContent = await downloadEncryptedContent(multiaddr, { + ipfsGateway: TEST_IPFS_GATEWAY, + }); expect(actualContent).toEqual(expectedContent); }); it('should throw an error if the content cannot be loaded', async () => { const multiaddr = '/ipfs/QmYhXeg4p4D729m432t8b9877b35e756a82749723456789invalid'; - await expect(downloadEncryptedContent(multiaddr)).rejects.toThrow( - Error('Failed to download encrypted content') - ); + await expect( + downloadEncryptedContent(multiaddr, { ipfsGateway: TEST_IPFS_GATEWAY }) + ).rejects.toThrow(Error('Failed to download encrypted content')); }); }); From c2915a0d879f1d8e5134b0866d2a12e0e4e1a13d Mon Sep 17 00:00:00 2001 From: paypes <43441600+abbesBenayache@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:14:48 +0200 Subject: [PATCH 2/2] chore(dapp): restore e2e result.json fixture to match main Made-with: Cursor --- .../_test_outputs_/iexec_out/result.json | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/dapp/tests/_test_outputs_/iexec_out/result.json b/dapp/tests/_test_outputs_/iexec_out/result.json index 680203c..31cb693 100644 --- a/dapp/tests/_test_outputs_/iexec_out/result.json +++ b/dapp/tests/_test_outputs_/iexec_out/result.json @@ -1,4 +1,58 @@ { - "success": false, - "error": "App secret error: \"TELEGRAM_BOT_TOKEN\" is required" + "success": true, + "totalCount": 10, + "successCount": 10, + "errorCount": 0, + "results": [ + { + "index": 1, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 2, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 3, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 4, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 5, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 6, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 7, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 8, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 9, + "protectedData": "data-chatId.zip", + "success": true + }, + { + "index": 10, + "protectedData": "data-chatId.zip", + "success": true + } + ] } \ No newline at end of file