Skip to content

Commit

Permalink
Release TW Extension v1.27 (#177)
Browse files Browse the repository at this point in the history
Merge pull request #177 from madfish-solutions/development
  • Loading branch information
alex-tsx authored Oct 18, 2024
2 parents e95969e + a24bcaa commit 058bc4a
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 432 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,5 @@ dist

# IDE
.idea

.DS_Store
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"author": "Inokentii Mazhara <[email protected]>",
"license": "MIT",
"dependencies": {
"@covalenthq/client-sdk": "^1.0.2",
"@covalenthq/client-sdk": "^2",
"@ethersproject/address": "^5.7.0",
"@ethersproject/hash": "^5.7.0",
"@ethersproject/strings": "^5.7.0",
Expand Down
12 changes: 4 additions & 8 deletions src/advertising/external-ads.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { satisfies as versionSatisfiesRange } from 'semver';

import { objectStorageMethodsFactory, redisClient } from '../redis';
import { objectStorageMethodsFactory, setStorageMethodsFactory } from '../redis';

/** Style properties names that are likely to be unnecessary for banners are skipped */
export const stylePropsNames = [
Expand Down Expand Up @@ -176,6 +176,7 @@ const PERMANENT_NATIVE_AD_PLACES_RULES_KEY = 'permanent_native_ad_places_rules';
const REPLACE_ADS_URLS_BLACKLIST_KEY = 'replace_ads_urls_blacklist';
const ELEMENTS_TO_HIDE_OR_REMOVE_KEY = 'elements_to_hide_or_remove';
const AD_PROVIDERS_CATEGORIES_KEY = 'ad_providers_categories';
const HYPELAB_CAMPAIGNS_BLACKLIST_KEY = 'hypelab_campaigns_blacklist';

export const adPlacesRulesMethods = objectStorageMethodsFactory<AdPlacesRule[]>(AD_PLACES_RULES_KEY, []);

Expand Down Expand Up @@ -210,13 +211,8 @@ export const adProvidersCategoriesMethods = objectStorageMethodsFactory<string[]
'crypto'
]);

export const getAdProvidersForAllSites = async () => redisClient.smembers(AD_PROVIDERS_ALL_SITES_KEY);

export const addAdProvidersForAllSites = async (providers: string[]) =>
redisClient.sadd(AD_PROVIDERS_ALL_SITES_KEY, ...providers);

export const removeAdProvidersForAllSites = async (providers: string[]) =>
redisClient.srem(AD_PROVIDERS_ALL_SITES_KEY, ...providers);
export const adProvidersForAllSitesMethods = setStorageMethodsFactory(AD_PROVIDERS_ALL_SITES_KEY);
export const hypelabCampaignsBlacklistMethods = setStorageMethodsFactory(HYPELAB_CAMPAIGNS_BLACKLIST_KEY);

const FALLBACK_VERSION = '0.0.0';

Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getPlatforms } from './notifications/utils/get-platforms.util';
import { redisClient } from './redis';
import { evmRouter } from './routers/evm';
import { adRulesRouter } from './routers/slise-ad-rules';
import { templeWalletAdsRouter } from './routers/temple-wallet-ads';
import { getTkeyStats } from './tkey-stats';
import { getABData } from './utils/ab-test';
import { cancelAliceBobOrder } from './utils/alice-bob/cancel-alice-bob-order';
Expand Down Expand Up @@ -343,6 +344,8 @@ app.use('/api/slise-ad-rules', adRulesRouter);

app.use('/api/evm', evmRouter);

app.use('/api/temple-wallet-ads', templeWalletAdsRouter);

app.post('/api/magic-square-quest/start', async (req, res) => {
try {
await startMagicSquareQuest(req.body);
Expand Down
6 changes: 6 additions & 0 deletions src/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ export const objectStorageMethodsFactory = <V, F = V>(storageKey: string, fallba
),
removeValues: (keys: string[]) => redisClient.hdel(storageKey, ...keys)
});

export const setStorageMethodsFactory = (storageKey: string) => ({
addValues: (values: string[]) => redisClient.sadd(storageKey, ...values),
removeValues: (values: string[]) => redisClient.srem(storageKey, ...values),
getAllValues: () => redisClient.smembers(storageKey)
});
104 changes: 71 additions & 33 deletions src/routers/evm/covalent.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,41 @@
import { ChainID, CovalentClient } from '@covalenthq/client-sdk';
import {
GoldRushClient,
ChainID,
GoldRushResponse,
GetTransactionsForAddressV3QueryParamOpts
} from '@covalenthq/client-sdk';
import retry from 'async-retry';

import { EnvVars } from '../../config';
import { CodedError } from '../../utils/errors';

const client = new CovalentClient(EnvVars.COVALENT_API_KEY, { enableRetry: false, threadCount: 10 });
const client = new GoldRushClient(EnvVars.COVALENT_API_KEY, { enableRetry: false, threadCount: 10 });

const RETRY_OPTIONS = { maxRetryTime: 30_000 };
const RETRY_OPTIONS: retry.Options = { maxRetryTime: 30_000 };

export const getEvmBalances = async (walletAddress: string, chainId: string) =>
await retry(
async () =>
/** For v2 only for now. No support in v3. */
const ACTIVITIES_PER_PAGE = 30;

export const getEvmBalances = (walletAddress: string, chainId: string) =>
retry(
() =>
client.BalanceService.getTokenBalancesForWalletAddress(Number(chainId) as ChainID, walletAddress, {
nft: true,
noNftAssetMetadata: true,
quoteCurrency: 'USD',
noSpam: false
}).then(({ data, error, error_message, error_code }) => {
if (error) {
throw new CodedError(Number(error_code) || 500, error_message);
}

return data;
}),
}).then(processGoldRushResponse),
RETRY_OPTIONS
);

