Node.js bindings for the TapTap PC SDK, built with Rust and NAPI-RS.
Based on TapTap PC SDK v4.3.0.
- Game Ownership - Verify if users own your game or DLC
- User Authentication - OAuth authentication via TapTap
- Cloud Saves - Full cloud save support (create, update, download, delete)
- Achievements - Unlock achievements, increment step-based achievements, and open the achievements page
- Native Performance - Built with Rust and NAPI-RS
📚 View Full Documentation - Or run pnpm docs:dev to start locally.
pnpm add tapsdk-pcOr with npm/yarn:
npm install tapsdk-pc
yarn add tapsdk-pcimport { TapSdk, EventId, SystemState } from 'tapsdk-pc';
// Check if restart is needed (call before init)
if (TapSdk.restartAppIfNecessary('your_client_id')) {
process.exit(0); // TapTap will relaunch the game
}
// Initialize SDK
const sdk = new TapSdk('your_public_key');
// Check game ownership
if (!sdk.isGameOwned()) {
console.log('User does not own this game');
process.exit(1);
}
// Request authorization
sdk.authorize('public_profile');
// Listen for events (automatically polled in background)
sdk.on('event', (event) => {
switch (event.eventId) {
case EventId.AUTHORIZE_FINISHED:
if (event.token) {
console.log('Authorized! OpenID:', sdk.getOpenId());
}
break;
case EventId.SYSTEM_STATE_CHANGED:
if (event.state === SystemState.PLATFORM_SHUTDOWN) {
sdk.shutdown();
process.exit(0);
}
break;
}
});import { CloudSave, EventId } from 'tapsdk-pc';
const cloudSave = CloudSave.get();
// List saves
cloudSave.list(1);
// Create a save
cloudSave.create(2, {
name: 'save1',
summary: 'Chapter 1 completed',
playtime: 3600,
dataFilePath: './savegame.dat',
coverFilePath: './screenshot.png'
});
// Handle responses from the event stream
sdk.on('event', (event) => {
if (event.eventId === EventId.CLOUD_SAVE_LIST) {
console.log(`Found ${event.saves.length} saves`);
}
});import { Achievement, EventId } from 'tapsdk-pc';
const achievement = Achievement.get();
achievement.unlock(1, 'first_win');
achievement.increment(2, 'kill_100_enemies', 1);
achievement.showAchievements();
sdk.on('event', (event) => {
if (event.eventId === EventId.ACHIEVEMENT_UNLOCK) {
console.log('Achievement unlocked:', event.achievement?.name);
}
});tapsdk-pc-js/
├── docs/ # VitePress documentation
├── crates/
│ ├── tapsdk-pc-sys/ # Raw FFI bindings (bindgen)
│ │ └── sdk/ # Bundled SDK files (headers, DLL, lib)
│ └── tapsdk-pc/ # Safe Rust API
└── packages/
└── tapsdk-pc-js/ # Node.js bindings (NAPI-RS)
┌─────────────────────────────────────┐
│ JavaScript App │
│ (Node.js / Electron) │
├─────────────────────────────────────┤
│ tapsdk-pc-js │ ← NAPI-RS bindings
│ (Native Node module) │
├─────────────────────────────────────┤
│ tapsdk-pc │ ← Safe Rust wrapper
│ (High-level API) │
├─────────────────────────────────────┤
│ tapsdk-pc-sys │ ← Raw FFI (bindgen)
│ (Unsafe bindings) │
├─────────────────────────────────────┤
│ taptap_api.dll │ ← Native C library
└─────────────────────────────────────┘
- mise for project toolchain management
- Windows x64
- TapTap Client installed and running
- For building from source:
- Project tools installed via
mise install(Node.js 24, pnpm 10.28.2, Rust stable) - LLVM/Clang (for bindgen)
- Project tools installed via
mise installpnpm installcargo build --workspace --releasecd packages/tapsdk-pc-js
pnpm run buildpnpm docs:dev| Method | Description |
|---|---|
TapSdk.restartAppIfNecessary(clientId) |
Check if app needs restart |
new TapSdk(pubKey) |
Initialize the SDK |
TapSdk.isInitialized() |
Check if SDK is initialized |
sdk.getClientId() |
Get the client ID |
sdk.on('event', cb) |
Listen for SDK events |
sdk.off('event', cb) |
Remove event listener |
sdk.once('event', cb) |
Listen once for an event |
sdk.authorize(scopes) |
Request user authorization |
sdk.getOpenId() |
Get user's OpenID |
sdk.isGameOwned() |
Check if user owns game |
sdk.isDlcOwned(dlcId) |
Check if user owns DLC |
sdk.showDlcStore(dlcId) |
Open DLC store page |
sdk.shutdown() |
Shut down the SDK |
| Method | Description |
|---|---|
CloudSave.get() |
Get singleton instance |
cloudSave.list(requestId) |
List all saves |
cloudSave.create(requestId, request) |
Create a new save |
cloudSave.update(requestId, request) |
Update existing save |
cloudSave.delete(requestId, uuid) |
Delete a save |
cloudSave.getData(requestId, uuid, fileId) |
Download save data |
cloudSave.getCover(requestId, uuid, fileId) |
Download save cover |
| Method | Description |
|---|---|
Achievement.get() |
Get singleton instance |
achievement.unlock(requestId, achievementId) |
Unlock an achievement |
achievement.increment(requestId, achievementId, steps) |
Increment step-based achievement progress |
achievement.showAchievements() |
Open the TapTap achievements page |
| Event ID | Constant | Description |
|---|---|---|
| 1 | SYSTEM_STATE_CHANGED |
Platform online/offline/shutdown |
| 2002 | AUTHORIZE_FINISHED |
Auth flow completed |
| 4001 | GAME_PLAYABLE_STATUS_CHANGED |
Game ownership changed |
| 4002 | DLC_PLAYABLE_STATUS_CHANGED |
DLC ownership changed |
| 6001 | CLOUD_SAVE_LIST |
Save list response |
| 6002 | CLOUD_SAVE_CREATE |
Save created |
| 6003 | CLOUD_SAVE_UPDATE |
Save updated |
| 6004 | CLOUD_SAVE_DELETE |
Save deleted |
| 6005 | CLOUD_SAVE_GET_DATA |
Save data downloaded |
| 6006 | CLOUD_SAVE_GET_COVER |
Cover image downloaded |
| 7001 | ACHIEVEMENT_UNLOCK |
Achievement unlock response |
| 7002 | ACHIEVEMENT_INCREMENT |
Achievement increment response |
Contributions are welcome! Please read CONTRIBUTING.md for guidelines.
MIT