Skip to content

Commit 2a1ecce

Browse files
committed
Migrated finally to new backend, removed old backend
1 parent 6f00c27 commit 2a1ecce

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+216
-11461
lines changed
File renamed without changes.

backend/Dockerfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
FROM node:17
2+
RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
3+
4+
# pnpm fetch does require only lockfile
5+
COPY pnpm-lock.yaml ./
6+
RUN pnpm fetch --prod
7+
8+
ADD . ./
9+
RUN pnpm install
10+
11+
RUN pnpm run build
12+
RUN mkdir -p /cache/metadata && mkdir -p /cache/fullmap
13+
#
14+
# If you need to compile your source, do it here.
15+
#
16+
CMD [ "node", "dist/src/main.js" ]
17+
18+
EXPOSE 3001
19+
20+
21+
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

old-backend/chart/templates/deployment.yaml renamed to backend/chart/templates/deployment.yaml

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,31 @@ spec:
2424
{{- toYaml .Values.securityContext | nindent 12 }}
2525
image: "{{ .Values.image }}"
2626
env:
27-
- name: AWS_BUCKET_NAME
28-
value: "{{ .Values.AWS_BUCKET_NAME }}"
29-
- name: AWS_ID
30-
value: "{{ .Values.AWS_ID }}"
31-
- name: AWS_SECRET
32-
value: "{{ .Values.AWS_SECRET }}"
33-
- name: WEB3_URL
34-
value: "{{ .Values.WEB3_URL }}"
35-
- name: CONTRACT_ADDRESS
36-
value: "{{ .Values.CONTRACT_ADDRESS }}"
37-
- name: CONTRACT_WRAPPER_ADDRESS
38-
value: "{{ .Values.CONTRACT_WRAPPER_ADDRESS }}"
27+
- name: AWS_ACCESS_KEY_ID
28+
value: "{{ .Values.AWS_ACCESS_KEY_ID }}"
29+
- name: AWS_SECRET_ACCESS_KEY
30+
value: "{{ .Values.AWS_SECRET_ACCESS_KEY }}"
31+
- name: DATABASE_USERNAME
32+
value: "{{ .Values.DATABASE_USERNAME }}"
33+
- name: DATABASE_PASSWORD
34+
value: "{{ .Values.DATABASE_PASSWORD }}"
35+
- name: DATABASE_NAME
36+
value: "{{ .Values.DATABASE_NAME }}"
37+
- name: DATABASE_HOST
38+
value: "{{ .Values.DATABASE_HOST }}"
39+
- name: DISCORD_TOKEN
40+
value: "{{ .Values.DISCORD_TOKEN }}"
41+
- name: ETHERSCAN_API_KEY
42+
value: "{{ .Values.ETHERSCAN_API_KEY }}"
43+
- name: OPENSEA_API_KEY
44+
value: "{{ .Values.OPENSEA_API_KEY }}"
3945
imagePullPolicy: Always
4046
ports:
4147
- name: http
4248
containerPort: 3001
4349
protocol: TCP
4450
volumeMounts:
45-
- mountPath: "/app/cache"
51+
- mountPath: "/cache"
4652
name: backend-storage
4753
livenessProbe:
4854
httpGet:
@@ -52,4 +58,4 @@ spec:
5258
httpGet:
5359
path: /tiledata
5460
port: http
55-
initialDelaySeconds: 240
61+
File renamed without changes.
File renamed without changes.

backend/nest-cli.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
22
"collection": "@nestjs/schematics",
3-
"sourceRoot": "src",
4-
"entryFile": "backend/src/main"
3+
"sourceRoot": "src"
54
}

