Monitor 10 Wallets
Canonical REST, SDK, and CLI starter for monitoring a fixed wallet set with recent activity, transactions, holdings, and token flows.
Canonical REST, SDK, and CLI starter for monitoring a fixed wallet set with recent activity, transactions, holdings, and token flows.
Use this guide when your job is not “explore one address” but “keep a fixed set of wallets under watch.”
This is the canonical public starter for that workflow across:
export MEZCAL_BASE_URL="https://<your-mezcal-host>/api"
export MEZCAL_API_KEY="mzk_test_your_key_here"
export MEZCAL_CHAIN="SN_MAIN"
export MEZCAL_WATCHED_WALLETS="0xwalletA,0xwalletB,0xwalletC,0xwalletD,0xwalletE,0xwalletF,0xwalletG,0xwalletH,0xwalletI,0xwalletJ"
export MEZCAL_WATCHED_TOKENS="0xstrkToken,0xethToken,0xusdcToken"
export MEZCAL_ACTIVITY_LIMIT="50"
export MEZCAL_TRANSACTION_LIMIT="50"
export MEZCAL_TRANSFER_LIMIT="100"
MEZCAL_BASE_URL should already include /api for hosted external access.
All examples below then call the normal /v1/* routes relative to that base.
Use REST first when you want the shortest path and need to see the exact wire behavior.
OUTPUT_DIR="${OUTPUT_DIR:-./mezcal-wallet-monitor-rest}"
mkdir -p "$OUTPUT_DIR"
IFS=',' read -r -a MEZCAL_WALLETS <<< "$MEZCAL_WATCHED_WALLETS"
IFS=',' read -r -a MEZCAL_TOKENS <<< "$MEZCAL_WATCHED_TOKENS"
for wallet in "${MEZCAL_WALLETS[@]}"; do
wallet="$(printf '%s' "$wallet" | xargs)"
curl -sS \
-H "X-Mezcal-Api-Key: $MEZCAL_API_KEY" \
"$MEZCAL_BASE_URL/v1/$MEZCAL_CHAIN/address/$wallet/activity?limit=$MEZCAL_ACTIVITY_LIMIT" \
> "$OUTPUT_DIR/${wallet}.activity.json"
curl -sS \
-H "X-Mezcal-Api-Key: $MEZCAL_API_KEY" \
"$MEZCAL_BASE_URL/v1/$MEZCAL_CHAIN/address/$wallet/transactions?limit=$MEZCAL_TRANSACTION_LIMIT" \
> "$OUTPUT_DIR/${wallet}.transactions.json"
curl -sS \
-H "X-Mezcal-Api-Key: $MEZCAL_API_KEY" \
"$MEZCAL_BASE_URL/v1/$MEZCAL_CHAIN/address/$wallet/token-holdings" \
> "$OUTPUT_DIR/${wallet}.holdings.json"
done
for token in "${MEZCAL_TOKENS[@]}"; do
token="$(printf '%s' "$token" | xargs)"
url="$MEZCAL_BASE_URL/v1/$MEZCAL_CHAIN/token/$token/transfers?limit=$MEZCAL_TRANSFER_LIMIT"
for wallet in "${MEZCAL_WALLETS[@]}"; do
wallet="$(printf '%s' "$wallet" | xargs)"
url="${url}&address=${wallet}"
done
curl -sS \
-H "X-Mezcal-Api-Key: $MEZCAL_API_KEY" \
"$url" \
> "$OUTPUT_DIR/${token}.transfers.json"
done
Use the SDK when this workflow belongs inside application code.
Save this as monitor-wallets.ts:
import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { createMezcalClient } from '@mezcal/sdk';
function requiredEnv(name: string): string {
const value = process.env[name]?.trim();
if (!value) throw new Error(`${name} is required`);
return value;
}
function csvEnv(name: string): string[] {
return requiredEnv(name)
.split(',')
.map((value) => value.trim())
.filter(Boolean);
}
const baseUrl = requiredEnv('MEZCAL_BASE_URL');
const apiKey = requiredEnv('MEZCAL_API_KEY');
const chainId = process.env.MEZCAL_CHAIN?.trim() || 'SN_MAIN';
const wallets = csvEnv('MEZCAL_WATCHED_WALLETS');
const tokens = csvEnv('MEZCAL_WATCHED_TOKENS');
const activityLimit = Number(process.env.MEZCAL_ACTIVITY_LIMIT || '50');
const transactionLimit = Number(process.env.MEZCAL_TRANSACTION_LIMIT || '50');
const transferLimit = Number(process.env.MEZCAL_TRANSFER_LIMIT || '100');
const outputDir = process.env.MEZCAL_OUTPUT_DIR?.trim() || './mezcal-wallet-monitor-sdk';
const mezcal = createMezcalClient({ apiKey, baseUrl, chainId });
await mkdir(outputDir, { recursive: true });
for (const wallet of wallets) {
const [activity, transactions, holdings] = await Promise.all([
mezcal.addressActivity(wallet, undefined, activityLimit),
mezcal.addressTransactions(wallet, undefined, transactionLimit),
mezcal.addressTokenHoldings(wallet),
]);
await writeFile(join(outputDir, `${wallet}.activity.json`), JSON.stringify(activity, null, 2));
await writeFile(
join(outputDir, `${wallet}.transactions.json`),
JSON.stringify(transactions, null, 2),
);
await writeFile(join(outputDir, `${wallet}.holdings.json`), JSON.stringify(holdings, null, 2));
}
for (const token of tokens) {
const transfers = await mezcal.tokenTransfers(token, {
addresses: wallets,
limit: transferLimit,
});
await writeFile(
join(outputDir, `${token}.transfers.json`),
JSON.stringify(transfers, null, 2),
);
}
Run it with:
npm install @mezcal/sdk@alpha
bun run ./monitor-wallets.ts
If you need a single typed summary layer, derive it from the activity, transactions, holdings, and filtered transfer reads above rather than depending on an unpublished batch helper.
Use that only as a top-level summary. Keep the activity, transactions, holdings, and transfer calls for the full monitoring view.
Use the CLI when you want repeatable shell commands, local JSON files, and no app code.
OUTPUT_DIR="${OUTPUT_DIR:-./mezcal-wallet-monitor-cli}"
mkdir -p "$OUTPUT_DIR"
IFS=',' read -r -a MEZCAL_WALLETS <<< "$MEZCAL_WATCHED_WALLETS"
IFS=',' read -r -a MEZCAL_TOKENS <<< "$MEZCAL_WATCHED_TOKENS"
for wallet in "${MEZCAL_WALLETS[@]}"; do
wallet="$(printf '%s' "$wallet" | xargs)"
mezcal --output-format json address-activity "$wallet" --limit "$MEZCAL_ACTIVITY_LIMIT" \
> "$OUTPUT_DIR/${wallet}.activity.json"
mezcal --output-format json address-transactions "$wallet" --limit "$MEZCAL_TRANSACTION_LIMIT" \
> "$OUTPUT_DIR/${wallet}.transactions.json"
mezcal --output-format json address-token-holdings "$wallet" \
> "$OUTPUT_DIR/${wallet}.holdings.json"
done
for token in "${MEZCAL_TOKENS[@]}"; do
token="$(printf '%s' "$token" | xargs)"
transfer_args=()
for wallet in "${MEZCAL_WALLETS[@]}"; do
wallet="$(printf '%s' "$wallet" | xargs)"
transfer_args+=(--address "$wallet")
done
mezcal --output-format json token-transfers "$token" \
"${transfer_args[@]}" \
--limit "$MEZCAL_TRANSFER_LIMIT" \
> "$OUTPUT_DIR/${token}.transfers.json"
done
If your workflow needs a single shell sanity check before the full loop:
mezcal status
mezcal address-activity "$(printf '%s' "$MEZCAL_WATCHED_WALLETS" | cut -d',' -f1)" --limit 10