Level up/down based on trading volume

In this post there’s an example of automatically leveling up a user account after successful verification:

I’m wondering if there are other plugins or modules that can automatically upgrade or downgrade a user’s account based on their trading volume for example, how much a user has traded in a month, and then dynamically adjust their account level accordingly.

Specifically:

  • Are there existing plugins for automatically adjusting user tiers based on trading activity?
  • Can this be customized (e.g., monthly reset, tier thresholds, etc.)?
4 Likes

+1
upgrading users based on activity/trade vol. would be useful as a plugin

3 Likes

+1, would also like this plugin

2 Likes

Below is a sample volume-based tier plugin.

It automatically upgrades or downgrades users based on their trading volume over a rolling 30-day period.

1. Tiers are defined statically

const TIERS = [
  { level: 1, min: 0 },
  { level: 2, min: 1000 },
  { level: 3, min: 10000 },
  { level: 4, min: 50000 }
];

Each tier sets:

  • level → the verification level

  • min → minimum required volume (in native currency)

You can adjust these thresholds as needed.

2. Rolling window

const VOLUME_WINDOW_DAYS = 30;

The plugin calculates total trading volume for each user within this period.

3. Automatic update

For each user:

  • It sums their trades (converted to native currency).

  • It determines the correct tier.

  • If their current level differs, it updates it.

The cron job runs daily, but you can change the schedule if needed.

This provides a simple, fully customizable way to implement volume-based tiering.

'use strict';

/**
 * Simple Static Volume-Based Tier Plugin
 *
 * - Calculates rolling 30-day trading volume
 * - Converts to native currency using oracle prices
 * - Automatically upgrades/downgrades users
 * - Runs once per day
 */

module.exports = async function () {
	const { loggerPlugin, toolsLib, moment, cron } = this;

	// -----------------------------
	// Static Configuration
	// -----------------------------

	const VOLUME_WINDOW_DAYS = 30;

	// Define tier thresholds here
	// Ordered from lowest to highest
	const TIERS = [
		{ level: 1, min: 0 },
		{ level: 2, min: 1000 },
		{ level: 3, min: 10000 },
		{ level: 4, min: 50000 }
	];

	// -----------------------------
	// Helpers
	// -----------------------------

	const determineLevelFromVolume = (volume) => {
		let level = TIERS[0].level;

		for (const tier of TIERS) {
			if (volume >= tier.min) {
				level = tier.level;
			}
		}

		return level;
	};

	const getOracleIndex = async () => {
		const coins = toolsLib.getKitCoins();
		return toolsLib.getAssetsPrices(
			coins,
			toolsLib.getKitConfig().native_currency
		);
	};

	const calculateUserTradeVolume = async (user_id, from, to) => {
		let volume = 0;

		const oracleIndex = await getOracleIndex();
		const native = toolsLib.getKitConfig().native_currency;

		const trades = await toolsLib.order.getAllUserTradesByKitId(
			user_id,
			null, null, null, null, null,
			from,
			to,
			'all'
		);

		for (const trade of (trades.data || [])) {
			let size = Number(trade.size) || 0;
			const base = trade.symbol.split('-')[0];

			if (base !== native) {
				const price = oracleIndex[base];
				if (!price || price <= 0) continue;
				size = size * price;
			}

			volume += size;
		}

		return volume;
	};

	// -----------------------------
	// Main Tier Logic
	// -----------------------------

	const runVolumeTiering = async () => {
		try {
			const now = moment().seconds(0).milliseconds(0);
			const from = now.clone().subtract(VOLUME_WINDOW_DAYS, 'days').toISOString();
			const to = now.toISOString();

			const users = await toolsLib.database.findAll('user', {
				where: { activated: true, flagged: false },
				raw: true,
				attributes: ['id', 'verification_level']
			});

			for (const user of users) {
				const volume = await calculateUserTradeVolume(user.id, from, to);
				const newLevel = determineLevelFromVolume(volume);

				if (user.verification_level !== newLevel) {
					loggerPlugin.info(
						`volume-tier update: user=${user.id} volume=${volume} ${user.verification_level} -> ${newLevel}`
					);

					await toolsLib.user.changeUserVerificationLevelById(
						user.id,
						newLevel
					);
				}
			}
		} catch (err) {
			loggerPlugin.error('runVolumeTiering error', err.message);
		}
	};

	// -----------------------------
	// Daily Execution (00:00 UTC)
	// -----------------------------

	cron.schedule('0 0 * * *', runVolumeTiering, {
		timezone: 'UTC'
	}).start();

	loggerPlugin.info('static volume-based tier plugin initialized');
};