• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hicommonwealth / commonwealth / 12304263166

12 Dec 2024 08:28PM UTC coverage: 46.87%. First build
12304263166

Pull #10167

github

web-flow
Merge 8892fe0b8 into 807071c54
Pull Request #10167: Farcaster weighted voting

1192 of 2847 branches covered (41.87%)

Branch coverage included in aggregate %.

4 of 59 new or added lines in 5 files covered. (6.78%)

2447 of 4917 relevant lines covered (49.77%)

30.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/libs/model/src/contest/GetFarcasterContestCasts.query.ts
1
import { Query } from '@hicommonwealth/core';
2
import * as schemas from '@hicommonwealth/schemas';
3
import { NeynarAPIClient } from '@neynar/nodejs-sdk';
4
import { QueryTypes } from 'sequelize';
5
import { config } from '../config';
6
import { models } from '../database';
7
import { mustExist } from '../middleware/guards';
8

9
export function GetFarcasterContestCasts(): Query<
10
  typeof schemas.GetFarcasterContestCasts
11
> {
NEW
12
  return {
×
13
    ...schemas.GetFarcasterContestCasts,
14
    auth: [],
15
    secure: false,
16
    body: async ({ payload }) => {
NEW
17
      const contestManager = await models.ContestManager.findOne({
×
18
        where: {
19
          contest_address: payload.contest_address,
20
        },
21
      });
NEW
22
      mustExist('Contest Manager', contestManager);
×
NEW
23
      if (!contestManager.farcaster_frame_hashes?.length) {
×
NEW
24
        return [];
×
25
      }
NEW
26
      const contents = await models.sequelize.query<{
×
27
        contest_address: string;
28
        contest_id: number;
29
        content_id: number;
30
        actor_address: string;
31
        added_action: 'added';
32
        content_url: string;
33
        voting_weights_sum: number;
34
      }>(
35
        `
36
        SELECT
37
            ca1.contest_address,
38
            ca1.contest_id,
39
            ca1.content_id,
40
            ca1.actor_address,
41
            ca1.action AS added_action,
42
            ca1.content_url,
43
            SUM(ca2.calculated_voting_weight) AS voting_weights_sum
44
        FROM
45
            "ContestActions" ca1
46
        LEFT JOIN
47
            "ContestActions" ca2
48
            ON ca1.contest_address = ca2.contest_address
49
            AND ca1.contest_id = ca2.contest_id
50
            AND ca1.content_id = ca2.content_id
51
            AND ca2.action = 'upvoted'
52
        WHERE
53
            ca1.action = 'added'
54
            AND ca1.contest_address = :contest_address
55
            AND ca1.contest_id = :contest_id
56
        GROUP BY
57
            ca1.contest_address,
58
            ca1.contest_id,
59
            ca1.content_id,
60
            ca1.actor_address,
61
            ca1.action
62
        ORDER BY
63
            ca1.contest_address,
64
            ca1.contest_id,
65
            ca1.content_id;
66
      `,
67
        {
68
          replacements: {
69
            contest_address: payload.contest_address,
70
            contest_id: 0, // only support one-off contests for now
71
          },
72
          type: QueryTypes.SELECT,
73
        },
74
      );
NEW
75
      if (!contents.length) {
×
NEW
76
        return [];
×
77
      }
78

NEW
79
      const replyCastHashes = contents.map((action) => {
×
80
        /*
81
          /farcaster/0x123/0x234
82
        */
NEW
83
        const [, , , replyCastHash] = action.content_url!.split('/');
×
NEW
84
        return replyCastHash;
×
85
      });
NEW
86
      const frameHashesToFetch = [...replyCastHashes];
×
NEW
87
      const client = new NeynarAPIClient(config.CONTESTS.NEYNAR_API_KEY!);
×
NEW
88
      const castsResponse = await client.fetchBulkCasts(frameHashesToFetch);
×
89

NEW
90
      const { casts } = castsResponse.result;
×
91

NEW
92
      const replyVoteSums = contents.reduce(
×
93
        (acc, content) => {
NEW
94
          const [, , , replyCastHash] = content.content_url!.split('/');
×
NEW
95
          return {
×
96
            ...acc,
97
            [replyCastHash]: content.voting_weights_sum || 0,
×
98
          };
99
        },
100
        {} as Record<string, number>,
101
      );
102

NEW
103
      return casts
×
NEW
104
        .map((cast) => ({
×
105
          ...cast,
106
          calculated_vote_weight: replyVoteSums[cast.hash],
107
        }))
108
        .sort((a, b) => {
NEW
109
          if (payload.sort_by === 'upvotes') {
×
NEW
110
            return b.calculated_vote_weight - a.calculated_vote_weight;
×
111
          }
NEW
112
          return (
×
113
            new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
114
          );
115
        });
116
    },
117
  };
118
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc