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

hicommonwealth / commonwealth / 16596294465

29 Jul 2025 12:37PM UTC coverage: 39.017% (-0.08%) from 39.099%
16596294465

Pull #12693

github

web-flow
Merge fc4da5236 into c2910e8eb
Pull Request #12693: Finish backend for Thread Tokens

1859 of 5131 branches covered (36.23%)

Branch coverage included in aggregate %.

3 of 83 new or added lines in 8 files covered. (3.61%)

3310 of 8117 relevant lines covered (40.78%)

35.06 hits per line

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

0.0
/libs/model/src/aggregates/thread/CreateThreadToken.command.ts
1
import {
2
  TokenBondingCurveAbi,
3
  TokenLaunchpadAbi,
4
} from '@commonxyz/common-protocol-abis';
5
import { type Command, InvalidState } from '@hicommonwealth/core';
6
import * as protocols from '@hicommonwealth/evm-protocols';
7
import { withRetries } from '@hicommonwealth/evm-protocols';
8
import * as schemas from '@hicommonwealth/schemas';
9
import { createPublicClient, Hash, http, parseEventLogs } from 'viem';
10
import { models } from '../../database';
11
import { authRoles, mustExist } from '../../middleware';
12

13
export function CreateThreadToken(): Command<typeof schemas.CreateThreadToken> {
NEW
14
  return {
×
15
    ...schemas.CreateThreadToken,
16
    auth: [authRoles('admin')],
17
    body: async ({ payload }) => {
NEW
18
      const { eth_chain_id, transaction_hash } = payload;
×
19

NEW
20
      const chainNode = await models.ChainNode.findOne({
×
21
        where: { eth_chain_id },
22
        attributes: ['url', 'private_url'],
23
      });
NEW
24
      mustExist('ChainNode', chainNode);
×
25

NEW
26
      const rpc = chainNode.private_url! || chainNode.url!;
×
NEW
27
      const client = createPublicClient({
×
28
        transport: http(rpc),
29
      });
30

NEW
31
      const receipt = await withRetries(() =>
×
NEW
32
        client.getTransactionReceipt({
×
33
          hash: transaction_hash as Hash,
34
        }),
35
      );
36

NEW
37
      const parsedLogs = parseEventLogs({
×
38
        abi: TokenBondingCurveAbi,
39
        eventName: 'TokenRegistered',
40
        logs: receipt.logs,
41
      });
42

NEW
43
      if (parsedLogs.length === 0) {
×
NEW
44
        throw new InvalidState(
×
45
          'TokenRegistered event could not be processed from txReceipt',
46
        );
47
      }
48

49
      const {
50
        token: tokenAddress,
51
        totalSupply,
52
        launchpadLiquidity,
NEW
53
      } = parsedLogs[0].args;
×
54

NEW
55
      const tokenCreatedParsedLogs = parseEventLogs({
×
56
        abi: TokenLaunchpadAbi,
57
        eventName: 'NewTokenCreated',
58
        logs: receipt.logs,
59
      });
60

NEW
61
      if (tokenCreatedParsedLogs.length === 0) {
×
NEW
62
        throw new InvalidState(
×
63
          'NewTokenCreated event could not be processed from txReceipt',
64
        );
65
      }
66

NEW
67
      const { name, symbol, threadId } = tokenCreatedParsedLogs[0].args;
×
68

NEW
69
      const block = await client.getBlock({ blockHash: receipt.blockHash });
×
NEW
70
      const date = new Date(Number(block.timestamp) * 1000);
×
71

NEW
72
      return await models.sequelize.transaction(async (transaction) => {
×
NEW
73
        const [token] = await models.ThreadToken.findOrCreate({
×
74
          where: { token_address: tokenAddress.toLowerCase() },
75
          defaults: {
76
            token_address: tokenAddress.toLowerCase(),
77
            name,
78
            symbol,
79
            initial_supply: Number(BigInt(totalSupply) / BigInt(1e18)),
80
            liquidity_transferred: false,
81
            launchpad_liquidity: BigInt(launchpadLiquidity).toString(),
82
            eth_market_cap_target: protocols.getTargetMarketCap(),
83
            creator_address: receipt.from,
84
            thread_id: threadId.toString(),
85
            created_at: date,
86
            updated_at: date,
87
          },
88
          transaction,
89
        });
90

NEW
91
        return token!.toJSON();
×
92
      });
93
    },
94
  };
95
}
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