@merkl/api 0.16.40 → 0.16.41
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/database/api/.generated/edge.js +2 -2
- package/dist/database/api/.generated/index.js +2 -2
- package/dist/database/api/.generated/package.json +1 -1
- package/dist/database/api/.generated/schema.prisma +4 -0
- package/dist/src/eden/index.d.ts +7600 -5065
- package/dist/src/entities/opportunity.js +4 -0
- package/dist/src/index.d.ts +753 -246
- package/dist/src/jobs/etl/update-dynamic-data.d.ts +1 -0
- package/dist/src/jobs/etl/update-dynamic-data.js +71 -0
- package/dist/src/libs/campaigns/campaignsDynamicData.d.ts +1 -1
- package/dist/src/libs/campaigns/campaignsDynamicData.js +22 -0
- package/dist/src/modules/v4/airflow/airflow.service.d.ts +3 -0
- package/dist/src/modules/v4/airflow/airflow.service.js +20 -0
- package/dist/src/modules/v4/campaign/campaign.repository.d.ts +81 -1
- package/dist/src/modules/v4/campaign/campaign.repository.js +57 -1
- package/dist/src/modules/v4/campaign/campaign.service.d.ts +57 -3
- package/dist/src/modules/v4/campaign/campaign.service.js +15 -6
- package/dist/src/modules/v4/campaign/index.d.ts +0 -1
- package/dist/src/modules/v4/campaign/index.js +0 -1
- package/dist/src/modules/v4/chain/chain.controller.d.ts +12 -36
- package/dist/src/modules/v4/chain/chain.controller.js +8 -6
- package/dist/src/modules/v4/chain/chain.model.d.ts +2 -0
- package/dist/src/modules/v4/chain/chain.model.js +2 -0
- package/dist/src/modules/v4/chain/chain.repository.d.ts +9 -11
- package/dist/src/modules/v4/chain/chain.repository.js +5 -18
- package/dist/src/modules/v4/chain/chain.service.d.ts +5 -0
- package/dist/src/modules/v4/chain/chain.service.js +4 -1
- package/dist/src/modules/v4/chain/index.d.ts +2 -1
- package/dist/src/modules/v4/chain/index.js +6 -1
- package/dist/src/modules/v4/computedValue/computedValue.repository.d.ts +1 -1
- package/dist/src/modules/v4/computedValue/computedValue.service.d.ts +1 -1
- package/dist/src/modules/v4/computedValue/index.d.ts +0 -1
- package/dist/src/modules/v4/computedValue/index.js +0 -1
- package/dist/src/modules/v4/dynamicData/dynamicData.service.js +1 -1
- package/dist/src/modules/v4/enso/enso.service.d.ts +1 -12
- package/dist/src/modules/v4/interaction/interaction.controller.d.ts +2 -12
- package/dist/src/modules/v4/opportunity/opportunity.controller.d.ts +703 -134
- package/dist/src/modules/v4/opportunity/opportunity.controller.js +2 -4
- package/dist/src/modules/v4/opportunity/opportunity.model.js +1 -1
- package/dist/src/modules/v4/opportunity/opportunity.repository.js +2 -1
- package/dist/src/modules/v4/opportunity/opportunity.service.d.ts +0 -204
- package/dist/src/modules/v4/opportunity/opportunity.service.js +6 -4
- package/dist/src/modules/v4/opportunity/subservices/getVestMetaData.service.d.ts +1 -1
- package/dist/src/modules/v4/opportunity/subservices/getVestMetaData.service.js +1 -1
- package/dist/src/modules/v4/protocol/index.d.ts +2 -1
- package/dist/src/modules/v4/protocol/index.js +8 -1
- package/dist/src/modules/v4/protocol/protocol.controller.d.ts +10 -40
- package/dist/src/modules/v4/protocol/protocol.controller.js +11 -9
- package/dist/src/modules/v4/protocol/protocol.service.d.ts +7 -7
- package/dist/src/modules/v4/protocol/protocol.service.js +10 -10
- package/dist/src/modules/v4/reward/index.d.ts +0 -1
- package/dist/src/modules/v4/reward/index.js +0 -1
- package/dist/src/modules/v4/reward/reward.service.d.ts +5 -5
- package/dist/src/modules/v4/reward/reward.service.js +6 -7
- package/dist/src/modules/v4/router.d.ts +752 -245
- package/dist/src/modules/v4/status/index.d.ts +0 -1
- package/dist/src/modules/v4/status/index.js +0 -1
- package/dist/src/modules/v4/status/status.controller.d.ts +1 -1
- package/dist/src/modules/v4/status/status.repository.d.ts +1 -1
- package/dist/src/modules/v4/status/status.service.d.ts +2 -2
- package/dist/src/modules/v4/token/token.controller.d.ts +2 -0
- package/dist/src/modules/v4/token/token.model.d.ts +1 -0
- package/dist/src/modules/v4/token/token.model.js +1 -0
- package/dist/src/modules/v4/token/token.repository.js +4 -1
- package/dist/src/modules/v4/token/token.service.d.ts +1 -0
- package/dist/src/modules/v4/token/token.service.js +10 -0
- package/dist/src/routes/v3/campaigns.d.ts +1 -1
- package/dist/src/routes/v3/router.d.ts +1 -1
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- package/package.json +2 -1
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import { campaignsDynamicData } from "../../libs/campaigns/campaignsDynamicData";
|
2
|
+
import { AprService } from "../../modules/v4/apr";
|
3
|
+
import { CampaignService } from "../../modules/v4/campaign";
|
4
|
+
import { OpportunityService } from "../../modules/v4/opportunity";
|
5
|
+
import { OpportunityRepository } from "../../modules/v4/opportunity/opportunity.repository";
|
6
|
+
import { RewardService } from "../../modules/v4/reward";
|
7
|
+
import { TvlService } from "../../modules/v4/tvl";
|
8
|
+
import { executeSimple } from "../../utils/execute";
|
9
|
+
import { Campaign } from "@sdk";
|
10
|
+
const chainId = Number(process.env.CHAIN_ID);
|
11
|
+
if (!chainId)
|
12
|
+
throw new Error("Environment variable CHAIN_ID is required.");
|
13
|
+
const campaignType = process.env.CAMPAIGN_TYPE;
|
14
|
+
if (!campaignType)
|
15
|
+
throw new Error("Environment variable CAMPAIGN_TYPE is required.");
|
16
|
+
async function updateDynamicData() {
|
17
|
+
const liveCampaigns = (await CampaignService.getLiveCampaigns({ computeChainId: chainId, type: campaignType })).map(c => {
|
18
|
+
return {
|
19
|
+
amount: c.amount,
|
20
|
+
campaignId: c.campaignId,
|
21
|
+
mainParameter: c.Opportunity.identifier,
|
22
|
+
campaignParameters: c.params,
|
23
|
+
campaignSubType: c.subType,
|
24
|
+
campaignType,
|
25
|
+
chainId: c.distributionChainId,
|
26
|
+
computeChainId: c.computeChainId,
|
27
|
+
creator: c.creatorAddress,
|
28
|
+
endTimestamp: c.endTimestamp,
|
29
|
+
rewardToken: c.rewardTokenId,
|
30
|
+
startTimestamp: c.startTimestamp,
|
31
|
+
};
|
32
|
+
});
|
33
|
+
const dynamicData = await executeSimple(chainId, campaignsDynamicData(chainId, liveCampaigns, campaignType));
|
34
|
+
const oppMap = {};
|
35
|
+
for (const data of dynamicData) {
|
36
|
+
if (!!data) {
|
37
|
+
// Main Parameter OVERRIDING
|
38
|
+
if (data.campaignType === Campaign.SILO && data.campaignParameters.whitelist?.length === 1)
|
39
|
+
data.mainParameter = `${data.mainParameter}-${data.campaignParameters.whitelist[0]}`;
|
40
|
+
if (!oppMap[`${data.campaignType}_${data.mainParameter}`])
|
41
|
+
oppMap[`${data.campaignType}_${data.mainParameter}`] = {};
|
42
|
+
oppMap[`${data.campaignType}_${data.mainParameter}`][data.campaignId] = data;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
for (const entry of Object.entries(oppMap)) {
|
46
|
+
const [type, mainParameter] = entry[0].split("_");
|
47
|
+
try {
|
48
|
+
const apr = AprService.extractFromDynamicData(+type, Object.values(entry[1]));
|
49
|
+
const tvl = TvlService.extractFromDynamicData(+type, Object.values(entry[1]));
|
50
|
+
const dailyRewards = await RewardService.extractDailyRewardsRecordFromDynamicData(+type, Object.values(entry[1]));
|
51
|
+
const opportunityId = OpportunityService.hashId({
|
52
|
+
chainId,
|
53
|
+
identifier: mainParameter,
|
54
|
+
type: type,
|
55
|
+
});
|
56
|
+
await OpportunityRepository.updateRecords(opportunityId, apr, tvl, dailyRewards);
|
57
|
+
}
|
58
|
+
catch (err) {
|
59
|
+
console.log(mainParameter);
|
60
|
+
console.error(err);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
try {
|
65
|
+
await updateDynamicData();
|
66
|
+
process.exit(0);
|
67
|
+
}
|
68
|
+
catch (err) {
|
69
|
+
console.error(err);
|
70
|
+
process.exit(1);
|
71
|
+
}
|
@@ -1,3 +1,3 @@
|
|
1
1
|
import { Campaign, type CampaignDynamicData, type CampaignParameters, type MerklChainId } from "@sdk";
|
2
2
|
import type { UncachedResult } from "../../utils/execute";
|
3
|
-
export declare function campaignsDynamicData<T extends Campaign>(chainId: MerklChainId, campaigns: CampaignParameters<T>[], type: T): Promise<UncachedResult<Partial<CampaignDynamicData<T>[]>>>;
|
3
|
+
export declare function campaignsDynamicData<T extends Campaign>(chainId: MerklChainId, campaigns: CampaignParameters<T>[], type: T | string): Promise<UncachedResult<Partial<CampaignDynamicData<T>[]>>>;
|
@@ -26,67 +26,89 @@ export async function campaignsDynamicData(chainId, campaigns, type) {
|
|
26
26
|
}
|
27
27
|
catch (_err) { }
|
28
28
|
switch (type) {
|
29
|
+
case "ERC20":
|
29
30
|
case Campaign.ERC20: {
|
30
31
|
return ERC20DynamicData(chainId, campaigns);
|
31
32
|
}
|
33
|
+
case "ERC20LOGPROCESSOR":
|
32
34
|
case Campaign.ERC20LOGPROCESSOR: {
|
33
35
|
return ERC20DynamicData(chainId, campaigns);
|
34
36
|
}
|
37
|
+
case "ERC20REBASELOGPROCESSOR":
|
35
38
|
case Campaign.ERC20REBASELOGPROCESSOR: {
|
36
39
|
return ERC20DynamicData(chainId, campaigns);
|
37
40
|
}
|
41
|
+
case "CLAMM":
|
38
42
|
case Campaign.CLAMM: {
|
39
43
|
return CLAMMDynamicData(chainId, campaigns);
|
40
44
|
}
|
45
|
+
case "ERC20_SNAPSHOT":
|
41
46
|
case Campaign.ERC20_SNAPSHOT: {
|
42
47
|
return ERC20_SNAPSHOTDynamicData(chainId, campaigns);
|
43
48
|
}
|
49
|
+
case "JSON_AIRDROP":
|
44
50
|
case Campaign.JSON_AIRDROP: {
|
45
51
|
return JSON_AIRDROPDynamicData(chainId, campaigns);
|
46
52
|
}
|
53
|
+
case "SILO":
|
47
54
|
case Campaign.SILO: {
|
48
55
|
return SILODynamicData(chainId, campaigns);
|
49
56
|
}
|
57
|
+
case "RADIANT":
|
50
58
|
case Campaign.RADIANT: {
|
51
59
|
return RadiantDynamicData(chainId, campaigns);
|
52
60
|
}
|
61
|
+
case "MORPHO":
|
53
62
|
case Campaign.MORPHO: {
|
54
63
|
return MORPHODynamicData(chainId, campaigns);
|
55
64
|
}
|
65
|
+
case "EULER":
|
56
66
|
case Campaign.EULER: {
|
57
67
|
return ERC20DynamicData(chainId, campaigns);
|
58
68
|
}
|
69
|
+
case "DOLOMITE":
|
59
70
|
case Campaign.DOLOMITE: {
|
60
71
|
return DolomiteDynamicData(chainId, campaigns);
|
61
72
|
}
|
73
|
+
case "BADGER":
|
62
74
|
case Campaign.BADGER: {
|
63
75
|
return BadgerDynamicData(chainId, campaigns);
|
64
76
|
}
|
77
|
+
case "AJNA":
|
65
78
|
case Campaign.AJNA: {
|
66
79
|
return AjnaDynamicData(chainId, campaigns);
|
67
80
|
}
|
81
|
+
case "COMPOUND":
|
68
82
|
case Campaign.COMPOUND: {
|
69
83
|
return CompoundDynamicData(chainId, campaigns);
|
70
84
|
}
|
85
|
+
case "EIGENLAYER":
|
71
86
|
case Campaign.EIGENLAYER: {
|
72
87
|
return EigenLayerDynamicData(chainId, campaigns);
|
73
88
|
}
|
89
|
+
case "VEST":
|
74
90
|
case Campaign.VEST: {
|
75
91
|
return VestDynamicData(chainId, campaigns);
|
76
92
|
}
|
93
|
+
case "ERC20_FIX_APR":
|
77
94
|
case Campaign.ERC20_FIX_APR: {
|
78
95
|
return ERC20DynamicData(chainId, campaigns);
|
79
96
|
}
|
97
|
+
case "HYPERDRIVELOGPROCESSOR":
|
98
|
+
case "HYPERDRIVELOGFIXPROCESSOR":
|
80
99
|
case Campaign.HYPERDRIVELOGPROCESSOR:
|
81
100
|
case Campaign.HYPERDRIVELOGFIXPROCESSOR: {
|
82
101
|
return HyperdriveDynamicData(chainId, campaigns);
|
83
102
|
}
|
103
|
+
case "AMBIENTPROCESSOR":
|
84
104
|
case Campaign.AMBIENTPROCESSOR: {
|
85
105
|
return AmbientDynamicData(chainId, campaigns);
|
86
106
|
}
|
107
|
+
case "UNISWAP_V4":
|
87
108
|
case Campaign.UNISWAP_V4: {
|
88
109
|
return UniswapV4DynamicData(chainId, campaigns);
|
89
110
|
}
|
111
|
+
case "ENCOMPASSING":
|
90
112
|
case Campaign.ENCOMPASSING: {
|
91
113
|
return EncompassingDynamicData(chainId, campaigns);
|
92
114
|
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { log } from "../../../utils/logger";
|
2
|
+
import { withRetry } from "@sdk";
|
3
|
+
import { GoogleAuth } from "google-auth-library";
|
4
|
+
export class AirflowService {
|
5
|
+
static async triggerDAGRun(dagId, conf) {
|
6
|
+
const auth = new GoogleAuth({
|
7
|
+
scopes: "https://www.googleapis.com/auth/cloud-platform",
|
8
|
+
});
|
9
|
+
const client = await auth.getClient();
|
10
|
+
const reqParams = {
|
11
|
+
method: "POST",
|
12
|
+
url: `${process.env.AIRFLOW_URL}/api/v1/dags/${dagId}/dagRuns`,
|
13
|
+
data: {
|
14
|
+
conf,
|
15
|
+
},
|
16
|
+
};
|
17
|
+
await withRetry(async () => await client.request(reqParams), [], 2, 10_000);
|
18
|
+
log.info(`✅ triggered DAG ${dagId}`);
|
19
|
+
}
|
20
|
+
}
|
@@ -66,6 +66,86 @@ export declare abstract class CampaignRepository {
|
|
66
66
|
} | undefined;
|
67
67
|
};
|
68
68
|
};
|
69
|
+
/**
|
70
|
+
* Retrieves all past campaigns from the database.
|
71
|
+
* A campaign is considered past if the current timestamp is greater than the campaign's end timestamp.
|
72
|
+
*
|
73
|
+
* @returns A promise that resolves to an array of past campaigns.
|
74
|
+
*/
|
75
|
+
static getPastCampaigns(chainId?: number): Promise<{
|
76
|
+
type: string;
|
77
|
+
id: string;
|
78
|
+
params: Prisma.JsonValue;
|
79
|
+
subType: number | null;
|
80
|
+
startTimestamp: bigint;
|
81
|
+
endTimestamp: bigint;
|
82
|
+
computeChainId: number;
|
83
|
+
distributionChainId: number;
|
84
|
+
campaignId: string;
|
85
|
+
rewardTokenId: string;
|
86
|
+
amount: string;
|
87
|
+
opportunityId: string;
|
88
|
+
creatorAddress: string;
|
89
|
+
}[]>;
|
90
|
+
/**
|
91
|
+
* Retrieves all live campaigns from the database.
|
92
|
+
* A campaign is considered live if the current timestamp is between the campaign's start and end timestamps.
|
93
|
+
*
|
94
|
+
* @returns A promise that resolves to an array of live campaigns.
|
95
|
+
*/
|
96
|
+
static getLiveCampaigns(query?: {
|
97
|
+
computeChainId?: number;
|
98
|
+
type?: string;
|
99
|
+
}): Promise<({
|
100
|
+
Opportunity: {
|
101
|
+
name: string;
|
102
|
+
type: string;
|
103
|
+
id: string;
|
104
|
+
status: import("../../../../database/api/.generated").$Enums.Status;
|
105
|
+
tags: string[];
|
106
|
+
identifier: string;
|
107
|
+
chainId: number;
|
108
|
+
action: import("../../../../database/api/.generated").$Enums.OpportunityAction;
|
109
|
+
depositUrl: string | null;
|
110
|
+
mainProtocolId: string | null;
|
111
|
+
tvl: number;
|
112
|
+
apr: number;
|
113
|
+
dailyRewards: number;
|
114
|
+
};
|
115
|
+
} & {
|
116
|
+
type: string;
|
117
|
+
id: string;
|
118
|
+
params: Prisma.JsonValue;
|
119
|
+
subType: number | null;
|
120
|
+
startTimestamp: bigint;
|
121
|
+
endTimestamp: bigint;
|
122
|
+
computeChainId: number;
|
123
|
+
distributionChainId: number;
|
124
|
+
campaignId: string;
|
125
|
+
rewardTokenId: string;
|
126
|
+
amount: string;
|
127
|
+
opportunityId: string;
|
128
|
+
creatorAddress: string;
|
129
|
+
})[]>;
|
130
|
+
/**
|
131
|
+
* Upserts a campaign in the database. If the campaign already exists, it updates the existing record;
|
132
|
+
* otherwise, it creates a new one.
|
133
|
+
*
|
134
|
+
* @param {CreateCampaignModel} campaign - The campaign data to be upserted.
|
135
|
+
* @returns The upserted campaign record.
|
136
|
+
*
|
137
|
+
* @throws {Error} If unable to fetch data for the reward token.
|
138
|
+
*
|
139
|
+
* @remarks
|
140
|
+
* This method performs the following steps:
|
141
|
+
* 1. Determines the campaign type from the provided campaign data.
|
142
|
+
* 2. Fetches or creates the reward token associated with the campaign.
|
143
|
+
* 3. Parses the campaign parameters.
|
144
|
+
* 4. Computes the opportunity ID based on the campaign data.
|
145
|
+
* 5. Constructs the data object for the campaign to be upserted.
|
146
|
+
* 6. Upserts the campaign in the database using the constructed data object.
|
147
|
+
* 7. Logs an error if the upsert operation fails.
|
148
|
+
*/
|
69
149
|
static upsert(campaign: CreateCampaignModel): Promise<{
|
70
150
|
type: string;
|
71
151
|
id: string;
|
@@ -86,7 +166,7 @@ export declare abstract class CampaignRepository {
|
|
86
166
|
fail: number;
|
87
167
|
}>;
|
88
168
|
/**
|
89
|
-
* Fetches the campaign
|
169
|
+
* Fetches the campaign data for a v3 campaign in database
|
90
170
|
* @param chainId
|
91
171
|
* @param timestamp from which campaigns endTimestamp are filtered
|
92
172
|
* @returns
|
@@ -49,6 +49,62 @@ export class CampaignRepository {
|
|
49
49
|
};
|
50
50
|
}
|
51
51
|
// ─── Public Methods ──────────────────────────────────────────────────
|
52
|
+
/**
|
53
|
+
* Retrieves all past campaigns from the database.
|
54
|
+
* A campaign is considered past if the current timestamp is greater than the campaign's end timestamp.
|
55
|
+
*
|
56
|
+
* @returns A promise that resolves to an array of past campaigns.
|
57
|
+
*/
|
58
|
+
static async getPastCampaigns(chainId) {
|
59
|
+
const now = moment().unix();
|
60
|
+
return await apiDbClient.campaign.findMany({
|
61
|
+
where: {
|
62
|
+
computeChainId: chainId,
|
63
|
+
endTimestamp: {
|
64
|
+
lt: now,
|
65
|
+
},
|
66
|
+
},
|
67
|
+
});
|
68
|
+
}
|
69
|
+
/**
|
70
|
+
* Retrieves all live campaigns from the database.
|
71
|
+
* A campaign is considered live if the current timestamp is between the campaign's start and end timestamps.
|
72
|
+
*
|
73
|
+
* @returns A promise that resolves to an array of live campaigns.
|
74
|
+
*/
|
75
|
+
static async getLiveCampaigns(query) {
|
76
|
+
const now = moment().unix();
|
77
|
+
const where = {
|
78
|
+
...query,
|
79
|
+
endTimestamp: { gte: now },
|
80
|
+
startTimestamp: { lte: now },
|
81
|
+
};
|
82
|
+
return await apiDbClient.campaign.findMany({
|
83
|
+
where,
|
84
|
+
include: {
|
85
|
+
Opportunity: true,
|
86
|
+
},
|
87
|
+
});
|
88
|
+
}
|
89
|
+
/**
|
90
|
+
* Upserts a campaign in the database. If the campaign already exists, it updates the existing record;
|
91
|
+
* otherwise, it creates a new one.
|
92
|
+
*
|
93
|
+
* @param {CreateCampaignModel} campaign - The campaign data to be upserted.
|
94
|
+
* @returns The upserted campaign record.
|
95
|
+
*
|
96
|
+
* @throws {Error} If unable to fetch data for the reward token.
|
97
|
+
*
|
98
|
+
* @remarks
|
99
|
+
* This method performs the following steps:
|
100
|
+
* 1. Determines the campaign type from the provided campaign data.
|
101
|
+
* 2. Fetches or creates the reward token associated with the campaign.
|
102
|
+
* 3. Parses the campaign parameters.
|
103
|
+
* 4. Computes the opportunity ID based on the campaign data.
|
104
|
+
* 5. Constructs the data object for the campaign to be upserted.
|
105
|
+
* 6. Upserts the campaign in the database using the constructed data object.
|
106
|
+
* 7. Logs an error if the upsert operation fails.
|
107
|
+
*/
|
52
108
|
static async upsert(campaign) {
|
53
109
|
const campaignType = CampaignService.getTypeFromV3(campaign.type);
|
54
110
|
try {
|
@@ -174,7 +230,7 @@ export class CampaignRepository {
|
|
174
230
|
return { success: successCampaigns.length, fail: failedCampaigns.length };
|
175
231
|
}
|
176
232
|
/**
|
177
|
-
* Fetches the campaign
|
233
|
+
* Fetches the campaign data for a v3 campaign in database
|
178
234
|
* @param chainId
|
179
235
|
* @param timestamp from which campaigns endTimestamp are filtered
|
180
236
|
* @returns
|
@@ -1,9 +1,58 @@
|
|
1
1
|
import type { CampaignUnique, CampaignWithParams, CreateCampaignModel, GetCampaignQueryModel, UpdateCampaignModel, UpdateMetaDataCampaignModel } from "./";
|
2
|
-
import { CampaignRepository } from "./campaign.repository";
|
3
2
|
import { Campaign as CampaignEnum, type CampaignParameters, type ChainId } from "@sdk";
|
3
|
+
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(chainId?: number): Promise<{
|
8
|
+
type: string;
|
9
|
+
id: string;
|
10
|
+
params: import("database/api/.generated/runtime/library").JsonValue;
|
11
|
+
subType: number | null;
|
12
|
+
startTimestamp: bigint;
|
13
|
+
endTimestamp: bigint;
|
14
|
+
computeChainId: number;
|
15
|
+
distributionChainId: number;
|
16
|
+
campaignId: string;
|
17
|
+
rewardTokenId: string;
|
18
|
+
amount: string;
|
19
|
+
opportunityId: string;
|
20
|
+
creatorAddress: string;
|
21
|
+
}[]>;
|
22
|
+
static getLiveCampaigns(query?: {
|
23
|
+
computeChainId?: number;
|
24
|
+
type?: string;
|
25
|
+
}): Promise<({
|
26
|
+
Opportunity: {
|
27
|
+
name: string;
|
28
|
+
type: string;
|
29
|
+
id: string;
|
30
|
+
status: import("../../../../database/api/.generated").$Enums.Status;
|
31
|
+
tags: string[];
|
32
|
+
identifier: string;
|
33
|
+
chainId: number;
|
34
|
+
action: import("../../../../database/api/.generated").$Enums.OpportunityAction;
|
35
|
+
depositUrl: string | null;
|
36
|
+
mainProtocolId: string | null;
|
37
|
+
tvl: number;
|
38
|
+
apr: number;
|
39
|
+
dailyRewards: number;
|
40
|
+
};
|
41
|
+
} & {
|
42
|
+
type: string;
|
43
|
+
id: string;
|
44
|
+
params: import("database/api/.generated/runtime/library").JsonValue;
|
45
|
+
subType: number | null;
|
46
|
+
startTimestamp: bigint;
|
47
|
+
endTimestamp: bigint;
|
48
|
+
computeChainId: number;
|
49
|
+
distributionChainId: number;
|
50
|
+
campaignId: string;
|
51
|
+
rewardTokenId: string;
|
52
|
+
amount: string;
|
53
|
+
opportunityId: string;
|
54
|
+
creatorAddress: string;
|
55
|
+
})[]>;
|
7
56
|
static create(campaign: Omit<CreateCampaignModel, "id">): Promise<{
|
8
57
|
type: string;
|
9
58
|
id: string;
|
@@ -46,6 +95,11 @@ export declare abstract class CampaignService {
|
|
46
95
|
* @dev back-office function
|
47
96
|
*/
|
48
97
|
static moveToOpportunity(campaign: Omit<UpdateCampaignModel, "id">, upsert?: boolean): Promise<string>;
|
98
|
+
/**
|
99
|
+
* Get the list of campaigns satisfying the query
|
100
|
+
* @param query
|
101
|
+
* @returns A list of campaigns
|
102
|
+
*/
|
49
103
|
static findMany(query: GetCampaignQueryModel): Promise<{
|
50
104
|
params: any;
|
51
105
|
chain: {
|
@@ -228,9 +282,9 @@ export declare abstract class CampaignService {
|
|
228
282
|
* Convert raw
|
229
283
|
* @param query
|
230
284
|
* @returns A list of opportunities
|
231
|
-
* TODO: remove
|
285
|
+
* TODO: remove CampaignService function in favor of prisma client extensions
|
232
286
|
*/
|
233
|
-
static format(campaign: NonNullable<Awaited<ReturnType<typeof CampaignRepository
|
287
|
+
static format(campaign: NonNullable<Awaited<ReturnType<(typeof CampaignRepository)["findMany"]>>>[number]): {
|
234
288
|
params: any;
|
235
289
|
chain: {
|
236
290
|
name: string;
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { HttpError } from "../../../errors";
|
2
2
|
import { campaignsDynamicData } from "../../../libs/campaigns/campaignsDynamicData";
|
3
|
-
import { CampaignRepository } from "./campaign.repository";
|
4
3
|
import { OpportunityService } from "../opportunity";
|
5
4
|
import { StatusService } from "../status/status.service";
|
6
5
|
import { TokenRepository } from "../token/token.repository";
|
@@ -11,6 +10,7 @@ import { log } from "../../../utils/logger";
|
|
11
10
|
import { Campaign as CampaignEnum, NETWORK_LABELS, } from "@sdk";
|
12
11
|
import { utils } from "ethers";
|
13
12
|
import moment from "moment";
|
13
|
+
import { CampaignRepository } from "./campaign.repository";
|
14
14
|
export class CampaignService {
|
15
15
|
static hashId(campaign) {
|
16
16
|
return Bun.hash(`${campaign.distributionChain}${campaign.campaignId}`).toString();
|
@@ -21,6 +21,12 @@ export class CampaignService {
|
|
21
21
|
const [chainId, campaignId] = chainAndCampaignId.split("-");
|
22
22
|
return { distributionChain: +chainId, campaignId };
|
23
23
|
}
|
24
|
+
static async getPastCampaigns(chainId) {
|
25
|
+
return await CampaignRepository.getPastCampaigns(chainId);
|
26
|
+
}
|
27
|
+
static async getLiveCampaigns(query) {
|
28
|
+
return await CampaignRepository.getLiveCampaigns(query);
|
29
|
+
}
|
24
30
|
static async create(campaign) {
|
25
31
|
const id = CampaignService.hashId({ distributionChain: campaign.chainId, campaignId: campaign.campaignId });
|
26
32
|
await OpportunityService.createFromCampaign(campaign);
|
@@ -81,7 +87,7 @@ export class CampaignService {
|
|
81
87
|
.slice(0, 42);
|
82
88
|
}
|
83
89
|
if (campaign.opportunityIdentifier === undefined) {
|
84
|
-
throw new HttpError("Bad Request: opportunityIdentifier is required for
|
90
|
+
throw new HttpError("Bad Request: opportunityIdentifier is required for CampaignService campaign type", 400);
|
85
91
|
}
|
86
92
|
const updatedCampaign = {
|
87
93
|
...existingCampaign,
|
@@ -115,6 +121,11 @@ export class CampaignService {
|
|
115
121
|
// Return new opportunityId
|
116
122
|
return (await CampaignService.findUniqueOrThrow(campaign)).opportunityId;
|
117
123
|
}
|
124
|
+
/**
|
125
|
+
* Get the list of campaigns satisfying the query
|
126
|
+
* @param query
|
127
|
+
* @returns A list of campaigns
|
128
|
+
*/
|
118
129
|
static async findMany(query) {
|
119
130
|
if (query.subType && !query.type) {
|
120
131
|
throw new HttpError("Bad Request: Cannot specify a subType without a type", 400);
|
@@ -156,9 +167,7 @@ export class CampaignService {
|
|
156
167
|
}
|
157
168
|
static async findNextCampaignToProcess(chainId) {
|
158
169
|
const campaigns = await CampaignService.findCampaignsToProcess(chainId);
|
159
|
-
return {
|
160
|
-
campaignId: campaigns?.[0]?.campaignId,
|
161
|
-
};
|
170
|
+
return { campaignId: campaigns?.[0]?.campaignId };
|
162
171
|
}
|
163
172
|
static async pickCampaignToProcess(chainId) {
|
164
173
|
const campaigns = await CampaignService.findCampaignsToProcess(chainId);
|
@@ -241,7 +250,7 @@ export class CampaignService {
|
|
241
250
|
* Convert raw
|
242
251
|
* @param query
|
243
252
|
* @returns A list of opportunities
|
244
|
-
* TODO: remove
|
253
|
+
* TODO: remove CampaignService function in favor of prisma client extensions
|
245
254
|
*/
|
246
255
|
static format(campaign) {
|
247
256
|
const { DistributionChain, ComputeChain, RewardToken, params, CampaignStatus, ...c } = campaign;
|
@@ -22,17 +22,8 @@ export declare const ChainController: Elysia<"/chains", false, {
|
|
22
22
|
query: unknown;
|
23
23
|
headers: unknown;
|
24
24
|
response: {
|
25
|
-
|
26
|
-
|
27
|
-
id: number;
|
28
|
-
icon: string;
|
29
|
-
explorers: {
|
30
|
-
type: import("../../../../database/api/.generated").$Enums.ExplorerType;
|
31
|
-
url: string;
|
32
|
-
id: string;
|
33
|
-
chainId: number;
|
34
|
-
}[];
|
35
|
-
} | null;
|
25
|
+
[x: string]: any;
|
26
|
+
200: any;
|
36
27
|
};
|
37
28
|
};
|
38
29
|
};
|
@@ -48,17 +39,8 @@ export declare const ChainController: Elysia<"/chains", false, {
|
|
48
39
|
};
|
49
40
|
headers: unknown;
|
50
41
|
response: {
|
51
|
-
|
52
|
-
|
53
|
-
id: number;
|
54
|
-
icon: string;
|
55
|
-
explorers: {
|
56
|
-
type: import("../../../../database/api/.generated").$Enums.ExplorerType;
|
57
|
-
url: string;
|
58
|
-
id: string;
|
59
|
-
chainId: number;
|
60
|
-
}[];
|
61
|
-
}[];
|
42
|
+
[x: string]: any;
|
43
|
+
200: any;
|
62
44
|
};
|
63
45
|
};
|
64
46
|
};
|
@@ -74,7 +56,8 @@ export declare const ChainController: Elysia<"/chains", false, {
|
|
74
56
|
};
|
75
57
|
headers: unknown;
|
76
58
|
response: {
|
77
|
-
|
59
|
+
[x: string]: any;
|
60
|
+
200: any;
|
78
61
|
};
|
79
62
|
};
|
80
63
|
};
|
@@ -85,6 +68,8 @@ export declare const ChainController: Elysia<"/chains", false, {
|
|
85
68
|
patch: {
|
86
69
|
body: {
|
87
70
|
icon?: string | undefined;
|
71
|
+
dailyRewards?: number | undefined;
|
72
|
+
liveCampaigns?: number | undefined;
|
88
73
|
};
|
89
74
|
params: {
|
90
75
|
chainId: number;
|
@@ -94,11 +79,8 @@ export declare const ChainController: Elysia<"/chains", false, {
|
|
94
79
|
authorization: string;
|
95
80
|
};
|
96
81
|
response: {
|
97
|
-
|
98
|
-
|
99
|
-
id: number;
|
100
|
-
icon: string;
|
101
|
-
};
|
82
|
+
[x: string]: any;
|
83
|
+
200: any;
|
102
84
|
};
|
103
85
|
};
|
104
86
|
};
|
@@ -120,14 +102,8 @@ export declare const ChainController: Elysia<"/chains", false, {
|
|
120
102
|
authorization: string;
|
121
103
|
};
|
122
104
|
response: {
|
123
|
-
|
124
|
-
|
125
|
-
type: import("../../../../database/api/.generated").$Enums.ExplorerType;
|
126
|
-
url: string;
|
127
|
-
id: string;
|
128
|
-
chainId: number;
|
129
|
-
}[];
|
130
|
-
};
|
105
|
+
[x: string]: any;
|
106
|
+
200: any;
|
131
107
|
};
|
132
108
|
};
|
133
109
|
};
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import { AuthorizationHeadersDto, BackOfficeGuard } from "../../../guards/BackOffice.guard";
|
2
|
+
import { apiDbClient } from "../../../utils/prisma";
|
2
3
|
import Elysia, { t } from "elysia";
|
4
|
+
import { initChainService } from ".";
|
3
5
|
import { ChainResourceDto, ChainUniqueDto, CreateChainDto, GetChainQueryDto, UpdateChainDto, } from "./chain.model";
|
4
|
-
|
6
|
+
const chainService = initChainService(apiDbClient);
|
5
7
|
// ─── Chains Controller ───────────────────────────────────────────────────────
|
6
8
|
export const ChainController = new Elysia({ prefix: "/chains", detail: { tags: ["Chains"] } })
|
7
9
|
// ─── Get A Chain By Id ───────────────────────────────────────────────
|
8
10
|
.get("/:chainId", async ({ params: { chainId } }) => {
|
9
|
-
const chain = await
|
11
|
+
const chain = await chainService.get(chainId);
|
10
12
|
if (!chain)
|
11
13
|
return null;
|
12
14
|
const { Explorer, ...rest } = chain;
|
@@ -17,7 +19,7 @@ export const ChainController = new Elysia({ prefix: "/chains", detail: { tags: [
|
|
17
19
|
})
|
18
20
|
// ─── Get All Supported Chains ────────────────────────────────────────
|
19
21
|
.get("/", async ({ query }) => {
|
20
|
-
const chains = await
|
22
|
+
const chains = await chainService.findMany(query);
|
21
23
|
return chains.map(({ Explorer, ...chain }) => ({ explorers: Explorer, ...chain }));
|
22
24
|
}, {
|
23
25
|
query: GetChainQueryDto,
|
@@ -25,18 +27,18 @@ export const ChainController = new Elysia({ prefix: "/chains", detail: { tags: [
|
|
25
27
|
detail: { description: "List chains supported and integrated by Merkl." },
|
26
28
|
})
|
27
29
|
// ─── Count Chains ────────────────────────────────────────
|
28
|
-
.get("/count", async ({ query }) => await
|
30
|
+
.get("/count", async ({ query }) => await chainService.countMany(query), {
|
29
31
|
query: GetChainQueryDto,
|
30
32
|
detail: { hide: true },
|
31
33
|
})
|
32
|
-
.patch("/:chainId", async ({ params, body }) => await
|
34
|
+
.patch("/:chainId", async ({ params, body }) => await chainService.update(params.chainId, body), {
|
33
35
|
params: ChainUniqueDto,
|
34
36
|
body: UpdateChainDto,
|
35
37
|
headers: AuthorizationHeadersDto,
|
36
38
|
beforeHandle: BackOfficeGuard,
|
37
39
|
detail: { hide: true },
|
38
40
|
})
|
39
|
-
.post("/", async ({ body }) => await
|
41
|
+
.post("/", async ({ body }) => await chainService.create(body), {
|
40
42
|
body: CreateChainDto,
|
41
43
|
headers: AuthorizationHeadersDto,
|
42
44
|
beforeHandle: BackOfficeGuard,
|
@@ -24,6 +24,8 @@ export declare const ChainArrayOptionalDto: import("@sinclair/typebox").TObject<
|
|
24
24
|
}>;
|
25
25
|
export declare const UpdateChainDto: import("@sinclair/typebox").TObject<{
|
26
26
|
icon: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
27
|
+
dailyRewards: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
28
|
+
liveCampaigns: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
27
29
|
}>;
|
28
30
|
export declare const CreateChainDto: import("@sinclair/typebox").TObject<{
|
29
31
|
id: import("@sinclair/typebox").TNumber;
|