Skip to content

Commit

Permalink
Add pseudo random jitter generator
Browse files Browse the repository at this point in the history
  • Loading branch information
deniszagumennov committed Nov 25, 2024
1 parent f16cb65 commit 3fdff9a
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 40 deletions.
Binary file modified bun.lockb
Binary file not shown.
8 changes: 6 additions & 2 deletions crawler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { getSigningCosmWasmClient } from '../lib/stargate';
import { validateOnChainContractInfo } from '../lib/validations/config';
import { getValidData } from '../types/utils';
import { dropletRuleSchema } from '../types/config/dropletRule';
import { getPseudoRandom, getTrueRandom } from './random';

const program = new Command();
program.option('--config <config>', 'Config file path', 'config.toml');
Expand Down Expand Up @@ -126,7 +127,10 @@ program

const assetsToGetPrice = new Set<string>();
const protocolIds = new Set<string>();
const timeShift = Math.random();
const timeShift =
config.random && config.random === 'pseudo'
? await getPseudoRandom(config.protocols['neutron']?.rpc)
: getTrueRandom();

for (const protocol of protocolsInDb) {
if (protocolIds.has(protocol.protocol_id)) {
Expand All @@ -140,7 +144,7 @@ program
assetsToGetPrice.add(assetId.split('_')[0]);
}

const jitter = (protocolObj.jitter * timeShift) | 0;
const jitter = Math.round(protocolObj.jitter * timeShift) | 0;
if (!jitter) {
logger.warn('Jitter is 0 for protocol %s', protocol.protocol_id);
}
Expand Down
26 changes: 26 additions & 0 deletions crawler/random.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Tendermint34Client } from '@cosmjs/tendermint-rpc';
import seedrandom from 'seedrandom';

const getTrueRandom = () => Math.random();

const uint8ArrayToHex = (array: Uint8Array): string =>
Array.from(array)
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('');

const getPseudoRandom = async (neutronRpc: string) => {
const client = await Tendermint34Client.connect(neutronRpc);
const status = await client.status();

const blockHeight = Math.floor(status.syncInfo.latestBlockHeight / 100) * 100;
const block = await client.block(blockHeight);
const blockHash = block?.blockId?.hash;
const hexHash = blockHash ? uint8ArrayToHex(blockHash) : undefined;

client.disconnect();

const rng = seedrandom(hexHash);
return rng();
};

export { getTrueRandom, getPseudoRandom };
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@trpc/server": "^10.45.2",
"@types/lodash": "^4.17.4",
"@types/pg": "^8.11.10",
"@types/seedrandom": "^3.0.8",
"bech32": "^2.0.0",
"commander": "^12.0.0",
"cosmjs-types": "^0.9.0",
Expand All @@ -36,6 +37,7 @@
"pm2": "^5.4.2",
"prom-client": "^15.1.2",
"rimraf": "^5.0.7",
"seedrandom": "^3.0.5",
"toml": "^3.0.0",
"zod": "^3.24.0-canary.20240523T174819"
},
Expand Down
23 changes: 18 additions & 5 deletions server/controllers/getDroplets/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { TRPCError } from '@trpc/server';
import { Client } from 'pg';

import {
tRPCGetDropletsRequest,
tRPCGetDropletsResponse,
} from '../../../types/tRPC/tRPCGetDroplets';
import { Logger } from 'pino';
import { connect } from '../../../db';

