Skip to content

Commit

Permalink
Merge pull request #20 from near-daos/develop
Browse files Browse the repository at this point in the history
RC2
  • Loading branch information
vhorin-mp authored Dec 1, 2021
2 parents 6678a65 + 42146a3 commit fcbf06d
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 21 deletions.
2 changes: 2 additions & 0 deletions apps/aggregator/src/aggregator.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { TransactionModule } from '@sputnik-v2/transaction';
import { TransactionHandlerModule } from '@sputnik-v2/transaction-handler';
import { HttpCacheModule } from '@sputnik-v2/cache';
import { TokenModule } from '@sputnik-v2/token';
import { ProposalModule } from '@sputnik-v2/proposal';

import { AggregatorService } from './aggregator.service';
import { DaoAggregatorModule } from './dao-aggregator/dao-aggregator.module';
Expand All @@ -35,6 +36,7 @@ import { TokenAggregatorModule } from './token-aggregator/token-aggregator.modul
ScheduleModule.forRoot(),
NearIndexerModule,
DaoModule,
ProposalModule,
TransactionHandlerModule,
TransactionModule,
TokenModule,
Expand Down
4 changes: 4 additions & 0 deletions apps/aggregator/src/aggregator.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { DaoService } from '@sputnik-v2/dao';
import { TransactionHandlerService } from '@sputnik-v2/transaction-handler';
import { CacheService } from '@sputnik-v2/cache';
import { TokenService } from '@sputnik-v2/token';
import { ProposalService } from '@sputnik-v2/proposal';

