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

hicommonwealth / commonwealth / 13857847430

14 Mar 2025 01:40PM CUT coverage: 44.662%. First build
13857847430

Pull #11468

github

web-flow
Merge 12539e2f2 into c69a48143
Pull Request #11468: Added fields for thread - token mapping

1367 of 3410 branches covered (40.09%)

Branch coverage included in aggregate %.

2 of 5 new or added lines in 3 files covered. (40.0%)

2574 of 5414 relevant lines covered (47.54%)

38.7 hits per line

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

0.0
/libs/model/src/aggregates/bot/LaunchTokenBot.command.ts
1
import { LaunchpadAbi } from '@commonxyz/common-protocol-abis';
2
import {
3
  AppError,
4
  InvalidState,
5
  ServerError,
6
  command,
7
  type Command,
8
} from '@hicommonwealth/core';
9
import {
10
  commonProtocol as cp,
11
  getErc20TokenInfo,
12
  getLaunchpadTokenCreatedTransaction,
13
} from '@hicommonwealth/evm-protocols';
14
import { config } from '@hicommonwealth/model';
15
import * as schemas from '@hicommonwealth/schemas';
16
import { TokenView } from '@hicommonwealth/schemas';
17
import { ChainBase, ChainType } from '@hicommonwealth/shared';
18
import _ from 'lodash';
19
import { z } from 'zod';
20
import { models } from '../../database';
21
import { mustExist } from '../../middleware/guards';
22
import { CreateCommunity } from '../community';
23

24
export function LaunchTokenBot(): Command<typeof schemas.LaunchToken> {
25
  return {
×
26
    ...schemas.LaunchToken,
27
    auth: [],
28
    body: async ({ payload, actor }) => {
29
      const { name, symbol, totalSupply, eth_chain_id, icon_url, description } =
30
        payload;
×
31

32
      if (!cp.isValidChain(eth_chain_id)) {
×
33
        throw new AppError('eth_chain_id is not supported');
×
34
      }
35

36
      if (!config.WEB3.CONTEST_BOT_PRIVATE_KEY)
×
37
        throw new ServerError('Contest bot private key not set!');
×
38

39
      const communityId = _.kebabCase(name.toLowerCase());
×
40
      const existingCommunity = await models.Community.findOne({
×
41
        where: { id: communityId },
42
      });
43

44
      if (existingCommunity) {
×
45
        throw new AppError('Token already exists, choose another name');
×
46
      }
47

48
      const chainNode = await models.ChainNode.findOne({
×
49
        where: { eth_chain_id },
50
        attributes: ['id', 'eth_chain_id', 'url', 'private_url'],
51
      });
52

53
      mustExist('Chain Node', chainNode);
×
54

55
      const web3 = cp.createPrivateEvmClient({
×
56
        rpc: chainNode.private_url!,
57
        privateKey: config.WEB3.CONTEST_BOT_PRIVATE_KEY,
58
      });
59
      const launchpadContract = new web3.eth.Contract(
×
60
        LaunchpadAbi,
61
        cp.factoryContracts[
62
          eth_chain_id as cp.ValidChains.SepoliaBase
63
        ].launchpad,
64
      );
65
      const receipt = await cp.launchToken(
×
66
        launchpadContract,
67
        name,
68
        symbol,
69
        [],
70
        [],
71
        web3.utils.toWei(totalSupply.toString(), 'ether') as string,
72
        web3.eth.defaultAccount as string,
73
        830000,
74
        cp.factoryContracts[eth_chain_id as cp.ValidChains.SepoliaBase]
75
          .tokenCommunityManager,
76
      );
77

78
      const tokenData = await getLaunchpadTokenCreatedTransaction({
×
79
        rpc: chainNode.private_url! || chainNode.url!,
×
80
        transactionHash: receipt.transactionHash,
81
      });
82

83
      if (!tokenData) {
×
84
        throw new InvalidState('Transaction not found');
×
85
      }
86

87
      let tokenInfo: { name: string; symbol: string; totalSupply: bigint };
88
      try {
×
89
        tokenInfo = await getErc20TokenInfo({
×
90
          rpc: chainNode.private_url || chainNode.url,
×
91
          tokenAddress: tokenData.parsedArgs.tokenAddress,
92
        });
93
      } catch (e) {
94
        throw new Error(
×
95
          `Failed to get erc20 token properties for token ${tokenData.parsedArgs.tokenAddress}`,
96
        );
97
      }
98

99
      const [token] = await models.LaunchpadToken.findOrCreate({
×
100
        where: {
101
          token_address: tokenData.parsedArgs.tokenAddress.toLowerCase(),
102
          namespace: tokenData.parsedArgs.namespace,
103
        },
104
        defaults: {
105
          token_address: tokenData.parsedArgs.tokenAddress.toLowerCase(),
106
          namespace: tokenData.parsedArgs.namespace,
107
          name: tokenInfo.name,
108
          symbol: tokenInfo.symbol,
109
          initial_supply: Number(tokenInfo.totalSupply / BigInt(1e18)),
110
          liquidity_transferred: false,
111
          launchpad_liquidity: tokenData.parsedArgs.launchpadLiquidity,
112
          eth_market_cap_target: cp.getTargetMarketCap(),
113
          description: description ?? null,
×
114
          icon_url: icon_url ?? null,
×
115
        },
116
      });
117

118
      // Create corresponding community for token
119
      await command(CreateCommunity(), {
×
120
        actor,
121
        payload: {
122
          id: communityId,
123
          name,
124
          default_symbol: symbol,
125
          icon_url,
126
          description,
127
          base: ChainBase.Ethereum,
128
          token_name: name,
129
          chain_node_id: chainNode!.id!,
130
          type: ChainType.Offchain,
131
          social_links: [],
132
          directory_page_enabled: false,
133
          tags: [],
134
          allow_tokenized_threads: false,
135
        },
136
      });
137

138
      await models.Community.update(
×
139
        { namespace: name },
140
        { where: { id: communityId } },
141
      );
142

143
      const response = {
×
144
        community_url: `${config.SERVER_URL}/${communityId}`,
145
        ...token!.toJSON(),
146
      };
147
      return response as unknown as z.infer<typeof TokenView> & {
×
148
        community_url: string;
149
      };
150
    },
151
  };
152
}
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