const getDroplets =
(db: Client, logger: Logger) =>
(config: any, logger: Logger) =>
async (req: tRPCGetDropletsRequest): Promise<tRPCGetDropletsResponse> => {
const db = await connect(true, config, logger);

const {
input: { address },
} = req;
Expand All @@ -18,8 +20,12 @@ const getDroplets =

let row = null;
try {
const result = await db.query(
'SELECT points + points_l1 + points_l2 as points, change, place FROM user_points_public WHERE address = $1 LIMIT 1',
const result = await db.query<{
points: number;
change: number;
place: number;
}>(
'SELECT (points + points_l1 + points_l2)::int as points, change::int as change, place::int as place FROM user_points_public WHERE address = $1 LIMIT 1',
[address],
);
row = result.rows[0];
Expand All @@ -29,6 +35,8 @@ const getDroplets =
(e as Error).message,
);

await db.end();

throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'Unexpected error occurred',
Expand All @@ -40,6 +48,9 @@ const getDroplets =
'Address %s not found in public user points table',
req.input.address,
);

await db.end();

throw new TRPCError({
code: 'NOT_FOUND',
message: 'Address not found',
Expand All @@ -49,7 +60,7 @@ const getDroplets =
let countResult;
try {
const countRes = await db.query(
'SELECT count(*) as total FROM user_points_public',
'SELECT count(*)::int as total FROM user_points_public',
);
countResult = countRes.rows[0];
} catch (e) {
Expand All @@ -62,6 +73,8 @@ const getDroplets =
code: 'INTERNAL_SERVER_ERROR',
message: 'Unexpected error occurred',
});
} finally {
await db.end();
}

if (!countResult) {
Expand Down
7 changes: 6 additions & 1 deletion server/controllers/getKVData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import {
tRPCGetKVDataRequest,
tRPCGetKVDataResponse,
} from '../../../types/tRPC/tRPCGetKVData';
import { connect } from '../../../db';

const getKVData =
(db: Client, logger: Logger) =>
(config: any, logger: Logger) =>
async (req: tRPCGetKVDataRequest): Promise<tRPCGetKVDataResponse> => {
const db = await connect(true, config, logger);

const {
input: { key },
} = req;
Expand All @@ -32,6 +35,8 @@ const getKVData =
code: 'INTERNAL_SERVER_ERROR',
message: 'Unexpected error occurred',
});
} finally {
await db.end();
}

if (!row) {
Expand Down
18 changes: 13 additions & 5 deletions server/controllers/getReferralCode/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import { TRPCError } from '@trpc/server';
import { Client } from 'pg';

import {
tRPCGetReferralCodeRequest,
tRPCGetReferralCodeResponse,
} from '../../../types/tRPC/tRPCGetReferralCode';
import { Logger } from 'pino';
import { connect } from '../../../db';

const UNEXPECTED_TRPC_ERROR = new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'Unexpected error occurred',
});

const getReferralCode =
(db: Client, logger: Logger) =>
(config: any, logger: Logger) =>
async (
req: tRPCGetReferralCodeRequest,
): Promise<tRPCGetReferralCodeResponse> => {
const db = await connect(true, config, logger);

const {
input: { address },
} = req;
Expand All @@ -30,9 +32,9 @@ const getReferralCode =
try {
const { rows } = await db.query(
`SELECT
uk.referral_code AS referralCode,
CASE WHEN b.address IS NULL THEN 0 ELSE 1 END AS blacklisted,
CASE WHEN uk.address IS NULL THEN 0 ELSE 1 END AS kycPassed
uk.referral_code AS "referralCode",
CASE WHEN b.address IS NULL THEN 0 ELSE 1 END AS "blacklisted",
CASE WHEN uk.address IS NULL THEN 0 ELSE 1 END AS "kycPassed"
FROM
(SELECT $1 AS address) f
LEFT JOIN blacklist b ON b.address = f.address
Expand All @@ -49,13 +51,16 @@ const getReferralCode =
);

throw UNEXPECTED_TRPC_ERROR;
} finally {
await db.end();
}

if (!row) {
logger.error(
'Referral code cannot be fetched for %s from user KYC table',
address,
);

throw new TRPCError({
code: 'UNPROCESSABLE_CONTENT',
message: 'Failed to fetch data',
Expand All @@ -66,6 +71,7 @@ const getReferralCode =

if (blacklisted) {
logger.error('The address %s is blacklisted', address);

throw new TRPCError({
code: 'FORBIDDEN',
message: 'This address is blacklisted',
Expand All @@ -74,6 +80,7 @@ const getReferralCode =

if (!kycPassed) {
logger.error('KYC is not passed for %s', address);

throw new TRPCError({
code: 'NOT_FOUND',
message: 'KYC is not passed',
Expand All @@ -85,6 +92,7 @@ const getReferralCode =
'KYC passed for %s but referral code not found in user KYC table',
address,
);

throw new TRPCError({
code: 'CONFLICT',
message: 'Referral code not found',
Expand Down
12 changes: 9 additions & 3 deletions server/controllers/getReferrals/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { TRPCError } from '@trpc/server';
import { Client } from 'pg';

import {
referral,
tRPCGetReferralsRequest,
tRPCGetReferralsResponse,
} from '../../../types/tRPC/tRPCGetReferrals';
import { Logger } from 'pino';
import { connect } from '../../../db';

const getReferrals =
(db: Client, config: any, logger: Logger) =>
(config: any, logger: Logger) =>
async (req: tRPCGetReferralsRequest): Promise<tRPCGetReferralsResponse> => {
const db = await connect(true, config, logger);

const {
input: { address },
} = req;
Expand All @@ -25,7 +27,7 @@ const getReferrals =
let rows: dbResponse[] | null = [];
try {
const queryResult = await db.query(
`SELECT r1.referral as l1Referral, r2.referral as l2Referral
`SELECT r1.referral as "l1Referral", r2.referral as "l2Referral"
FROM referrals r1
LEFT JOIN referrals r2 ON r2.referrer = r1.referral
WHERE r1.referrer = $1`,
Expand All @@ -42,6 +44,8 @@ const getReferrals =
code: 'INTERNAL_SERVER_ERROR',
message: 'Unexpected error occurred',
});
} finally {
await db.end();
}

