diff --git a/hasura/metadata/databases/auratestnet/tables/public_erc20_contract.yaml b/hasura/metadata/databases/auratestnet/tables/public_erc20_contract.yaml index 80f7c2f37..a294ba6af 100644 --- a/hasura/metadata/databases/auratestnet/tables/public_erc20_contract.yaml +++ b/hasura/metadata/databases/auratestnet/tables/public_erc20_contract.yaml @@ -49,6 +49,7 @@ select_permissions: - decimal - name - track + - total_holder - last_updated_height filter: {} limit: 100 diff --git a/migrations/evm/20240920024049_erc20_contract_add_total_holder.ts b/migrations/evm/20240920024049_erc20_contract_add_total_holder.ts new file mode 100644 index 000000000..58c06f09f --- /dev/null +++ b/migrations/evm/20240920024049_erc20_contract_add_total_holder.ts @@ -0,0 +1,29 @@ +import { Knex } from 'knex'; +import { AccountBalance } from '../../src/models'; + +export async function up(knex: Knex): Promise { + await knex.schema.alterTable('erc20_contract', (table) => { + table.integer('total_holder').defaultTo(0).index(); + }); + await knex.raw(`set statement_timeout to 0`); + const totalHolders = await AccountBalance.query(knex) + .select('account_balance.denom') + .where('account_balance.type', AccountBalance.TYPE.ERC20_TOKEN) + .andWhere('account_balance.amount', '>', 0) + .count() + .groupBy('account_balance.denom'); + if (totalHolders.length > 0) { + const stringListUpdates = totalHolders + .map((totalHolder) => `('${totalHolder.denom}', ${totalHolder.count})`) + .join(','); + await knex.raw( + `UPDATE erc20_contract SET total_holder = temp.total_holder from (VALUES ${stringListUpdates}) as temp(address, total_holder) where temp.address = erc20_contract.address` + ); + } +} + +export async function down(knex: Knex): Promise { + await knex.schema.alterTable('erc20_contract', (table) => { + table.dropColumn('total_holder'); + }); +} diff --git a/src/models/account_balance.ts b/src/models/account_balance.ts index 4f78806cd..81d98e51d 100644 --- a/src/models/account_balance.ts +++ b/src/models/account_balance.ts @@ -4,6 +4,8 @@ import BaseModel from './base'; import { Account } from './account'; export class AccountBalance extends BaseModel { + [relation: string]: any; + static softDelete = false; account!: Account; diff --git a/src/models/erc20_contract.ts b/src/models/erc20_contract.ts index 7694b430c..cf07704a4 100644 --- a/src/models/erc20_contract.ts +++ b/src/models/erc20_contract.ts @@ -23,6 +23,8 @@ export class Erc20Contract extends BaseModel { track!: boolean; + total_holder!: number; + last_updated_height!: number; static get tableName() { diff --git a/src/services/evm/erc20_handler.ts b/src/services/evm/erc20_handler.ts index d4f5fc058..6dfc43333 100644 --- a/src/services/evm/erc20_handler.ts +++ b/src/services/evm/erc20_handler.ts @@ -113,6 +113,9 @@ export class Erc20Handler { const amount = ( BigInt(fromAccountBalance?.amount || 0) - BigInt(erc20Activity.amount) ).toString(); + if (BigInt(amount) === BigInt(0)) { + erc20Contract.total_holder -= 1; + } // update object accountBalance this.accountBalances[key] = AccountBalance.fromJson({ denom: erc20Activity.erc20_contract_address, @@ -143,10 +146,14 @@ export class Erc20Handler { `Process erc20 balance: toAccountBalance ${erc20Activity.to} was updated` ); } + const initAmount = toAccountBalance?.amount || 0; // calculate new balance: increase balance of to account const amount = ( - BigInt(toAccountBalance?.amount || 0) + BigInt(erc20Activity.amount) + BigInt(initAmount) + BigInt(erc20Activity.amount) ).toString(); + if (BigInt(amount) > BigInt(0) && BigInt(initAmount) === BigInt(0)) { + erc20Contract.total_holder += 1; + } // update object accountBalance this.accountBalances[key] = AccountBalance.fromJson({ denom: erc20Activity.erc20_contract_address,