Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: nft asset #791

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/config.json.ci
Original file line number Diff line number Diff line change
Expand Up @@ -424,5 +424,9 @@
"jobSyncSourcify": {
"millisecondCrawl": 2000,
"recordsPerCall": 100
},
"jobUpdateNftAssets": {
"millisecondRepeatJob": 10000,
"lcdRecordGet": 5
}
}
4 changes: 4 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -422,5 +422,9 @@
"jobSyncSourcify": {
"millisecondCrawl": 2000,
"recordsPerCall": 100
},
"jobUpdateNftAssets": {
"millisecondRepeatJob": 10000,
"lcdRecordGet": 5
}
}
17 changes: 17 additions & 0 deletions migrations/evm/20240516065356_nft_asset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Knex } from 'knex';

export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable('nft_asset', (table) => {
table.increments('id').primary();
table.string('address').index().notNullable();
table.integer('total_activity').index().notNullable();
table.string('type').index().notNullable();
table.integer('transfer_24h').index().notNullable();
table.timestamp('updated_at').notNullable().defaultTo(knex.raw('now()'));
table.unique('address');
});
}

export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTable('nft_asset');
}
5 changes: 5 additions & 0 deletions src/common/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export const BULL_JOB_NAME = {
JOB_CW721_UPDATE: 'job:cw721-update',
CHECKPOINT_UPDATE_DELEGATOR: 'job:checkpoint_update_delegator',
REFRESH_ACCOUNT_BALANCE_STATISTIC: 'refresh:account-balance-statistic',
JOB_UPDATE_NFT_ASSETS: 'job:update-nft-assets',
};

export const SERVICE = {
Expand Down Expand Up @@ -342,6 +343,10 @@ export const SERVICE = {
key: 'UpdateAssets',
path: 'v1.UpdateAssets',
},
UpdateNftAssets: {
key: 'UpdateNftAssets',
path: 'v1.UpdateNftAssets',
},
CreateConstraintInTransactionPartition: {
key: 'CreateConstraintInTransactionPartition',
path: 'v1.CreateConstraintInTransactionPartition',
Expand Down
14 changes: 12 additions & 2 deletions src/models/cw721_contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { cosmwasm } from '@aura-nw/aurajs';
import { fromBase64, fromUtf8, toHex, toUtf8 } from '@cosmjs/encoding';
import { JsonRpcSuccessResponse } from '@cosmjs/json-rpc';
import { createJsonRpcRequest } from '@cosmjs/tendermint-rpc/build/jsonrpc';
import { Model } from 'objection';
import { Knex } from 'knex';
import { Model } from 'objection';
import { getHttpBatchClient } from '../common';
import BaseModel from './base';
// eslint-disable-next-line import/no-cycle
import CW721Token from './cw721_token';
// eslint-disable-next-line import/no-cycle
import CW721ContractStats from './cw721_stats';
// eslint-disable-next-line import/no-cycle
import CW721Activity from './cw721_tx';
import { SmartContract } from './smart_contract';

Expand All @@ -18,7 +20,7 @@ export interface IContractInfoAndMinter {
symbol?: string;
minter?: string;
}
export default class CW721Contract extends BaseModel {
export class CW721Contract extends BaseModel {
static softDelete = false;

[relation: string]: any;
Expand Down Expand Up @@ -88,6 +90,14 @@ export default class CW721Contract extends BaseModel {
to: 'smart_contract.id',
},
},
cw721_contract_stats: {
relation: Model.BelongsToOneRelation,
modelClass: CW721ContractStats,
join: {
from: 'cw721_contract.id',
to: 'cw721_contract_stats.cw721_contract_id',
},
},
};
}

Expand Down
3 changes: 2 additions & 1 deletion src/models/cw721_stats.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Model } from 'objection';
import BaseModel from './base';
import CW721Contract from './cw721_contract';
// eslint-disable-next-line import/no-cycle
import { CW721Contract } from './cw721_contract';

export default class CW721ContractStats extends BaseModel {
static softDelete = false;
Expand Down
2 changes: 1 addition & 1 deletion src/models/cw721_token.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Model } from 'objection';
import BaseModel from './base';
// eslint-disable-next-line import/no-cycle
import CW721Contract from './cw721_contract';
import { CW721Contract } from './cw721_contract';

export default class CW721Token extends BaseModel {
static softDelete = false;
Expand Down
2 changes: 1 addition & 1 deletion src/models/cw721_tx.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Model } from 'objection';
import BaseModel from './base';
// eslint-disable-next-line import/no-cycle
import CW721Contract from './cw721_contract';
import { CW721Contract } from './cw721_contract';
import CW721Token from './cw721_token';
import { Event } from './event';
import { SmartContractEvent } from './smart_contract_event';
Expand Down
10 changes: 10 additions & 0 deletions src/models/erc721_contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { EVMSmartContract } from './evm_smart_contract';
import { Erc721Token } from './erc721_token';
// eslint-disable-next-line import/no-cycle
import { Erc721Activity } from './erc721_activity';
// eslint-disable-next-line import/no-cycle
import { Erc721Stats } from './erc721_stats';

