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

hicommonwealth / commonwealth / 19508639478

19 Nov 2025 04:27PM UTC coverage: 37.649%. Remained the same
19508639478

push

github

web-flow
fix updates with event id (#13205)

Co-authored-by: rotorsoft <rotorsoft@outlook.com>

2041 of 5832 branches covered (35.0%)

Branch coverage included in aggregate %.

0 of 2 new or added lines in 2 files covered. (0.0%)

3 existing lines in 1 file now uncovered.

3574 of 9082 relevant lines covered (39.35%)

45.82 hits per line

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

64.44
/libs/model/src/integrations/token-allocation/magna.sync.ts
1
import { logger } from '@hicommonwealth/core';
2
import { delay } from '@hicommonwealth/shared';
3
import { QueryTypes } from 'sequelize';
4
import { config } from '../../config';
5
import { models } from '../../database';
6

7
const log = logger(import.meta);
31✔
8

9
export type TokenAllocationSyncArgs = {
10
  key: string;
11
  category: string;
12
  description: string;
13
  user_id: number;
14
  user_name: string;
15
  wallet_address: string;
16
  token_allocation: number;
17
  contract_id: string;
18
  token_id: string;
19
  schedule_id: string;
20
  unlock_start_at: Date;
21
};
22

23
async function sendToSlack(created: number) {
24
  const webhookUrl = config.SLACK.CHANNELS.MAGNA_NOTIFS;
1✔
25
  if (!webhookUrl) {
1!
26
    log.error(
1✔
27
      'SLACK_WEBHOOK_URL_MAGNA_NOTIFS is not set in the configuration. Cannot send Slack message.',
28
    );
29
    return;
1✔
30
  }
31
  try {
×
32
    const payload = {
×
33
      text: `:rotating_light: *Attention Product Team!* :rotating_light:\n
34
*${created} new allocations* have been created in *Magna*.\n
35
Please check the Magna dashboard for required signatures :memo: :rocket:`,
36
    };
37
    const response = await fetch(webhookUrl, {
×
38
      method: 'POST',
39
      body: JSON.stringify(payload),
40
      headers: { 'Content-Type': 'application/json' },
41
    });
42
    if (!response.ok) {
×
43
      const responseBody = await response.text();
×
44
      log.error(
×
45
        `Error sending message to Slack: ${response.statusText} - ${responseBody}`,
46
      );
47
    }
48
  } catch (error) {
49
    log.error('Error sending message to Slack:', error as Error);
×
50
  }
51
}
52

53
export async function magnaSync(
54
  apiCallback: (args: TokenAllocationSyncArgs) => Promise<string>,
55
  batchSize = 10,
×
56
  breatherMs = 1000,
×
57
) {
58
  let created = 0;
1✔
59
  let errors = 0;
1✔
60
  try {
1✔
61
    let found = true;
1✔
62
    while (found && errors < 3) {
1✔
63
      // Load next batch of allocations to sync with Magna
64
      const batch = await models.sequelize.query<TokenAllocationSyncArgs>(
9✔
65
        `SELECT
66
            CE.id || '-' || A.user_id as key,
67
            CE.id as category,
68
            CE.description || ' for ' || COALESCE(U.profile->>'name', 'Anonymous') as description,
69
            CE.contract_id,
70
            CE.token_id,
71
            CE.unlock_schedule_id as schedule_id,
72
            CE.unlock_start_at,
73
            A.user_id,
74
            A.address as wallet_address,
75
            COALESCE(U.profile->>'name', 'Anonymous-' || A.user_id) as user_name,
76
            (A.aura + A.historic + A.nft)::double precision as token_allocation
77
          FROM
78
            "ClaimAddresses" A -- this is the driving table with sync watermarks
79
            JOIN "Users" U ON A.user_id = U.id
80
            JOIN "ClaimEvents" CE ON A.event_id = CE.id
81
          WHERE
82
            A.address IS NOT NULL -- there is an address to sync
83
            AND A.magna_synced_at IS NULL -- and it hasn't been synced yet
84
            AND (A.aura + A.historic + A.nft) > 0
85
          ORDER BY
86
            A.user_id ASC
87
          LIMIT :limit
88
        `,
89
        {
90
          type: QueryTypes.SELECT,
91
          replacements: {
92
            limit: batchSize,
93
          },
94
        },
95
      );
96
      // break when no more allocations to sync
97
      if (batch.length === 0) {
9✔
98
        found = false;
1✔
99
        break;
1✔
100
      }
101

102
      const promises = batch.map(async (args) => {
8✔
103
        try {
80✔
104
          const allocationId = await apiCallback(args);
80✔
105
          await models.ClaimAddresses.update(
80✔
106
            {
107
              magna_allocation_id: allocationId,
108
              magna_synced_at: new Date(),
109
            },
110
            { where: { user_id: args.user_id } },
111
          );
112
          log.info(`Synced allocation for user ${args.user_id}`);
80✔
113
          created++;
114
        } catch (err) {
115
          log.error(
80✔
116
            `Failed to sync allocation for user ${args.user_id}:`,
UNCOV
117
            err as Error,
×
118
          );
119
        }
120
      });
121
      await Promise.all(promises);
122

123
      await delay(breatherMs); // take a breath to keep rate limit at BATCH_SIZE/sec
8✔
124
    }
125
  } catch (err) {
8✔
126
    log.error('Error syncing with Magna', err as Error);
127
    errors++;
UNCOV
128
  }
×
UNCOV
129
  if (created > 0) await sendToSlack(created);
×
130
}
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