const PORT = 5555;
const ETHEREUM_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;
const CHAINSTACK_NODE_URL = Bun.env.CHAINSTACK_NODE_URL;
const JSON_HEADERS = { "Content-Type": "application/json" };
function isValidEthereumAddress(address) {
return ETHEREUM_ADDRESS_REGEX.test(address);
}
async function fetchFromEthereumNode(address) {
console.log(`Calling Ethereum node with address: ${address}\n`);
const response = await fetch(CHAINSTACK_NODE_URL, {
method: "POST",
headers: {
"accept": "application/json",
"content-type": "application/json",
},
body: JSON.stringify({
id: 1,
jsonrpc: "2.0",
method: "eth_getBalance",
params: [address, "latest"],
}),
});
const responseBody = await response.json();
console.log(
`Received response from Ethereum node: ${JSON.stringify(responseBody)}\n`
);
if (!response.ok) {
throw new Error("Error fetching balance");
}
if (responseBody.error) {
throw new Error(
responseBody.error.message || "Error in Ethereum node response"
);
}
return responseBody;
}
function convertWeiToEther(weiValue) {
const divisor = BigInt("1000000000000000000");
const wholeEthers = weiValue / divisor;
const remainderWei = weiValue % divisor;
const remainderEther = remainderWei.toString().padStart(18, "0");
return `${wholeEthers}.${remainderEther}`;
}
async function getEthereumBalance(address) {
const responseBody = await fetchFromEthereumNode(address);
const decimalValue = parseInt(responseBody.result.substring(2), 16);
const weiValue = BigInt(decimalValue);
return convertWeiToEther(weiValue);
}
function logAndReturnResponse(status, content) {
console.log(
`Sending response back to user: ${status} ${JSON.stringify(content)} \n`
);
return new Response(JSON.stringify(content), {
status: status,
headers: JSON_HEADERS,
});
}
Bun.serve({
port: PORT,
async fetch(request) {
console.log(`Received request: ${request.method} ${request.url}\n`);
const urlObject = new URL(request.url);
const pathname = urlObject.pathname;
try {
if (request.method === "GET" && pathname.startsWith("/getBalance/")) {
const address = pathname.split("/getBalance/")[1];
if (!isValidEthereumAddress(address)) {
return logAndReturnResponse(400, {
error: "Invalid Ethereum address format",
});
}
const balance = await getEthereumBalance(address);
return logAndReturnResponse(200, {
address: address,
balance: balance,
unit: "Ether",
});
}
return logAndReturnResponse(404, { error: "Endpoint does not exist" });
} catch (error) {
console.error(`Error occurred: ${error.message}`);
return logAndReturnResponse(500, { error: error.message });
}
},
});
console.log(`Bun server running on port ${PORT}...`);