export class Erc721Contract extends BaseModel {
static softDelete = false;
Expand Down Expand Up @@ -67,6 +69,14 @@ export class Erc721Contract extends BaseModel {
to: 'erc721_activity.erc721_contract_address',
},
},
erc721_stats: {
relation: Model.BelongsToOneRelation,
modelClass: Erc721Stats,
join: {
to: 'erc721_stats.erc721_contract_id',
from: 'erc721_contract.id',
},
},
};
}

Expand Down
1 change: 1 addition & 0 deletions src/models/erc721_stats.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Model } from 'objection';
import BaseModel from './base';
// eslint-disable-next-line import/no-cycle
import { Erc721Contract } from './erc721_contract';

export class Erc721Stats extends BaseModel {
Expand Down
2 changes: 2 additions & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ export * from './erc721_token';
export * from './account_balance';
export * from './erc721_contract';
export * from './erc721_stats';
export * from './nft_asset';
export * from './cw721_contract';
25 changes: 25 additions & 0 deletions src/models/nft_asset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* eslint-disable import/no-cycle */
import BaseModel from './base';

export class NftAsset extends BaseModel {
id!: number;

address!: string;

total_activity!: number;

type!: number;

transfer_24h!: number;

updated_at!: Date;

static get tableName() {
return 'nft_asset';
}

static TYPE = {
ERC721: 'ERC721',
CW721: 'CW721',
};
}
2 changes: 1 addition & 1 deletion src/services/cw721/cw721-reindexing.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
SERVICE,
} from '../../common';
import { SmartContract } from '../../models';
import CW721Contract from '../../models/cw721_contract';
import { CW721Contract } from '../../models/cw721_contract';
import CW721ContractStats from '../../models/cw721_stats';
import CW721Token from '../../models/cw721_token';
import CW721Activity from '../../models/cw721_tx';
Expand Down
2 changes: 1 addition & 1 deletion src/services/cw721/cw721.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { BULL_JOB_NAME, SERVICE } from '../../common/constant';
import knex from '../../common/utils/db_connection';
import { getAttributeFrom } from '../../common/utils/smart_contract';
import { Block, BlockCheckpoint, EventAttribute } from '../../models';
import CW721Contract from '../../models/cw721_contract';
import { CW721Contract } from '../../models/cw721_contract';
import CW721ContractStats from '../../models/cw721_stats';
import CW721Token from '../../models/cw721_token';
import CW721Activity from '../../models/cw721_tx';
Expand Down
2 changes: 1 addition & 1 deletion src/services/cw721/cw721_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import CW721Activity from '../../models/cw721_tx';
import { SmartContractEvent } from '../../models/smart_contract_event';
import { getAttributeFrom } from '../../common/utils/smart_contract';
import { EventAttribute } from '../../models';
import CW721Contract from '../../models/cw721_contract';
import { CW721Contract } from '../../models/cw721_contract';

export const CW721_ACTION = {
MINT: 'mint',
Expand Down
5 changes: 5 additions & 0 deletions src/services/evm/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ export const SERVICE = {
key: 'SyncSourcify',
path: 'v1.SyncSourcify',
},
UpdateEvmNftAssets: {
key: 'UpdateEvmNftAssets',
path: 'v1.UpdateEvmNftAssets',
},
},
},
V2: {
Expand Down Expand Up @@ -207,6 +211,7 @@ export const BULL_JOB_NAME = {
HANDLE_ERC721_TOKEN_MEDIA: 'handle:erc721-token-media',
REFRESH_ERC721_STATS: 'refresh:erc721-stats',
SYNC_SOURCIFY: 'sync:sourcify',
JOB_UPDATE_EVM_NFT_ASSETS: 'job:update-evm-nft-assets',
};

export const MSG_TYPE = {
Expand Down
61 changes: 61 additions & 0 deletions src/services/evm/update_nft_asset.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Service } from '@ourparentcenter/moleculer-decorators-extended';
import { ServiceBroker } from 'moleculer';
import config from '../../../config.json' assert { type: 'json' };
import BullableService, { QueueHandler } from '../../base/bullable.service';
import { Erc721Contract, NftAsset } from '../../models';
import { BULL_JOB_NAME, SERVICE } from './constant';

@Service({
name: SERVICE.V1.JobService.UpdateEvmNftAssets.key,
version: 1,
})
export default class UpdateEvmNftAssetsJob extends BullableService {
public constructor(public broker: ServiceBroker) {
super(broker);
}

@QueueHandler({
queueName: BULL_JOB_NAME.JOB_UPDATE_EVM_NFT_ASSETS,
jobName: BULL_JOB_NAME.JOB_UPDATE_EVM_NFT_ASSETS,
})
async jobUpdateAssets() {
const erc721Assets = await Erc721Contract.query()
.joinRelated('erc721_stats')
.select(
'erc721_contract.address',
'erc721_stats.total_activity',
'erc721_stats.transfer_24h'
);
const nftAssets: NftAsset[] = [];
nftAssets.push(
...erc721Assets.map((erc721Asset) =>
NftAsset.fromJson({
...erc721Asset,
type: NftAsset.TYPE.ERC721,
updated_at: new Date(),
})
)
);
if (nftAssets.length > 0) {
await NftAsset.query().insert(nftAssets).onConflict(['address']).merge();
}
}

public async _start(): Promise<void> {
await this.createJob(
BULL_JOB_NAME.JOB_UPDATE_EVM_NFT_ASSETS,
BULL_JOB_NAME.JOB_UPDATE_EVM_NFT_ASSETS,
{},
{
removeOnComplete: true,
removeOnFail: {
count: 3,
},
repeat: {
every: config.jobUpdateNftAssets.millisecondRepeatJob,
},
}
);
return super._start();
}
}
61 changes: 61 additions & 0 deletions src/services/job/update_nft_asset.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Service } from '@ourparentcenter/moleculer-decorators-extended';
import { ServiceBroker } from 'moleculer';
import config from '../../../config.json' assert { type: 'json' };
import BullableService, { QueueHandler } from '../../base/bullable.service';
import { BULL_JOB_NAME, SERVICE } from '../../common';
import { CW721Contract, NftAsset } from '../../models';

