diff --git a/packages/airnode-examples/src/scripts/derive-and-fund-sponsor-wallet.ts b/packages/airnode-examples/src/scripts/derive-and-fund-sponsor-wallet.ts index 3644b265a8..ee4fc18e83 100644 --- a/packages/airnode-examples/src/scripts/derive-and-fund-sponsor-wallet.ts +++ b/packages/airnode-examples/src/scripts/derive-and-fund-sponsor-wallet.ts @@ -16,7 +16,7 @@ const main = async () => { // Fund the derived sponsor wallet using sponsor account const balance = await sponsor.getBalance(); - const amountToSend = ethers.utils.parseEther('0.1'); + const amountToSend = ethers.utils.parseEther('0.3'); if (balance.lt(amountToSend)) throw new Error(`Sponsor account (${sponsor.address}) doesn't have enough funds!`); const tx = await sponsor.sendTransaction({ to: sponsorWalletAddress, value: amountToSend }); await tx.wait(); diff --git a/packages/airnode-node/src/workers/cloud-platforms/aws.ts b/packages/airnode-node/src/workers/cloud-platforms/aws.ts index 2fab9c6590..6fa4201360 100644 --- a/packages/airnode-node/src/workers/cloud-platforms/aws.ts +++ b/packages/airnode-node/src/workers/cloud-platforms/aws.ts @@ -1,9 +1,11 @@ +import { logger } from '@api3/airnode-utilities'; +import { goSync } from '@api3/promise-utils'; import AWS from 'aws-sdk'; import { WorkerParameters, WorkerResponse } from '../../types'; export function spawn(params: WorkerParameters): Promise { // lambda.invoke is synchronous so we need to wrap this in a promise - return new Promise((resolve, reject) => { + return new Promise((spawnResolve, spawnReject) => { // Uses the current region by default const lambda = new AWS.Lambda(); @@ -15,12 +17,32 @@ export function spawn(params: WorkerParameters): Promise { Payload: JSON.stringify(params.payload), }; + const resolve: typeof spawnResolve = (value) => { + logger.debug(`Successful Lambda response: ${value}`); + spawnResolve(value); + }; + + const reject: typeof spawnReject = (error) => { + logger.debug(`Lambda invocation or execution failed. Response: ${error}`); + spawnReject(error); + }; + + // The Lambda invocation callback populates the error (first argument) only when the invocation fails (e.g. status + // code is 400) or the request is not parsed properly by the SDK and can't be invoked. For errors and timeouts that + // happen inside the invoked lambda have "data.FunctionError" and "data.Payload.errorMessage" populated instead. + // See: https://stackoverflow.com/q/42672023 and https://stackoverflow.com/q/48644093 lambda.invoke(options, (err, data) => { - if (err) { - reject(err); - return; - } - resolve(JSON.parse(JSON.parse(data.Payload as string).body) as WorkerResponse); + if (err) return reject(err); + + if (data.FunctionError) return reject(data.Payload); + + const goPayload = goSync(() => JSON.parse(data.Payload?.toString() ?? '')); + if (!goPayload.success) return reject(goPayload.error); + + const goBody = goSync(() => JSON.parse(goPayload.data.body)); + if (!goBody.success) return reject(goBody.error); + + resolve(goBody.data as WorkerResponse); }); }); }