@merkl/api 0.20.3 → 0.20.4
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/cache/declaration.d.ts +2 -2
- package/dist/src/cache/declaration.js +2 -2
- package/dist/src/engine/dynamicData/utils/getEulerV2Vaults.d.ts +0 -1
- package/dist/src/engine/dynamicData/utils/getEulerV2Vaults.js +77 -40
- package/dist/src/engine/erc20SubTypeProcessors/implementations/EulerLendProcessor.js +6 -1
- package/dist/src/jobs/update-euler-vaults.d.ts +1 -1
- package/dist/src/jobs/update-euler-vaults.js +5 -121
- package/dist/src/modules/v4/icon/icon.model.d.ts +4 -0
- package/dist/src/modules/v4/icon/icon.model.js +1 -0
- package/dist/src/modules/v4/icon/icon.service.d.ts +5 -0
- package/dist/src/modules/v4/icon/icon.service.js +15 -0
- package/dist/src/modules/v4/programPayload/programPayload.repository.js +4 -0
- package/dist/src/modules/v4/token/token.service.js +6 -9
- package/dist/src/routes/v3/euler.d.ts +0 -6
- package/dist/src/routes/v3/euler.js +3 -3
- package/dist/tsconfig.package.tsbuildinfo +1 -1
- package/package.json +1 -1
@@ -32,7 +32,7 @@ export declare const CacheDeclaration: {
|
|
32
32
|
};
|
33
33
|
EulerV2Vaults: {
|
34
34
|
compressed: false;
|
35
|
-
redisTTL: TTLType.
|
35
|
+
redisTTL: TTLType.Day;
|
36
36
|
localCache: false;
|
37
37
|
};
|
38
38
|
CompoundV2ForksVaults: {
|
@@ -127,7 +127,7 @@ export declare const CacheDeclaration: {
|
|
127
127
|
};
|
128
128
|
UniswapV4Pools: {
|
129
129
|
compressed: false;
|
130
|
-
redisTTL: TTLType.
|
130
|
+
redisTTL: TTLType.Day;
|
131
131
|
localCache: false;
|
132
132
|
};
|
133
133
|
};
|
@@ -20,7 +20,7 @@ export const CacheDeclaration = {
|
|
20
20
|
},
|
21
21
|
EulerV2Vaults: {
|
22
22
|
compressed: false,
|
23
|
-
redisTTL: TTLType.
|
23
|
+
redisTTL: TTLType.Day,
|
24
24
|
localCache: false,
|
25
25
|
},
|
26
26
|
CompoundV2ForksVaults: {
|
@@ -115,7 +115,7 @@ export const CacheDeclaration = {
|
|
115
115
|
},
|
116
116
|
UniswapV4Pools: {
|
117
117
|
compressed: false,
|
118
|
-
redisTTL: TTLType.
|
118
|
+
redisTTL: TTLType.Day,
|
119
119
|
localCache: false,
|
120
120
|
},
|
121
121
|
};
|
@@ -4,5 +4,4 @@ export declare enum LoggedEntityType {
|
|
4
4
|
UNISWAP_V4 = "UNISWAP_V4"
|
5
5
|
}
|
6
6
|
export declare function getEulerV2Vaults(): Promise<EulerVaultType[]>;
|
7
|
-
export declare const getEulerV2VaultsWithCache: () => Promise<EulerVaultType[]>;
|
8
7
|
export declare function updateEulerVaultsCollatInDatabase(): Promise<void>;
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import { Redis } from "@/cache";
|
2
1
|
import { fetchEulerVaultName } from "@/engine/erc20SubTypeProcessors/helpers/eulerVaultNames";
|
3
2
|
import { batchMulticallCallWithRetry } from "@/utils/generic";
|
4
|
-
import { log } from "@/utils/logger";
|
3
|
+
import { log, logger } from "@/utils/logger";
|
5
4
|
import { providers } from "@/utils/providers";
|
6
5
|
import { apiDbClient } from "@db";
|
7
6
|
import { ChainInteractionService, ERC20Interface, EULER_ADDRESSES, EulerEVKInterface, EulerVaultLensInterface, EulerVault__factory, NETWORK_LABELS, eulerChainIds, getContractCreationBlock, } from "@sdk";
|
@@ -27,59 +26,93 @@ async function computeCollatListAndReturnVaults(chainId, vaults) {
|
|
27
26
|
};
|
28
27
|
}),
|
29
28
|
});
|
30
|
-
const
|
31
|
-
const
|
29
|
+
const callsToCollat = [];
|
30
|
+
const callsToCollatUnderlying = [];
|
31
|
+
// To keep track of all collat data
|
32
|
+
const collateralDataArray = [];
|
33
|
+
let k = 0;
|
32
34
|
for (const [index, vault] of vaults.entries()) {
|
33
35
|
const collatArray = EulerVaultLensInterface.decodeFunctionResult("getRecognizedCollateralsLTVInfo", resCollat[index].returnData)[0];
|
34
36
|
for (const collat of collatArray) {
|
37
|
+
// FIXME
|
35
38
|
if (!!vault.collaterals &&
|
36
|
-
vault.collaterals.map(c => c.address.toLowerCase()).includes(collat.collateral.toLowerCase()))
|
39
|
+
vault.collaterals.map(c => c.address.toLowerCase()).includes(collat.collateral.toLowerCase())) {
|
37
40
|
continue;
|
41
|
+
}
|
38
42
|
log.info(`🦭 found new collateral ${collat.collateral} for vault ${vault.address} (${NETWORK_LABELS[chainId]})`);
|
39
|
-
|
43
|
+
collateralDataArray.push({ vaultAddress: vault.address, address: collat.collateral, callsToCollatIndex: k });
|
44
|
+
k++;
|
45
|
+
callsToCollat.push({
|
40
46
|
allowFailure: true,
|
41
|
-
callData: EulerEVKInterface.encodeFunctionData("
|
47
|
+
callData: EulerEVKInterface.encodeFunctionData("symbol"),
|
42
48
|
target: collat.collateral,
|
43
49
|
}, {
|
44
50
|
allowFailure: true,
|
45
|
-
callData: EulerEVKInterface.encodeFunctionData("
|
51
|
+
callData: EulerEVKInterface.encodeFunctionData("asset"),
|
46
52
|
target: collat.collateral,
|
47
53
|
});
|
48
54
|
}
|
49
55
|
}
|
50
|
-
const
|
51
|
-
calls:
|
56
|
+
const resCallsToCollat = await batchMulticallCallWithRetry(chainId, {
|
57
|
+
calls: callsToCollat,
|
52
58
|
});
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
+
let j = 0;
|
60
|
+
for (let i = 0; i < resCallsToCollat.length; i = i + 2) {
|
61
|
+
const collatData = collateralDataArray.find(collat => collat.callsToCollatIndex === i / 2);
|
62
|
+
try {
|
63
|
+
// 1_ Collat symbol
|
64
|
+
const symbolCollateral = EulerEVKInterface.decodeFunctionResult("symbol", resCallsToCollat[i].returnData)[0];
|
65
|
+
collatData.symbolCollateral = symbolCollateral;
|
66
|
+
// 2_ Underlying asset => warning it can be undefined and throw an error
|
67
|
+
const underlyingToken = EulerEVKInterface.decodeFunctionResult("asset", resCallsToCollat[i + 1].returnData)[0];
|
68
|
+
callsToCollatUnderlying.push({
|
69
|
+
allowFailure: true,
|
70
|
+
callData: ERC20Interface.encodeFunctionData("symbol"),
|
71
|
+
target: underlyingToken,
|
72
|
+
});
|
73
|
+
collatData.callsToCollatUnderlyingIndex = j;
|
74
|
+
j++;
|
75
|
+
}
|
76
|
+
catch {
|
77
|
+
logger.warn(`🦭 error while decoding underlying token address for collat ${JSON.stringify(collatData)}`);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
let resCallsToCollatUnderlying;
|
81
|
+
if (callsToCollatUnderlying.length > 0) {
|
82
|
+
resCallsToCollatUnderlying = await batchMulticallCallWithRetry(chainId, {
|
83
|
+
calls: callsToCollatUnderlying,
|
59
84
|
});
|
60
85
|
}
|
61
|
-
const resCollatUnderlyingSymbol = await batchMulticallCallWithRetry(chainId, {
|
62
|
-
calls: callsCollatUnderlyingSymbol,
|
63
|
-
});
|
64
86
|
vaultsPerChain = vaultsPerChain.concat((await Promise.all(vaults.map(async (vault, index) => {
|
65
87
|
const collatArray = EulerVaultLensInterface.decodeFunctionResult("getRecognizedCollateralsLTVInfo", resCollat[index].returnData)[0];
|
66
88
|
if (!vault.collaterals)
|
67
89
|
vault.collaterals = [];
|
68
|
-
let offset = 0;
|
69
90
|
for (const [_index, collat] of collatArray.entries()) {
|
70
91
|
// _ Check whether the collat was already registered
|
71
92
|
if (!!vault.collaterals &&
|
72
93
|
vault.collaterals.map(c => c.address.toLowerCase()).includes(collat.collateral.toLowerCase())) {
|
73
|
-
offset += 1;
|
74
94
|
continue;
|
75
95
|
}
|
76
|
-
const
|
96
|
+
const collatData = collateralDataArray.find(c => c.vaultAddress?.toLowerCase() === vault.address?.toLowerCase() && c.address === collat.collateral);
|
97
|
+
if (!collatData || collatData.address !== collat.collateral) {
|
98
|
+
logger.warn(`🦭 issue when fetching data for collat ${collat.collateral} on vault ${vault.address}`);
|
99
|
+
console.log(collatData, collat.collateral);
|
100
|
+
process.exit(1);
|
101
|
+
}
|
102
|
+
// Collateral symbol
|
103
|
+
const symbolCollateral = collatData.symbolCollateral ?? "Unknown";
|
104
|
+
// Collat underlying symbol
|
105
|
+
let symbolUnderlying = "Unknown";
|
106
|
+
try {
|
107
|
+
symbolUnderlying = ERC20Interface.decodeFunctionResult("symbol", resCallsToCollatUnderlying[collatData.callsToCollatUnderlyingIndex ?? -1].returnData)[0];
|
108
|
+
}
|
109
|
+
catch { }
|
77
110
|
vault.collaterals.push({
|
78
111
|
address: collat.collateral,
|
79
|
-
symbolCollateral:
|
80
|
-
symbolUnderlying,
|
112
|
+
symbolCollateral: symbolCollateral,
|
113
|
+
symbolUnderlying: symbolUnderlying,
|
81
114
|
borrowLTV: collat.borrowLTV.toString(),
|
82
|
-
nameCollateral: (await fetchEulerVaultName(collat.collateral, chainId)) ??
|
115
|
+
nameCollateral: (await fetchEulerVaultName(collat.collateral, chainId)) ?? symbolCollateral,
|
83
116
|
});
|
84
117
|
}
|
85
118
|
return { ...vault };
|
@@ -113,20 +146,26 @@ export async function getEulerV2Vaults() {
|
|
113
146
|
}
|
114
147
|
const logs = await safeFetchLogs(chainId, [EulerEVKInterface.getEventTopic("EVaultCreated")], [], fromBlock, toBlock);
|
115
148
|
const decodedVaults = await Promise.all(logs.map(async (log) => {
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
149
|
+
try {
|
150
|
+
const aux = EulerEVKInterface.decodeEventLog("EVaultCreated", log.data, log.topics);
|
151
|
+
const name = (await EulerVault__factory.connect(log.address, providers[chainId]).name()).split(" ");
|
152
|
+
const vaultName = (await fetchEulerVaultName(getAddress(log.address), chainId)) ?? name[name.length - 1];
|
153
|
+
/** Respect the previous typing */
|
154
|
+
return {
|
155
|
+
address: log.address.toString(),
|
156
|
+
asset: aux[1].toString(),
|
157
|
+
fetchedAtBlock: Number(log.blockNumber),
|
158
|
+
chainId: chainId,
|
159
|
+
debtTokenAddress: aux[2].toString(),
|
160
|
+
name: vaultName,
|
161
|
+
};
|
162
|
+
}
|
163
|
+
catch {
|
164
|
+
logger.warn(`issue when fetching data on ${NETWORK_LABELS[chainId]} for vault ${log.address}`);
|
165
|
+
process.exit(1);
|
166
|
+
}
|
128
167
|
}));
|
129
|
-
log.
|
168
|
+
log.info(`fetched ${decodedVaults.length} vaults(s) on ${NETWORK_LABELS[chainId]} between blocks ${fromBlock} and ${toBlock}`);
|
130
169
|
vaultsPerChain = await computeCollatListAndReturnVaults(chainId, decodedVaults);
|
131
170
|
return vaultsPerChain;
|
132
171
|
}
|
@@ -160,14 +199,12 @@ export async function getEulerV2Vaults() {
|
|
160
199
|
throw new Error("Error while saving vaults to API database (`Logged` table)");
|
161
200
|
}
|
162
201
|
}
|
163
|
-
log.info("✅ successfully fetched new vaults on Euler V2");
|
164
202
|
if (storedVaults.length > 0) {
|
165
203
|
vaults = vaults.concat(storedVaults.map(v => v.entityData));
|
166
204
|
}
|
167
205
|
log.info("👋 exiting getEulerV2Vaults");
|
168
206
|
return vaults;
|
169
207
|
}
|
170
|
-
export const getEulerV2VaultsWithCache = async () => await Redis.getOrSet("EulerV2Vaults", getEulerV2Vaults);
|
171
208
|
export async function updateEulerVaultsCollatInDatabase() {
|
172
209
|
// 0_ Fetch all euler vaults from database
|
173
210
|
const vaults = await apiDbClient.logged.findMany({
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { generateCardName } from "@/utils/generateCardName";
|
2
|
+
import { log } from "@/utils/logger";
|
2
3
|
import { BN2Number } from "@sdk";
|
3
4
|
import { GenericProcessor } from "../GenericProcessor";
|
4
5
|
import { fetchEulerVaultName } from "../helpers/eulerVaultNames";
|
@@ -18,8 +19,12 @@ export class EulerLendProcessor extends GenericProcessor {
|
|
18
19
|
async processingRound5(index, type, typeInfo, calls, campaign, pricer) {
|
19
20
|
const { whitelistedSupplyTargetToken, totalSupply, blacklistedSupply } = this.handleWhiteListBlacklistRound5(typeInfo, campaign);
|
20
21
|
const symbolAsset = campaign.campaignParameters.symbolAsset;
|
21
|
-
|
22
|
+
let decimalsAsset = Number(campaign.campaignParameters.decimalsAsset) ?? 18;
|
22
23
|
const priceAsset = (await pricer.get({ symbol: symbolAsset })) ?? 1;
|
24
|
+
if (Number.isNaN(decimalsAsset)) {
|
25
|
+
log.warn(`decimalsAsset is NaN for ${symbolAsset} on campaign ${campaign.campaignId}`);
|
26
|
+
decimalsAsset = 18;
|
27
|
+
}
|
23
28
|
const totalAssets = BN2Number(typeInfo.totalAssets, decimalsAsset);
|
24
29
|
typeInfo.symbolUnderlyingToken = symbolAsset;
|
25
30
|
let cardName = generateCardName(type, typeInfo, campaign);
|
@@ -1 +1 @@
|
|
1
|
-
export
|
1
|
+
export {};
|
@@ -1,122 +1,6 @@
|
|
1
1
|
import { Redis } from "@/cache";
|
2
|
-
import {
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
import { ERC20Interface, EULER_ADDRESSES, EulerEVKInterface, EulerVaultLensInterface, NETWORK_LABELS, eulerChainIds, } from "@sdk";
|
8
|
-
import _ from "lodash";
|
9
|
-
async function computeCollatListAndReturnVaults(chainId, vaults) {
|
10
|
-
let vaultsPerChain = [];
|
11
|
-
/** Extra calls batch to get the collateral addresses */
|
12
|
-
const resCollat = await batchMulticallCallWithRetry(chainId, {
|
13
|
-
calls: vaults
|
14
|
-
.map(vault => vault.address)
|
15
|
-
.map(vaultAddress => {
|
16
|
-
return {
|
17
|
-
allowFailure: true,
|
18
|
-
callData: EulerVaultLensInterface.encodeFunctionData("getRecognizedCollateralsLTVInfo", [vaultAddress]),
|
19
|
-
target: EULER_ADDRESSES[chainId].VAULT_LENS,
|
20
|
-
};
|
21
|
-
}),
|
22
|
-
});
|
23
|
-
const callsCollatUnderlying = [];
|
24
|
-
const callsCollatUnderlyingSymbol = [];
|
25
|
-
for (const [index, vault] of vaults.entries()) {
|
26
|
-
const collatArray = EulerVaultLensInterface.decodeFunctionResult("getRecognizedCollateralsLTVInfo", resCollat[index].returnData)[0];
|
27
|
-
for (const collat of collatArray) {
|
28
|
-
if (!!vault.collaterals &&
|
29
|
-
vault.collaterals.map(c => c.address.toLowerCase()).includes(collat.collateral.toLowerCase()))
|
30
|
-
continue;
|
31
|
-
log.info(`🦭 found new collateral ${collat.collateral} for vault ${vault.address} (${NETWORK_LABELS[chainId]})`);
|
32
|
-
callsCollatUnderlying.push({
|
33
|
-
allowFailure: true,
|
34
|
-
callData: EulerEVKInterface.encodeFunctionData("asset"),
|
35
|
-
target: collat.collateral,
|
36
|
-
}, {
|
37
|
-
allowFailure: true,
|
38
|
-
callData: EulerEVKInterface.encodeFunctionData("symbol"),
|
39
|
-
target: collat.collateral,
|
40
|
-
});
|
41
|
-
}
|
42
|
-
}
|
43
|
-
const resCollatUnderlying = await batchMulticallCallWithRetry(chainId, {
|
44
|
-
calls: callsCollatUnderlying,
|
45
|
-
});
|
46
|
-
for (let i = 0; i < resCollatUnderlying.length; i = i + 2) {
|
47
|
-
const underlyingToken = EulerEVKInterface.decodeFunctionResult("asset", resCollatUnderlying[i].returnData)[0];
|
48
|
-
callsCollatUnderlyingSymbol.push({
|
49
|
-
allowFailure: true,
|
50
|
-
callData: ERC20Interface.encodeFunctionData("symbol"),
|
51
|
-
target: underlyingToken,
|
52
|
-
});
|
53
|
-
}
|
54
|
-
const resCollatUnderlyingSymbol = await batchMulticallCallWithRetry(chainId, {
|
55
|
-
calls: callsCollatUnderlyingSymbol,
|
56
|
-
});
|
57
|
-
vaultsPerChain = vaultsPerChain.concat((await Promise.all(vaults.map(async (vault, index) => {
|
58
|
-
const collatArray = EulerVaultLensInterface.decodeFunctionResult("getRecognizedCollateralsLTVInfo", resCollat[index].returnData)[0];
|
59
|
-
if (!vault.collaterals)
|
60
|
-
vault.collaterals = [];
|
61
|
-
let offset = 0;
|
62
|
-
for (const [_index, collat] of collatArray.entries()) {
|
63
|
-
// _ Check whether the collat was already registered
|
64
|
-
if (!!vault.collaterals &&
|
65
|
-
vault.collaterals.map(c => c.address.toLowerCase()).includes(collat.collateral.toLowerCase())) {
|
66
|
-
offset += 1;
|
67
|
-
continue;
|
68
|
-
}
|
69
|
-
const symbolUnderlying = ERC20Interface.decodeFunctionResult("symbol", resCollatUnderlyingSymbol[_index - offset].returnData)[0];
|
70
|
-
vault.collaterals.push({
|
71
|
-
address: collat.collateral,
|
72
|
-
symbolCollateral: EulerEVKInterface.decodeFunctionResult("symbol", resCollatUnderlying[2 * (_index - offset) + 1].returnData)[0],
|
73
|
-
symbolUnderlying,
|
74
|
-
borrowLTV: collat.borrowLTV.toString(),
|
75
|
-
nameCollateral: (await fetchEulerVaultName(collat.collateral, chainId)) ?? symbolUnderlying,
|
76
|
-
});
|
77
|
-
}
|
78
|
-
return { ...vault };
|
79
|
-
}))));
|
80
|
-
return vaultsPerChain;
|
81
|
-
}
|
82
|
-
export async function updateEulerVaultsCollatInDatabase() {
|
83
|
-
// 0_ Fetch all euler vaults from database
|
84
|
-
const vaults = await apiDbClient.logged.findMany({
|
85
|
-
where: { type: LoggedEntityType.EULER },
|
86
|
-
});
|
87
|
-
const clonedVaults = _.cloneDeep(vaults);
|
88
|
-
let toUpdateVaults = [];
|
89
|
-
// 1_ Return all vaults already stored with their collateral updated
|
90
|
-
const res = await Promise.all(eulerChainIds.map(async (chainId) => computeCollatListAndReturnVaults(chainId, clonedVaults.filter(entity => entity.chainId === chainId).map(entity => entity.entityData))));
|
91
|
-
for (const resPerChain of res) {
|
92
|
-
if (!!resPerChain && resPerChain.length > 0) {
|
93
|
-
toUpdateVaults = toUpdateVaults.concat(resPerChain.filter(updatedVault => {
|
94
|
-
return (updatedVault.collaterals.length >
|
95
|
-
vaults.find(vault => vault.address?.toLowerCase() === updatedVault.address.toLowerCase())
|
96
|
-
?.entityData?.collaterals.length);
|
97
|
-
}));
|
98
|
-
}
|
99
|
-
}
|
100
|
-
// 2_ Update the API database
|
101
|
-
if (toUpdateVaults.length > 0) {
|
102
|
-
try {
|
103
|
-
for (const vault of toUpdateVaults) {
|
104
|
-
await apiDbClient.logged.updateMany({
|
105
|
-
where: {
|
106
|
-
address: vault.address,
|
107
|
-
chainId: vault.chainId,
|
108
|
-
},
|
109
|
-
data: {
|
110
|
-
entityData: vault,
|
111
|
-
},
|
112
|
-
});
|
113
|
-
}
|
114
|
-
log.info(`✅ successfully updated ${toUpdateVaults.length} vault(s) collaterals in API database ('Logged' table)`);
|
115
|
-
}
|
116
|
-
catch {
|
117
|
-
throw new Error("Error while updating vaults to API database (`Logged` table)");
|
118
|
-
}
|
119
|
-
}
|
120
|
-
}
|
121
|
-
await updateEulerVaultsCollatInDatabase();
|
122
|
-
await Redis.safeSet("EulerV2Vaults", await getEulerV2Vaults());
|
2
|
+
import { getEulerV2Vaults, updateEulerVaultsCollatInDatabase } from "@/engine/dynamicData/utils/getEulerV2Vaults";
|
3
|
+
(async () => {
|
4
|
+
await Redis.safeSet("EulerV2Vaults", await getEulerV2Vaults());
|
5
|
+
await updateEulerVaultsCollatInDatabase();
|
6
|
+
})();
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,15 @@
|
|
1
|
+
export class IconService {
|
2
|
+
static async pullPush(url, bucket, metadata) {
|
3
|
+
const filename = metadata?.name ?? url;
|
4
|
+
const iconFile = await fetch(url);
|
5
|
+
const mimeType = iconFile.headers.get("content-type");
|
6
|
+
const extension = metadata?.extension ? metadata.extension : mimeType.split("/")[1].split("+")[0];
|
7
|
+
const byteArray = await iconFile.bytes();
|
8
|
+
return await bucket.pushRaw(`${filename}.${extension}`, byteArray, {
|
9
|
+
type: mimeType,
|
10
|
+
isPublic: true,
|
11
|
+
compression: true,
|
12
|
+
overwrite: true,
|
13
|
+
});
|
14
|
+
}
|
15
|
+
}
|
@@ -96,6 +96,10 @@ const blacklistEtherlink = [
|
|
96
96
|
"0x9D0E0e95305872E0f8065093b66E5FA224B5826f",
|
97
97
|
"0xa0E147eA78D8d696D73bbd43dE353b3ab076B3a0",
|
98
98
|
"0x196A8F57ff3AfB509f0014EDBa108A0BFeF0a84a",
|
99
|
+
"0x8F6dcd0db53029d1116E86DA6d38Bf047f504e08",
|
100
|
+
"0x1CC9F701399f586568F2B0498b137c561B288F6B",
|
101
|
+
"0xB387D0A73619791420De4a1e5e710023Cb0f49c0",
|
102
|
+
"0xA0fc58e4EE3a3E183dfa492147C97e81D42f5C86",
|
99
103
|
];
|
100
104
|
export var swapxCampaigns;
|
101
105
|
(function (swapxCampaigns) {
|
@@ -10,6 +10,7 @@ import { getAddress, parseUnits } from "viem";
|
|
10
10
|
import { BucketService } from "../bucket/bucket.service";
|
11
11
|
import { CacheService } from "../cache";
|
12
12
|
import { TTLPresets } from "../cache/cache.model";
|
13
|
+
import { IconService } from "../icon/icon.service";
|
13
14
|
import { PriceService } from "../price";
|
14
15
|
import { TokenRepository } from "./token.repository";
|
15
16
|
export class TokenService {
|
@@ -291,9 +292,9 @@ export class TokenService {
|
|
291
292
|
const bucket = new BucketService(`merkl-${env}-tokens`, `angle-${env}-1`);
|
292
293
|
const properties = body.data.properties;
|
293
294
|
const file = properties["Icon (Required)"].files[0];
|
294
|
-
const
|
295
|
-
const
|
296
|
-
const mimeType =
|
295
|
+
const iconURL = "external" in file ? file.external.url : file.file.url;
|
296
|
+
const icon = await fetch(iconURL);
|
297
|
+
const mimeType = icon.headers.get("content-type");
|
297
298
|
const extension = mimeType.split("/")[1].split("+")[0];
|
298
299
|
const address = throwOnInvalidRequiredAddress(properties["Address (in checksum format) (Required)"].rich_text[0].plain_text);
|
299
300
|
const chainId = properties["Chain ID (Required)"].number;
|
@@ -301,7 +302,6 @@ export class TokenService {
|
|
301
302
|
const displaySymbol = properties["Symbol (Optional)"].rich_text[0]?.plain_text;
|
302
303
|
const isVerified = properties.Verified.checkbox;
|
303
304
|
const coingeckoApiId = properties["CoinGecko API ID (Recommended)"].rich_text[0]?.plain_text;
|
304
|
-
const byteArray = await iconFile.bytes(); // Unknown type error here probably due to bun/types
|
305
305
|
const [token] = await TokenService.findManyOrCreate([
|
306
306
|
{
|
307
307
|
chainId,
|
@@ -311,15 +311,12 @@ export class TokenService {
|
|
311
311
|
if (!token || !token.name)
|
312
312
|
throw new HttpError(`Failed to fetch on-chain data for token ${token?.symbol} (${address} on chainId ${chainId}).`);
|
313
313
|
try {
|
314
|
-
await
|
315
|
-
type: mimeType,
|
316
|
-
isPublic: true,
|
317
|
-
});
|
314
|
+
await IconService.pullPush(iconURL, bucket, { name: `${chainId}/${address}` });
|
318
315
|
token.icon = `${process.env.GCS_ENDPOINT}/merkl-${env}-tokens/${chainId}/${address}.${extension}`;
|
319
316
|
}
|
320
317
|
catch (err) {
|
321
318
|
console.error(err);
|
322
|
-
token.icon =
|
319
|
+
token.icon = iconURL;
|
323
320
|
}
|
324
321
|
if (coingeckoApiId) {
|
325
322
|
try {
|
@@ -1,10 +1,4 @@
|
|
1
1
|
import { type Elysia } from "elysia";
|
2
|
-
export declare const response: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
3
|
-
address: import("@sinclair/typebox").TString;
|
4
|
-
asset: import("@sinclair/typebox").TString;
|
5
|
-
chaind: import("@sinclair/typebox").TNumber;
|
6
|
-
debtTokenAddress: import("@sinclair/typebox").TString;
|
7
|
-
}>>;
|
8
2
|
declare const _default: (app: Elysia) => Elysia<"", false, {
|
9
3
|
decorator: {};
|
10
4
|
store: {};
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import {
|
1
|
+
import { Redis } from "@/cache";
|
2
|
+
import { getEulerV2Vaults, updateEulerVaultsCollatInDatabase } from "@/engine/dynamicData/utils/getEulerV2Vaults";
|
2
3
|
import { t } from "elysia";
|
3
|
-
export const response = t.Array(t.Object({ address: t.String(), asset: t.String(), chaind: t.Number(), debtTokenAddress: t.String() }));
|
4
4
|
export default (app) => app
|
5
5
|
.get("/euler", async () => {
|
6
|
-
return await
|
6
|
+
return await Redis.getOrSet("EulerV2Vaults", getEulerV2Vaults);
|
7
7
|
}, {
|
8
8
|
query: t.Object({}),
|
9
9
|
tags: ["euler"],
|