Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"buffer": "^6.0.3",
"ethers": "^6.8.1",
"graphql-request": "^6.1.0",
"iexec": "^8.16.1",
"iexec": "^8.17.0",
"kubo-rpc-client": "^4.1.3",
"yup": "^1.1.1"
},
Expand Down
4 changes: 2 additions & 2 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const DEFAULT_CHAIN_ID = 134;

interface ChainConfig {
name: string;
dappAddress: string;
dappAddress?: string;
prodWorkerpoolAddress: string;
dataProtectorSubgraph: string;
ipfsUploadUrl: string;
Expand All @@ -29,7 +29,7 @@ export const CHAIN_CONFIG: Record<number, ChainConfig> = {
},
421614: {
name: 'arbitrum-sepolia-testnet',
dappAddress: 'web3telegram.apps.iexec.eth',
dappAddress: undefined, // ENS not supported on this network, address will be resolved from Compass
prodWorkerpoolAddress: '0x39c3cdd91a7f1c4ed59108a9da4e79de9a1c1b59',
dataProtectorSubgraph:
'https://thegraph.arbitrum-sepolia-testnet.iex.ec/api/subgraphs/id/5YjRPLtjS6GH6bB4yY55Qg4HzwtRGQ8TaHtGf9UBWWd',
Expand Down
55 changes: 55 additions & 0 deletions src/utils/resolveDappAddressFromCompass.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { CompassCallError } from 'iexec/errors';
import { AddressOrENS } from '../web3telegram/types.js';

export async function resolveDappAddressFromCompass(
compassUrl: string,
chainId: number
): Promise<AddressOrENS | undefined> {
if (!compassUrl) {
return undefined;
}

return (
fetch(`${compassUrl}/${chainId}/iapps/web3telegram`)
// Handle network errors
.catch((error) => {
throw new CompassCallError(
`Connection to ${compassUrl} failed with a network error`,
error
);
})
// Handle server errors
.then((response) => {
if (response.status >= 500 && response.status <= 599) {
throw new CompassCallError(
`Server at ${compassUrl} encountered an internal error`,
Error(
`Server internal error: ${response.status} ${response.statusText}`
)
);
}
return response;
})
// Handle unexpected response formats
.then((response) => {
if (response.status !== 200) {
throw new Error(
`Failed to fetch dapp address from compass: ${response.statusText}`
);
}
const contentType = response.headers.get('Content-Type');
if (!contentType || contentType.indexOf('application/json') === -1) {
Copy link

Copilot AI Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Use includes() method instead of indexOf() for better readability and modern JavaScript practices.

Suggested change
if (!contentType || contentType.indexOf('application/json') === -1) {
if (!contentType || !contentType.includes('application/json')) {

Copilot uses AI. Check for mistakes.
throw new Error(
'Failed to fetch dapp address from compass: response is not JSON'
);
}
return response.json();
})
.then((data) => {
if (!data || !data.address) {
throw new Error(`No dapp address found in compass response`);
}
return data.address;
})
);
}
44 changes: 26 additions & 18 deletions src/web3telegram/IExecWeb3telegram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import { getChainDefaultConfig } from '../config/config.js';
import { isValidProvider } from '../utils/validators.js';
import { getChainIdFromProvider } from '../utils/getChainId.js';
import { resolveDappAddressFromCompass } from '../utils/resolveDappAddressFromCompass.js';

type EthersCompatibleProvider =
| AbstractProvider
Expand Down Expand Up @@ -126,16 +127,38 @@
allowExperimentalNetworks: this.options.allowExperimentalNetworks,
});

const ipfsGateway =
this.options?.ipfsGateway || chainDefaultConfig?.ipfsGateway;

let iexec: IExec, graphQLClient: GraphQLClient;

try {
iexec = new IExec(
{ ethProvider: this.ethProvider },
{
ipfsGatewayURL: ipfsGateway,
...this.options?.iexecOptions,
allowExperimentalNetworks: this.options.allowExperimentalNetworks,
}
);
} catch (e: any) {

Check warning on line 144 in src/web3telegram/IExecWeb3telegram.ts

View workflow job for this annotation

GitHub Actions / check-code

Unexpected any. Specify a different type
throw new Error(`Unsupported ethProvider: ${e.message}`);
}

const subgraphUrl =
this.options?.dataProtectorSubgraph ||
chainDefaultConfig?.dataProtectorSubgraph;
const dappAddressOrENS =
this.options?.dappAddressOrENS || chainDefaultConfig?.dappAddress;
this.options?.dappAddressOrENS ||
chainDefaultConfig?.dappAddress ||
(await resolveDappAddressFromCompass(
await iexec.config.resolveCompassURL(),
chainId
));
const dappWhitelistAddress =
this.options?.dappWhitelistAddress ||
chainDefaultConfig?.whitelistSmartContract;
const ipfsGateway =
this.options?.ipfsGateway || chainDefaultConfig?.ipfsGateway;

const defaultWorkerpool = chainDefaultConfig?.prodWorkerpoolAddress;
const ipfsNode =
this.options?.ipfsNode || chainDefaultConfig?.ipfsUploadUrl;
Expand All @@ -156,24 +179,9 @@
);
}

let iexec: IExec, graphQLClient: GraphQLClient;