backend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"@nestjs/core": "^8.0.0",
4141
"@nestjs/platform-express": "^8.0.0",
4242
"@nestjs/schedule": "^1.0.1",
43+
"bignumber.js": "^9.0.1",
4344
"canvas": "^2.8.0",
4445
"compression": "^1.7.4",
4546
"discord-nestjs": "^1.2.1",
@@ -53,7 +54,8 @@
5354
"reflect-metadata": "^0.1.13",
5455
"rimraf": "^3.0.2",
5556
"rxjs": "^7.2.0",
56-
"s3-sync-client": "^2.1.0"
57+
"s3-sync-client": "^2.1.0",
58+
"uuid": "^8.3.2"
5759
},
5860
"devDependencies": {
5961
"@nestjs/cli": "^8.0.0",

backend/pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/src/app.module.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,31 @@ import { RendererModule } from './renderer/renderer.module';
1717
import { CurrentState } from './ingestor/entities/currentState.entity';
1818
import { MetadataService } from './metadata/metadata.service';
1919
import { MetadataModule } from './metadata/metadata.module';
20+
import { OpenseaModule } from './opensea/opensea.module';
2021

2122
@Module({
2223
imports: [
2324
ConfigModule.forRoot({ isGlobal: true }),
2425
ScheduleModule.forRoot(),
2526
MikroOrmModule.forFeature([Tile, DataHistory]),
26-
MikroOrmModule.forRoot({
27-
metadataProvider: TsMorphMetadataProvider,
28-
entities: [CurrentState, DataHistory, PixelMapEvent, PurchaseHistory, Tile, TransferHistory, WrappingHistory],
29-
type: 'postgresql',
30-
dbName: 'postgres',
31-
host: 'localhost',
32-
port: 5432,
33-
user: 'postgres',
34-
password: 'password',
27+
MikroOrmModule.forRootAsync({
28+
useFactory: (configService: ConfigService) => ({
29+
metadataProvider: TsMorphMetadataProvider,
30+
entities: [CurrentState, DataHistory, PixelMapEvent, PurchaseHistory, Tile, TransferHistory, WrappingHistory],
31+
type: 'postgresql',
32+
dbName: configService.get<string>('DATABASE_NAME'),
33+
host: configService.get<string>('DATABASE_HOST'),
34+
port: 5432,
35+
user: configService.get<string>('DATABASE_USERNAME'),
36+
password: configService.get<string>('DATABASE_PASSWORD'),
37+
}),
38+
inject: [ConfigService],
3539
}),
3640
IngestorModule,
3741
NotificationsModule,
3842
RendererModule,
3943
MetadataModule,
44+
OpenseaModule,
4045
],
4146
controllers: [AppController],
4247
providers: [AppService, MetadataService],

backend/src/ingestor/utils/initializeEthersJS.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ethers } from 'ethers';
2-
import * as pixelMapABI from '../../../../abi/PixelMap.json';
3-
import * as pixelMapWrapperABI from '../../../../abi/PixelMapWrapper.json';
2+
import * as pixelMapABI from '../../../abi/PixelMap.json';
3+
import * as pixelMapWrapperABI from '../../../abi/PixelMapWrapper.json';
44

55
export function initializeEthersJS() {
66
const provider = new ethers.providers.JsonRpcProvider(

backend/src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ async function bootstrap() {
66
if (process.env.NODE_ENV !== 'production') {
77
app.getHttpAdapter().getInstance().set('json spaces', 2);
88
}
9-
await app.listen(3000);
9+
await app.listen(3001);
1010
}
1111
bootstrap();

backend/src/metadata/metadata.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class MetadataService {
3232

3333
this.currentlyGeneratingMetadata = false;
3434
} else {
35-
this.logger.debug('Already rendering images, not starting again yet');
35+
this.logger.debug('Already rendering metadata, not starting again yet');
3636
}
3737
}
3838

backend/src/opensea/opensea.module.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Module } from '@nestjs/common';
2+
import { OpenseaService } from './opensea.service';
3+
import { MikroOrmModule } from '@mikro-orm/nestjs';
4+
import { Tile } from '../ingestor/entities/tile.entity';
5+
import { HttpModule } from '@nestjs/axios';
6+
7+
@Module({
8+
providers: [OpenseaService],
9+
imports: [MikroOrmModule.forFeature([Tile]), HttpModule],
10+
})
11+
export class OpenseaModule {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import { OpenseaService } from './opensea.service';
3+
4+
describe('OpenseaService', () => {
5+
let service: OpenseaService;
6+
7+
beforeEach(async () => {
8+
const module: TestingModule = await Test.createTestingModule({
9+
providers: [OpenseaService],
10+
}).compile();
11+
12+
service = module.get<OpenseaService>(OpenseaService);
13+
});
14+
15+
it('should be defined', () => {
16+
expect(service).toBeDefined();
17+
});
18+
});
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { Injectable, Logger } from '@nestjs/common';
2+
import { InjectRepository, UseRequestContext } from '@mikro-orm/nestjs';
3+
import { Tile } from '../ingestor/entities/tile.entity';
4+
import { EntityRepository, MikroORM, QueryOrder } from '@mikro-orm/core';
5+
import { Cron } from '@nestjs/schedule';
6+
import { HttpService } from '@nestjs/axios';
7+
import { lastValueFrom } from 'rxjs';
8+
import { ConfigService } from '@nestjs/config';
9+
import BigNumber from 'bignumber.js';
10+
import { formatEther } from 'ethers/lib/utils';
11+
12+
@Injectable()
13+
export class OpenseaService {
14+
private readonly logger = new Logger(OpenseaService.name);
15+
private updatingOpenSeaPrices = false;
16+
17+
constructor(
18+
@InjectRepository(Tile)
19+
private tileData: EntityRepository<Tile>,
20+
private httpService: HttpService,
21+
private readonly orm: MikroORM,
22+
private configService: ConfigService,
23+
) {}
24+
25+
// Update OpenSea prices every 15 minutes
26+
@Cron('*/15 * * * *', {
27+
name: 'updateOpenSeaPrices',
28+
})
29+
@UseRequestContext()
30+
async updateOpenSeaPrices() {
31+
if (!this.updatingOpenSeaPrices) {
32+
this.updatingOpenSeaPrices = true;
33+
34+
const tiles = await this.tileData.find({}, [], { id: QueryOrder.ASC });
35+
const limit = 15; //max 30 items for token_ids
36+
37+
try {
38+
for (let id = 0; id <= 3969; id += limit) {
39+
this.logger.verbose(`Opensea update offset: ${id}`);
40+
const openseaURL = new URL('https://api.opensea.io/wyvern/v1/orders');
41+
openseaURL.searchParams.set('asset_contract_address', '0x050dc61dFB867E0fE3Cf2948362b6c0F3fAF790b');
42+
openseaURL.searchParams.set('side', '1');
43+
openseaURL.searchParams.set('include_bundled', 'false');
44+
openseaURL.searchParams.set('include_invalid', 'false');
45+
openseaURL.searchParams.set('order_by', 'created_date');
46+
openseaURL.searchParams.set('order_direction', 'asc');
47+
48+
for (let i = id; i < id + limit; i++) {
49+
openseaURL.searchParams.append('token_ids', i.toString());
50+
}
51+
const openseaAPIKey = this.configService.get('OPENSEA_API_KEY');
52+
const response = await lastValueFrom(
53+
this.httpService.get(openseaURL.toString(), {
54+
headers: {
55+
'X-API-KEY': openseaAPIKey,
56+
},
57+
}),
58+
);
59+
60+
const results = await response.data;
61+
62+
if (results && results.orders && results.orders.length > 0) {
63+
results.orders.forEach((order) => {
64+
const location = parseInt(order.asset.token_id);
65+
const weiPrice = new BigNumber(order.current_price);
66+
const price = formatEther(weiPrice.toFixed(0));
67+
tiles[location].openseaPrice = parseFloat(price);
68+
});
69+
}
70+
await this.tileData.flush();
71+
await sleep(1000); //throttle requests to prevent rate limiting with OS
72+
}
73+
} catch (err) {
74+
console.log(err);
75+
}
76+
77+
this.updatingOpenSeaPrices = false;
78+
} else {
79+
this.logger.debug('Already updating OpenSea prices, not starting again yet');
80+
}
81+
}
82+
}
83+
84+
async function sleep(millis) {
85+
return new Promise((resolve) => setTimeout(resolve, millis));
86+
}

backend/temp/CurrentState.js.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"data":{"propertyOrder":{},"properties":{"state":{"name":"state","reference":"scalar","primary":true,"type":"StatesToTrack","enum":true,"items":["INGESTION_LAST_DOWNLOADED_BLOCK","INGESTION_LAST_PROCESSED_PIXEL_MAP_EVENT","NOTIFICATIONS_LAST_PROCESSED_PURCHASE_ID","RENDERER_LAST_PROCESSED_DATA_CHANGE"]},"value":{"name":"value","reference":"scalar","default":0,"getter":false,"setter":false,"type":"number"}},"props":[{"name":"state","reference":"scalar","primary":true,"type":"StatesToTrack","enum":true,"items":["INGESTION_LAST_DOWNLOADED_BLOCK","INGESTION_LAST_PROCESSED_PIXEL_MAP_EVENT","NOTIFICATIONS_LAST_PROCESSED_PURCHASE_ID","RENDERER_LAST_PROCESSED_DATA_CHANGE"]},{"name":"value","reference":"scalar","default":0,"getter":false,"setter":false,"type":"number"}],"primaryKeys":["state"],"filters":{},"hooks":{},"indexes":[],"uniques":[],"className":"CurrentState","path":"./dist/backend/src/ingestor/entities/currentState.entity.js","name":"CurrentState","abstract":false,"constructorParams":["init"],"toJsonParams":[],"useCache":true,"compositePK":false,"relations":[],"collection":"current_state"},"origin":"./dist/backend/src/ingestor/entities/currentState.entity.js","hash":"d4e8b201177e83544ad8d72b803b8b4f","version":"4.5.9"}
1+
{"data":{"propertyOrder":{},"properties":{"state":{"name":"state","reference":"scalar","primary":true,"type":"StatesToTrack","enum":true,"items":["INGESTION_LAST_DOWNLOADED_BLOCK","INGESTION_LAST_PROCESSED_PIXEL_MAP_EVENT","NOTIFICATIONS_LAST_PROCESSED_PURCHASE_ID","RENDERER_LAST_PROCESSED_DATA_CHANGE"]},"value":{"name":"value","reference":"scalar","default":0,"getter":false,"setter":false,"type":"number"}},"props":[{"name":"state","reference":"scalar","primary":true,"type":"StatesToTrack","enum":true,"items":["INGESTION_LAST_DOWNLOADED_BLOCK","INGESTION_LAST_PROCESSED_PIXEL_MAP_EVENT","NOTIFICATIONS_LAST_PROCESSED_PURCHASE_ID","RENDERER_LAST_PROCESSED_DATA_CHANGE"]},{"name":"value","reference":"scalar","default":0,"getter":false,"setter":false,"type":"number"}],"primaryKeys":["state"],"filters":{},"hooks":{},"indexes":[],"uniques":[],"className":"CurrentState","path":"./dist/src/ingestor/entities/currentState.entity.js","name":"CurrentState","abstract":false,"constructorParams":["init"],"toJsonParams":[],"useCache":true,"compositePK":false,"relations":[],"collection":"current_state"},"origin":"./dist/src/ingestor/entities/currentState.entity.js","hash":"d4e8b201177e83544ad8d72b803b8b4f","version":"4.5.9"}

backend/temp/DataHistory.js.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"data":{"propertyOrder":{},"properties":{"id":{"name":"id","reference":"scalar","primary":true,"type":"number"},"timeStamp":{"name":"timeStamp","reference":"scalar","getter":false,"setter":false,"type":"Date"},"blockNumber":{"name":"blockNumber","reference":"scalar","getter":false,"setter":false,"type":"number"},"tx":{"name":"tx","reference":"scalar","getter":false,"setter":false,"type":"string"},"logIndex":{"name":"logIndex","reference":"scalar","getter":false,"setter":false,"type":"number"},"image":{"name":"image","reference":"scalar","length":800,"getter":false,"setter":false,"type":"string"},"price":{"name":"price","reference":"scalar","getter":false,"setter":false,"type":"number","columnTypes":["decimal(10, 2)"]},"url":{"name":"url","reference":"scalar","getter":false,"setter":false,"type":"string"},"updatedBy":{"name":"updatedBy","reference":"scalar","getter":false,"setter":false,"type":"string"},"tile":{"name":"tile","reference":"m:1","cascade":["persist"],"type":"Tile","nullable":false}},"props":[{"name":"id","reference":"scalar","primary":true,"type":"number"},{"name":"timeStamp","reference":"scalar","getter":false,"setter":false,"type":"Date"},{"name":"blockNumber","reference":"scalar","getter":false,"setter":false,"type":"number"},{"name":"tx","reference":"scalar","getter":false,"setter":false,"type":"string"},{"name":"logIndex","reference":"scalar","getter":false,"setter":false,"type":"number"},{"name":"image","reference":"scalar","length":800,"getter":false,"setter":false,"type":"string"},{"name":"price","reference":"scalar","getter":false,"setter":false,"type":"number","columnTypes":["decimal(10, 2)"]},{"name":"url","reference":"scalar","getter":false,"setter":false,"type":"string"},{"name":"updatedBy","reference":"scalar","getter":false,"setter":false,"type":"string"},{"name":"tile","reference":"m:1","cascade":["persist"],"type":"Tile","nullable":false}],"primaryKeys":["id"],"filters":{},"hooks":{},"indexes":[],"uniques":[{"properties":["tile","tx"]}],"className":"DataHistory","path":"./dist/backend/src/ingestor/entities/dataHistory.entity.js","name":"DataHistory","abstract":false,"constructorParams":["init"],"toJsonParams":[],"useCache":true,"compositePK":false,"relations":[{"name":"tile","reference":"m:1","cascade":["persist"],"type":"Tile","nullable":false}],"collection":"data_history"},"origin":"./dist/backend/src/ingestor/entities/dataHistory.entity.js","hash":"59c6479897b73c6db715f86538437682","version":"4.5.9"}
1+
{"data":{"propertyOrder":{},"properties":{"id":{"name":"id","reference":"scalar","primary":true,"type":"number"},"timeStamp":{"name":"timeStamp","reference":"scalar","getter":false,"setter":false,"type":"Date"},"blockNumber":{"name":"blockNumber","reference":"scalar","getter":false,"setter":false,"type":"number"},"tx":{"name":"tx","reference":"scalar","getter":false,"setter":false,"type":"string"},"logIndex":{"name":"logIndex","reference":"scalar","getter":false,"setter":false,"type":"number"},"image":{"name":"image","reference":"scalar","length":800,"getter":false,"setter":false,"type":"string"},"price":{"name":"price","reference":"scalar","getter":false,"setter":false,"type":"number","columnTypes":["decimal(10, 2)"]},"url":{"name":"url","reference":"scalar","getter":false,"setter":false,"type":"string"},"updatedBy":{"name":"updatedBy","reference":"scalar","getter":false,"setter":false,"type":"string"},"tile":{"name":"tile","reference":"m:1","cascade":["persist"],"type":"Tile","nullable":false}},"props":[{"name":"id","reference":"scalar","primary":true,"type":"number"},{"name":"timeStamp","reference":"scalar","getter":false,"setter":false,"type":"Date"},{"name":"blockNumber","reference":"scalar","getter":false,"setter":false,"type":"number"},{"name":"tx","reference":"scalar","getter":false,"setter":false,"type":"string"},{"name":"logIndex","reference":"scalar","getter":false,"setter":false,"type":"number"},{"name":"image","reference":"scalar","length":800,"getter":false,"setter":false,"type":"string"},{"name":"price","reference":"scalar","getter":false,"setter":false,"type":"number","columnTypes":["decimal(10, 2)"]},{"name":"url","reference":"scalar","getter":false,"setter":false,"type":"string"},{"name":"updatedBy","reference":"scalar","getter":false,"setter":false,"type":"string"},{"name":"tile","reference":"m:1","cascade":["persist"],"type":"Tile","nullable":false}],"primaryKeys":["id"],"filters":{},"hooks":{},"indexes":[],"uniques":[{"properties":["tile","tx"]}],"className":"DataHistory","path":"./dist/src/ingestor/entities/dataHistory.entity.js","name":"DataHistory","abstract":false,"constructorParams":["init"],"toJsonParams":[],"useCache":true,"compositePK":false,"relations":[{"name":"tile","reference":"m:1","cascade":["persist"],"type":"Tile","nullable":false}],"collection":"data_history"},"origin":"./dist/src/ingestor/entities/dataHistory.entity.js","hash":"59c6479897b73c6db715f86538437682","version":"4.5.9"}

0 commit comments

Comments
 (0)