CONNECTION ERROR: Couldn't connect to node https://rinkeby.infura.io on AWS lambda function

Using AWS lambda to call infura and check for a token balance and custom method calls.

imported web3, via npm module as a zip into lambda.

Code looks as follows:

const https = require('https');
const AWS = require('aws-sdk');
var docClient = new AWS.DynamoDB.DocumentClient({region: 'us-east-2', apiVersion: '2012-08-10'});
const Web3 = require('./Web3.js');
// const HttpProvider = Web3.providers.HttpProvider;
// const WsProvider = Web3.providers.WebSocketProvider;
// const WsProvider = require('./web3-providers-ws')

const generatorAddresses = {
    1: "0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
    4: "0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

// const providerUrls = {
//     1: "wss://mainnet.infura.io/ws/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
//     4: "wss://rinkeby.infura.io/ws/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
// }
const providerUrls = {
    1: "https://mainnet.infura.io/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    4: "https://rinkeby.infura.io/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

const providerOptions = {
    1: {
        hostname: 'mainnet.infura.io',
        port: 443,
        path: '/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    },
    4: {
        hostname: 'rinkeby.infura.io',
        port: 443,
        path: '/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    },
}

exports.handler = async (event, context, callback) => {
    console.log(event)

        
    const callBody = JSON.parse(event.body || "{}");
    const network = callBody.network || 1;

    const provider =  providerOptions[network];
    const web3 = new Web3(providerUrls[network]);
    // const web3 = new Web3(new Web3.providers.HttpProvider(providerUrls[network]));
    // const web3 = new Web3(new Web3.providers.WebSocket(providerUrls[network]));
    // const eth = web3.eth;
    // const provider =  new WsProvider(providerUrls[1]);
    // const provider =  new HttpProvider(providerUrls[1]);
    // console.log(web3)
    // console.log(eth)
    // console.log(provider);

    const getFunctionSignature  = (fn) => {
        return web3.utils.sha3(fn).substring(0,10);
    }

    const craftRpcCall = (method, args=[]) => {
        const rpcObject = {
            jsonrpc: '2.0',
            method: method,
            id: new Date().getTime()
        };
        if (args.length > 0) {
            rpcObject.params = args;
        }
        return rpcObject;
    }
    
    const craftHttpsCall = (urlOptions, data) => {
        data = typeof data !=='string' ? JSON.stringify(data) : data;
        return {
            hostname: urlOptions.hostname,
            port: urlOptions.port,
            path: urlOptions.path,
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': data.length
            }
        }  
    }

    const makeRpcCall = async (providerOptions, { to, from, data }, args=[]) => {
        // const send = provider.sendAsync || provider.send;
        // const send = provider.send.bind(provider);
        // console.log(send)
        const rpcRequest = {
            to,
            data: data || '0x'
        };

        if (from) {
            rpcRequest.from = from;
        }

        if (!args || typeof args !== 'object') {
            args = [];
        }
        args.unshift(rpcRequest);
        const prepEthCall = craftRpcCall('eth_call', args);
        console.log(prepEthCall)

        const rpcCall = await new Promise ((resolve, reject) => {
            // send(ethCall, function (err, res) {
            //     if (err) {
            //         reject(err);
            //     }
            //     resolve(res);
            // });
            // const options = {
            //   hostname: 'encrypted.google.com',
            //   port: 443,
            //   path: '/',
            //   method: 'GET',
            //   key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
            //   cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
            // };
            const ethCall = JSON.stringify(prepEthCall);
            const options = craftHttpsCall(providerOptions, ethCall);
            const req = https.request(Object.assign({}, options, {method: 'POST'}), (res) => {
              res.on('data', (d) => {
                d = Buffer.isBuffer(d) ? JSON.parse(d) : d;
                console.log(d)
                resolve(true)
                // resolve(priceFeedApi.priceResponse ? priceFeedApi.priceResponse(d) : d);
                }).on('error', (e) => {
                  reject(e);
                });
            });
            console.log('req', req)
            req.write(data);
            // req.end();
        });
        if (rpcCall.error) {
            throw rpcCall.error;
        }
        return rpcCall.result;
    }

Lambda returns:

Error: CONNECTION ERROR: Couldn't connect to node https://rinkeby.infura.io/v3/xxxxxxxxxxxxxxxxxx.
at Object.InvalidConnection (/var/task/node_modules/web3/lib/web3/errors.js:31:16)
at HttpProvider.send (/var/task/node_modules/web3/lib/web3/httpprovider.js:94:18)
at RequestManager.send (/var/task/node_modules/web3/lib/web3/requestmanager.js:58:32)
at Eth.send [as call] (/var/task/node_modules/web3/lib/web3/method.js:145:58)
at SolidityFunction.call (/var/task/node_modules/web3/lib/web3/function.js:135:32)
at exports.handler (/var/task/index.js:197:78)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)

We are using web3 0.20.7
also tried 1.0.0-.37

What could cause this connection issue? We’ve have tried two different api keys as well, so those are correct.

1 Like

Are you running your lambda in a VPC? There can be some complications with configuring the VPC to allow the lambda an external internet connection which could be causing the issues you are seeing.

No, lambda is just being called either from API gateway (passing in an address to check balance) or via another lambda function. No virtual instances.

One thing to try, since this is a 403 it’s very likely it is something to do with the lambda’s ability to connect outside of it’s network,
Try the code outside of lambda, if it works there then the issue it is likely an issue with the lambda’s setup/ability to access external urls

We have had issues using API Gateway in the past with regards to external connections, it’s possible the lambda is running in a VPC without that being clear in the AWS dashboard. It may help to contact AWS if the code works outside of the lambda.