diff --git a/.env.example b/.env.example index 0bfcfb0..7951733 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,7 @@ AUTH0_AUDIENCE= AUTH0_ISSUER_URL= REDIS_HOST= REDIS_PORT= -TOPOS_SUBNET_ENDPOINT= +TOPOS_SUBNET_ENDPOINT_WS= SUBNET_REGISTRATOR_CONTRACT_ADDRESS= TOPOS_CORE_PROXY_CONTRACT_ADDRESS= TRACING_SERVICE_NAME= diff --git a/README.md b/README.md index 3b503ff..9bfed0c 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ AUTH0_AUDIENCE= AUTH0_ISSUER_URL= REDIS_HOST= REDIS_PORT= -TOPOS_SUBNET_ENDPOINT= +TOPOS_SUBNET_ENDPOINT_WS= SUBNET_REGISTRATOR_CONTRACT_ADDRESS= TOPOS_CORE_PROXY_CONTRACT_ADDRESS= ERC20_MESSAGING_CONTRACT_ADDRESS= diff --git a/package-lock.json b/package-lock.json index 19639a7..1fafe46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@nestjs/passport": "^9.0.0", "@nestjs/platform-express": "^9.4.0", "@nestjs/swagger": "^6.1.2", - "@topos-protocol/topos-smart-contracts": "^1.2.3", + "@topos-protocol/topos-smart-contracts": "^2.0.0", "bcrypt": "^5.1.0", "bull": "^4.10.1", "class-transformer": "^0.5.1", @@ -2774,9 +2774,9 @@ } }, "node_modules/@topos-protocol/topos-smart-contracts": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@topos-protocol/topos-smart-contracts/-/topos-smart-contracts-1.2.3.tgz", - "integrity": "sha512-oLMJGG+1fwhFxWdPQIzBZITd8R8dN+3VGovnWnQKrCb0VHip4oXBPI8bJUYzhdAm1IUAIPWK7iT1cEVuNITV9g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@topos-protocol/topos-smart-contracts/-/topos-smart-contracts-2.0.0.tgz", + "integrity": "sha512-9ElAqlPg7puWCH0F58l7TgnXheybzkmyNr2ssla/olwKRxcfKJl10k3U5CN03KaTkbkZY+Jhp5JW7BLL+8xhNA==", "dependencies": { "@openzeppelin/contracts": "^4.8.3", "ethers": "^5.7.2", @@ -13725,9 +13725,9 @@ "dev": true }, "@topos-protocol/topos-smart-contracts": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@topos-protocol/topos-smart-contracts/-/topos-smart-contracts-1.2.3.tgz", - "integrity": "sha512-oLMJGG+1fwhFxWdPQIzBZITd8R8dN+3VGovnWnQKrCb0VHip4oXBPI8bJUYzhdAm1IUAIPWK7iT1cEVuNITV9g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@topos-protocol/topos-smart-contracts/-/topos-smart-contracts-2.0.0.tgz", + "integrity": "sha512-9ElAqlPg7puWCH0F58l7TgnXheybzkmyNr2ssla/olwKRxcfKJl10k3U5CN03KaTkbkZY+Jhp5JW7BLL+8xhNA==", "requires": { "@openzeppelin/contracts": "^4.8.3", "ethers": "^5.7.2", diff --git a/package.json b/package.json index 2924116..8427a9a 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@nestjs/passport": "^9.0.0", "@nestjs/platform-express": "^9.4.0", "@nestjs/swagger": "^6.1.2", - "@topos-protocol/topos-smart-contracts": "^1.2.3", + "@topos-protocol/topos-smart-contracts": "^2.0.0", "bcrypt": "^5.1.0", "bull": "^4.10.1", "class-transformer": "^0.5.1", diff --git a/src/execute/execute.processor.spec.ts b/src/execute/execute.processor.spec.ts index 3393129..1e638a8 100644 --- a/src/execute/execute.processor.spec.ts +++ b/src/execute/execute.processor.spec.ts @@ -13,7 +13,7 @@ const VALID_PRIVATE_KEY = '0xc6cbd7d76bc5baca530c875663711b947efa6a86a900a9e8645ce32e5821484e' const TOPOS_CORE_PROXY_CONTRACT_ADDRESS = '0x1D7b9f9b1FF6cf0A3BEB0F84fA6F8628E540E97F' -const TOPOS_SUBNET_ENDPOINT = 'topos-subnet-endpoint' +const TOPOS_SUBNET_ENDPOINT_WS = 'ws://topos-subnet-endpoint/ws' const validExecuteJob: Partial> = { data: { @@ -27,7 +27,7 @@ const validExecuteJob: Partial> = { progress: jest.fn(), } -const subnetMock = { endpoint: 'endpoint' } +const subnetMock = { endpointWs: 'ws://endpoint/ws' } const providerMock = Object.assign(new EventEmitter(), { getCode: jest.fn().mockResolvedValue('0x123'), }) @@ -57,8 +57,8 @@ describe('ExecuteProcessor', () => { return VALID_PRIVATE_KEY case 'TOPOS_CORE_PROXY_CONTRACT_ADDRESS': return TOPOS_CORE_PROXY_CONTRACT_ADDRESS - case 'TOPOS_SUBNET_ENDPOINT': - return TOPOS_SUBNET_ENDPOINT + case 'TOPOS_SUBNET_ENDPOINT_WS': + return TOPOS_SUBNET_ENDPOINT_WS } }), } @@ -97,12 +97,8 @@ describe('ExecuteProcessor', () => { validExecuteJob as unknown as Job ) - expect(ethersProviderMock).toHaveBeenCalledWith( - `ws://${TOPOS_SUBNET_ENDPOINT}/ws` - ) - expect(ethersProviderMock).toHaveBeenCalledWith( - `ws://${subnetMock.endpoint}/ws` - ) + expect(ethersProviderMock).toHaveBeenCalledWith(TOPOS_SUBNET_ENDPOINT_WS) + expect(ethersProviderMock).toHaveBeenCalledWith(subnetMock.endpointWs) expect(ethersWalletMock).toHaveBeenCalledWith( VALID_PRIVATE_KEY, providerMock diff --git a/src/execute/execute.processor.ts b/src/execute/execute.processor.ts index 5f785a0..01b4d6e 100644 --- a/src/execute/execute.processor.ts +++ b/src/execute/execute.processor.ts @@ -23,7 +23,6 @@ import { Job } from 'bull' import { ethers, providers } from 'ethers' import { ApmService } from '../apm/apm.service' -import { sanitizeURLProtocol } from '../utils' import { ExecuteDto } from './execute.dto' import { CONTRACT_ERRORS, @@ -137,7 +136,7 @@ export class ExecutionProcessorV1 { private async _getReceivingSubnetEndpointFromId(subnetId: string) { const toposSubnetEndpoint = this.configService.get( - 'TOPOS_SUBNET_ENDPOINT' + 'TOPOS_SUBNET_ENDPOINT_WS' ) const toposCoreContractAddress = this.configService.get( 'TOPOS_CORE_PROXY_CONTRACT_ADDRESS' @@ -166,31 +165,36 @@ export class ExecutionProcessorV1 { )) as SubnetRegistrator const receivingSubnet = await subnetRegistratorContract.subnets(subnetId) - return receivingSubnet.endpoint + return receivingSubnet.endpointWs || receivingSubnet.endpointHttp } } private _createProvider(endpoint: string) { - return new Promise((resolve, reject) => { - const provider = new ethers.providers.WebSocketProvider( - sanitizeURLProtocol('ws', `${endpoint}/ws`) - ) - - // Fix: Timeout to leave time to errors to be asynchronously caught - const timeoutId = setTimeout(() => { - resolve(provider) - }, 1000) - - provider.on('debug', (data) => { - if (data.error) { - clearTimeout(timeoutId) - reject(new Error(PROVIDER_ERRORS.INVALID_ENDPOINT)) - } - }) - }) + return new Promise( + (resolve, reject) => { + const url = new URL(endpoint) + const provider = url.protocol.startsWith('ws') + ? new providers.WebSocketProvider(endpoint) + : new providers.JsonRpcProvider(endpoint) + + // Fix: Timeout to leave time to errors to be asynchronously caught + const timeoutId = setTimeout(() => { + resolve(provider) + }, 1000) + + provider.on('debug', (data) => { + if (data.error) { + clearTimeout(timeoutId) + reject(new Error(PROVIDER_ERRORS.INVALID_ENDPOINT)) + } + }) + } + ) } - private _createWallet(provider: providers.WebSocketProvider) { + private _createWallet( + provider: providers.WebSocketProvider | providers.JsonRpcProvider + ) { try { return new ethers.Wallet( this.configService.get('PRIVATE_KEY'), @@ -202,7 +206,7 @@ export class ExecutionProcessorV1 { } private async _getContract( - provider: providers.WebSocketProvider, + provider: providers.WebSocketProvider | providers.JsonRpcProvider, contractAddress: string, contractInterface: ethers.ContractInterface, wallet?: ethers.Wallet diff --git a/src/utils/index.ts b/src/utils/index.ts index a735a7e..e69de29 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,6 +0,0 @@ -export function sanitizeURLProtocol(protocol: 'ws' | 'http', endpoint: string) { - return endpoint.indexOf('localhost') > -1 || - endpoint.indexOf('127.0.0.1') > -1 - ? `${protocol}://${endpoint}` - : `${protocol}s://${endpoint}` -}