diff --git a/CHANGELOG.md b/CHANGELOG.md index 79f6652..d537278 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.0.1-alpha.92](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.91...v0.0.1-alpha.92) (2024-09-26) + + +### Features + +* allow override of TRUSTED_FULLNODE_PORT ([954ac95](https://github.com/DIG-Network/dig-chia-sdk/commit/954ac95dfdaeba5734e39ce4255893ad148ef132)) +* allow override of TRUSTED_FULLNODE_PORT ([b2a02f5](https://github.com/DIG-Network/dig-chia-sdk/commit/b2a02f51da4f534b832e3c7eb0599aed10434ef7)) + +### [0.0.1-alpha.91](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.90...v0.0.1-alpha.91) (2024-09-26) + + +### Features + +* add inactivity timeout to content server requests ([a3fee47](https://github.com/DIG-Network/dig-chia-sdk/commit/a3fee4713107f552950aaeef0fd11e60ba894247)) + ### [0.0.1-alpha.90](https://github.com/DIG-Network/dig-chia-sdk/compare/v0.0.1-alpha.89...v0.0.1-alpha.90) (2024-09-26) diff --git a/package-lock.json b/package-lock.json index 1b8d6b5..487a9eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.90", + "version": "0.0.1-alpha.92", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.90", + "version": "0.0.1-alpha.92", "license": "ISC", "dependencies": { "@dignetwork/datalayer-driver": "^0.1.25", diff --git a/package.json b/package.json index e172b75..142ae6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dignetwork/dig-sdk", - "version": "0.0.1-alpha.90", + "version": "0.0.1-alpha.92", "description": "", "type": "commonjs", "main": "./dist/index.js", diff --git a/src/DigNetwork/ContentServer.ts b/src/DigNetwork/ContentServer.ts index ef9f132..8241c81 100644 --- a/src/DigNetwork/ContentServer.ts +++ b/src/DigNetwork/ContentServer.ts @@ -40,7 +40,7 @@ export class ContentServer { } // Method to get the payment address from the peer - public async getPaymentAddress(): Promise { + public async getPaymentAddress(): Promise { console.log(`Fetching payment address from peer ${this.ipAddress}...`); try { @@ -50,7 +50,7 @@ export class ContentServer { console.error( `Failed to fetch payment address from ${this.ipAddress}: ${error.message}` ); - throw new Error(`Failed to fetch payment address: ${error.message}`); + return null; } } @@ -253,7 +253,7 @@ export class ContentServer { // Helper method to fetch content with retries and redirection handling private async fetchWithRetries(url: string): Promise { let attempt = 0; - const maxRetries = 5; + const maxRetries = 1; const initialDelay = 2000; // 2 seconds const maxDelay = 10000; // 10 seconds const delayMultiplier = 1.5; @@ -283,10 +283,13 @@ export class ContentServer { ); } - // Core method to fetch content from a URL + // Core method to fetch content from a URL with a 5-second inactivity timeout private async fetch(url: string, maxRedirects: number = 5): Promise { return new Promise((resolve, reject) => { const urlObj = new URL(url); + const timeoutDuration = 5000; // 5 seconds + + let timeout: NodeJS.Timeout | null = null; // Initialize timeout const requestOptions = { hostname: urlObj.hostname, @@ -301,12 +304,54 @@ export class ContentServer { const request = http.request(requestOptions, (response) => { let data = ""; + // Set timeout for inactivity + timeout = setTimeout(() => { + console.error( + `Request timeout: No data received for ${ + timeoutDuration / 1000 + } seconds.` + ); + request.destroy(); // Use destroy instead of abort + reject( + new Error( + `Request timed out after ${ + timeoutDuration / 1000 + } seconds of inactivity` + ) + ); + }, timeoutDuration); + + const resetTimeout = () => { + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(() => { + console.error( + `Request timeout: No data received for ${ + timeoutDuration / 1000 + } seconds.` + ); + request.destroy(); // Use destroy instead of abort + reject( + new Error( + `Request timed out after ${ + timeoutDuration / 1000 + } seconds of inactivity` + ) + ); + }, timeoutDuration); + }; + if (response.statusCode === 200) { response.on("data", (chunk) => { data += chunk; + resetTimeout(); // Reset the timeout every time data is received }); response.on("end", () => { + if (timeout) { + clearTimeout(timeout); + } resolve(data); }); } else if ( @@ -316,9 +361,9 @@ export class ContentServer { // Handle redirects if (maxRedirects > 0) { const redirectUrl = new URL(response.headers.location, url); // Resolve relative URLs based on the original URL - - // Recursively follow the redirect, passing the same query params - // console.log(`Redirecting to: ${redirectUrl.toString()}`); + if (timeout) { + clearTimeout(timeout); + } this.fetch(redirectUrl.toString(), maxRedirects - 1) .then(resolve) .catch(reject); @@ -326,6 +371,9 @@ export class ContentServer { reject(new Error("Too many redirects")); } } else { + if (timeout) { + clearTimeout(timeout); + } reject( new Error( `Failed to retrieve data from ${url}. Status code: ${response.statusCode}` @@ -334,7 +382,10 @@ export class ContentServer { } }); - request.on("error", (error) => { + request.on("error", (error: NodeJS.ErrnoException) => { + if (timeout) { + clearTimeout(timeout); + } console.error(`GET ${url}:`, error.message); reject(error); }); diff --git a/src/DigNetwork/DigPeer.ts b/src/DigNetwork/DigPeer.ts index cdfc5b9..e956e70 100644 --- a/src/DigNetwork/DigPeer.ts +++ b/src/DigNetwork/DigPeer.ts @@ -130,6 +130,11 @@ export class DigPeer { memos: Buffer[] = [] ): Promise { const paymentAddress = await this.contentServer.getPaymentAddress(); + + if (!paymentAddress) { + throw new Error("Payment address not found."); + } + const paymentAddressPuzzleHash = addressToPuzzleHash(paymentAddress); const output: Output = { puzzleHash: paymentAddressPuzzleHash, diff --git a/src/blockchain/FullNodePeer.ts b/src/blockchain/FullNodePeer.ts index 84682d7..0a9ae30 100644 --- a/src/blockchain/FullNodePeer.ts +++ b/src/blockchain/FullNodePeer.ts @@ -240,9 +240,17 @@ export class FullNodePeer { const peers = await Promise.all( peerIPs.map(async (ip) => { if (ip) { + // Allow override of the trusted fullnode port if the override exists + let port = FULLNODE_PORT; + if (trustedNodeIp && ip === trustedNodeIp) { + const trustedFullNodePort = process.env.TRUSTED_FULLNODE_PORT; + if (trustedFullNodePort) { + port = parseInt(trustedFullNodePort); + } + } try { const peer = await Peer.new( - `${ip}:${FULLNODE_PORT}`, + `${ip}:${port}`, false, certFile, keyFile