try {
iexec = new IExec(
{ ethProvider: this.ethProvider },
{
ipfsGatewayURL: ipfsGateway,
...this.options?.iexecOptions,
allowExperimentalNetworks: this.options.allowExperimentalNetworks,
}
);
} catch (e: any) {
throw new Error(`Unsupported ethProvider: ${e.message}`);
}

try {
graphQLClient = new GraphQLClient(subgraphUrl);
} catch (error: any) {

Check warning on line 184 in src/web3telegram/IExecWeb3telegram.ts

View workflow job for this annotation

GitHub Actions / check-code

Unexpected any. Specify a different type
throw new Error(`Failed to create GraphQLClient: ${error.message}`);
}

Expand Down
59 changes: 42 additions & 17 deletions tests/e2e/constructor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,21 @@ describe('IExecWeb3telegram()', () => {
expect(await iexec.config.resolveIexecGatewayURL()).toBe(iexecGatewayURL);
});

it(
'When calling a read method should work as expected',
async () => {
// --- GIVEN
const web3telegram = new IExecWeb3telegram();
const wallet = Wallet.createRandom();

// --- WHEN/THEN
await expect(
web3telegram.fetchUserContacts({ userAddress: wallet.address })
).resolves.not.toThrow();
},
MAX_EXPECTED_WEB2_SERVICES_TIME
);

describe('When instantiating SDK with an experimental network', () => {
const experimentalNetworkSigner = getWeb3Provider(
Wallet.createRandom().privateKey,
Expand Down Expand Up @@ -157,10 +172,10 @@ describe('IExecWeb3telegram()', () => {
expect(web3telegram['ipfsGateway']).toBe(
arbitrumSepoliaConfig!.ipfsGateway
);
expect(web3telegram['ipfsNode']).toBe(arbitrumSepoliaConfig!.ipfsUploadUrl);
expect(web3telegram['dappAddressOrENS']).toBe(
arbitrumSepoliaConfig!.dappAddress
expect(web3telegram['ipfsNode']).toBe(
arbitrumSepoliaConfig!.ipfsUploadUrl
);
expect(web3telegram['dappAddressOrENS']).toMatch(/^0x[a-fA-F0-9]{40}$/); // resolved from Compass
expect(web3telegram['dappWhitelistAddress']).toBe(
arbitrumSepoliaConfig!.whitelistSmartContract.toLowerCase()
);
Expand Down Expand Up @@ -190,7 +205,9 @@ describe('IExecWeb3telegram()', () => {
allowExperimentalNetworks: true,
});
expect(arbitrumSepoliaConfig).not.toBeNull();
expect(web3telegram['ipfsNode']).toBe(arbitrumSepoliaConfig!.ipfsUploadUrl);
expect(web3telegram['ipfsNode']).toBe(
arbitrumSepoliaConfig!.ipfsUploadUrl
);
expect(web3telegram['dappWhitelistAddress']).toBe(
arbitrumSepoliaConfig!.whitelistSmartContract.toLowerCase()
);
Expand All @@ -204,18 +221,26 @@ describe('IExecWeb3telegram()', () => {
});
});

it(
'When calling a read method should work as expected',
async () => {
// --- GIVEN
const web3telegram = new IExecWeb3telegram();
const wallet = Wallet.createRandom();
describe('When instantiating SDK with on a network backed by Compass', () => {
it('should resolve dapp address from Compass', async () => {
const chainId = 421614; // Arbitrum Sepolia Testnet ENS not supported
const chainConfig = getChainDefaultConfig(chainId, {
allowExperimentalNetworks: true,
});
expect(chainConfig.dappAddress).toBeUndefined(); // ENS not supported on this network

// --- WHEN/THEN
await expect(
web3telegram.fetchUserContacts({ userAddress: wallet.address })
).resolves.not.toThrow();
},
MAX_EXPECTED_WEB2_SERVICES_TIME
);
const web3telegram = new IExecWeb3telegram(
getWeb3Provider(Wallet.createRandom().privateKey, {
host: chainId,
allowExperimentalNetworks: true,
}),
{ allowExperimentalNetworks: true }
);
await web3telegram.init();

const dappAddressOrENS = web3telegram['dappAddressOrENS'];
expect(typeof dappAddressOrENS).toBe('string');
expect(dappAddressOrENS).toMatch(/^0x[a-fA-F0-9]{40}$/);
});
});
});
23 changes: 23 additions & 0 deletions tests/unit/utils/resolveDappAddressFromCompass.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { describe, it, expect } from '@jest/globals';
import { resolveDappAddressFromCompass } from '../../../src/utils/resolveDappAddressFromCompass.js';

describe('resolveDappAddressFromCompass', () => {
it('should return undefined if compassUrl is not provided', async () => {
const result = await resolveDappAddressFromCompass('', 1);
expect(result).toBeUndefined();
});

it('should resolve dapp address from a valid compass instance', async () => {
const compassUrl = 'https://compass.arbitrum-sepolia-testnet.iex.ec';
const chainId = 421614;
const address = await resolveDappAddressFromCompass(compassUrl, chainId);
expect(address).toBeDefined();
});

it('should throw CompassCallError on network error', async () => {
const compassUrl = 'https://invalid-url.iex.ec';
await expect(resolveDappAddressFromCompass(compassUrl, 1)).rejects.toThrow(
'Compass API error: Connection to https://invalid-url.iex.ec failed with a network error'
);
});
});
Loading