Skip to content

Commit

Permalink
test: test
Browse files Browse the repository at this point in the history
  • Loading branch information
phamphong9981 committed Sep 16, 2024
1 parent 1a394f4 commit d835468
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 102 deletions.
5 changes: 3 additions & 2 deletions migrations/evm/20240912082032_erc721_holder_statistic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ export async function up(knex: Knex): Promise<void> {
select count(*), erc721_token.owner, erc721_token.erc721_contract_address
from erc721_token
group by erc721_token.owner, erc721_token.erc721_contract_address;
ALTER TABLE erc721_holder_statistic ADD COLUMN id SERIAL PRIMARY KEY;
CREATE INDEX erc721_holder_statistic_owner_index
ON erc721_holder_statistic (owner);
CREATE INDEX erc721_holder_statistic_erc721_contract_address_count_index
ON erc721_holder_statistic (erc721_contract_address, count);
CREATE UNIQUE INDEX erc721_holder_statistic_erc721_contract_address_owner_index
ON erc721_holder_statistic (erc721_contract_address, owner);
`);
}

Expand Down
4 changes: 2 additions & 2 deletions migrations/evm/20240916032201_erc721_contract_totalSupply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Erc721Token } from '../../src/models';

export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable('erc721_contract', (table) => {
table.integer('total_supply').defaultTo(0).index();
table.bigInteger('total_supply').defaultTo(0).index();
});
await knex.raw(`set statement_timeout to 0`);
const totalSupplies = await Erc721Token.query(knex)
Expand All @@ -14,7 +14,7 @@ export async function up(knex: Knex): Promise<void> {
const stringListUpdates = totalSupplies
.map(
(totalSuply) =>
`('${totalSuply.erc721_contract_address}', ${totalSuply.count})`
`('${totalSuply.erc721_contract_address}', '${totalSuply.count}')`
)
.join(',');
await knex.raw(
Expand Down
2 changes: 1 addition & 1 deletion src/models/erc721_contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class Erc721Contract extends BaseModel {

last_updated_height!: number;

total_supply!: number;
total_supply!: string;

static get tableName() {
return 'erc721_contract';
Expand Down
4 changes: 2 additions & 2 deletions src/models/erc721_holder_statistic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class Erc721HolderStatistic extends BaseModel {

owner!: string;

count!: number;
count!: string;

static get tableName() {
return 'erc721_holder_statistic';
Expand All @@ -20,7 +20,7 @@ export class Erc721HolderStatistic extends BaseModel {
properties: {
erc721_contract_address: { type: 'string' },
owner: { type: 'string' },
count: { type: 'number' },
count: { type: 'string' },
},
};
}
Expand Down
38 changes: 29 additions & 9 deletions src/services/evm/erc721_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ export class Erc721Handler {
token.owner = erc721Activity.to;
token.last_updated_height = erc721Activity.height;
if (erc721Activity.to === ZERO_ADDRESS) {
erc721Contract.total_supply -= 1;
erc721Contract.total_supply = (
BigInt(erc721Contract.total_supply) - BigInt(1)
).toString();
}
} else if (erc721Activity.from === ZERO_ADDRESS) {
// handle mint
Expand All @@ -120,7 +122,9 @@ export class Erc721Handler {
last_updated_height: erc721Activity.height,
burned: false,
});
erc721Contract.total_supply += 1;
erc721Contract.total_supply = (
BigInt(erc721Contract.total_supply) + BigInt(1)
).toString();
} else {
throw new Error('Handle erc721 tranfer error');
}
Expand All @@ -132,19 +136,27 @@ export class Erc721Handler {
];
if (!erc721HolderStatFrom) {
throw new Error(
`Erc721 holder ${ erc721Activity.from } havent been audited`
`Erc721 holder ${erc721Activity.from} havent been audited`
);
}
erc721HolderStatFrom.count -= 1;
erc721HolderStatFrom.count = (
BigInt(erc721HolderStatFrom.count) - BigInt(1)
).toString();
}
if (erc721Activity.to !== ZERO_ADDRESS) {
const erc721HolderStatTo =
this.erc721HolderStats[
`${erc721Activity.erc721_contract_address}_${erc721Activity.to}`
];
erc721HolderStatTo.count = erc721HolderStatTo
? erc721HolderStatTo.count + 1
: 1;
this.erc721HolderStats[
`${erc721Activity.erc721_contract_address}_${erc721Activity.to}`
] = Erc721HolderStatistic.fromJson({
erc721_contract_address: erc721Activity.erc721_contract_address,
owner: erc721Activity.to,
count: erc721HolderStatTo
? (BigInt(erc721HolderStatTo.count) + BigInt(1)).toString()
: BigInt(1).toString(),
});
}
}

Expand Down Expand Up @@ -314,7 +326,7 @@ export class Erc721Handler {
const stringListUpdates = erc721Contracts
.map(
(erc721Contract) =>
`('${erc721Contract.id}', ${erc721Contract.total_supply})`
`(${erc721Contract.id}, ${erc721Contract.total_supply})`
)
.join(',');
await knex
Expand Down Expand Up @@ -368,7 +380,15 @@ export class Erc721Handler {
if (erc721HolderStats.length > 0) {
await Erc721HolderStatistic.query()
.transacting(trx)
.insert(erc721HolderStats)
.insert(
erc721HolderStats.map((e) =>
Erc721HolderStatistic.fromJson({
erc721_contract_address: e.erc721_contract_address,
owner: e.owner,
count: e.count,
})
)
)
.onConflict(['erc721_contract_address', 'owner'])
.merge();
}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@ import {
Test,
} from '@jest-decorated/core';
import { ServiceBroker } from 'moleculer';
import _ from 'lodash';
import knex from '../../../../src/common/utils/db_connection';
import {
BlockCheckpoint,
EVMSmartContract,
EVMTransaction,
Erc721Activity,
Erc721Contract,
Erc721HolderStatistic,
Erc721Token,
EvmEvent,
} from '../../../../src/models';
import Erc721Service from '../../../../src/services/evm/erc721.service';
import { ERC721_ACTION } from '../../../../src/services/evm/erc721_handler';
import { BULL_JOB_NAME } from '../../../../src/services/evm/constant';

@Describe('Test erc721')
export default class Erc721Test {
Expand All @@ -27,22 +30,24 @@ export default class Erc721Test {

evmSmartContract = EVMSmartContract.fromJson({
id: 555,
address: 'ghghdfgdsgre',
creator: 'dfgdfbvxcvxgfds',
address: '0x98605ae21dd3be686337a6d7a8f156d0d8baee92',
creator: '0xc7663c6a454fc9971C93235A170c8997e8c5E661',
created_height: 100,
created_hash: 'cvxcvcxv',
created_hash:
'0x9ed3b06713baf17b7d7266294a82d51c36c84514a7d29f28585d85e586249525',
type: EVMSmartContract.TYPES.ERC721,
code_hash: 'dfgdfghf',
code_hash: '0x623d4ffdfa5555aa1234366sdaff1a1sdfafa4dasdfas4r',
});

evmSmartContract2 = EVMSmartContract.fromJson({
id: 666,
address: 'bcvbcvbcv',
creator: 'dfgdfbvxcvxgfds',
address: '0xc211C2CF383A38933f8352CBDd326B51b94574e6',
creator: '0xc7663c6a454fc9971C93235A170c8997e8c5E661',
created_height: 100,
created_hash: 'xdasfsf',
created_hash:
'0x888d3b06713baf17b7d7266294a82d51c36c84514a7d29f28585d85e586252200',
type: EVMSmartContract.TYPES.ERC721,
code_hash: 'xcsadf',
code_hash: '0x5fdfa5555aa1234366sdaff1a1sdfafa4dasdfas4r',
});

evmTx = EVMTransaction.fromJson({
Expand All @@ -53,10 +58,11 @@ export default class Erc721Test {
tx_id: 223,
contract_address: '',
index: 1,
from: '0x38828FA9766dE6eb49011fCC970ed1beFE15974a',
});

evmEvent = EvmEvent.fromJson({
id: 888,
id: 1,
tx_id: 1234,
evm_tx_id: this.evmTx.id,
tx_hash: '',
Expand All @@ -73,12 +79,23 @@ export default class Erc721Test {
address: this.evmSmartContract.address,
});

blockCheckpoints = [
BlockCheckpoint.fromJson({
job_name: BULL_JOB_NAME.HANDLE_ERC721_ACTIVITY,
height: this.evmTx.height - 1,
}),
BlockCheckpoint.fromJson({
job_name: BULL_JOB_NAME.HANDLE_ERC721_CONTRACT,
height: 400,
}),
];

@BeforeAll()
async initSuite() {
this.erc721Service.getQueueManager().stopAll();
await this.erc721Service.getQueueManager().stopAll();
await this.broker.start();
await knex.raw(
'TRUNCATE TABLE erc721_contract, account, erc721_activity, evm_smart_contract, evm_event, evm_transaction, block_checkpoint RESTART IDENTITY CASCADE'
'TRUNCATE TABLE erc721_contract, account, erc721_activity, evm_smart_contract, evm_event, evm_transaction, block_checkpoint, erc721_holder_statistic RESTART IDENTITY CASCADE'
);
await EVMSmartContract.query().insert([
this.evmSmartContract,
Expand All @@ -92,8 +109,9 @@ export default class Erc721Test {
@BeforeEach()
async beforeEach() {
await knex.raw(
'TRUNCATE TABLE erc721_activity, erc721_token RESTART IDENTITY CASCADE'
'TRUNCATE TABLE erc721_activity, erc721_token, block_checkpoint, evm_event RESTART IDENTITY CASCADE'
);
await BlockCheckpoint.query().insert(this.blockCheckpoints);
}

@AfterAll()
Expand All @@ -105,124 +123,101 @@ export default class Erc721Test {

@Test('test handleErc721Activity')
async testHandleErc721Activity() {
jest.spyOn(BlockCheckpoint, 'getCheckpoint').mockResolvedValue([
this.evmSmartContract.created_height - 1,
this.evmSmartContract.created_height,
BlockCheckpoint.fromJson({
job_name: 'dfdsfgsg',
height: this.evmSmartContract.created_height - 1,
}),
]);
const holder1 = '0x1317df02a4e712265f5376a9d34156f73ebad640';
const holder2 = '0xa3b6d252c1df2ce88f01fdb75b5479bcdc8f5007';
const erc721Events = [
EvmEvent.fromJson({
id: this.evmEvent.id,
block_hash:
'0x6d70a03cda3fb815b54742fbd47c6141a7e754ff4d7426f10a73644ac44411d2',
block_height: 21937980,
block_height: this.blockCheckpoints[0].height + 1,
data: null,
topic0:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
topic1:
'0x0000000000000000000000000000000000000000000000000000000000000000',
topic2:
'0x0000000000000000000000001317df02a4e712265f5376a9d34156f73ebad640',
topic2: `0x000000000000000000000000${ holder1.slice(2)}`,
topic3:
'0x0000000000000000000000000000000000000000000000000000000000000000',
address: this.evmSmartContract.address,
evm_tx_id: this.evmTx.id,
tx_id: 1234,
tx_hash: this.evmTx.hash,
tx_index: 1,
sender: 'fgfdg',
evm_smart_contract_id: this.evmSmartContract.id,
track: true,
}),
EvmEvent.fromJson({
id: this.evmEvent.id,
block_hash:
'0xd39b1e6c35a7985db6ca367b1e061162b7a8610097e99cadaf98bea6b81a6096',
block_height: 21937981,
block_height: this.blockCheckpoints[0].height + 2,
data: null,
topic0:
'0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925',
topic1:
'0x0000000000000000000000001317df02a4e712265f5376a9d34156f73ebad640',
topic2:
'0x000000000000000000000000a3b6d252c1df2ce88f01fdb75b5479bcdc8f5007',
topic1: `0x000000000000000000000000${ holder1.slice(2)}`,
topic2: `0x000000000000000000000000${ holder2.slice(2)}`,
topic3:
'0x0000000000000000000000000000000000000000000000000000000000000000',
address: this.evmSmartContract.address,
evm_tx_id: this.evmTx.id,
tx_id: 1234,
tx_hash: this.evmTx.hash,
tx_index: 1,
sender: 'fgfdg',
evm_smart_contract_id: this.evmSmartContract.id,
track: true,
}),
EvmEvent.fromJson({
id: this.evmEvent.id,
block_hash:
'0x6d70a03cda3fb815b54742fbd47c6141a7e754ff4d7426f10a73644ac44411d2',
block_height: 21937982,
block_height: this.blockCheckpoints[0].height + 3,
data: null,
topic0:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
topic1:
'0x0000000000000000000000001317df02a4e712265f5376a9d34156f73ebad640',
topic2:
'0x000000000000000000000000e39633931ec4a1841e438b15005a6f141d30789e',
topic1: `0x000000000000000000000000${ holder1.slice(2)}`,
topic2: `0x000000000000000000000000${ holder2.slice(2)}`,
topic3:
'0x0000000000000000000000000000000000000000000000000000000000000000',
address: this.evmSmartContract.address,
evm_tx_id: this.evmTx.id,
tx_id: 1234,
tx_hash: this.evmTx.hash,
tx_index: 1,
sender: 'fgfdg',
evm_smart_contract_id: this.evmSmartContract.id,
track: true,
}),
];
const mockQueryEvents: any = {
select: () => erc721Events,
transacting: () => mockQueryEvents,
joinRelated: () => mockQueryEvents,
where: () => mockQueryEvents,
andWhere: () => mockQueryEvents,
orderBy: () => mockQueryEvents,
innerJoin: () => mockQueryEvents,
modify: () => mockQueryEvents,
};
jest.spyOn(EvmEvent, 'query').mockImplementation(() => mockQueryEvents);
await EvmEvent.query().insert(erc721Events);
await this.erc721Service.handleErc721Activity();
const erc721Token = await Erc721Token.query().first().throwIfNotFound();
expect(erc721Token).toMatchObject({
token_id: '0',
owner: '0xe39633931ec4a1841e438b15005a6f141d30789e',
owner: holder2,
erc721_contract_address: this.evmSmartContract.address,
});
const erc721Activities = await Erc721Activity.query().orderBy('height');
expect(erc721Activities[0]).toMatchObject({
action: ERC721_ACTION.TRANSFER,
erc721_contract_address: erc721Events[0].address,
from: '0x0000000000000000000000000000000000000000',
to: '0x1317df02a4e712265f5376a9d34156f73ebad640',
to: holder1,
erc721_token_id: erc721Token.id,
});
expect(erc721Activities[1]).toMatchObject({
action: ERC721_ACTION.APPROVAL,
erc721_contract_address: erc721Events[0].address,
from: '0x1317df02a4e712265f5376a9d34156f73ebad640',
to: '0xa3b6d252c1df2ce88f01fdb75b5479bcdc8f5007',
from: holder1,
to: holder2,
erc721_token_id: erc721Token.id,
});
expect(erc721Activities[2]).toMatchObject({
action: ERC721_ACTION.TRANSFER,
erc721_contract_address: erc721Events[0].address,
from: '0x1317df02a4e712265f5376a9d34156f73ebad640',
to: '0xe39633931ec4a1841e438b15005a6f141d30789e',
from: holder1,
to: holder2,
erc721_token_id: erc721Token.id,
});
const erc721Contract = await Erc721Contract.query()
.first()
.throwIfNotFound();
expect(erc721Contract.total_supply).toEqual('1');
const erc721HolderStats = _.keyBy(
await Erc721HolderStatistic.query(),
'owner'
);
expect(erc721HolderStats[holder1].count).toEqual('0');
expect(erc721HolderStats[holder2].count).toEqual('1');
}
}
Loading

0 comments on commit d835468

Please sign in to comment.