export const getEvmTokensMetadata = async (walletAddress: string, chainId: string) =>
await retry(
async () =>
export const getEvmTokensMetadata = (walletAddress: string, chainId: string) =>
retry(
() =>
client.BalanceService.getTokenBalancesForWalletAddress(Number(chainId) as ChainID, walletAddress, {
nft: false,
quoteCurrency: 'USD',
noSpam: false
}).then(({ data, error, error_message, error_code }) => {
if (error) {
throw new CodedError(Number(error_code) || 500, error_message);
}

return data;
}),
}).then(processGoldRushResponse),
RETRY_OPTIONS
);

Expand All @@ -49,20 +45,62 @@ export const getEvmCollectiblesMetadata = async (walletAddress: string, chainId:
const withUncached = CHAIN_IDS_WITHOUT_CACHE_SUPPORT.includes(Number(chainId));

return await retry(
async () =>
() =>
client.NftService.getNftsForAddress(Number(chainId) as ChainID, walletAddress, {
withUncached,
noSpam: false
}).then(({ data, error, error_message, error_code }) => {
if (error) {
throw new CodedError(Number(error_code) || 500, error_message);
}

return data;
}),
}).then(processGoldRushResponse),
RETRY_OPTIONS
);
};

export const getStringifiedResponse = (response: any) =>
JSON.stringify(response, (_, value) => (typeof value === 'bigint' ? value.toString() : value));
export const getEvmAccountTransactions = (walletAddress: string, chainId: string, page?: number) =>
retry(async () => {
const options: GetTransactionsForAddressV3QueryParamOpts = {
// blockSignedAtAsc: true,
noLogs: false,
quoteCurrency: 'USD',
withSafe: false
};

const res = await (typeof page === 'number'
? client.TransactionService.getTransactionsForAddressV3(Number(chainId) as ChainID, walletAddress, page, options)
: client.TransactionService.getAllTransactionsForAddressByPage(
Number(chainId) as ChainID,
walletAddress,
options
));

return processGoldRushResponse(res);
}, RETRY_OPTIONS);

export const getEvmAccountERC20Transfers = (
walletAddress: string,
chainId: string,
contractAddress: string,
page?: number
) =>
retry(async () => {
const res = await client.BalanceService.getErc20TransfersForWalletAddressByPage(
Number(chainId) as ChainID,
walletAddress,
{
contractAddress,
quoteCurrency: 'USD',
pageNumber: page,
pageSize: ACTIVITIES_PER_PAGE
}
);

return processGoldRushResponse(res);
}, RETRY_OPTIONS);

function processGoldRushResponse<T>({ data, error, error_message, error_code }: GoldRushResponse<T>) {
if (error) {
const code = error_code && Number.isSafeInteger(Number(error_code)) ? Number(error_code) : 500;

throw new CodedError(code, error_message ?? 'Unknown error');
}

return JSON.stringify(data, (_, value) => (typeof value === 'bigint' ? value.toString() : value));
}
71 changes: 48 additions & 23 deletions src/routers/evm/index.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,69 @@
import { Router } from 'express';

import { withCodedExceptionHandler, withEvmQueryValidation } from '../../utils/express-helpers';
import { getEvmBalances, getEvmCollectiblesMetadata, getEvmTokensMetadata, getStringifiedResponse } from './covalent';
import { withCodedExceptionHandler } from '../../utils/express-helpers';
import {
evmQueryParamsSchema,
evmQueryParamsPaginatedSchema,
evmQueryParamsTransfersSchema
} from '../../utils/schemas';
import {
getEvmBalances,
getEvmCollectiblesMetadata,
getEvmTokensMetadata,
getEvmAccountTransactions,
getEvmAccountERC20Transfers
} from './covalent';

export const evmRouter = Router();

