diff --git a/.eslintrc.js b/.eslintrc.js index a326e012..b42a5f3c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,22 +1,22 @@ module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: 'tsconfig.json', - tsconfigRootDir: __dirname, - sourceType: 'module', - }, - plugins: ['@typescript-eslint/eslint-plugin'], - extends: ['plugin:@typescript-eslint/recommended'], - root: true, - env: { - node: true, - jest: true, - }, - ignorePatterns: ['.eslintrc.js'], - rules: { - '@typescript-eslint/interface-name-prefix': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-explicit-any': 'off', - }, + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: ['plugin:@typescript-eslint/recommended'], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js', '**/test/*'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, }; diff --git a/docker-compose-hasura.yml b/docker-compose-hasura.yml index 103b8f94..19280a55 100644 --- a/docker-compose-hasura.yml +++ b/docker-compose-hasura.yml @@ -1,4 +1,3 @@ -version: '3.6' services: postgres: image: postgres:15 @@ -29,7 +28,7 @@ services: ## uncomment next line to set an admin secret HASURA_GRAPHQL_ADMIN_SECRET: z6KTncr37daLn5Vq HASURA_GRAPHQL_METADATA_DEFAULTS: '{"backend_configs":{"dataconnector":{"athena":{"uri":"http://data-connector-agent:8081/api/v1/athena"},"mariadb":{"uri":"http://data-connector-agent:8081/api/v1/mariadb"},"mysql8":{"uri":"http://data-connector-agent:8081/api/v1/mysql"},"oracle":{"uri":"http://data-connector-agent:8081/api/v1/oracle"},"snowflake":{"uri":"http://data-connector-agent:8081/api/v1/snowflake"}}}}' - HASURA_GRAPHQL_JWT_SECRET: '{"type": "RS256", "key": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAu4H5cKl1P1wnZB9mUgLjUAtyA7kmlzlJwXwUBwPIInxP3kKWJIF8\no4oW4EO5d75qeRjUueYPVh6WCe0OHrOyoFNcd0VsTkuYVMyXlPYlQM1HmBA64b5r\nC7nmr+mk4xlBE6i3EPx1kQAUJTR147WqeFvS3PeWaQVwocffb1KZjfVks3+3WOYA\nNkxoYiDmxGwi+MShzOSyvYizxBHPFm8WgTUhHWPiBCHkX+CRXlz3R7k2nDVxnD7s\nnDDJ8ITxxeY3DJVH4qvARNE+cbFyLbQsmnw72zzsBQmuTt7qLXdQlEmYxxgBZceE\nilkPJOtV11LM/S/CzZOkYZg+Df2F9+PggwIDAQAB\n-----END RSA PUBLIC KEY-----"}' + HASURA_GRAPHQL_JWT_SECRET: '{"type": "RS256", "key": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAs4q6OBeCTUhVWUTGa3+uw7d2lWbPrIKjU2hvSlvOQE1SIK0AtUP+\nTagi2xIQpNj05j+yb8hh2fX0SqcWmTBGkZksMecesThpYd+YQ30yDHGoI8F70l8D\nRbytmO6habfPqjx1qvXYUscyWycDZyEM0KIxvgQhhR/Nf1CfReIMHmFQtgmTIRnZ\n6nwHXVrHBbVN5LtUYuY4QNpILgwDH0mJAQ0//Fasr0vq5WwkEHlJ5Grzv1jkl6Y8\nERvaNhfvh4vm2lSiS6RkwgWB6wvdNKy2j1AxKmHl2Xdt9aoGsqC5G8nvrmICeEgL\nFTMpJ+nswMIpDqSmYhoraMmnUqoAvNegNwIDAQAB\n-----END RSA PUBLIC KEY-----"}' HASURA_GRAPHQL_UNAUTHORIZED_ROLE: 'anonymous' ACTION_API_DOMAIN: 'http://172.27.10.137:3000' # HASURA_GRAPHQL_ENABLED_APIS: graphql diff --git a/hasura/metadata/databases/punkga-pg/tables/public_authorizer_users.yaml b/hasura/metadata/databases/punkga-pg/tables/public_authorizer_users.yaml index 4a6a134e..507cdc3b 100644 --- a/hasura/metadata/databases/punkga-pg/tables/public_authorizer_users.yaml +++ b/hasura/metadata/databases/punkga-pg/tables/public_authorizer_users.yaml @@ -91,6 +91,7 @@ select_permissions: - revoked_timestamp - roles - signup_methods + - ton_wallet_address - updated_at - wallet_address computed_fields: @@ -109,6 +110,7 @@ update_permissions: - gender - nickname - picture + - ton_wallet_address - wallet_address filter: id: diff --git a/hasura/metadata/databases/punkga-pg/tables/public_top_creator_donate.yaml b/hasura/metadata/databases/punkga-pg/tables/public_top_creator_donate.yaml new file mode 100644 index 00000000..2d69074a --- /dev/null +++ b/hasura/metadata/databases/punkga-pg/tables/public_top_creator_donate.yaml @@ -0,0 +1,3 @@ +table: + name: top_creator_donate + schema: public diff --git a/hasura/metadata/databases/punkga-pg/tables/public_top_user_donate.yaml b/hasura/metadata/databases/punkga-pg/tables/public_top_user_donate.yaml new file mode 100644 index 00000000..af8b39da --- /dev/null +++ b/hasura/metadata/databases/punkga-pg/tables/public_top_user_donate.yaml @@ -0,0 +1,3 @@ +table: + name: top_user_donate + schema: public diff --git a/hasura/metadata/databases/punkga-pg/tables/tables.yaml b/hasura/metadata/databases/punkga-pg/tables/tables.yaml index 6c708103..7cb1eb3f 100644 --- a/hasura/metadata/databases/punkga-pg/tables/tables.yaml +++ b/hasura/metadata/databases/punkga-pg/tables/tables.yaml @@ -38,6 +38,8 @@ - "!include public_telegram_quest_history.yaml" - "!include public_telegram_quests.yaml" - "!include public_telegram_users.yaml" +- "!include public_top_creator_donate.yaml" +- "!include public_top_user_donate.yaml" - "!include public_user_campaign.yaml" - "!include public_user_campaign_reward.yaml" - "!include public_user_level.yaml" diff --git a/hasura/metadata/query_collections.yaml b/hasura/metadata/query_collections.yaml index 80020556..3df4edb5 100644 --- a/hasura/metadata/query_collections.yaml +++ b/hasura/metadata/query_collections.yaml @@ -1077,118 +1077,6 @@ } } } - - name: User - Get Profile - query: | - query GetUserProfile { - authorizer_users(limit: 1) { - id - email - email_verified_at - bio - birthdate - gender - active_wallet_address: active_evm_address - wallet_address - nickname - picture - signup_methods - levels { - xp - level - user_level_chain { - id - name - punkga_config - } - } - authorizer_users_user_wallet { - address - } - user_quests_aggregate { - aggregate { - count - } - } - user_quests(order_by: {created_at:desc}, limit: 20) { - created_at - status - user_quest_rewards { - tx_hash - } - quest { - id - name - quests_campaign { - campaign_chain { - punkga_config - } - } - quests_i18n { - id - quest_id - language_id - data - i18n_language { - id - description - icon - is_main - symbol - } - } - reward - } - } - } - } - - name: Public - Get manga by creator - query: | - query manga ($id: Int!, $limit: Int = 10, $offset: Int = 0) { - manga(limit: $limit, offset: $offset, where: {manga_creators:{creator_id:{_eq:$id}},status:{_neq:"Removed"}}) { - id - slug - status - poster - banner - manga_creators { - creator { - name - pen_name - id - slug - isActive - } - } - manga_total_likes { - likes - } - manga_total_views { - views - } - manga_tags { - tag { - tag_languages { - language_id - value - } - id - } - } - chapters(limit: 1, order_by: {chapter_number:desc}, where: {status:{_eq:"Published"}}) { - id - chapter_number - chapter_name - } - contract_addresses - manga_languages { - id - is_main_language - title - description - language_id - } - } - } - name: Public - query artwork by creator query: | query artworks ($creator_id: Int!, $limit: Int = 10, $offset: Int = 0) { @@ -1472,40 +1360,153 @@ } } } + - name: Public - Query albums by creator id + query: | + query albums ($creator_id: Int!, $limit: Int = 100, $offset: Int = 0) { + albums(where: {_or:[{_and:{id:{_eq:1},show:{_eq:true}}},{_and:{creator_id:{_eq:$creator_id},show:{_eq:true}}}]}, limit: $limit, offset: $offset) { + id + show + thumbnail_url + name + disable + } + albums_aggregate(where: {_or:[{_and:{id:{_eq:1},show:{_eq:true}}},{_and:{creator_id:{_eq:$creator_id},show:{_eq:true}}}]}) { + aggregate { + count + } + } + } - name: Public - Query album detail query: | - query albums ($id: Int!, $limit: Int = 10, $offset: Int = 0) { + query albums ($id: Int!, $limit: Int = 10, $offset: Int = 0, $creator_id: Int!) { albums(where: {id:{_eq:$id},show:{_eq:true},disable:{_eq:false}}) { id name thumbnail_url show disable - artworks(limit: $limit, offset: $offset) { + artworks(limit: $limit, offset: $offset, where: {creator_id:{_eq:$creator_id}}) { id name url } - artworks_aggregate { + artworks_aggregate(where: {creator_id:{_eq:$creator_id}}) { aggregate { count } } } } - - name: Public - Query albums by creator id + - name: Public - Get manga by creator query: | - query albums ($creator_id: Int!, $limit: Int = 100, $offset: Int = 0) { - albums(where: {_or:[{_and:{id:{_eq:1},show:{_eq:true}}},{_and:{creator_id:{_eq:$creator_id},show:{_eq:true}}}]}, limit: $limit, offset: $offset) { + query manga ($id: Int!, $limit: Int = 10, $offset: Int = 0) { + manga(limit: $limit, offset: $offset, where: {manga_creators:{creator_id:{_eq:$id}},status:{_neq:"Removed"}}) { id - show - thumbnail_url - name - disable + slug + status + poster + banner + manga_creators { + creator { + name + pen_name + id + slug + isActive + } + } + manga_total_likes { + likes + } + manga_total_views { + views + } + manga_tags { + tag { + tag_languages { + language_id + value + } + id + } + } + chapters(limit: 1, order_by: {chapter_number:desc}, where: {status:{_eq:"Published"}}) { + id + chapter_number + chapter_name + } + contract_addresses + manga_languages { + id + is_main_language + title + description + language_id + } } - albums_aggregate(where: {_or:[{_and:{id:{_eq:1},show:{_eq:true}}},{_and:{creator_id:{_eq:$creator_id},show:{_eq:true}}}]}) { - aggregate { - count + } + - name: User - Get Profile + query: | + query GetUserProfile { + authorizer_users(limit: 1) { + id + email + email_verified_at + bio + birthdate + gender + active_wallet_address: active_evm_address + wallet_address + ton_wallet_address + nickname + picture + signup_methods + levels { + xp + level + user_level_chain { + id + name + punkga_config + } + } + authorizer_users_user_wallet { + address + } + user_quests_aggregate { + aggregate { + count + } + } + user_quests(order_by: {created_at:desc}, limit: 20) { + created_at + status + user_quest_rewards { + tx_hash + } + quest { + id + name + quests_campaign { + campaign_chain { + punkga_config + } + } + quests_i18n { + id + quest_id + language_id + data + i18n_language { + id + description + icon + is_main + symbol + } + } + reward + } } } } diff --git a/hasura/migrations/punkga-pg/1726730858341_top_user_donate/down.sql b/hasura/migrations/punkga-pg/1726730858341_top_user_donate/down.sql new file mode 100644 index 00000000..3b4c4465 --- /dev/null +++ b/hasura/migrations/punkga-pg/1726730858341_top_user_donate/down.sql @@ -0,0 +1,12 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE OR REPLACE VIEW "public"."top_user_donate" AS +-- SELECT +-- telegram_users.username, +-- telegram_users.user_id, +-- donate_history.telegram_id, +-- sum(donate_history.value) AS value +-- FROM donate_history +-- INNER JOIN telegram_users on telegram_users.telegram_id = donate_history.telegram_id +-- GROUP BY telegram_users.username,telegram_users.user_id,donate_history.telegram_id +-- LIMIT 10; diff --git a/hasura/migrations/punkga-pg/1726730858341_top_user_donate/up.sql b/hasura/migrations/punkga-pg/1726730858341_top_user_donate/up.sql new file mode 100644 index 00000000..3d08c22b --- /dev/null +++ b/hasura/migrations/punkga-pg/1726730858341_top_user_donate/up.sql @@ -0,0 +1,10 @@ +CREATE OR REPLACE VIEW "public"."top_user_donate" AS + SELECT + telegram_users.username, + telegram_users.user_id, + donate_history.telegram_id, + sum(donate_history.value) AS value + FROM donate_history + INNER JOIN telegram_users on telegram_users.telegram_id = donate_history.telegram_id + GROUP BY telegram_users.username,telegram_users.user_id,donate_history.telegram_id + LIMIT 10; diff --git a/hasura/migrations/punkga-pg/1726733949687_top_creator_donate/down.sql b/hasura/migrations/punkga-pg/1726733949687_top_creator_donate/down.sql new file mode 100644 index 00000000..bca1b438 --- /dev/null +++ b/hasura/migrations/punkga-pg/1726733949687_top_creator_donate/down.sql @@ -0,0 +1,26 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE +-- OR REPLACE VIEW "public"."top_creator_donate" AS +-- SELECT +-- creators.id, +-- creators.email, +-- creators.name, +-- creators.avatar_url, +-- sum(donate_history.value) AS value +-- FROM +-- ( +-- donate_history +-- JOIN creators ON ( +-- ( +-- creators.id = donate_history.creator_id +-- ) +-- ) +-- ) +-- GROUP BY +-- creators.id, +-- creators.email, +-- creators.name, +-- creators.avatar_url +-- LIMIT +-- 10; diff --git a/hasura/migrations/punkga-pg/1726733949687_top_creator_donate/up.sql b/hasura/migrations/punkga-pg/1726733949687_top_creator_donate/up.sql new file mode 100644 index 00000000..4943814c --- /dev/null +++ b/hasura/migrations/punkga-pg/1726733949687_top_creator_donate/up.sql @@ -0,0 +1,24 @@ +CREATE +OR REPLACE VIEW "public"."top_creator_donate" AS +SELECT + creators.id, + creators.email, + creators.name, + creators.avatar_url, + sum(donate_history.value) AS value +FROM + ( + donate_history + JOIN creators ON ( + ( + creators.id = donate_history.creator_id + ) + ) + ) +GROUP BY + creators.id, + creators.email, + creators.name, + creators.avatar_url +LIMIT + 10; diff --git a/hasura/migrations/punkga-pg/1727059964949_alter_table_public_authorizer_users_add_column_ton_wallet_address/down.sql b/hasura/migrations/punkga-pg/1727059964949_alter_table_public_authorizer_users_add_column_ton_wallet_address/down.sql new file mode 100644 index 00000000..ffe1cf52 --- /dev/null +++ b/hasura/migrations/punkga-pg/1727059964949_alter_table_public_authorizer_users_add_column_ton_wallet_address/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."authorizer_users" add column "ton_wallet_address" text +-- null; diff --git a/hasura/migrations/punkga-pg/1727059964949_alter_table_public_authorizer_users_add_column_ton_wallet_address/up.sql b/hasura/migrations/punkga-pg/1727059964949_alter_table_public_authorizer_users_add_column_ton_wallet_address/up.sql new file mode 100644 index 00000000..6b508315 --- /dev/null +++ b/hasura/migrations/punkga-pg/1727059964949_alter_table_public_authorizer_users_add_column_ton_wallet_address/up.sql @@ -0,0 +1,2 @@ +alter table "public"."authorizer_users" add column "ton_wallet_address" text + null; diff --git a/src/chain-gateway/interfaces/chain-client.interface.ts b/src/chain-gateway/interfaces/chain-client.interface.ts index c14679e1..d084ff2d 100644 --- a/src/chain-gateway/interfaces/chain-client.interface.ts +++ b/src/chain-gateway/interfaces/chain-client.interface.ts @@ -1,4 +1,3 @@ -import { JsonRpcProvider } from 'ethers'; import { ICustodialWalletAsset } from './account-onchain.interface'; export interface IChainClient { diff --git a/src/modules/album/album.controller.ts b/src/modules/album/album.controller.ts index 2f7c7b79..cdb9e9ad 100644 --- a/src/modules/album/album.controller.ts +++ b/src/modules/album/album.controller.ts @@ -32,12 +32,19 @@ import { UpdateAlbumParamDto, UpdateAlbumRequestDto, } from './dto/update-album-request.dto'; +import { QueryAlbumPublicDto } from './dto/query-album-public-query.dto'; @Controller('album') @ApiTags('album') export class AlbumController { constructor(private readonly albumSvc: AlbumService) {} + @Get('public') + @ApiOperation({ summary: 'list album - public' }) + listPublic(@Query() query: QueryAlbumPublicDto) { + return this.albumSvc.getAllPublicAlbum(query); + } + @Get() @UseGuards(AuthGuard, RolesGuard) @ApiBearerAuth() diff --git a/src/modules/album/album.graphql.ts b/src/modules/album/album.graphql.ts index c9ba7e71..3d39c12f 100644 --- a/src/modules/album/album.graphql.ts +++ b/src/modules/album/album.graphql.ts @@ -9,6 +9,89 @@ export class AlbumGraphql { private graphqlSvc: GraphqlService ) {} + countArtworkInDefault(variables: any) { + const headers = { + 'x-hasura-admin-secret': this.configSvc.get( + 'graphql.adminSecret' + ), + }; + return this.graphqlSvc.query( + this.configSvc.get('graphql.endpoint'), + '', + `query artworks_aggregate($creator_id: Int!) { + artworks_aggregate(where: {id: {_eq: 1}, creator_id: {_eq: $creator_id}}) { + aggregate { + count + } + } + } + `, + 'artworks_aggregate', + variables, + headers + ); + } + + getPublicAlbumsWithDefaultAlbum(variables: any) { + const headers = { + 'x-hasura-admin-secret': this.configSvc.get( + 'graphql.adminSecret' + ), + }; + return this.graphqlSvc.query( + this.configSvc.get('graphql.endpoint'), + '', + `query albums($creator_id: Int!, $limit: Int = 100, $offset: Int = 0) { + albums(where: {_or: [{_and: {id: {_eq: 1}, show: {_eq: true}}}, {_and: {creator_id: {_eq: $creator_id}, show: {_eq: true}}}]}, limit: $limit, offset: $offset) { + id + show + thumbnail_url + name + disable + } + albums_aggregate(where: {_or: [{_and: {id: {_eq: 1}, show: {_eq: true}}}, {_and: {creator_id: {_eq: $creator_id}, show: {_eq: true}}}]}) { + aggregate { + count + } + } + } + `, + 'albums', + variables, + headers + ); + } + + getPublicAlbums(variables: any) { + const headers = { + 'x-hasura-admin-secret': this.configSvc.get( + 'graphql.adminSecret' + ), + }; + return this.graphqlSvc.query( + this.configSvc.get('graphql.endpoint'), + '', + `query albums($creator_id: Int!, $limit: Int = 100, $offset: Int = 0) { + albums(where: {_and: {creator_id: {_eq: $creator_id}, show: {_eq: true}}}, limit: $limit, offset: $offset) { + id + show + thumbnail_url + name + disable + } + albums_aggregate(where: {_and: {creator_id: {_eq: $creator_id}, show: {_eq: true}}}) { + aggregate { + count + } + } + } + `, + 'albums', + variables, + headers + ); + } + getListAlbum(variables: any) { const headers = { 'x-hasura-admin-secret': this.configSvc.get( diff --git a/src/modules/album/album.service.ts b/src/modules/album/album.service.ts index aafe4236..65827931 100644 --- a/src/modules/album/album.service.ts +++ b/src/modules/album/album.service.ts @@ -8,6 +8,7 @@ import { AlbumGraphql } from './album.graphql'; import { CreateAlbumRequestDto } from './dto/create-album-request.dto'; import { QueryAlbumDto } from './dto/query-album-query.dto'; import { UpdateAlbumRequestDto } from './dto/update-album-request.dto'; +import { QueryAlbumPublicDto } from './dto/query-album-public-query.dto'; @Injectable() export class AlbumService { @@ -137,6 +138,32 @@ export class AlbumService { }); } + async getAllPublicAlbum(query: QueryAlbumPublicDto) { + const { creator_id, limit, offset } = query; + + const result = await this.albumGraphql.countArtworkInDefault({ + creator_id, + }); + + if (result.errors) return result; + const count = result.data.artworks_aggregate.aggregate.count; + + if (count > 0) + return this.albumGraphql.getPublicAlbumsWithDefaultAlbum({ + creator_id, + limit: Number(limit), + offset: Number(offset), + }); + + const queryResult = await this.albumGraphql.getPublicAlbums({ + creator_id, + limit: Number(limit), + offset: Number(offset), + }); + + return queryResult.data; + } + async getDetail(id: number) { const creatorId = await this.creatorService.getCreatorIdAuthToken(); diff --git a/src/modules/album/dto/create-album-request.dto.ts b/src/modules/album/dto/create-album-request.dto.ts index 4bd0085a..a7cc2c8a 100644 --- a/src/modules/album/dto/create-album-request.dto.ts +++ b/src/modules/album/dto/create-album-request.dto.ts @@ -1,4 +1,4 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { ApiProperty } from '@nestjs/swagger'; export class CreateAlbumRequestDto { @ApiProperty() diff --git a/src/modules/album/dto/query-album-public-query.dto.ts b/src/modules/album/dto/query-album-public-query.dto.ts new file mode 100644 index 00000000..b94b6cf4 --- /dev/null +++ b/src/modules/album/dto/query-album-public-query.dto.ts @@ -0,0 +1,12 @@ +import { ApiPropertyOptional } from '@nestjs/swagger'; + +export class QueryAlbumPublicDto { + @ApiPropertyOptional() + creator_id: number; + + @ApiPropertyOptional() + limit: string; + + @ApiPropertyOptional() + offset: string; +} diff --git a/src/modules/artwork/artwork.controller.ts b/src/modules/artwork/artwork.controller.ts index 463c2798..96607867 100644 --- a/src/modules/artwork/artwork.controller.ts +++ b/src/modules/artwork/artwork.controller.ts @@ -2,11 +2,9 @@ import { Body, Controller, Delete, - Get, Param, Post, Put, - Query, UploadedFile, UploadedFiles, UseGuards, diff --git a/src/modules/artwork/artwork.graphql.ts b/src/modules/artwork/artwork.graphql.ts index 1eead31f..584c74f0 100644 --- a/src/modules/artwork/artwork.graphql.ts +++ b/src/modules/artwork/artwork.graphql.ts @@ -1,8 +1,7 @@ -import { ForbiddenException, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { GraphqlService } from '../graphql/graphql.service'; -import { errorOrEmpty } from '../graphql/utils'; @Injectable() export class ArtworkGraphql { diff --git a/src/modules/banner/banner.controller.ts b/src/modules/banner/banner.controller.ts index 23f2a72a..949f8c2c 100644 --- a/src/modules/banner/banner.controller.ts +++ b/src/modules/banner/banner.controller.ts @@ -1,11 +1,9 @@ import { Body, Controller, - Get, Param, Post, Put, - Query, UploadedFiles, UseGuards, UseInterceptors, diff --git a/src/modules/campaign/campaign.controller.ts b/src/modules/campaign/campaign.controller.ts index 4b25bb37..2a827090 100644 --- a/src/modules/campaign/campaign.controller.ts +++ b/src/modules/campaign/campaign.controller.ts @@ -23,7 +23,7 @@ import { GetAllCampaignQuery } from './dto/get-all-campaign.dto'; import { GetCampaignDetailDto } from './dto/get-campaign-detail.dto'; import { CacheInterceptor } from '@nestjs/cache-manager'; import { GetUserCampaignRankDto } from './dto/get-user-campaign-rank.dto'; -import { AnyFilesInterceptor, FileInterceptor } from '@nestjs/platform-express'; +import { AnyFilesInterceptor } from '@nestjs/platform-express'; import { CreateCampaignDto } from './dto/create-campaign.dto'; import { UpdateCampaignParam } from './dto/update-campaign.dto'; diff --git a/src/modules/campaign/campaign.service.ts b/src/modules/campaign/campaign.service.ts index 778b26bd..3f346b07 100644 --- a/src/modules/campaign/campaign.service.ts +++ b/src/modules/campaign/campaign.service.ts @@ -18,7 +18,6 @@ import { RedisService } from '../redis/redis.service'; import { UserGraphql } from '../user/user.graphql'; import { CampaignGraphql } from './campaign.graphql'; import { - CampaignLanguageDto, CampaignLanguagesDto as CreateCampaignLanguagesDto, CreateCampaignDto, } from './dto/create-campaign.dto'; diff --git a/src/modules/chain/chain.controller.ts b/src/modules/chain/chain.controller.ts index 3e63fe67..0cd03baa 100644 --- a/src/modules/chain/chain.controller.ts +++ b/src/modules/chain/chain.controller.ts @@ -5,7 +5,7 @@ import { UseGuards, UseInterceptors, } from '@nestjs/common'; -import { ApiBearerAuth, ApiConsumes, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; import { AuthGuard } from '../../auth/auth.guard'; import { Role } from '../../auth/role.enum'; diff --git a/src/modules/chain/chain.graphql.ts b/src/modules/chain/chain.graphql.ts index b269ccaa..4d74a8f4 100644 --- a/src/modules/chain/chain.graphql.ts +++ b/src/modules/chain/chain.graphql.ts @@ -1,8 +1,7 @@ -import { ForbiddenException, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { GraphqlService } from '../graphql/graphql.service'; -import { errorOrEmpty } from '../graphql/utils'; @Injectable() export class ChainGraphql { diff --git a/src/modules/chain/dto/create-chain.dto.ts b/src/modules/chain/dto/create-chain.dto.ts index 52d63436..61a6ea4d 100644 --- a/src/modules/chain/dto/create-chain.dto.ts +++ b/src/modules/chain/dto/create-chain.dto.ts @@ -1,4 +1,4 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { ApiProperty } from '@nestjs/swagger'; export class Contracts { @ApiProperty({ example: '0xFfABBAC4b8860268317d787A181aD4D7F8E93D00' }) diff --git a/src/modules/chapter/chapter.service.ts b/src/modules/chapter/chapter.service.ts index 75fa8b62..5e250594 100644 --- a/src/modules/chapter/chapter.service.ts +++ b/src/modules/chapter/chapter.service.ts @@ -176,7 +176,7 @@ export class ChapterService { } if (collection_ids) { const collectionIdListStr = collection_ids.toString().split(','); - let collectionIdList = Array.from(collectionIdListStr, Number); + const collectionIdList = Array.from(collectionIdListStr, Number); if (collectionIdList.length > 0) { const updateResult = await this.addChapterCollection( chapterId, @@ -258,7 +258,7 @@ export class ChapterService { ); if (collection_ids) { const collectionIdListStr = collection_ids.toString().split(','); - let collectionIdList = Array.from(collectionIdListStr, Number); + const collectionIdList = Array.from(collectionIdListStr, Number); if (collectionIdList.length > 0) { const updateResult = await this.addChapterCollection( chapter_id, @@ -449,7 +449,7 @@ export class ChapterService { } } - async addChapterCollection(chapterId: Number, collectionIdList: number[]) { + async addChapterCollection(chapterId: number, collectionIdList: number[]) { try { // const { token } = ContextProvider.getAuthUser(); const objects = []; diff --git a/src/modules/collection/dto/create-launchpad-request.dto.ts b/src/modules/collection/dto/create-launchpad-request.dto.ts index 3290d1ce..5a0b0820 100644 --- a/src/modules/collection/dto/create-launchpad-request.dto.ts +++ b/src/modules/collection/dto/create-launchpad-request.dto.ts @@ -1,4 +1,4 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { ApiProperty } from '@nestjs/swagger'; export class CreateLaunchpadRequestDto { @ApiProperty() @@ -18,19 +18,19 @@ export class CreateLaunchpadRequestDto { @ApiProperty() seo_description_in_vn: string; - + @ApiProperty({ type: 'string', format: 'binary' }) thumbnail: Express.Multer.File; - + @ApiProperty({ type: 'string', format: 'binary' }) thumbnail_in_vn: Express.Multer.File; - + // @ApiProperty({ type: 'string', format: 'binary' }) // logo: Express.Multer.File; - + @ApiProperty({ type: ['string'], format: 'binary' }) featured_images: Express.Multer.File[]; - + @ApiProperty() creator_id: number; @@ -39,5 +39,4 @@ export class CreateLaunchpadRequestDto { @ApiProperty() fund: number; - } diff --git a/src/modules/collection/dto/edit-draft-launchpad-request.dto.ts b/src/modules/collection/dto/edit-draft-launchpad-request.dto.ts index 11dfd303..ec51a291 100644 --- a/src/modules/collection/dto/edit-draft-launchpad-request.dto.ts +++ b/src/modules/collection/dto/edit-draft-launchpad-request.dto.ts @@ -1,4 +1,4 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { ApiProperty } from '@nestjs/swagger'; export class EditDraftLaunchpadRequestDto { @ApiProperty() diff --git a/src/modules/collection/launchpad.controller.ts b/src/modules/collection/launchpad.controller.ts index db6ca742..db1af845 100644 --- a/src/modules/collection/launchpad.controller.ts +++ b/src/modules/collection/launchpad.controller.ts @@ -4,7 +4,6 @@ import { Get, Param, Post, - Put, Query, UploadedFiles, UseGuards, diff --git a/src/modules/collection/launchpad.service.ts b/src/modules/collection/launchpad.service.ts index 9631b83a..ee628e2c 100644 --- a/src/modules/collection/launchpad.service.ts +++ b/src/modules/collection/launchpad.service.ts @@ -65,7 +65,7 @@ export class LaunchpadService { }, }); const mangaId = result.data.insert_launchpad_one.id; - const slug = generateSlug(name,mangaId); + const slug = generateSlug(name, mangaId); if (result.errors) return result; const launchpadId = result.data.insert_launchpad_one.id; @@ -167,7 +167,6 @@ export class LaunchpadService { async unpublish(launchpadId: number) { // Update offchain launchpad data - const { token } = ContextProvider.getAuthUser(); const launchpad = await this.getExistingLaunchpad(launchpadId); if (launchpad.status != LaunchpadStatus.Published) diff --git a/src/modules/creator/creator.graphql.ts b/src/modules/creator/creator.graphql.ts index f2b9600d..b499c79d 100644 --- a/src/modules/creator/creator.graphql.ts +++ b/src/modules/creator/creator.graphql.ts @@ -58,6 +58,7 @@ export class CreatorGraphql { pen_name id slug + isActive } } manga_total_likes { diff --git a/src/modules/creator/creator.service.ts b/src/modules/creator/creator.service.ts index d6560dc7..176ab660 100644 --- a/src/modules/creator/creator.service.ts +++ b/src/modules/creator/creator.service.ts @@ -29,7 +29,7 @@ export class CreatorService { } async getCreator() { - const { userId, token } = ContextProvider.getAuthUser(); + const { userId } = ContextProvider.getAuthUser(); const result = await this.creatorGraphql.queryCreatorIdByUserId({ id: userId, }); diff --git a/src/modules/keys/kms.service.ts b/src/modules/keys/kms.service.ts index 23010c66..c6349ef4 100644 --- a/src/modules/keys/kms.service.ts +++ b/src/modules/keys/kms.service.ts @@ -1,11 +1,9 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { KMSService } from '@aura-nw/aura-kms'; import { ConfigService } from '@nestjs/config'; @Injectable() export class KMSBuilderService { - private readonly logger = new Logger(KMSBuilderService.name); - private SystemKey = null; private KMS: KMSService = null; constructor(private configService: ConfigService) { diff --git a/src/modules/manga/dto/manage-manga-collection-request.dto.ts b/src/modules/manga/dto/manage-manga-collection-request.dto.ts index 5b9a794e..75f0987d 100644 --- a/src/modules/manga/dto/manage-manga-collection-request.dto.ts +++ b/src/modules/manga/dto/manage-manga-collection-request.dto.ts @@ -1,5 +1,5 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { IsBoolean, IsNumber } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; +import { IsNumber } from 'class-validator'; export class MangaCollection { @ApiProperty({ type: [Number], example: [1] }) diff --git a/src/modules/manga/manga.service.ts b/src/modules/manga/manga.service.ts index 89318472..48d8b9fb 100644 --- a/src/modules/manga/manga.service.ts +++ b/src/modules/manga/manga.service.ts @@ -267,7 +267,7 @@ export class MangaService { } } - async addMangaCollection(mangaId: Number, collectionIdList: number[]) { + async addMangaCollection(mangaId: number, collectionIdList: number[]) { try { // const { token } = ContextProvider.getAuthUser(); const objects = []; diff --git a/src/modules/quest/dto/upload-nft-image.dto.ts b/src/modules/quest/dto/upload-nft-image.dto.ts index 4c810c3f..5b5211a8 100644 --- a/src/modules/quest/dto/upload-nft-image.dto.ts +++ b/src/modules/quest/dto/upload-nft-image.dto.ts @@ -1,4 +1,4 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { ApiProperty } from '@nestjs/swagger'; export class UploadNftImageRequestDto { @ApiProperty() diff --git a/src/modules/quest/quest.service.ts b/src/modules/quest/quest.service.ts index e8faaefb..21c5873c 100644 --- a/src/modules/quest/quest.service.ts +++ b/src/modules/quest/quest.service.ts @@ -2,7 +2,6 @@ import { Queue } from 'bull'; import { InjectQueue } from '@nestjs/bull'; import { - BadRequestException, ForbiddenException, Injectable, Logger, diff --git a/src/modules/system-custodial-wallet/system-custodial-wallet.service.ts b/src/modules/system-custodial-wallet/system-custodial-wallet.service.ts index a9538ab2..c29b902c 100644 --- a/src/modules/system-custodial-wallet/system-custodial-wallet.service.ts +++ b/src/modules/system-custodial-wallet/system-custodial-wallet.service.ts @@ -26,7 +26,6 @@ export class SystemCustodialWalletService implements OnModuleInit { async initGranterWallet() { // get from db const granterWalletData = await this.walletGraphql.getGranterWallet(); - const providerUrl = this.configService.get('network.rpcEndpoint'); if (granterWalletData) { const phrase = this.masterWalletService.decryptPhrase( diff --git a/src/modules/telegram/telegram.controller.ts b/src/modules/telegram/telegram.controller.ts index 2a97fc2a..b474bc15 100644 --- a/src/modules/telegram/telegram.controller.ts +++ b/src/modules/telegram/telegram.controller.ts @@ -94,4 +94,43 @@ export class TelegramController { createAndLink() { return this.telegramSvc.createAndLink(); } + + @UseGuards(AuthGuard, RolesGuard) + @ApiBearerAuth() + @Roles(Role.TelegramUser) + @Post('get-top-donate') + @UseInterceptors(AuthUserInterceptor) + @ApiOperation({ summary: '' }) + getTopDonate() { + return this.telegramSvc.getTopDonate(); + } + + @UseGuards(AuthGuard, RolesGuard) + @ApiBearerAuth() + @Roles(Role.TelegramUser) + @Post('get-top-creator-donate') + @UseInterceptors(AuthUserInterceptor) + @ApiOperation({ summary: '' }) + getTopCreatorDonate() { + return this.telegramSvc.getTopCreatorDonate(); + } + + @UseGuards(AuthGuard, RolesGuard) + @ApiBearerAuth() + @Post('gen-telegram-qr') + @UseInterceptors(AuthUserInterceptor) + @ApiOperation({ summary: '' }) + generateTelegramAccountLink() { + return this.telegramSvc.genTelegramQr(); + } + + @UseGuards(AuthGuard, RolesGuard) + @ApiBearerAuth() + @Roles(Role.TelegramUser) + @Post('scan-telegram-qr') + @UseInterceptors(AuthUserInterceptor) + @ApiOperation({ summary: '' }) + scanAndLink(@Body() body: any) { + return this.telegramSvc.linkFromScan(body); + } } diff --git a/src/modules/telegram/telegram.graphql.ts b/src/modules/telegram/telegram.graphql.ts index 9f563fff..d56ab585 100644 --- a/src/modules/telegram/telegram.graphql.ts +++ b/src/modules/telegram/telegram.graphql.ts @@ -160,7 +160,7 @@ export class TelegramGraphql { this.configSvc.get('graphql.endpoint'), '', `query telegram_quests($telegram_user_id: Int!) { - telegram_quests { + telegram_quests(where: {activated: {_eq: true}, deleted: {_eq: false}}) { id quest_name quest_url @@ -205,7 +205,7 @@ export class TelegramGraphql { this.configSvc.get('graphql.endpoint'), '', `query telegram_quests($id: bigint!, $telegram_user_id: Int!) { - telegram_quests(where: {id: {_eq: $id}}) { + telegram_quests(where: {id: {_eq: $id},activated: {_eq: true}, deleted: {_eq: false}}) { id quest_name quest_url @@ -343,4 +343,51 @@ export class TelegramGraphql { headers ); } + getTopDonate() { + const headers = { + 'x-hasura-admin-secret': this.configSvc.get( + 'graphql.adminSecret' + ), + }; + + return this.graphqlSvc.query( + this.configSvc.get('graphql.endpoint'), + '', + `query top_user_donate { + top_user_donate(limit: 10) { + user_id + telegram_id + username + value + } + }`, + 'top_user_donate', + {}, + headers + ); + } + getTopCreatorDonate() { + const headers = { + 'x-hasura-admin-secret': this.configSvc.get( + 'graphql.adminSecret' + ), + }; + + return this.graphqlSvc.query( + this.configSvc.get('graphql.endpoint'), + '', + `query top_creator_donate { + top_creator_donate(limit: 10) { + id + name + email + avatar_url + value + } + }`, + 'top_creator_donate', + {}, + headers + ); + } } diff --git a/src/modules/telegram/telegram.service.ts b/src/modules/telegram/telegram.service.ts index ba04454d..49cab9e5 100644 --- a/src/modules/telegram/telegram.service.ts +++ b/src/modules/telegram/telegram.service.ts @@ -11,6 +11,8 @@ import { SaveDonateTxDto } from './dto/save-donate-tx.dto'; import { TelegramGraphql } from './telegram.graphql'; import { Role } from '../../auth/role.enum'; import { v4 as uuidv4 } from 'uuid'; +var CryptoJS = require("crypto-js"); +const AES = require("crypto-js/aes"); @Injectable() export class TelegramService { @@ -136,22 +138,23 @@ export class TelegramService { throw new UnauthorizedException(error.message); } } - async createAndLink(){ + async createAndLink() { const { telegramId, telegramUserId } = ContextProvider.getAuthUser(); - const email = `tele_${telegramId}_${(new Date()).getTime()}@punkga.me`; - const username = `tele_${telegramId}_${(new Date()).getTime()}`; + const email = `tele_${telegramId}_${new Date().getTime()}@punkga.me`; + const username = `tele_${telegramId}_${new Date().getTime()}`; const uuidTemp = uuidv4(); const insertedUser = await this.telegramGraphql.insertTempAuthorizedUser({ id: uuidTemp, key: uuidTemp, email: email, nickname: username, - email_verified_at: (new Date()).getTime(), - signup_methods: 'telegram' - }) + email_verified_at: new Date().getTime(), + signup_methods: 'telegram', + }); if (insertedUser.errors) return insertedUser; - try { - const userId = insertedUser.data?.insert_authorizer_users?.returning[0].id; + try { + const userId = + insertedUser.data?.insert_authorizer_users?.returning[0].id; const updateResult = await this.telegramGraphql.updateTelegramUser({ id: telegramUserId, user_id: userId, @@ -185,7 +188,7 @@ export class TelegramService { async saveTx(data: SaveDonateTxDto) { const { telegramId, telegramUserId } = ContextProvider.getAuthUser(); const { creator_id, txn, value } = data; - var saveDonate = this.telegramGraphql.saveDonateHistory({ + const saveDonate = this.telegramGraphql.saveDonateHistory({ object: { telegram_id: telegramId, creator_id, @@ -198,7 +201,7 @@ export class TelegramService { id: telegramUserId, }); const chip = data.value * 20000 + user?.data?.telegram_user.chip; - var res = await this.telegramGraphql.updateTelegramUserChip({ + const res = await this.telegramGraphql.updateTelegramUserChip({ telegram_user_id: telegramUserId, chip: chip, }); @@ -211,7 +214,38 @@ export class TelegramService { const quests = await this.telegramGraphql.getTelegramQuest({ telegram_user_id: telegramUserId, }); - + if (quests?.data) { + quests?.data?.telegram_quests?.map((q, i) => { + if (q.type == 'Daily' && q.telegram_quest_histories) { + q.telegram_quest_histories = q.telegram_quest_histories.map( + (h, j) => { + const fullToday = new Date(); + const today = new Date( + Date.UTC( + fullToday.getUTCFullYear(), + fullToday.getUTCMonth(), + fullToday.getUTCDate(), + 0, + 0, + 0 + ) + ); + if ( + Date.parse(today.toISOString()) - + Date.parse(h.created_date + 'Z') > + 0 + ) { + return null; + } + return h; + } + ); + } + q.telegram_quest_histories = q.telegram_quest_histories.filter( + (x) => x != null + ); + }); + } return quests; } catch (errors) { return { @@ -220,14 +254,58 @@ export class TelegramService { } } - async saveQuest(id) { + async getQuestById(id) { try { const { telegramUserId } = ContextProvider.getAuthUser(); - let quest; const quests = await this.telegramGraphql.getTelegramQuestById({ id: id, telegram_user_id: telegramUserId, }); + if (quests?.data) { + quests?.data?.telegram_quests?.map((q, i) => { + if (q.type == 'Daily' && q.telegram_quest_histories) { + q.telegram_quest_histories = q.telegram_quest_histories.map( + (h, j) => { + const fullToday = new Date(); + const today = new Date( + Date.UTC( + fullToday.getUTCFullYear(), + fullToday.getUTCMonth(), + fullToday.getUTCDate(), + 0, + 0, + 0 + ) + ); + if ( + Date.parse(today.toISOString()) - + Date.parse(h.created_date + 'Z') > + 0 + ) { + return null; + } + return h; + } + ); + } + q.telegram_quest_histories = q.telegram_quest_histories.filter( + (x) => x != null + ); + }); + } + return quests; + } catch (errors) { + return { + errors, + }; + } + } + + async saveQuest(id) { + try { + const { telegramUserId } = ContextProvider.getAuthUser(); + let quest; + const quests = await this.getQuestById(id); if (quests?.data?.telegram_quests.length > 0) { quest = quests?.data?.telegram_quests[0]; @@ -239,7 +317,7 @@ export class TelegramService { }; } if (quest) { - var history = quest.telegram_quest_histories; + const history = quest.telegram_quest_histories; if (!history || history.length <= 0) { var r = await this.telegramGraphql.insertTelegramQuestHistory({ quest_id: id, @@ -247,7 +325,7 @@ export class TelegramService { is_claim: false, }); } else { - var h = history[0]; + const h = history[0]; if (h.is_claim) { return { errors: { @@ -270,7 +348,7 @@ export class TelegramService { id: telegramUserId, }); const chip = quest?.reward + user?.data?.telegram_user.chip; - var res = await this.telegramGraphql.updateTelegramUserChip({ + const res = await this.telegramGraphql.updateTelegramUserChip({ telegram_user_id: telegramUserId, chip: chip, }); @@ -285,10 +363,7 @@ export class TelegramService { }, }; } - var lastResponse = await this.telegramGraphql.getTelegramQuestById({ - id: id, - telegram_user_id: telegramUserId, - }); + const lastResponse = await this.getQuestById(id); return lastResponse?.data?.telegram_quests[0]; } catch (errors) { return { @@ -296,4 +371,114 @@ export class TelegramService { }; } } + + async getTopDonate() { + try { + const topDonate = await this.telegramGraphql.getTopDonate(); + + return topDonate; + } catch (errors) { + return { + errors, + }; + } + } + async getTopCreatorDonate() { + try { + const topDonate = await this.telegramGraphql.getTopCreatorDonate(); + + return topDonate; + } catch (errors) { + return { + errors, + }; + } + } + async genTelegramQr() { + try { + const TELEGRAM_QR_SECRET = + this.configService.get('telgram.qr_secret'); + let { userId } = ContextProvider.getAuthUser(); + if (userId) { + var message = `${userId}|${Date.parse((new Date()).toISOString())}`; + var encrypted = AES.encrypt(message, TELEGRAM_QR_SECRET); + return { + data: encrypted.toString() + } + } else { + return { + errors: [ + { + message: 'Unauthorized', + }, + ], + }; + } + } catch (errors) { + return { + errors, + }; + } + } + async linkFromScan(data: any) { + const { telegramUserId } = ContextProvider.getAuthUser(); + try { + const TELEGRAM_QR_SECRET = + this.configService.get('telgram.qr_secret'); + var decrypted = AES.decrypt(data?.data, TELEGRAM_QR_SECRET)?.toString(CryptoJS.enc.Utf8); + if (decrypted && decrypted.indexOf('|') != -1) { + let arr = decrypted.split('|'); + const time = new Date(parseFloat(arr[1])); + var seconds = (new Date().getTime() - time.getTime()) / 1000; + if (seconds <= 300) { + const userId = arr[0]; + if (userId) { + const updateResult = await this.telegramGraphql.updateTelegramUser({ + id: telegramUserId, + user_id: userId, + }); + if (updateResult.errors) return updateResult; + const payload = { + 'https://hasura.io/jwt/claims': { + 'x-hasura-allowed-roles': [Role.User], + 'x-hasura-default-role': Role.User, + 'x-hasura-user-email': + updateResult.data.telegram_user.authorizer_user.email, + 'x-hasura-user-id': + updateResult.data.telegram_user.authorizer_user.id, + }, + }; + const privateKey = await readFile( + path.resolve(__dirname, '../../../private.pem') + ); + const access_token = await this.jwtService.signAsync(payload, { + algorithm: 'RS256', + privateKey, + }); + updateResult.data.telegram_user.authorizer_user.token = + access_token; + return updateResult; + } else { + return { + errors: [ + { + message: 'User Id is not valid', + }, + ], + }; + } + } else { + return { + errors: [ + { + message: 'Expired', + }, + ], + }; + } + } + } catch (error) { + throw new UnauthorizedException(error.message); + } + } } diff --git a/src/modules/user-wallet/master-wallet.service.ts b/src/modules/user-wallet/master-wallet.service.ts index 4cfe1949..d2a46597 100644 --- a/src/modules/user-wallet/master-wallet.service.ts +++ b/src/modules/user-wallet/master-wallet.service.ts @@ -1,19 +1,13 @@ -import { - BaseContract, - Contract, - HDNodeWallet, - JsonRpcProvider, - Wallet, -} from 'ethers'; +import { Contract, HDNodeWallet, JsonRpcProvider, Wallet } from 'ethers'; import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Crypter } from '../../utils/crypto'; import { SysKeyService } from '../keys/syskey.service'; +import { IChainInfo } from '../quest/interface/ichain-info'; import { abi as levelingAbi } from './../../abi/PunkgaReward.json'; import { UserWalletGraphql } from './user-wallet.graphql'; -import { IChainInfo } from '../quest/interface/ichain-info'; @Injectable() export class MasterWalletService implements OnModuleInit { diff --git a/src/modules/user-wallet/user-wallet.process.ts b/src/modules/user-wallet/user-wallet.process.ts index 3b39dfb1..6e054c96 100644 --- a/src/modules/user-wallet/user-wallet.process.ts +++ b/src/modules/user-wallet/user-wallet.process.ts @@ -1,12 +1,11 @@ import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; import { Cron, CronExpression } from '@nestjs/schedule'; +import { ConfigService } from '@nestjs/config'; import { SysKeyService } from '../keys/syskey.service'; import { RedisService } from '../redis/redis.service'; import { IGenerateUserWallet } from './interfaces/generate-user-wallet.interface'; import { UserWalletGraphql } from './user-wallet.graphql'; -import { ConfigService } from '@nestjs/config'; -import { Wallet } from 'ethers'; @Injectable() export class UserWalletProcessor implements OnModuleInit { diff --git a/src/modules/user/dto/update-profile-request.dto.ts b/src/modules/user/dto/update-profile-request.dto.ts index 285050ae..1e39198f 100644 --- a/src/modules/user/dto/update-profile-request.dto.ts +++ b/src/modules/user/dto/update-profile-request.dto.ts @@ -14,6 +14,9 @@ export class UpdateProfileRequestDto { @ApiPropertyOptional({ example: '' }) nickname: string; + @ApiPropertyOptional({ example: '' }) + ton_wallet_address: string; + @ApiPropertyOptional({ type: 'string', format: 'binary' }) picture: Express.Multer.File; } diff --git a/src/modules/user/interfaces/update-profile.interface.ts b/src/modules/user/interfaces/update-profile.interface.ts index 810e29f0..81d17897 100644 --- a/src/modules/user/interfaces/update-profile.interface.ts +++ b/src/modules/user/interfaces/update-profile.interface.ts @@ -5,6 +5,7 @@ export interface IUpdateProfile { gender: string; birthdate: string; nickname: string; + ton_wallet_address: string; picture?: string; }; } diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts index f1e30be0..4a951879 100644 --- a/src/modules/user/user.service.ts +++ b/src/modules/user/user.service.ts @@ -212,7 +212,7 @@ export class UserService { files: Array ) { try { - const { birthdate, gender, bio, nickname } = data; + const { birthdate, gender, bio, nickname, ton_wallet_address } = data; const { token, userId } = ContextProvider.getAuthUser(); const variables: IUpdateProfile = { @@ -222,25 +222,29 @@ export class UserService { gender, birthdate, nickname, + ton_wallet_address, }, }; - const pictureFile = files.filter((f) => f.fieldname === 'picture')[0]; - if (pictureFile) { - const pictureUrl = await this.filesService.uploadImageToS3( - `user-${userId}`, - pictureFile - ); + if (files && files.length > 0) { + const pictureFile = files.filter((f) => f.fieldname === 'picture')[0]; + if (pictureFile) { + const pictureUrl = await this.filesService.uploadImageToS3( + `user-${userId}`, + pictureFile + ); - variables._set.picture = pictureUrl; + variables._set.picture = pictureUrl; + } } - const result = await this.userGraphql.updateUserProfile(token, variables); return result; - } catch (errors) { + } catch (error) { return { - errors, + errors: { + message: error.toString(), + }, }; } }