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

hicommonwealth / commonwealth / 12775040644

14 Jan 2025 07:32PM UTC coverage: 48.144% (-0.02%) from 48.168%
12775040644

Pull #10529

github

web-flow
Merge 603ba182e into fc164f9cc
Pull Request #10529: Add contest bot webhook

1313 of 3044 branches covered (43.13%)

Branch coverage included in aggregate %.

5 of 19 new or added lines in 5 files covered. (26.32%)

36 existing lines in 4 files now uncovered.

2590 of 5063 relevant lines covered (51.16%)

34.59 hits per line

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

0.0
/libs/model/src/bot/CreateBotContest.command.ts
1
import { InvalidState, ServerError, type Command } from '@hicommonwealth/core';
2
import {
3
  commonProtocol as cp,
4
  deployERC20Contest,
5
  getTokenAttributes,
6
} from '@hicommonwealth/evm-protocols';
7
import { config } from '@hicommonwealth/model';
8
import * as schemas from '@hicommonwealth/schemas';
9
import { buildFarcasterContestFrameUrl } from '@hicommonwealth/shared';
10
import { models } from '../database';
11
import { mustExist } from '../middleware/guards';
12
import { TokenAttributes } from '../services';
13
import { parseBotCommand } from '../services/openai/parseBotCommand';
14

15
export function CreateBotContest(): Command<typeof schemas.CreateBotContest> {
16
  return {
×
17
    ...schemas.CreateBotContest,
18
    auth: [],
19
    body: async ({ payload }) => {
NEW
20
      const { prompt } = payload;
×
21
      const contestMetadata = await parseBotCommand(prompt);
×
22

23
      const botNamespace = config.BOT.CONTEST_BOT_NAMESPACE;
×
24

25
      if (!botNamespace || botNamespace === '') {
×
26
        new InvalidState('bot not enabled on given chain');
×
27
      }
28

29
      const community = await models.Community.scope('withPrivateData').findOne(
×
30
        {
31
          where: {
32
            namespace: botNamespace as string,
33
          },
34
        },
35
      );
36

37
      mustExist('Community', community);
×
38

39
      let tokenMetadata: TokenAttributes;
40
      try {
×
41
        tokenMetadata = await getTokenAttributes(
×
42
          contestMetadata.tokenAddress,
43
          community!.ChainNode!.private_url!,
44
          false,
45
        );
46
      } catch {
47
        new InvalidState('invalid token address');
×
48
      }
49

50
      // use short duration for testnet contests
51
      const contestDurationSecs =
NEW
52
        community.ChainNode!.eth_chain_id === cp.ValidChains.SepoliaBase
×
53
          ? 60 * 60
54
          : 60 * 60 * 24 * 7;
55

56
      const namespaceFactory =
NEW
57
        cp.factoryContracts[
×
58
          community!.ChainNode!.eth_chain_id as cp.ValidChains
59
        ].factory;
60

61
      if (!config.WEB3.CONTEST_BOT_PRIVATE_KEY)
×
62
        throw new ServerError('Contest bot private key not set!');
×
63

64
      const contestAddress = await deployERC20Contest({
×
65
        privateKey: config.WEB3.CONTEST_BOT_PRIVATE_KEY,
66
        namespaceName: botNamespace!,
67
        contestInterval: 604800,
68
        winnerShares: contestMetadata.payoutStructure,
69
        voteToken: contestMetadata.tokenAddress,
70
        voterShare: contestMetadata.voterShare,
71
        exchangeToken: contestMetadata.tokenAddress,
72
        namespaceFactory,
73
        rpc: community!.ChainNode!.private_url!,
74
      });
75

76
      await models.sequelize.transaction(async (transaction) => {
×
77
        const manager = await models.ContestManager.create(
×
78
          {
79
            name: contestMetadata.contestName,
80
            community_id: community!.id,
81
            created_at: new Date(),
82
            cancelled: false,
83
            farcaster_frame_url: buildFarcasterContestFrameUrl(contestAddress),
84
            is_farcaster_contest: true,
85
            image_url: contestMetadata.image_url,
86
            interval: contestDurationSecs,
87
            funding_token_address: contestMetadata.tokenAddress,
88
            payout_structure: contestMetadata.payoutStructure,
89
            ticker: tokenMetadata.ticker,
90
            decimals: tokenMetadata.decimals,
91
            contest_address: contestAddress,
92
          },
93
          { transaction },
94
        );
95
        return manager;
×
96
      });
97
      return contestAddress;
×
98
    },
99
  };
100
}
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

© 2026 Coveralls, Inc