Query daily wallet rewards
Use this example to fetch the most recent UTC day of MOBILE rewards for every gateway owned by a Solana wallet. It calls GET /v0/solaccounts/{address}/gateways/mobile/rewards/sum with a daily bucket and prints totals plus PoC/Data splits for each gateway.
Prerequisites
- Node.js 18 or newer (ships with the Fetch API).
- An API key exported as
HELIUMGEEK_API_KEY. - A Solana wallet address provided as
SOLANA_WALLET_ADDRESS(orACCOUNT_ADDRESS) or supplied as the first CLI argument. - (Optional) Set
PAGE_LIMIT(orWALLET_PAGE_LIMIT) to override the default 1000 gateway page size while testing pagination.
Run the example
-
Download wallet-mobile-daily.js and save it locally.
-
Export the environment variables and run:
export HELIUMGEEK_API_KEY="your-api-key"
export SOLANA_WALLET_ADDRESS="your-wallet-address"
node wallet-mobile-daily.jsOr pass the address inline:
HELIUMGEEK_API_KEY="your-api-key" node wallet-mobile-daily.js <wallet-address>
Script
wallet-mobile-daily.js
#!/usr/bin/env node
const BASE_URL = (process.env.HELIUMGEEK_API_BASE_URL ?? 'https://api.heliumgeek.com/v0').replace(/\/$/, '');
const API_KEY = process.env.HELIUMGEEK_API_KEY;
const WALLET_ADDRESS =
(process.argv[2] ?? process.env.SOLANA_WALLET_ADDRESS ?? process.env.ACCOUNT_ADDRESS ?? '').trim();
const BASE_URL_OBJECT = new URL(`${BASE_URL}/`);
const PAGE_LIMIT = Number(process.env.WALLET_PAGE_LIMIT ?? process.env.PAGE_LIMIT ?? 100);
if (!API_KEY) {
console.error('Set HELIUMGEEK_API_KEY before running this script.');
process.exit(1);
}
if (!WALLET_ADDRESS) {
console.error('Provide the Solana wallet address as an argument or set SOLANA_WALLET_ADDRESS.');
process.exit(1);
}
async function main() {
const { minTime, maxTime } = previousUtcDayRange();
const rewardSums = await fetchGatewayRewardSums(minTime, maxTime);
console.log(`Fetched ${rewardSums.length} reward records for ${minTime.toISOString()} – ${maxTime.toISOString()}.`);
if (rewardSums.length === 0) {
console.log(
`Wallet ${WALLET_ADDRESS} earned no MOBILE rewards between ${minTime.toISOString()} and ${maxTime.toISOString()}.`
);
return;
}
rewardSums.sort((a, b) => Number(b.tokenSum ?? 0) - Number(a.tokenSum ?? 0));
console.log(`Mobile rewards by gateway for wallet ${WALLET_ADDRESS}`);
console.log(`Window: ${minTime.toISOString()} – ${maxTime.toISOString()}`);
console.log('='.repeat(80));
let walletTotal = 0;
for (const entry of rewardSums) {
walletTotal += Number(entry.tokenSum ?? 0);
report(entry);
}
console.log('-'.repeat(80));
console.log(`Wallet total: ${formatToken(walletTotal)} MOBILE`);
}
async function fetchGatewayRewardSums(minTime, maxTime) {
return await fetchPaginated(
`solaccounts/${encodeURIComponent(WALLET_ADDRESS)}/gateways/mobile/rewards/sum`,
{
min_time: minTime.toISOString(),
max_time: maxTime.toISOString(),
bucket: 'day',
limit: PAGE_LIMIT,
}
);
}
async function fetchPaginated(path, query = {}) {
const results = [];
let nextUrl = buildUrl(path, query);
let page = 1;
while (nextUrl) {
console.log(`[wallet-mobile-daily] Requesting page ${page}: ${nextUrl}`);
const response = await fetch(nextUrl, {
headers: {
'x-api-key': API_KEY,
},
});
if (response.status === 404) {
break;
}
if (!response.ok) {
throw new Error(`Request failed: ${response.status} ${response.statusText}`);
}
const payload = await response.json();
if (!payload?.data) {
break;
}
results.push(...payload.data);
nextUrl = payload.next ? new URL(payload.next, nextUrl).toString() : null;
page += 1;
}
return results;
}
function report(summary) {
const unit = (summary.unit ?? 'mobile').toUpperCase();
const pocShare = formatPercentage(summary.pocSum, summary.sum);
const dataShare = formatPercentage(summary.dcTransferSum, summary.sum);
console.log(
`${summary.address} — ${formatToken(summary.tokenSum)} ${unit} | PoC share ${pocShare} | Data share ${dataShare}`
);
}
function formatToken(value) {
if (value === undefined || value === null) {
return '0.0000';
}
return new Intl.NumberFormat('en-US', {
minimumFractionDigits: 4,
maximumFractionDigits: 4,
}).format(Number(value));
}
function formatPercentage(portion, total) {
const ratio =
Number(total ?? 0) > 0 ? (Number(portion ?? 0) / Number(total ?? 0)) * 100 : 0;
return `${ratio.toFixed(2)}%`;
}
function previousUtcDayRange() {
const end = startOfUtcDay(new Date());
const start = new Date(end);
start.setUTCDate(start.getUTCDate() - 1);
return { minTime: start, maxTime: end };
}
function startOfUtcDay(date) {
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
}
function buildUrl(path, query = {}) {
const url = /^https?:\/\//.test(path)
? new URL(path)
: new URL(path, BASE_URL_OBJECT);
applyQuery(url, query);
return url.toString();
}
function applyQuery(url, query = {}) {
Object.entries(query).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== '') {
url.searchParams.set(key, String(value));
}
});
}
main().catch(error => {
console.error(error.message);
process.exit(1);
});