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
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@ WALLET_PRIVATE_KEY=<your_admin_wallet_private_key>
MIN_TRANSACTION_TO_PROCESS=1
TRANSACTIONS_TO_BATCH=10

# AWS KMS Support Variables
AWS_ACCESS_KEY_ID=<your_aws_access_key_id>
AWS_SECRET_ACCESS_KEY=<your_aws_secret_access_key>
AWS_KMS_KEY_ID=<your_aws_kms_key_id>
AWS_REGION=<your_aws_region>

#RPC OVERRIDE : OPTIONAL.
RPC_OVERRIDE_URI=<rpc_override_uri>
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ View all end-points details (Open API Specification) : https://web3-api-akbv.cha
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |
| `HOST` | Host name of the API Server | `localhost` | false |
| `PORT` | Port number of the API Server | `3005` | false |
| `WALLET_PRIVATE_KEY` | Private key of the wallet | | true |
| `THIRDWEB_API_KEY` | API Key to access ThirdWeb API | | true |
| `POSTGRES_HOST` | PostgreSQL Host Name | | true |
| `POSTGRES_DATABASE_NAME` | PostgreSQL Database Name | | true |
Expand All @@ -52,8 +51,28 @@ View all end-points details (Open API Specification) : https://web3-api-akbv.cha
## Setup Instructions

1. Create a `.env` file based off `.env.example` with all the variables filled in.
2. Update the `WALLET_PRIVATE_KEY` value on the `.env` file
3. Update the `THIRDWEB_API_KEY` value on the `.env` file
2. Update the `THIRDWEB_API_KEY` value on the `.env` file

### Wallet Setup

| Required |
| -------- |

There are multiple ways to setup a wallet for Web3-API using the below methods:

#### Wallet Private Key

1.Update the `WALLET_PRIVATE_KEY` value on the `.env` file

#### AWS KMS Wallet

1. Get the AWS KMS Support Variables which can be found in `.env.example` file
2. Update the AWS KMS ENV Variables with the correct values on `.env` file

- `AWS_ACCESS_KEY_ID` : AWS Access Key
- `AWS_SECRET_ACCESS_KEY` : AWS Secret Access Key
- `AWS_REGION` : AWS KMS Key Region
- `AWS_KMS_KEY_ID` : Needs to have the full ARN

### Advance Setup : PostgreSQL DB

