Skip to content

Commit 95cebd1

Browse files
committed
🦺 server: filter notifications to known tokens only
1 parent 4418e19 commit 95cebd1

4 files changed

Lines changed: 329 additions & 19 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@exactly/server": patch
3+
---
4+
5+
🦺 filter notifications to known tokens only

‎cspell.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,13 @@
140140
"reentrancy",
141141
"rpid",
142142
"rustup",
143+
"sadd",
143144
"scannability",
145+
"scard",
144146
"serde",
145147
"simctl",
146148
"simplewebauthn",
149+
"sismember",
147150
"siwe",
148151
"sixalime",
149152
"solady",

‎server/hooks/activity.ts‎

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ import { eq, inArray } from "drizzle-orm";
1515
import { Hono } from "hono";
1616
import * as v from "valibot";
1717
import { bytesToBigInt, hexToBigInt } from "viem";
18+
import { anvil } from "viem/chains";
1819

20+
import chain from "@exactly/common/generated/chain";
1921
import {
2022
exaAccountFactoryAbi,
2123
exaPreviewerAbi,
@@ -33,6 +35,7 @@ import keeper from "../utils/keeper";
3335
import { sendPushNotification } from "../utils/onesignal";
3436
import { autoCredit } from "../utils/panda";
3537
import publicClient from "../utils/publicClient";
38+
import redis from "../utils/redis";
3639
import revertFingerprint from "../utils/revertFingerprint";
3740
import { track } from "../utils/segment";
3841
import validatorHook from "../utils/validatorHook";
@@ -117,25 +120,65 @@ export default new Hono().post(
117120
if (rawContract?.address && markets.has(rawContract.address)) continue;
118121
const asset = rawContract?.address ?? ETH;
119122
const underlying = asset === ETH ? WETH : asset;
120-
sendPushNotification({
121-
userId: account,
122-
headings: t("Funds received"),
123-
contents: t(
124-
marketsByAsset.has(underlying)
125-
? "{{amount}} received and instantly started earning yield"
126-
: "{{amount}} received",
127-
{
128-
amount: value
129-
? Object.fromEntries(
130-
Object.entries(f(value)).map(([language, amount]) => [
131-
language,
132-
assetSymbol ? `${amount} ${assetSymbol}` : amount,
133-
]),
134-
)
135-
: assetSymbol,
136-
},
137-
),
138-
}).catch((error: unknown) => captureException(error));
123+
let knownToken = true;
124+
if (chain.id !== anvil.id) {
125+
const key = `lifi:tokens:${chain.id}`;
126+
const address = underlying.toLowerCase();
127+
try {
128+
const [[, isMember], [, count]] = v.parse(
129+
v.tuple([v.tuple([v.null(), v.number()]), v.tuple([v.null(), v.number()])]),
130+
await redis.pipeline().sismember(key, address).scard(key).exec(),
131+
);
132+
if (!isMember) {
133+
if (count > 0) {
134+
knownToken = false;
135+
} else {
136+
const response = await fetch(`https://li.quest/v1/tokens?chains=${chain.id}`, {
137+
signal: AbortSignal.timeout(5000),
138+
});
139+
if (response.ok) {
140+
const { tokens } = v.parse(
141+
v.object({ tokens: v.record(v.string(), v.array(v.object({ address: v.string() }))) }),
142+
await response.json(),
143+
);
144+
const tokenList = (tokens[String(chain.id)] ?? []).map((t) => t.address.toLowerCase());
145+
if (tokenList.length > 0) {
146+
await redis
147+
.multi()
148+
.del(key)
149+
.sadd(key, ...tokenList)
150+
.expire(key, 120)
151+
.exec();
152+
knownToken = tokenList.includes(address);
153+
}
154+
}
155+
}
156+
}
157+
} catch (error: unknown) {
158+
captureException(error, { level: "error" });
159+
}
160+
}
161+
if (marketsByAsset.has(underlying) || knownToken) {
162+
sendPushNotification({
163+
userId: account,
164+
headings: t("Funds received"),
165+
contents: t(
166+
marketsByAsset.has(underlying)
167+
? "{{amount}} received and instantly started earning yield"
168+
: "{{amount}} received",
169+
{
170+
amount: value
171+
? Object.fromEntries(
172+
Object.entries(f(value)).map(([language, amount]) => [
173+
language,
174+
assetSymbol ? `${amount} ${assetSymbol}` : amount,
175+
]),
176+
)
177+
: assetSymbol,
178+
},
179+
),
180+
}).catch((error: unknown) => captureException(error));
181+
}
139182
accounts.add(account);
140183
}
141184
const { "sentry-trace": sentryTrace, baggage } = getTraceData();

0 commit comments

Comments
 (0)