if (!rows) {
Expand Down Expand Up @@ -93,6 +97,8 @@ const getReferrals =
});
}
}

console.log(referrals);
return { referrals };
};

Expand Down
11 changes: 9 additions & 2 deletions server/controllers/getReferrer/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { TRPCError } from '@trpc/server';
import { Client } from 'pg';

import {
tRPCGetReferrerRequest,
tRPCGetReferrerResponse,
} from '../../../types/tRPC/tRPCGetReferrer';
import { Logger } from 'pino';
import { connect } from '../../../db';

const getReferrer =
(db: Client, logger: Logger) =>
(config: any, logger: Logger) =>
async (req: tRPCGetReferrerRequest): Promise<tRPCGetReferrerResponse> => {
const db = await connect(true, config, logger);

const {
input: { referralCode },
} = req;
Expand All @@ -32,17 +34,22 @@ const getReferrer =
(e as Error).message,
);

await db.end();

throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'Unexpected error occurred',
});
} finally {
await db.end();
}

if (!row) {
logger.error(
'Referrer address for code %s not found in user KYC table',
referralCode,
);

throw new TRPCError({
code: 'NOT_FOUND',
message: 'Referrer not found',
Expand Down
12 changes: 8 additions & 4 deletions server/controllers/getRules/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Client } from 'pg';
import { Logger } from 'pino';
import { tRPCGetRulesResponse } from '../../../types/tRPC/tRPCGetRules';
import { TRPCError } from '@trpc/server';
import { connect } from '../../../db';

const getRules =
(db: Client, logger: Logger) => async (): Promise<tRPCGetRulesResponse> => {
(config: any, logger: Logger) => async (): Promise<tRPCGetRulesResponse> => {
logger.debug('Receiving request to get Droplet rules');

const db = await connect(true, config, logger);

type dbResponse = {
strategy: string;
description: string;
Expand All @@ -25,11 +27,11 @@ const getRules =
`SELECT
strategy,
description,
multiplier AS dropRate,
multiplier AS "dropRate",
chain,
status,
link,
link_text AS linkText,
link_text AS "linkText",
type,
featured
FROM user_points_rules
Expand All @@ -43,6 +45,8 @@ const getRules =
code: 'INTERNAL_SERVER_ERROR',
message: 'Unexpected error occurred',
});
} finally {
await db.end();
}

if (rows.length === 0) {
Expand Down
Loading

0 comments on commit 3fdff9a

Please sign in to comment.