Expand Down
13 changes: 12 additions & 1 deletion core/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export const WEB3_API_REQUIRED_ENV_VARS = [
"WALLET_PRIVATE_KEY",
"THIRDWEB_API_KEY",
"POSTGRES_HOST",
"POSTGRES_DATABASE_NAME",
Expand All @@ -9,6 +8,18 @@ export const WEB3_API_REQUIRED_ENV_VARS = [
"POSTGRES_USE_SSL",
];

export const WEB3_API_WALLETS_ENV_VARS = [
{ walletPPK: ["WALLET_PRIVATE_KEY"] },
{
awsKmsWallet: [
"AWS_REGION",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"AWS_KMS_KEY_ID",
],
},
] as { [key: string]: string[] }[];

export const WEB3_API_SERVER_ENV_VARS = WEB3_API_REQUIRED_ENV_VARS.concat([
"OPENAPI_BASE_ORIGIN",
]);
36 changes: 32 additions & 4 deletions core/sdk/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ContractAddress } from "@thirdweb-dev/generated-abis";
import { BaseContract, BigNumber } from "ethers";
import { Static } from "@sinclair/typebox";
import { getEnv } from "../loadEnv";
import { AwsKmsWallet } from "@thirdweb-dev/wallets/evm/wallets/aws-kms";
import { networkResponseSchema } from "../schema";
import { isValidHttpUrl } from "../helpers";
import * as fs from "fs";
Expand All @@ -26,7 +27,14 @@ export const getSDK = async (chainName: ChainOrRpc): Promise<ThirdwebSDK> => {

const THIRDWEB_API_KEY = getEnv("THIRDWEB_API_KEY");
const WALLET_PRIVATE_KEY = getEnv("WALLET_PRIVATE_KEY", undefined);
const AWS_REGION = getEnv("AWS_REGION", undefined);
const AWS_ACCESS_KEY_ID = getEnv("AWS_ACCESS_KEY_ID", undefined);
const AWS_SECRET_ACCESS_KEY = getEnv("AWS_SECRET_ACCESS_KEY", undefined);
const AWS_KMS_KEY_ID = getEnv("AWS_KMS_KEY_ID", undefined);

let chain: Chain | null = null;
let wallet: AwsKmsWallet | LocalWallet | null = null;

try {
chain = getChainBySlug(chainName);
} catch (e) {
Expand All @@ -37,11 +45,31 @@ export const getSDK = async (chainName: ChainOrRpc): Promise<ThirdwebSDK> => {
}
}

const wallet = new LocalWallet({
chain,
});
wallet.import({ privateKey: WALLET_PRIVATE_KEY, encryption: false });
// Check for KMS
if (
AWS_ACCESS_KEY_ID &&
AWS_SECRET_ACCESS_KEY &&
AWS_KMS_KEY_ID &&
AWS_REGION
) {
wallet = new AwsKmsWallet({
region: AWS_REGION,
accessKeyId: AWS_ACCESS_KEY_ID,
secretAccessKey: AWS_SECRET_ACCESS_KEY,
keyId: AWS_KMS_KEY_ID,
});
} else if (WALLET_PRIVATE_KEY) {
wallet = new LocalWallet({
chain,
});
wallet.import({ privateKey: WALLET_PRIVATE_KEY, encryption: false });
}

if (!wallet) {
throw new Error(
"No wallet found. Please check the Wallet Environment Variables.",
);
}
// TODO: PLAT-982
// Currently we require WALLET_PRIVATE_KEY to be set in order to instantiate the SDK
// But we need to implement wallet.generate() and wallet.save() to save the private key to file system
Expand Down
36 changes: 33 additions & 3 deletions core/startup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,43 @@ export const envVariablesCheck = async (
server: FastifyInstance,
variables: string[],
) => {
server.log.info(`Checking for required env variables`);

server.log.info(`Checking for Required env variables`);
for (let str of variables) {
server.log.info(`Checking for ${str} in env`);
server.log.info(`\t Checking for ${str} in env`);
if (!getEnv(str, undefined)) {
server.log.error(`${str} not found in env`);
process.exit(1);
}
}
};

export const walletEnvVariablesCheck = async (
server: FastifyInstance,
variables: { [key: string]: string[] }[],
Copy link
Member

Choose a reason for hiding this comment

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

do we actually need this? feels much simpler to just do the checks in getSDK no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My goal was to not allow the server to start if the ENV variables required are missing. Otherwise, if I added it inside getSDK then the error will only be thrown when and if user pings an end-point.

) => {
let resultArr: boolean[] = [];
let keyResult: boolean;
server.log.info(`Checking for Wallet Setup ENV variables`);
for (let obj of variables) {
keyResult = true;
for (let key in obj) {
for (let str of obj[key]) {
server.log.info(
`\t Checking for ${key.toLowerCase()} -> ${str} in env`,
Copy link
Member

Choose a reason for hiding this comment

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

probably don't want to log the private key here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is just logging the ENV variables and not the value of it.

);
keyResult = keyResult && !!getEnv(str, undefined);
}
resultArr.push(keyResult);
}
if (resultArr.includes(true)) {
break;
}
}

if (!resultArr.includes(true)) {
server.log.error(
`Please set WALLET_PRIVATE_KEY or [AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_KMS_KEY_ID] for AWS KMS Wallet on .env file`,
);
process.exit(1);
}
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"copyfiles": "^2.4.1",
"dotenv": "^16.0.3",
"ethers": "5",
"express": "^4.18.2",
"ethers-aws-kms-signer": "^1.3.2",
"fastify": "^4.15.0",
"fastify-plugin": "^4.5.0",
"http-status-codes": "^2.2.0",
Expand Down
8 changes: 6 additions & 2 deletions server/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { getEnv } from "../core";
import createServer from "./helpers/server";
import { checkTablesExistence, implementTriggerOnStartUp } from "../core";
import { envVariablesCheck } from "../core/startup";
import { WEB3_API_SERVER_ENV_VARS } from "../core/constants";
import { envVariablesCheck, walletEnvVariablesCheck } from "../core/startup";
import {
WEB3_API_SERVER_ENV_VARS,
WEB3_API_WALLETS_ENV_VARS,
} from "../core/constants";

const main = async () => {
const server = await createServer("API-Server");
Expand All @@ -22,6 +25,7 @@ const main = async () => {

try {
await envVariablesCheck(server, WEB3_API_SERVER_ENV_VARS);
await walletEnvVariablesCheck(server, WEB3_API_WALLETS_ENV_VARS);
// Check for the Tables Existence post startup
await checkTablesExistence(server);
await implementTriggerOnStartUp(server);
Expand Down
12 changes: 10 additions & 2 deletions worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ import { errorHandler } from "../core";
import fastify, { FastifyInstance } from "fastify";
import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
import { startNotificationListener } from "./controller/listener";
import { getLogSettings, envVariablesCheck } from "../core";
import {
getLogSettings,
envVariablesCheck,
walletEnvVariablesCheck,
} from "../core";
import { setupWalletsForWorker } from "./controller/wallet";
import { WEB3_API_REQUIRED_ENV_VARS } from "../core/constants";
import {
WEB3_API_REQUIRED_ENV_VARS,
WEB3_API_WALLETS_ENV_VARS,
} from "../core/constants";

const main = async () => {
const logOptions = getLogSettings("Worker-Server");
Expand All @@ -16,6 +23,7 @@ const main = async () => {
await errorHandler(server);

await envVariablesCheck(server, WEB3_API_REQUIRED_ENV_VARS);
await walletEnvVariablesCheck(server, WEB3_API_WALLETS_ENV_VARS);

await setupWalletsForWorker(server);
// Start Listening to the Table for new insertion
Expand Down
Loading