@Service({
name: SERVICE.V1.JobService.UpdateNftAssets.key,
version: 1,
})
export default class UpdateNftAssetsJob extends BullableService {
public constructor(public broker: ServiceBroker) {
super(broker);
}

@QueueHandler({
queueName: BULL_JOB_NAME.JOB_UPDATE_NFT_ASSETS,
jobName: BULL_JOB_NAME.JOB_UPDATE_NFT_ASSETS,
})
async jobUpdateAssets() {
const cw721Assets = await CW721Contract.query()
.joinRelated('[cw721_contract_stats, smart_contract]')
.select(
'smart_contract.address',
'cw721_contract_stats.total_activity',
'cw721_contract_stats.transfer_24h'
);
const nftAssets: NftAsset[] = [];
nftAssets.push(
...cw721Assets.map((cw721Asset) =>
NftAsset.fromJson({
...cw721Asset,
type: NftAsset.TYPE.CW721,
updated_at: new Date(),
})
)
);
if (nftAssets.length > 0) {
await NftAsset.query().insert(nftAssets).onConflict(['address']).merge();
}
}

public async _start(): Promise<void> {
await this.createJob(
BULL_JOB_NAME.JOB_UPDATE_NFT_ASSETS,
BULL_JOB_NAME.JOB_UPDATE_NFT_ASSETS,
{},
{
removeOnComplete: true,
removeOnFail: {
count: 3,
},
repeat: {
every: config.jobUpdateNftAssets.millisecondRepeatJob,
},
}
);
return super._start();
}
}
2 changes: 1 addition & 1 deletion test/unit/services/cw721/cw721-media.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ServiceBroker } from 'moleculer';
import { BULL_JOB_NAME, Config } from '../../../../src/common';
import Cw721MediaService from '../../../../src/services/cw721/cw721-media.service';
import { BlockCheckpoint, Code } from '../../../../src/models';
import CW721Contract from '../../../../src/models/cw721_contract';
import { CW721Contract } from '../../../../src/models/cw721_contract';
import knex from '../../../../src/common/utils/db_connection';

const { IPFS_GATEWAY } = Config;
Expand Down
2 changes: 1 addition & 1 deletion test/unit/services/cw721/cw721-reindexing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Errors, ServiceBroker } from 'moleculer';
import { BULL_JOB_NAME, SERVICE } from '../../../../src/common';
import knex from '../../../../src/common/utils/db_connection';
import { BlockCheckpoint, Code, EventAttribute } from '../../../../src/models';
import CW721Contract from '../../../../src/models/cw721_contract';
import { CW721Contract } from '../../../../src/models/cw721_contract';
import CW721Token from '../../../../src/models/cw721_token';
import CW721Activity from '../../../../src/models/cw721_tx';
import { SmartContractEvent } from '../../../../src/models/smart_contract_event';
Expand Down
2 changes: 1 addition & 1 deletion test/unit/services/cw721/cw721.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
Transaction,
} from '../../../../src/models';
import { Code } from '../../../../src/models/code';
import CW721Contract from '../../../../src/models/cw721_contract';
import { CW721Contract } from '../../../../src/models/cw721_contract';
import CW721Token from '../../../../src/models/cw721_token';
import CW721Activity from '../../../../src/models/cw721_tx';
import { SmartContractEvent } from '../../../../src/models/smart_contract_event';
Expand Down
2 changes: 1 addition & 1 deletion test/unit/services/cw721/view_count.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AfterAll, BeforeAll, Describe, Test } from '@jest-decorated/core';
import knex from '../../../../src/common/utils/db_connection';
import CW721Contract from '../../../../src/models/cw721_contract';
import { CW721Contract } from '../../../../src/models/cw721_contract';
import { Code } from '../../../../src/models';

@Describe('Test view count')
Expand Down
Loading