import { DaoAggregatorService } from './dao-aggregator/dao-aggregator.service';
import { ProposalAggregatorService } from './proposal-aggregator/proposal-aggregator.service';
Expand All @@ -31,6 +32,7 @@ export class AggregatorService {
private readonly transactionService: TransactionService,
private readonly tokenService: TokenService,
private readonly daoService: DaoService,
private readonly proposalService: ProposalService,
private readonly transactionHandlerService: TransactionHandlerService,
private readonly daoAggregatorService: DaoAggregatorService,
private readonly proposalAggregatorService: ProposalAggregatorService,
Expand Down Expand Up @@ -128,6 +130,8 @@ export class AggregatorService {

this.state.startAggregation('dao');

await this.proposalService.updateExpiredProposals();

const { contractName } = this.configService.get('near');

const lastTx = await this.transactionService.lastTransaction();
Expand Down
2 changes: 2 additions & 0 deletions apps/aggregator/src/proposal-aggregator/types/proposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
castProposalKind,
ProposalActionDto,
ProposalDto,
ProposalVoteStatus,
} from '@sputnik-v2/proposal';
import { Transaction } from '@sputnik-v2/near-indexer';

Expand Down Expand Up @@ -94,6 +95,7 @@ export function castProposal(
{ submissionTime: proposal.submissionTime },
dao,
),
voteStatus: ProposalVoteStatus.Active,
actions,
transactionHash: txData?.transactionHash,
createTimestamp: txData?.blockTimestamp,
Expand Down
44 changes: 26 additions & 18 deletions libs/dao/src/dao.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ export class DaoService extends TypeOrmCrudService<Dao> {
return this.daoRepository.save(daoDto);
}

async search(req: CrudRequest, query: string): Promise<Dao[] | DaoResponse> {
async search(
req: CrudRequest,
query: string,
): Promise<DaoFeed[] | DaoFeedResponse> {
const likeQuery = `%${query.toLowerCase()}%`;
const daos = await this.daoRepository
.createQueryBuilder('dao')
Expand All @@ -63,7 +66,10 @@ export class DaoService extends TypeOrmCrudService<Dao> {
),
)
.getMany();
return paginate<Dao>(daos, req.parsed.limit, req.parsed.offset);

const daoFeed: DaoFeed[] = await this.getDaosFeed(daos);

return paginate<DaoFeed>(daoFeed, req.parsed.limit, req.parsed.offset);
}

async getFeed(req: CrudRequest): Promise<DaoFeed[] | DaoFeedResponse> {
Expand All @@ -76,22 +82,7 @@ export class DaoService extends TypeOrmCrudService<Dao> {
return daoFeedResponse as DaoFeedResponse;
}

const daoIds: string[] = daos.map(({ id }) => id);

// TODO: accelerate querying
const proposals = await this.proposalService.findProposalsByDaoIds(daoIds);

const proposalsByDao = proposals?.reduce(
(acc, cur) => ({
...acc,
[cur.daoId]: [...(acc[cur.daoId] || []), cur],
}),
{},
);

const daoFeed: DaoFeed[] = daos.map((dao) =>
this.buildFeedFromDao(dao, proposalsByDao?.[dao.id]),
);
const daoFeed: DaoFeed[] = await this.getDaosFeed(daos);

if (daoFeedResponse instanceof Array) {
return daoFeed;
Expand All @@ -111,6 +102,23 @@ export class DaoService extends TypeOrmCrudService<Dao> {
return this.buildFeedFromDao(dao, proposals);
}

async getDaosFeed(daos: Dao[]): Promise<DaoFeed[]> {
const daoIds: string[] = daos.map(({ id }) => id);
const proposals = await this.proposalService.findProposalsByDaoIds(daoIds);

const proposalsByDao = proposals?.reduce(
(acc, cur) => ({
...acc,
[cur.daoId]: [...(acc[cur.daoId] || []), cur],
}),
{},
);

return daos.map((dao) =>
this.buildFeedFromDao(dao, proposalsByDao?.[dao.id]),
);
}

private buildFeedFromDao(dao: Dao, proposals: Proposal[]): DaoFeed {
return {
...dao,
Expand Down
2 changes: 2 additions & 0 deletions libs/migrations/src/scripts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { ProposalActionsMigration } from './proposal-actions.migration';
import { TokenIdsMigration } from './token-ids.migration';
import { DaoMetadataMigration } from './dao-metadata.migration';
import { BountyClaimEndTimeMigration } from './bounty-claim-end-time';
import { ProposalVoteMigration } from './proposal-vote.migration';

export default [
ProposalPurgeMigration,
ProposalActionsMigration,
TokenIdsMigration,
DaoMetadataMigration,
BountyClaimEndTimeMigration,
ProposalVoteMigration,
];
47 changes: 47 additions & 0 deletions libs/migrations/src/scripts/proposal-vote.migration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Injectable, Logger } from '@nestjs/common';
import { calcProposalVotePeriodEnd } from '@sputnik-v2/utils';
import PromisePool from '@supercharge/promise-pool';
import { ProposalService, ProposalVoteStatus } from '@sputnik-v2/proposal';
import { Migration } from '..';

@Injectable()
export class ProposalVoteMigration implements Migration {
private readonly logger = new Logger(ProposalVoteMigration.name);

constructor(private readonly proposalService: ProposalService) {}

public async migrate(): Promise<void> {
this.logger.log('Starting Proposal Vote migration...');

this.logger.log('Collecting proposals...');
const proposals = await this.proposalService.find();

const currentTimestamp = new Date().getTime() * 1000 * 1000; // nanoseconds
const migratedProposals = proposals.map((proposal) => {
const votePeriodEnd = calcProposalVotePeriodEnd(proposal, proposal.dao);
return {
...proposal,
votePeriodEnd,
voteStatus:
votePeriodEnd < currentTimestamp
? ProposalVoteStatus.Active
: ProposalVoteStatus.Expired,
};
});

this.logger.log(`Updating migrated Proposals...`);
const { results, errors: proposalErrors } =
await PromisePool.withConcurrency(500)
.for(migratedProposals)
.process(
async (proposal) => await this.proposalService.update(proposal),
);

this.logger.log(
`Successfully updated Proposals: ${results.flat().length}. Errors: ${
proposalErrors.length
}`,
);
this.logger.log('Proposal Vote migration finished.');
}
}
3 changes: 1 addition & 2 deletions libs/proposal/src/proposal.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,15 +217,14 @@ export class ProposalService extends TypeOrmCrudService<Proposal> {

async updateExpiredProposals(): Promise<UpdateResult> {
const currentTimestamp = new Date().getTime() * 1000 * 1000; // nanoseconds

return this.connection
.createQueryBuilder()
.update(Proposal)
.where('voteStatus != :voteStatus', {
voteStatus: ProposalVoteStatus.Expired,
})
.andWhere('status = :status', { status: ProposalStatus.InProgress })
.andWhere('votePeriodEnd > :date', {
.andWhere('votePeriodEnd < :date', {
date: currentTimestamp,
})
.set({ voteStatus: ProposalVoteStatus.Expired })
Expand Down
7 changes: 6 additions & 1 deletion libs/transaction-handler/src/types/proposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import {
castProposalKind,
ProposalDto,
} from '@sputnik-v2/proposal/dto';
import { Action, ProposalStatus } from '@sputnik-v2/proposal/types';
import {
Action,
ProposalStatus,
ProposalVoteStatus,
} from '@sputnik-v2/proposal/types';

import {
buildProposalId,
Expand All @@ -30,6 +34,7 @@ export function castCreateProposal({
kind,
type: kind.kind.type,
status: ProposalStatus.InProgress,
voteStatus: ProposalVoteStatus.Active,
voteCounts: {},
votes: {},
votePeriodEnd: calcProposalVotePeriodEnd(
Expand Down

0 comments on commit fcbf06d

Please sign in to comment.