Backend API for working with TON NFTs, collections, users, and search. The service is built on Spring Boot + Kotlin, integrates with TON-related external APIs, and stores indexed data in PostgreSQL.
- gets NFT and collection data
- updates NFT price and processes NFT sale events
- creates and updates users by wallet address
- performs global and local search across collections, NFTs, and accounts
- fills the local database with collections and NFTs for faster access
- Kotlin 1.9
- Spring Boot 3.3
- Spring Web / WebFlux
- Spring Security
- Spring Data JPA / JDBC
- PostgreSQL
- Retrofit
- GraphQL client
- TON Kotlin libraries
- Swagger via Springfox
src/main/kotlin/backend/graabackend
|- controller HTTP contracts and REST implementations
|- service business logic
|- database entities and DAO layer
|- retrofit clients for external APIs
|- security auth header filter and security config
|- model request / response DTOs and mappers
- JDK 21
- Gradle 8+
- PostgreSQL
- access to TON API / GetGems API
Main Spring config lives in src/main/resources/application.yaml.
By default the app starts on port 8000 and uses PostgreSQL:
server:
port: 8000
spring:
datasource:
url: jdbc:postgresql://172.17.0.1:5432/graa_backend
username: observer
password: 1111Before running locally, adjust these values for your environment.
The project also uses a .env file. At minimum it contains:
TON_API_BASE_URL=https://tonapi.io
GET_GEMS_API_BASE_URL=https://api.getgems.io
API_AUTH_TOKEN=<your-api-token>
FIXED_PRICE_NUM=0x46495850Do not commit real secrets to the repository.
- Configure PostgreSQL and update
application.yaml. - Create or update the local
.envfile. - Start the service:
./gradlew bootRunFor Windows:
.\gradlew.bat bootRunAfter startup the API is available at http://localhost:8000.
./gradlew buildBuild and start with Docker Compose:
docker compose up --buildCurrent mapping in docker-compose.yaml exposes the service on 8013:
- host:
http://localhost:8013 - container:
8000
All requests go through Spring Security and require an Authorization header:
Authorization: Bearer <token>Important: authentication is currently implemented through a custom header filter. If you change the token source, update the security layer accordingly.
GET /health
GET /collection/get/{collectionAddress}/page/{pageNumber}/page-size/{pageSize}POST /collection/add-to-verified/{collectionAddress}DELETE /collection/delete-from-verified/{collectionAddress}GET /collection/sort-collection-nfts/{ascending}/{collectionAddress}/page/{pageNumber}/pageSize/{pageSize}
GET /nft/get/{nftAddress}POST /nft/updateNftPrice/{nftAddress}POST /nft/sell-nft/{nftAddress}/{boc}
GET /search/collection/{searchString}GET /search/nft/{searchString}?collectionAddress={collectionAddress}GET /search/account/{accountId}GET /search/local-search/nft/{accountId}/{searchString}
POST /users/add/{walletAddress}PUT /users/update/{walletAddress}
POST /fill-database/insert-collectionsPOST /fill-database/insert-nftsPOST /fill-database/fill-gateway/{item}
Example request body for fill endpoints:
{
"addresses": [
"EQ..."
]
}- CORS is currently configured for
http://localhost:5173. - The service expects TON addresses and converts them internally before processing.
- There is only a basic smoke test in
src/test, so critical flows should be covered with more tests before production rollout.