@merkl/api 0.17.7 → 0.17.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/jobs/etl/update-dynamic-data.js +40 -38
- package/dist/src/modules/v4/campaign/campaign.repository.d.ts +67 -2
- package/dist/src/modules/v4/campaign/campaign.repository.js +46 -6
- package/dist/src/modules/v4/campaign/campaign.service.d.ts +55 -2
- package/dist/src/modules/v4/campaign/campaign.service.js +5 -2
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- package/package.json +1 -1
@@ -6,7 +6,8 @@ import { OpportunityRepository } from "../../modules/v4/opportunity/opportunity.
|
|
6
6
|
import { RewardService } from "../../modules/v4/reward";
|
7
7
|
import { TvlService } from "../../modules/v4/tvl";
|
8
8
|
import { executeSimple } from "../../utils/execute";
|
9
|
-
import {
|
9
|
+
import { log } from "../../utils/logger";
|
10
|
+
import { Campaign as CampaignEnum } from "@sdk";
|
10
11
|
import moment from "moment";
|
11
12
|
// ─── Required Env Variables ──────────────────────────────────────────────────
|
12
13
|
const chainId = Number(process.env.CHAIN_ID);
|
@@ -31,7 +32,7 @@ async function updateDynamicData(liveCampaigns, campaignType) {
|
|
31
32
|
for (const data of dynamicData) {
|
32
33
|
if (!!data) {
|
33
34
|
// Main Parameter OVERRIDING
|
34
|
-
if (data.campaignType ===
|
35
|
+
if (data.campaignType === CampaignEnum.SILO && data.campaignParameters.whitelist?.length === 1)
|
35
36
|
data.mainParameter = `${data.mainParameter}-${data.campaignParameters.whitelist[0]}`;
|
36
37
|
if (!oppMap[`${data.campaignType}_${data.mainParameter}`])
|
37
38
|
oppMap[`${data.campaignType}_${data.mainParameter}`] = {};
|
@@ -57,25 +58,9 @@ async function updateDynamicData(liveCampaigns, campaignType) {
|
|
57
58
|
}
|
58
59
|
}
|
59
60
|
// ─── Get And Transform Live Campaigns Into A Map ─────────────────────────────
|
60
|
-
const
|
61
|
-
const liveCampaigns = (await CampaignService.getLiveCampaigns({ computeChainId: chainId })).map(c => {
|
62
|
-
return {
|
63
|
-
amount: c.amount,
|
64
|
-
campaignId: c.campaignId,
|
65
|
-
mainParameter: c.Opportunity.identifier,
|
66
|
-
campaignParameters: c.params,
|
67
|
-
campaignSubType: c.subType,
|
68
|
-
campaignType: c.type,
|
69
|
-
chainId: c.distributionChainId,
|
70
|
-
computeChainId: c.computeChainId,
|
71
|
-
creator: c.creatorAddress,
|
72
|
-
endTimestamp: c.endTimestamp,
|
73
|
-
rewardToken: c.rewardTokenId,
|
74
|
-
startTimestamp: c.startTimestamp,
|
75
|
-
};
|
76
|
-
});
|
61
|
+
const buildMapByType = async (campaignsToUpdate) => {
|
77
62
|
const campaignTypeToCampaigns = new Map();
|
78
|
-
for (const campaign of
|
63
|
+
for (const campaign of campaignsToUpdate) {
|
79
64
|
const type = campaign.campaignType;
|
80
65
|
let campaigns = campaignTypeToCampaigns.get(campaign.campaignType);
|
81
66
|
if (!campaigns)
|
@@ -87,22 +72,43 @@ const getLiveCampaignsByType = async (chainId) => {
|
|
87
72
|
return campaignTypeToCampaigns;
|
88
73
|
};
|
89
74
|
// ─── Main function / entry point ─────────────────────────────────────────────
|
90
|
-
const
|
75
|
+
const updateCampaigns = async (campaignsToUpdate) => {
|
91
76
|
// 1. Get a map of campaigns by campaign type
|
92
|
-
const
|
77
|
+
const campaignTypeToCampaigns = await buildMapByType(campaignsToUpdate);
|
93
78
|
// 2. Call updateDynamicData with each entries of the map (process by campaign type)
|
94
|
-
for (const [
|
79
|
+
for (const [campaignType, campaigns] of campaignTypeToCampaigns.entries()) {
|
80
|
+
log.info(`updating dynamic data for ${campaigns.length} campaigns of type ${CampaignEnum[campaignType]}`);
|
95
81
|
try {
|
96
|
-
await updateDynamicData(campaigns,
|
82
|
+
await updateDynamicData(campaigns, campaignType);
|
97
83
|
}
|
98
84
|
catch (err) {
|
99
|
-
console.error(`Failed to update dynamic data for campaign type ${
|
85
|
+
console.error(`Failed to update dynamic data for campaign type ${CampaignEnum[campaignType]}`, err);
|
100
86
|
}
|
101
87
|
}
|
102
|
-
|
103
|
-
|
88
|
+
};
|
89
|
+
const main = async () => {
|
90
|
+
const liveCampaigns = (await CampaignService.getLiveCampaigns({ computeChainId: chainId })).map(c => {
|
91
|
+
return {
|
92
|
+
amount: c.amount,
|
93
|
+
campaignId: c.campaignId,
|
94
|
+
mainParameter: c.Opportunity.identifier,
|
95
|
+
campaignParameters: c.params,
|
96
|
+
campaignSubType: c.subType,
|
97
|
+
campaignType: CampaignEnum[c.type],
|
98
|
+
chainId: c.distributionChainId,
|
99
|
+
computeChainId: c.computeChainId,
|
100
|
+
creator: c.creatorAddress,
|
101
|
+
endTimestamp: Number(c.endTimestamp),
|
102
|
+
rewardToken: c.rewardTokenId,
|
103
|
+
startTimestamp: Number(c.startTimestamp),
|
104
|
+
index: 0,
|
105
|
+
};
|
106
|
+
});
|
107
|
+
await updateCampaigns(liveCampaigns);
|
108
|
+
// Update status of opportunities
|
109
|
+
// 1. Get current live opportunities
|
104
110
|
const liveOpportunities = await OpportunityService.findLiveWithCampaigns(chainId);
|
105
|
-
//
|
111
|
+
// 2. For each currently live opportunities, infer its updated status by looping through its campaigns
|
106
112
|
const now = moment().unix();
|
107
113
|
for (const opportunity of liveOpportunities) {
|
108
114
|
let status = "NONE";
|
@@ -117,16 +123,12 @@ const main = async () => {
|
|
117
123
|
}
|
118
124
|
await OpportunityService.updateStatus(opportunity.id, status);
|
119
125
|
}
|
120
|
-
//
|
121
|
-
const
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
}
|
127
|
-
}
|
128
|
-
// 5. Update the status of the liveCampaigns opportunities
|
129
|
-
await OpportunityService.updateMany(Array.from(opportunities), { status: "LIVE" });
|
126
|
+
// 3. Update the status of the opportunities associated to future campaigns
|
127
|
+
const futureOpportunityIds = (await CampaignService.getFutureCampaigns({ computeChainId: chainId })).map(c => c.Opportunity.id);
|
128
|
+
await OpportunityService.updateMany(futureOpportunityIds, { status: "SOON" });
|
129
|
+
// 4. Update the status of the opportunities associated to live campaigns
|
130
|
+
const liveOpportunityIds = (await CampaignService.getLiveCampaigns({ computeChainId: chainId })).map(c => c.Opportunity.id);
|
131
|
+
await OpportunityService.updateMany(liveOpportunityIds, { status: "LIVE" });
|
130
132
|
};
|
131
133
|
try {
|
132
134
|
await main();
|
@@ -71,8 +71,29 @@ export declare abstract class CampaignRepository {
|
|
71
71
|
* A campaign is considered past if the current timestamp is greater than the campaign's end timestamp.
|
72
72
|
*
|
73
73
|
* @returns A promise that resolves to an array of past campaigns.
|
74
|
+
*
|
75
|
+
* @dev Excludes test campaigns
|
74
76
|
*/
|
75
|
-
static getPastCampaigns(
|
77
|
+
static getPastCampaigns(query?: {
|
78
|
+
computeChainId?: number;
|
79
|
+
type?: string;
|
80
|
+
}): Promise<({
|
81
|
+
Opportunity: {
|
82
|
+
name: string;
|
83
|
+
type: string;
|
84
|
+
id: string;
|
85
|
+
status: import("../../../../database/api/.generated").$Enums.Status;
|
86
|
+
tags: string[];
|
87
|
+
identifier: string;
|
88
|
+
chainId: number;
|
89
|
+
action: import("../../../../database/api/.generated").$Enums.OpportunityAction;
|
90
|
+
depositUrl: string | null;
|
91
|
+
mainProtocolId: string | null;
|
92
|
+
tvl: number;
|
93
|
+
apr: number;
|
94
|
+
dailyRewards: number;
|
95
|
+
};
|
96
|
+
} & {
|
76
97
|
type: string;
|
77
98
|
id: string;
|
78
99
|
params: Prisma.JsonValue;
|
@@ -86,12 +107,56 @@ export declare abstract class CampaignRepository {
|
|
86
107
|
amount: string;
|
87
108
|
opportunityId: string;
|
88
109
|
creatorAddress: string;
|
89
|
-
}[]>;
|
110
|
+
})[]>;
|
111
|
+
/**
|
112
|
+
* Retrieves all past campaigns from the database.
|
113
|
+
* A campaign is considered past if the current timestamp is greater than the campaign's end timestamp.
|
114
|
+
*
|
115
|
+
* @returns A promise that resolves to an array of past campaigns.
|
116
|
+
*
|
117
|
+
* @dev Excludes test campaigns
|
118
|
+
*/
|
119
|
+
static getFutureCampaigns(query?: {
|
120
|
+
computeChainId?: number;
|
121
|
+
type?: string;
|
122
|
+
}): Promise<({
|
123
|
+
Opportunity: {
|
124
|
+
name: string;
|
125
|
+
type: string;
|
126
|
+
id: string;
|
127
|
+
status: import("../../../../database/api/.generated").$Enums.Status;
|
128
|
+
tags: string[];
|
129
|
+
identifier: string;
|
130
|
+
chainId: number;
|
131
|
+
action: import("../../../../database/api/.generated").$Enums.OpportunityAction;
|
132
|
+
depositUrl: string | null;
|
133
|
+
mainProtocolId: string | null;
|
134
|
+
tvl: number;
|
135
|
+
apr: number;
|
136
|
+
dailyRewards: number;
|
137
|
+
};
|
138
|
+
} & {
|
139
|
+
type: string;
|
140
|
+
id: string;
|
141
|
+
params: Prisma.JsonValue;
|
142
|
+
subType: number | null;
|
143
|
+
startTimestamp: bigint;
|
144
|
+
endTimestamp: bigint;
|
145
|
+
computeChainId: number;
|
146
|
+
distributionChainId: number;
|
147
|
+
campaignId: string;
|
148
|
+
rewardTokenId: string;
|
149
|
+
amount: string;
|
150
|
+
opportunityId: string;
|
151
|
+
creatorAddress: string;
|
152
|
+
})[]>;
|
90
153
|
/**
|
91
154
|
* Retrieves all live campaigns from the database.
|
92
155
|
* A campaign is considered live if the current timestamp is between the campaign's start and end timestamps.
|
93
156
|
*
|
94
157
|
* @returns A promise that resolves to an array of live campaigns.
|
158
|
+
*
|
159
|
+
* @dev Excludes test campaigns
|
95
160
|
*/
|
96
161
|
static getLiveCampaigns(query?: {
|
97
162
|
computeChainId?: number;
|
@@ -54,15 +54,50 @@ export class CampaignRepository {
|
|
54
54
|
* A campaign is considered past if the current timestamp is greater than the campaign's end timestamp.
|
55
55
|
*
|
56
56
|
* @returns A promise that resolves to an array of past campaigns.
|
57
|
+
*
|
58
|
+
* @dev Excludes test campaigns
|
57
59
|
*/
|
58
|
-
static async getPastCampaigns(
|
60
|
+
static async getPastCampaigns(query) {
|
59
61
|
const now = moment().unix();
|
62
|
+
const where = {
|
63
|
+
...query,
|
64
|
+
endTimestamp: {
|
65
|
+
lt: now,
|
66
|
+
},
|
67
|
+
RewardToken: {
|
68
|
+
isTest: false,
|
69
|
+
},
|
70
|
+
};
|
60
71
|
return await apiDbClient.campaign.findMany({
|
61
|
-
where
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
72
|
+
where,
|
73
|
+
include: {
|
74
|
+
Opportunity: true,
|
75
|
+
},
|
76
|
+
});
|
77
|
+
}
|
78
|
+
/**
|
79
|
+
* Retrieves all past campaigns from the database.
|
80
|
+
* A campaign is considered past if the current timestamp is greater than the campaign's end timestamp.
|
81
|
+
*
|
82
|
+
* @returns A promise that resolves to an array of past campaigns.
|
83
|
+
*
|
84
|
+
* @dev Excludes test campaigns
|
85
|
+
*/
|
86
|
+
static async getFutureCampaigns(query) {
|
87
|
+
const now = moment().unix();
|
88
|
+
const where = {
|
89
|
+
...query,
|
90
|
+
startTimestamp: {
|
91
|
+
gt: now,
|
92
|
+
},
|
93
|
+
RewardToken: {
|
94
|
+
isTest: false,
|
95
|
+
},
|
96
|
+
};
|
97
|
+
return await apiDbClient.campaign.findMany({
|
98
|
+
where,
|
99
|
+
include: {
|
100
|
+
Opportunity: true,
|
66
101
|
},
|
67
102
|
});
|
68
103
|
}
|
@@ -71,6 +106,8 @@ export class CampaignRepository {
|
|
71
106
|
* A campaign is considered live if the current timestamp is between the campaign's start and end timestamps.
|
72
107
|
*
|
73
108
|
* @returns A promise that resolves to an array of live campaigns.
|
109
|
+
*
|
110
|
+
* @dev Excludes test campaigns
|
74
111
|
*/
|
75
112
|
static async getLiveCampaigns(query) {
|
76
113
|
const now = moment().unix();
|
@@ -78,6 +115,9 @@ export class CampaignRepository {
|
|
78
115
|
...query,
|
79
116
|
endTimestamp: { gte: now },
|
80
117
|
startTimestamp: { lte: now },
|
118
|
+
RewardToken: {
|
119
|
+
isTest: false,
|
120
|
+
},
|
81
121
|
};
|
82
122
|
return await apiDbClient.campaign.findMany({
|
83
123
|
where,
|
@@ -4,7 +4,26 @@ import { CampaignRepository } from "./campaign.repository";
|
|
4
4
|
export declare abstract class CampaignService {
|
5
5
|
static hashId(campaign: CampaignUnique): string;
|
6
6
|
static splitIdOrThrow(chainAndCampaignId: `${number}-${string}` | string): CampaignUnique;
|
7
|
-
static getPastCampaigns(
|
7
|
+
static getPastCampaigns(query?: {
|
8
|
+
computeChainId?: number;
|
9
|
+
type?: string;
|
10
|
+
}): Promise<({
|
11
|
+
Opportunity: {
|
12
|
+
name: string;
|
13
|
+
type: string;
|
14
|
+
id: string;
|
15
|
+
status: import("../../../../database/api/.generated").$Enums.Status;
|
16
|
+
tags: string[];
|
17
|
+
identifier: string;
|
18
|
+
chainId: number;
|
19
|
+
action: import("../../../../database/api/.generated").$Enums.OpportunityAction;
|
20
|
+
depositUrl: string | null;
|
21
|
+
mainProtocolId: string | null;
|
22
|
+
tvl: number;
|
23
|
+
apr: number;
|
24
|
+
dailyRewards: number;
|
25
|
+
};
|
26
|
+
} & {
|
8
27
|
type: string;
|
9
28
|
id: string;
|
10
29
|
params: import("database/api/.generated/runtime/library").JsonValue;
|
@@ -18,7 +37,41 @@ export declare abstract class CampaignService {
|
|
18
37
|
amount: string;
|
19
38
|
opportunityId: string;
|
20
39
|
creatorAddress: string;
|
21
|
-
}[]>;
|
40
|
+
})[]>;
|
41
|
+
static getFutureCampaigns(query?: {
|
42
|
+
computeChainId?: number;
|
43
|
+
type?: string;
|
44
|
+
}): Promise<({
|
45
|
+
Opportunity: {
|
46
|
+
name: string;
|
47
|
+
type: string;
|
48
|
+
id: string;
|
49
|
+
status: import("../../../../database/api/.generated").$Enums.Status;
|
50
|
+
tags: string[];
|
51
|
+
identifier: string;
|
52
|
+
chainId: number;
|
53
|
+
action: import("../../../../database/api/.generated").$Enums.OpportunityAction;
|
54
|
+
depositUrl: string | null;
|
55
|
+
mainProtocolId: string | null;
|
56
|
+
tvl: number;
|
57
|
+
apr: number;
|
58
|
+
dailyRewards: number;
|
59
|
+
};
|
60
|
+
} & {
|
61
|
+
type: string;
|
62
|
+
id: string;
|
63
|
+
params: import("database/api/.generated/runtime/library").JsonValue;
|
64
|
+
subType: number | null;
|
65
|
+
startTimestamp: bigint;
|
66
|
+
endTimestamp: bigint;
|
67
|
+
computeChainId: number;
|
68
|
+
distributionChainId: number;
|
69
|
+
campaignId: string;
|
70
|
+
rewardTokenId: string;
|
71
|
+
amount: string;
|
72
|
+
opportunityId: string;
|
73
|
+
creatorAddress: string;
|
74
|
+
})[]>;
|
22
75
|
static getLiveCampaigns(query?: {
|
23
76
|
computeChainId?: number;
|
24
77
|
type?: string;
|
@@ -21,8 +21,11 @@ export class CampaignService {
|
|
21
21
|
const [chainId, campaignId] = chainAndCampaignId.split("-");
|
22
22
|
return { distributionChain: +chainId, campaignId };
|
23
23
|
}
|
24
|
-
static async getPastCampaigns(
|
25
|
-
return await CampaignRepository.getPastCampaigns(
|
24
|
+
static async getPastCampaigns(query) {
|
25
|
+
return await CampaignRepository.getPastCampaigns(query);
|
26
|
+
}
|
27
|
+
static async getFutureCampaigns(query) {
|
28
|
+
return await CampaignRepository.getFutureCampaigns(query);
|
26
29
|
}
|
27
30
|
static async getLiveCampaigns(query) {
|
28
31
|
return await CampaignRepository.getLiveCampaigns(query);
|