Carbon Backend, built with Nest.js, serves as a specialized backend solution for aggregating insights from Carbon smart contracts and delivering them through APIs. It provides a suite of APIs offering valuable insights, such as trading activity and history.
Before setting up Carbon Backend, ensure you have the following prerequisites:
- TimescaleDB: Ensure TimescaleDB is properly installed and running.
- Redis: Ensure Redis is properly installed and running.
- CoinGecko: Obtain an API key from CoinGecko.
- This repo is set up to use Coingecko's PRO API, if you have a free plan you will need to adjust the coingecko api url and authentication header.
- CoinMarketCap: Obtain an API key from CoinMarketCap.
- Codex: Obtain an API key from Codex.
- Python 3 (Optional): Required for the simulator.
To set up Carbon Backend, follow these steps:
-
Clone the repository:
git clone https://github.com/bancorprotocol/carbon-backend
-
Navigate to the project directory:
cd carbon-backend
-
Install dependencies:
npm install
-
Run database migrations:
After installing dependencies, run the following command to execute all migrations and prepare the database:
npm run migration:run
-
Configure environment variables:
Duplicate the
.env.example
file as.env
:cp .env.example .env
Provide the required values in the
.env
file. -
(Optional) If you wish to utilize the simulator feature, install the required Python packages:
pip install -r src/simulator/requirements.txt
To run Carbon Backend:
npm start
On the first run, the application will sync each network to current state. This will heavily consume the RPC API urls, if you're using a free plan from Alchemy or another provider, you might be rate limited and the sync process will take some time.
If you're facing network issues when syncing the chain state, try reducing the parameters harvestEventsBatchSize
and harvestConcurrency
for each network in the deployment config on deployment.service.ts
. This will slow down the sync, but will be lighter on your network.
Access the API documentation by navigating to http://localhost:3000 in your browser.
Manually run the seed
function in src/historic-quote/historic-quote.service.ts
to populate the database with historic quotes for history-dependent functionalities such as the simulator.
To switch Carbon Backend's network for different deployments, follow these steps:
-
Replace Smart Contract Files:
- Replace files in
src/contracts/mainnet
with those from the new deployment.
- Replace files in
-
Modify CoinMarketCap Service:
- Adjust
src/coinmarketcap/coinmarketcap.service.ts
to align with the new network. - For guidance, check the CoinMarketCap API documentation.
- Adjust
-
Modify CoinGecko Service:
- Adjust
src/quote/coingecko.service.ts
to match the requirements of the new network. - Refer to the CoinGecko API documentation for assistance.
- Adjust
-
Customizing Networks and Exchange IDs:
To configure which networks are supported by Carbon Backend, make the following changes in
deployment.service.ts
andexchange-id-param.decorator.ts
.If you want to support multiple networks, update the following:
-
In
deployment.service.ts
:-
Update the
BlockchainType
andExchangeId
enums to reflect the networks you want to support:export enum BlockchainType { Ethereum = 'ethereum', Sei = 'sei-network', Celo = 'celo', Blast = 'blast', // Add or remove entries as needed } export enum ExchangeId { OGEthereum = 'ethereum', OGSei = 'sei', OGCelo = 'celo', OGBlast = 'blast', // Add or remove entries as needed }
-
Modify
initializeDeployments
with configuration for each network, includingexchangeId
,blockchainType
,rpcEndpoint
, and other network-specific values:private initializeDeployments(): Deployment[] { return [ { exchangeId: ExchangeId.OGEthereum, blockchainType: BlockchainType.Ethereum, rpcEndpoint: this.configService.get('ETHEREUM_RPC_ENDPOINT'), harvestEventsBatchSize: 2000000, harvestConcurrency: 10, multicallAddress: '0x5Eb3fa2DFECdDe21C950813C665E9364fa609bD2', startBlock: 17087000, gasToken: { name: 'Ethereum', symbol: 'ETH', address: NATIVE_TOKEN, }, }, // Repeat this block for each network ]; }
-
-
In
exchange-id-param.decorator.ts
:-
Adjust
extractExchangeId
to support dynamic handling for multiple networks:export function extractExchangeId(request: Request, exchangeIdParam?: string): ExchangeId { let exchangeId: ExchangeId; if (exchangeIdParam) { exchangeId = exchangeIdParam as ExchangeId; } else { let subdomain = request.hostname.split('.')[0]; if (subdomain.endsWith('-api')) { subdomain = subdomain.slice(0, -4); // Remove '-api' suffix } if (subdomain === 'api') { subdomain = ExchangeId.OGEthereum; // Adjust to your preferred default network } exchangeId = subdomain ? (subdomain as ExchangeId) : (ExchangeId.OGEthereum as ExchangeId); } if (!Object.values(ExchangeId).includes(exchangeId)) { throw new Error(`Invalid ExchangeId: ${exchangeId}`); } return exchangeId; }
-
If supporting only one network, simplify the configuration:
-
In
deployment.service.ts
:- Set a single
BlockchainType
andExchangeId
, and configureinitializeDeployments
for only that network.
- Set a single
-
In
exchange-id-param.decorator.ts
:-
Hardcode the
extractExchangeId
function to return only the supportedExchangeId
:export function extractExchangeId(request: Request, exchangeIdParam?: string): ExchangeId { const exchangeId = ExchangeId.OGEthereum; // Replace with the single supported ExchangeId if (exchangeIdParam && exchangeIdParam !== exchangeId) { throw new Error(`Unsupported ExchangeId: only ${exchangeId} is allowed`); } return exchangeId; }
-
-
Carbon Backend provides a command to automatically generate an Entity Relationship Diagram (ERD) from your TypeORM entities. This helps visualize the database structure and relationships between entities.
To generate the ERD:
npm run generate-erd
This command:
- Scans all TypeORM entity files
- Generates a Mermaid diagram definition
- Creates two files:
erd.mmd
: The Mermaid diagram definition fileerd.svg
: The rendered diagram in SVG format
The diagram includes:
- All entities with their properties
- Property types
- Primary key indicators
- Relationships between entities (one-to-one, one-to-many, many-to-many)
The Carbon Backend includes a notification system that sends alerts to Telegram channels.
Configure the notification system in your .env
file:
# Telegram Configuration
TELEGRAM_CHAT_ID=your-chat-id
# Google Cloud Tasks Configuration
QUEUE_NAME=bancor-alerts
QUEUE_LOCATION=europe-west2
GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
GOOGLE_CLOUD_PROJECT=your-project-id
API_URL=https://your-api-url.com
# Network-Specific Thread IDs
ETHEREUM_TELEGRAM_BOT_TOKEN=your-bot-token
ETHEREUM_CARBON_THREAD_ID=123
ETHEREUM_FASTLANE_THREAD_ID=456
ETHEREUM_VORTEX_THREAD_ID=789
# Explorer URLs (for transaction links)
ETHEREUM_EXPLORER_URL=https://etherscan.io/tx/
ETHEREUM_WALLET_URL=https://app.carbondefi.xyz/wallet/
-
Locate Format Function In
TelegramService
, find the corresponding format function:private async formatExistingEventMessage( event: ExistingEvent, tokens: TokensByAddress, quotes: QuotesByAddress, deployment: Deployment, ): Promise<string> { // Modify the message format here return `Your modified message format`; }
-
Helper Methods Available
amountToken(amount: string, precision: number, token: Token)
: Format token amountsamountUSD(amount: string, precision: number, usdPrice: string, token: Token)
: Format USD amountsgetUsdRate(tokenAddress: string, quotes: QuotesByAddress, deployment: Deployment)
: Get token USD rateprintNumber(num: number, precision: number)
: Format numbers with precision
-
Update Event Types
// In src/events/event-types.ts export enum EventTypes { YourNewEvent = 'YourNewEvent', // ... other events }
-
Add Format Function
private async formatYourNewEventMessage( event: YourNewEvent, tokens: TokensByAddress, quotes: QuotesByAddress, deployment: Deployment, ): Promise<string> { return `New Event: ${event.name} Transaction: ${deployment.notifications.explorerUrl}${event.transactionHash}`; }
-
Register in Switch Statement
switch (eventType) { case EventTypes.YourNewEvent: message = await this.formatYourNewEventMessage(event, tokens, quotes, deployment); threadId = deployment.notifications.telegram.threads.yourThreadId; break; }
-
Register Services
// In NotificationService private registerEventServices() { this.eventServices.set(EventTypes.YourNewEvent, this.yourEventService); } // In NotificationController this.eventServiceMap = new Map([ [EventTypes.YourNewEvent, yourEventService], ]);
-
Configure Thread IDs
# In .env ETHEREUM_YOUR_THREAD_ID=123
NotificationService
processes events in batches from the blockchain- For each event found, it creates a task in Google Cloud Tasks queue
- Tasks trigger the
/notifications/telegram
endpoint NotificationController
retrieves the event data and passes it toTelegramService
TelegramService
formats the message based on event type and sends it to the appropriate Telegram thread
This system ensures reliable delivery of notifications even with high event volumes and provides network-specific configuration options.
Carbon Backend is licensed under the MIT License.