evmRouter
.get(
'/balances',
withCodedExceptionHandler(
withEvmQueryValidation(async (_1, res, _2, evmQueryParams) => {
const { walletAddress, chainId } = evmQueryParams;
withCodedExceptionHandler(async (req, res) => {
const { walletAddress, chainId } = await evmQueryParamsSchema.validate(req.query);

const data = await getEvmBalances(walletAddress, chainId);
const data = await getEvmBalances(walletAddress, chainId);

res.status(200).send(getStringifiedResponse(data));
})
)
res.status(200).send(data);
})
)
.get(
'/tokens-metadata',
withCodedExceptionHandler(
withEvmQueryValidation(async (_1, res, _2, evmQueryParams) => {
const { walletAddress, chainId } = evmQueryParams;
withCodedExceptionHandler(async (req, res) => {
const { walletAddress, chainId } = await evmQueryParamsSchema.validate(req.query);

const data = await getEvmTokensMetadata(walletAddress, chainId);
const data = await getEvmTokensMetadata(walletAddress, chainId);

res.status(200).send(getStringifiedResponse(data));
})
)
res.status(200).send(data);
})
)
.get(
'/collectibles-metadata',
withCodedExceptionHandler(
withEvmQueryValidation(async (_1, res, _2, evmQueryParams) => {
const { walletAddress, chainId } = evmQueryParams;
withCodedExceptionHandler(async (req, res) => {
const { walletAddress, chainId } = await evmQueryParamsSchema.validate(req.query);

const data = await getEvmCollectiblesMetadata(walletAddress, chainId);
const data = await getEvmCollectiblesMetadata(walletAddress, chainId);

res.status(200).send(getStringifiedResponse(data));
})
)
res.status(200).send(data);
})
)
.get(
'/transactions',
withCodedExceptionHandler(async (req, res) => {
const { walletAddress, chainId, page } = await evmQueryParamsPaginatedSchema.validate(req.query);

const data = await getEvmAccountTransactions(walletAddress, chainId, page);

res.status(200).send(data);
})
)
.get(
'/erc20-transfers',
withCodedExceptionHandler(async (req, res) => {
const { walletAddress, chainId, contractAddress, page } = await evmQueryParamsTransfersSchema.validate(req.query);

const data = await getEvmAccountERC20Transfers(walletAddress, chainId, contractAddress, page);

res.status(200).send(data);
})
);
47 changes: 13 additions & 34 deletions src/routers/slise-ad-rules/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import { Request, Router } from 'express';
import { identity } from 'lodash';

import {
addAdProvidersForAllSites,
getAdProvidersForAllSites,
removeAdProvidersForAllSites,
adProvidersForAllSitesMethods,
adProvidersMethods,
adProvidersByDomainRulesMethods,
AdProviderSelectorsRule,
filterRules,
AdProvidersByDomainRule,
adProvidersCategoriesMethods
} from '../../advertising/external-ads';
import { basicAuth } from '../../middlewares/basic-auth.middleware';
import { addObjectStorageMethodsToRouter, withBodyValidation, withExceptionHandler } from '../../utils/express-helpers';
import {
addObjectStorageMethodsToRouter,
addSetStorageMethodsToRouter,
withExceptionHandler
} from '../../utils/express-helpers';
import { isDefined, transformValues } from '../../utils/helpers';
import {
nonEmptyStringsListSchema,
Expand Down Expand Up @@ -204,35 +205,13 @@ export const adProvidersRouter = Router();
* '500':
* $ref: '#/components/responses/ErrorResponse'
*/
adProvidersRouter
.route('/all-sites')
.get(
withExceptionHandler(async (_req, res) => {
const providers = await getAdProvidersForAllSites();

res.status(200).header('Cache-Control', 'public, max-age=300').send(providers);
})
)
.post(
basicAuth,
withExceptionHandler(
withBodyValidation(nonEmptyStringsListSchema, async (req, res) => {
const providersAddedCount = await addAdProvidersForAllSites(req.body);

res.status(200).send({ message: `${providersAddedCount} providers have been added` });
})
)
)
.delete(
basicAuth,
withExceptionHandler(
withBodyValidation(nonEmptyStringsListSchema, async (req, res) => {
const providersRemovedCount = await removeAdProvidersForAllSites(req.body);

res.status(200).send({ message: `${providersRemovedCount} providers have been removed` });
})
)
);
addSetStorageMethodsToRouter(adProvidersRouter, {
path: '/all-sites',
methods: adProvidersForAllSitesMethods,
arrayValidationSchema: nonEmptyStringsListSchema,
successfulAdditionMessage: addedEntriesCount => `${addedEntriesCount} providers have been added`,
successfulRemovalMessage: removedEntriesCount => `${removedEntriesCount} providers have been removed`
});

/**
* @swagger
Expand Down
Loading

0 comments on commit 058bc4a

Please sign in to comment.