Loyalty Points & Planetary Interaction
Needs an access tokenDemonstrates loyalty point balances, LP store offers, planetary colonies, colony layouts, customs offices, and PI schematics.
REQUIRES AUTHENTICATION — set ESI_ACCESS_TOKEN in your environment.
Calls: loyalty.getLoyaltyPoints · loyalty.getLoyaltyStoreOffers · pi.getColonies · pi.getColonyLayout · pi.getCorporationCustomsOffices · pi.getSchematicInformation
Run it
bash
git clone https://github.com/lgriffin/ESI.ts.git && cd ESI.ts
npm ci
npm run example:loyalty-piexamples/loyalty-pi.ts on GitHub. The imports below are written as a consumer of the package writes them; the file in the repository imports from ../src.
Source
ts
import { EsiClient } from '@lgriffin/esi.ts';
import { EsiError } from '@lgriffin/esi.ts/errors';
import { createConsoleLogger } from '@lgriffin/esi.ts';
// The program's own output. The client logs through the same console sink
// at ESI_LOG_LEVEL (default warn), so its diagnostics stay out of the way.
const log = createConsoleLogger('info');
const esiLog = createConsoleLogger();
const CHARACTER_ID = 90439768;
const CORP_ID = 98135622;
const CONCORD_CORP_ID = 1000125;
const SAMPLE_SCHEMATIC_ID = 65;
async function main() {
const client = new EsiClient({ logger: esiLog });
try {
log.info('Loyalty Points & Planetary Interaction\n');
// --- Loyalty Points ---
log.info('Loyalty Points');
log.info('-'.repeat(50));
const lpBalances = await client.loyalty.getLoyaltyPoints(CHARACTER_ID);
log.info(` LP balances with ${lpBalances.length} corporation(s)`);
for (const lp of lpBalances.slice(0, 10)) {
log.info(
` Corp ${lp.corporation_id}: ${lp.loyalty_points?.toLocaleString() ?? 0} LP`,
);
}
if (lpBalances.length > 10)
log.info(` ... and ${lpBalances.length - 10} more`);
// --- LP Store (public) ---
log.info('\nLP Store Offers (CONCORD)');
log.info('-'.repeat(50));
const offers = await client.loyalty.getLoyaltyStoreOffers(CONCORD_CORP_ID);
log.info(` Total offers: ${offers.length}`);
for (const offer of offers.slice(0, 5)) {
log.info(
` Offer ${offer.offer_id}: type ${offer.type_id}, ${offer.lp_cost} LP + ${offer.isk_cost?.toLocaleString() ?? 0} ISK`,
);
}
if (offers.length > 5) log.info(` ... and ${offers.length - 5} more`);
// --- PI Colonies ---
log.info('\nPlanetary Colonies');
log.info('-'.repeat(50));
const colonies = await client.pi.getColonies(CHARACTER_ID);
log.info(` Active colonies: ${colonies.length}`);
for (const colony of colonies) {
log.info(
` Planet ${colony.planet_id}: ${colony.planet_type} (upgraded ${colony.upgrade_level}, pins: ${colony.num_pins})`,
);
try {
const layout = await client.pi.getColonyLayout(
CHARACTER_ID,
colony.planet_id,
);
const pinCount = layout.pins?.length ?? 0;
const linkCount = layout.links?.length ?? 0;
const routeCount = layout.routes?.length ?? 0;
log.info(
` Layout: ${pinCount} pins, ${linkCount} links, ${routeCount} routes`,
);
} catch (err) {
if (err instanceof EsiError && err.statusCode === 404) {
log.info(' Layout not available');
} else {
throw err;
}
}
}
if (colonies.length === 0) log.info(' No active PI colonies');
// --- Customs Offices (corp, may 403) ---
log.info('\nCorporation Customs Offices');
log.info('-'.repeat(50));
try {
const pocos = await client.pi.getCorporationCustomsOffices(CORP_ID);
log.info(` Customs offices: ${pocos.length}`);
} catch (err) {
if (
err instanceof EsiError &&
(err.statusCode === 403 || err.statusCode === 401)
) {
log.info(' Requires corporation roles — skipped');
} else {
throw err;
}
}
// --- PI Schematic (public) ---
log.info('\nPI Schematic');
log.info('-'.repeat(50));
const schematic =
await client.pi.getSchematicInformation(SAMPLE_SCHEMATIC_ID);
log.info(` Schematic ${SAMPLE_SCHEMATIC_ID}: ${schematic.schematic_name}`);
log.info(` Cycle time: ${schematic.cycle_time}s`);
} catch (err) {
if (
err instanceof EsiError &&
(err.statusCode === 401 || err.statusCode === 403)
) {
log.error('Authentication required. Set ESI_ACCESS_TOKEN.');
} else {
log.error('Request failed', { error: err });
}
process.exit(1);
} finally {
await client.shutdown();
}
}
main();