@tinyburg/pocket-trains-sdk 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +8 -2
- package/dist/Endpoints.d.ts +201 -0
- package/dist/Endpoints.d.ts.map +1 -0
- package/dist/Endpoints.js +293 -0
- package/dist/Endpoints.js.map +1 -0
- package/dist/PocketTrains.d.ts +83 -0
- package/dist/PocketTrains.d.ts.map +1 -0
- package/dist/PocketTrains.js +172 -0
- package/dist/PocketTrains.js.map +1 -0
- package/dist/Scopes.d.ts +72 -0
- package/dist/Scopes.d.ts.map +1 -0
- package/dist/Scopes.js +80 -0
- package/dist/Scopes.js.map +1 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -3
- package/src/Endpoints.ts +325 -0
- package/src/PocketTrains.ts +186 -0
- package/src/Scopes.ts +89 -0
- package/src/index.ts +62 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pocket Trains SDK: signed calls against Nimblebit's NBSync service.
|
|
3
|
+
*
|
|
4
|
+
* Signing reuses `@tinyburg/nimblebit-sdk` (`NimblebitAuth`): the game secret
|
|
5
|
+
* salt (from `NBSync._ss`) is provided as the auth key, and each request is
|
|
6
|
+
* `md5(<preimage> + <secret salt>)` with a random uint32 `salt` in the path.
|
|
7
|
+
* All method preimages below are the Tiny Tower formula with the `pt` game code.
|
|
8
|
+
*
|
|
9
|
+
* The methods that were exercised live against sync.nimblebit.com are marked
|
|
10
|
+
* VERIFIED; save-bearing / write paths follow the same pattern but were not
|
|
11
|
+
* exercised. Save bytes are returned raw (base64-decoded); inflating (pako) and
|
|
12
|
+
* parsing into a save schema is left to the caller.
|
|
13
|
+
*
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
* @category SDK
|
|
16
|
+
*/
|
|
17
|
+
import * as Effect from "effect/Effect";
|
|
18
|
+
import * as Function from "effect/Function";
|
|
19
|
+
import { HttpClient, HttpClientRequest } from "effect/http";
|
|
20
|
+
import { HttpApiClient } from "effect/http-api";
|
|
21
|
+
import * as Redacted from "effect/Redacted";
|
|
22
|
+
import { NimblebitAuth, NimblebitError } from "@tinyburg/nimblebit-sdk";
|
|
23
|
+
import * as Endpoints from "./Endpoints.js";
|
|
24
|
+
/**
|
|
25
|
+
* Requests a new player ("burnbot") from the Nimblebit servers. VERIFIED.
|
|
26
|
+
*
|
|
27
|
+
* @since 1.0.0
|
|
28
|
+
* @category SDK
|
|
29
|
+
*/
|
|
30
|
+
export const device_newPlayer = /*#__PURE__*/Effect.gen(function* () {
|
|
31
|
+
const nimblebitAuth = yield* NimblebitAuth.NimblebitAuth;
|
|
32
|
+
const httpClient = yield* HttpClient.HttpClient;
|
|
33
|
+
const maybeAddBearerToken = nimblebitAuth.host !== "https://sync.nimblebit.com" ? HttpClientRequest.bearerToken(nimblebitAuth.authKey) : Function.identity;
|
|
34
|
+
const endpoint = yield* HttpApiClient.endpoint(Endpoints.Api, {
|
|
35
|
+
baseUrl: nimblebitAuth.host,
|
|
36
|
+
group: "DeviceManagementGroup",
|
|
37
|
+
endpoint: "DeviceNewPlayer",
|
|
38
|
+
httpClient: HttpClient.mapRequest(httpClient, maybeAddBearerToken)
|
|
39
|
+
});
|
|
40
|
+
const salt1 = yield* nimblebitAuth.salt;
|
|
41
|
+
const salt2 = yield* nimblebitAuth.salt;
|
|
42
|
+
const hash = yield* nimblebitAuth.sign(`pt/${salt1}/${salt2}`);
|
|
43
|
+
const response = yield* endpoint({
|
|
44
|
+
params: {
|
|
45
|
+
salt1,
|
|
46
|
+
salt2,
|
|
47
|
+
hash
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
if ("error" in response) {
|
|
51
|
+
return yield* new NimblebitError.NimblebitError({
|
|
52
|
+
method: "DeviceNewPlayer",
|
|
53
|
+
module: "DeviceManagementGroup",
|
|
54
|
+
cause: response.error
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return response;
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Retrieves player details. VERIFIED.
|
|
61
|
+
*
|
|
62
|
+
* @since 1.0.0
|
|
63
|
+
* @category SDK
|
|
64
|
+
*/
|
|
65
|
+
export const device_playerDetails = /*#__PURE__*/Effect.fn("device_playerDetails")(function* ({
|
|
66
|
+
playerAuthKey,
|
|
67
|
+
playerId
|
|
68
|
+
}) {
|
|
69
|
+
const nimblebitAuth = yield* NimblebitAuth.NimblebitAuth;
|
|
70
|
+
const httpClient = yield* HttpClient.HttpClient;
|
|
71
|
+
const maybeAddBearerToken = nimblebitAuth.host !== "https://sync.nimblebit.com" ? HttpClientRequest.bearerToken(nimblebitAuth.authKey) : Function.identity;
|
|
72
|
+
const endpoint = yield* HttpApiClient.endpoint(Endpoints.Api, {
|
|
73
|
+
baseUrl: nimblebitAuth.host,
|
|
74
|
+
group: "DeviceManagementGroup",
|
|
75
|
+
endpoint: "DevicePlayerDetails",
|
|
76
|
+
httpClient: HttpClient.mapRequest(httpClient, maybeAddBearerToken)
|
|
77
|
+
});
|
|
78
|
+
const salt = yield* nimblebitAuth.salt;
|
|
79
|
+
const hash = yield* nimblebitAuth.sign(`pt/${playerId}/${salt}${Redacted.value(playerAuthKey)}`);
|
|
80
|
+
const response = yield* endpoint({
|
|
81
|
+
params: {
|
|
82
|
+
playerId,
|
|
83
|
+
salt,
|
|
84
|
+
hash
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
if ("error" in response) {
|
|
88
|
+
return yield* new NimblebitError.NimblebitError({
|
|
89
|
+
method: "DevicePlayerDetails",
|
|
90
|
+
module: "DeviceManagementGroup",
|
|
91
|
+
cause: response.error
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return response.player;
|
|
95
|
+
});
|
|
96
|
+
/**
|
|
97
|
+
* Pulls the player's cloud save. Returns raw base64-decoded bytes (inflate +
|
|
98
|
+
* parse separately). Success envelope DERIVED from Tiny Tower.
|
|
99
|
+
*
|
|
100
|
+
* @since 1.0.0
|
|
101
|
+
* @category SDK
|
|
102
|
+
*/
|
|
103
|
+
export const sync_pullSave = /*#__PURE__*/Effect.fn("sync_pullSave")(function* ({
|
|
104
|
+
playerAuthKey,
|
|
105
|
+
playerId
|
|
106
|
+
}) {
|
|
107
|
+
const nimblebitAuth = yield* NimblebitAuth.NimblebitAuth;
|
|
108
|
+
const httpClient = yield* HttpClient.HttpClient;
|
|
109
|
+
const maybeAddBearerToken = nimblebitAuth.host !== "https://sync.nimblebit.com" ? HttpClientRequest.bearerToken(nimblebitAuth.authKey) : Function.identity;
|
|
110
|
+
const endpoint = yield* HttpApiClient.endpoint(Endpoints.Api, {
|
|
111
|
+
baseUrl: nimblebitAuth.host,
|
|
112
|
+
group: "SyncManagementGroup",
|
|
113
|
+
endpoint: "SyncPullSave",
|
|
114
|
+
httpClient: HttpClient.mapRequest(httpClient, maybeAddBearerToken)
|
|
115
|
+
});
|
|
116
|
+
const salt = yield* nimblebitAuth.salt;
|
|
117
|
+
const hash = yield* nimblebitAuth.sign(`pt/${playerId}/${salt}${Redacted.value(playerAuthKey)}`);
|
|
118
|
+
const response = yield* endpoint({
|
|
119
|
+
params: {
|
|
120
|
+
playerId,
|
|
121
|
+
salt,
|
|
122
|
+
hash
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
if ("error" in response) {
|
|
126
|
+
return yield* new NimblebitError.NimblebitError({
|
|
127
|
+
method: "SyncPullSave",
|
|
128
|
+
module: "SyncManagementGroup",
|
|
129
|
+
cause: response.error
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return response;
|
|
133
|
+
});
|
|
134
|
+
/**
|
|
135
|
+
* Lists items (parts/gifts) waiting for the player. VERIFIED
|
|
136
|
+
* (`/get_items/pt/...` -> `{ success:"Found", gifts:[...] }`, no total).
|
|
137
|
+
*
|
|
138
|
+
* @since 1.0.0
|
|
139
|
+
* @category SDK
|
|
140
|
+
*/
|
|
141
|
+
export const social_getItems = /*#__PURE__*/Effect.fn("social_getItems")(function* ({
|
|
142
|
+
playerAuthKey,
|
|
143
|
+
playerId
|
|
144
|
+
}) {
|
|
145
|
+
const nimblebitAuth = yield* NimblebitAuth.NimblebitAuth;
|
|
146
|
+
const httpClient = yield* HttpClient.HttpClient;
|
|
147
|
+
const maybeAddBearerToken = nimblebitAuth.host !== "https://sync.nimblebit.com" ? HttpClientRequest.bearerToken(nimblebitAuth.authKey) : Function.identity;
|
|
148
|
+
const endpoint = yield* HttpApiClient.endpoint(Endpoints.Api, {
|
|
149
|
+
baseUrl: nimblebitAuth.host,
|
|
150
|
+
group: "SocialGroup",
|
|
151
|
+
endpoint: "SocialGetItems",
|
|
152
|
+
httpClient: HttpClient.mapRequest(httpClient, maybeAddBearerToken)
|
|
153
|
+
});
|
|
154
|
+
const salt = yield* nimblebitAuth.salt;
|
|
155
|
+
const hash = yield* nimblebitAuth.sign(`pt/${playerId}/${salt}${Redacted.value(playerAuthKey)}`);
|
|
156
|
+
const response = yield* endpoint({
|
|
157
|
+
params: {
|
|
158
|
+
playerId,
|
|
159
|
+
salt,
|
|
160
|
+
hash
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
if ("error" in response) {
|
|
164
|
+
return yield* new NimblebitError.NimblebitError({
|
|
165
|
+
method: "SocialGetItems",
|
|
166
|
+
module: "SocialGroup",
|
|
167
|
+
cause: response.error
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return response;
|
|
171
|
+
});
|
|
172
|
+
//# sourceMappingURL=PocketTrains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PocketTrains.js","names":[],"sources":["../src/PocketTrains.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/dist/Scopes.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The scopes the Pocket Trains api is guarded by, as a game-rooted tree, built with
|
|
3
|
+
* `@tinyburg/nimblebit-sdk`'s `defineGame`. Only the endpoints this sdk defines
|
|
4
|
+
* are covered; areas without both a read and a write side are left out until
|
|
5
|
+
* their endpoints exist.
|
|
6
|
+
*
|
|
7
|
+
* @since 1.0.0
|
|
8
|
+
* @category Scopes
|
|
9
|
+
*/
|
|
10
|
+
import { type Game, type ScopeDescription } from "@tinyburg/nimblebit-sdk/NimblebitScopes";
|
|
11
|
+
/**
|
|
12
|
+
* @since 1.0.0
|
|
13
|
+
* @category Games
|
|
14
|
+
*/
|
|
15
|
+
export declare const PocketTrains: Game & {
|
|
16
|
+
readonly areas: {
|
|
17
|
+
readonly device: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Area & {
|
|
18
|
+
readonly read: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Branch & {
|
|
19
|
+
readonly player_details: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
20
|
+
};
|
|
21
|
+
readonly write: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Branch & {
|
|
22
|
+
readonly verify_device: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
readonly social: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Area & {
|
|
26
|
+
readonly read: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Branch & {
|
|
27
|
+
readonly get_gifts_pt: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
28
|
+
readonly get_items: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
29
|
+
readonly pull_friend_game: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
30
|
+
readonly pull_friend_meta: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
31
|
+
};
|
|
32
|
+
readonly write: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Branch & {
|
|
33
|
+
readonly send_item: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The game's areas, by name, for annotating endpoints.
|
|
40
|
+
*
|
|
41
|
+
* @since 1.0.0
|
|
42
|
+
* @category Areas
|
|
43
|
+
*/
|
|
44
|
+
export declare const Device: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Area & {
|
|
45
|
+
readonly read: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Branch & {
|
|
46
|
+
readonly player_details: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
47
|
+
};
|
|
48
|
+
readonly write: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Branch & {
|
|
49
|
+
readonly verify_device: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
50
|
+
};
|
|
51
|
+
}, Social: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Area & {
|
|
52
|
+
readonly read: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Branch & {
|
|
53
|
+
readonly get_gifts_pt: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
54
|
+
readonly get_items: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
55
|
+
readonly pull_friend_game: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
56
|
+
readonly pull_friend_meta: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
57
|
+
};
|
|
58
|
+
readonly write: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Branch & {
|
|
59
|
+
readonly send_item: import("@tinyburg/nimblebit-sdk/NimblebitScopes").Leaf;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* @since 1.0.0
|
|
64
|
+
* @category Tree
|
|
65
|
+
*/
|
|
66
|
+
export declare const Games: ReadonlyArray<Game>;
|
|
67
|
+
/**
|
|
68
|
+
* @since 1.0.0
|
|
69
|
+
* @category Tree
|
|
70
|
+
*/
|
|
71
|
+
export declare const all: () => ReadonlyArray<ScopeDescription>;
|
|
72
|
+
//# sourceMappingURL=Scopes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Scopes.d.ts","sourceRoot":"","sources":["../src/Scopes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,gBAAgB,EAAc,MAAM,yCAAyC,CAAC;AAEvG;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;CAwCvB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAgB,MAAM;;;;;;;GAAU,MAAM;;;;;;;;;;CAAuB,CAAC;AAErE;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,aAAa,CAAC,IAAI,CAAkB,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,GAAG,QAAO,aAAa,CAAC,gBAAgB,CAY/C,CAAC"}
|
package/dist/Scopes.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The scopes the Pocket Trains api is guarded by, as a game-rooted tree, built with
|
|
3
|
+
* `@tinyburg/nimblebit-sdk`'s `defineGame`. Only the endpoints this sdk defines
|
|
4
|
+
* are covered; areas without both a read and a write side are left out until
|
|
5
|
+
* their endpoints exist.
|
|
6
|
+
*
|
|
7
|
+
* @since 1.0.0
|
|
8
|
+
* @category Scopes
|
|
9
|
+
*/
|
|
10
|
+
import { defineGame } from "@tinyburg/nimblebit-sdk/NimblebitScopes";
|
|
11
|
+
/**
|
|
12
|
+
* @since 1.0.0
|
|
13
|
+
* @category Games
|
|
14
|
+
*/
|
|
15
|
+
export const PocketTrains = /*#__PURE__*/defineGame({
|
|
16
|
+
name: "pockettrains",
|
|
17
|
+
description: "Pocket Trains",
|
|
18
|
+
read: {
|
|
19
|
+
description: "Everything in Pocket Trains that only looks"
|
|
20
|
+
},
|
|
21
|
+
write: {
|
|
22
|
+
description: "Everything in Pocket Trains that changes a player's game"
|
|
23
|
+
},
|
|
24
|
+
areas: {
|
|
25
|
+
device: {
|
|
26
|
+
description: "Player accounts and their devices",
|
|
27
|
+
read: {
|
|
28
|
+
description: "Look up player accounts",
|
|
29
|
+
leaves: {
|
|
30
|
+
player_details: "Look up a player's public profile details"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
write: {
|
|
34
|
+
description: "Change a player's account or devices",
|
|
35
|
+
leaves: {
|
|
36
|
+
verify_device: "Complete a device verification code"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
social: {
|
|
41
|
+
description: "Gifts, visits and friends",
|
|
42
|
+
read: {
|
|
43
|
+
description: "See gifts, visits and friends' games",
|
|
44
|
+
leaves: {
|
|
45
|
+
get_items: "See the items waiting for a player",
|
|
46
|
+
get_gifts_pt: "See the gifts waiting for a player",
|
|
47
|
+
pull_friend_game: "Download a friend's game data",
|
|
48
|
+
pull_friend_meta: "Fetch metadata about a player's friends"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
write: {
|
|
52
|
+
description: "Send and accept gifts and items",
|
|
53
|
+
leaves: {
|
|
54
|
+
send_item: "Send items to another player"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* The game's areas, by name, for annotating endpoints.
|
|
62
|
+
*
|
|
63
|
+
* @since 1.0.0
|
|
64
|
+
* @category Areas
|
|
65
|
+
*/
|
|
66
|
+
export const {
|
|
67
|
+
device: Device,
|
|
68
|
+
social: Social
|
|
69
|
+
} = PocketTrains.areas;
|
|
70
|
+
/**
|
|
71
|
+
* @since 1.0.0
|
|
72
|
+
* @category Tree
|
|
73
|
+
*/
|
|
74
|
+
export const Games = [PocketTrains];
|
|
75
|
+
/**
|
|
76
|
+
* @since 1.0.0
|
|
77
|
+
* @category Tree
|
|
78
|
+
*/
|
|
79
|
+
export const all = () => Games.flatMap(game => [game, game.read, game.write, ...Object.values(game.areas).flatMap(area => [area, area.read, ...area.read.children, area.write, ...area.write.children])]);
|
|
80
|
+
//# sourceMappingURL=Scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Scopes.js","names":[],"sources":["../src/Scopes.ts"],"sourcesContent":[null],"mappings":"AAAA;;;;;;;;;AAUA,SAA2C,UAAU,QAAQ,yCAAyC;AAEtG;;;;AAIA,OAAO,MAAM,YAAY,gBAAG,UAAU,CAAC;EACnC,IAAI,EAAE,cAAc;EACpB,WAAW,EAAE,eAAe;EAC5B,IAAI,EAAE;IAAE,WAAW,EAAE;EAA6C,CAAE;EACpE,KAAK,EAAE;IAAE,WAAW,EAAE;EAA0D,CAAE;EAClF,KAAK,EAAE;IACH,MAAM,EAAE;MACJ,WAAW,EAAE,mCAAmC;MAChD,IAAI,EAAE;QACF,WAAW,EAAE,yBAAyB;QACtC,MAAM,EAAE;UACJ,cAAc,EAAE;;OAEvB;MACD,KAAK,EAAE;QACH,WAAW,EAAE,sCAAsC;QACnD,MAAM,EAAE;UACJ,aAAa,EAAE;;;KAG1B;IACD,MAAM,EAAE;MACJ,WAAW,EAAE,2BAA2B;MACxC,IAAI,EAAE;QACF,WAAW,EAAE,sCAAsC;QACnD,MAAM,EAAE;UACJ,SAAS,EAAE,oCAAoC;UAC/C,YAAY,EAAE,oCAAoC;UAClD,gBAAgB,EAAE,+BAA+B;UACjD,gBAAgB,EAAE;;OAEzB;MACD,KAAK,EAAE;QACH,WAAW,EAAE,iCAAiC;QAC9C,MAAM,EAAE;UACJ,SAAS,EAAE;;;;;CAK9B,CAAC;AAEF;;;;;;AAMA,OAAO,MAAM;EAAE,MAAM,EAAE,MAAM;EAAE,MAAM,EAAE;AAAM,CAAE,GAAG,YAAY,CAAC,KAAK;AAEpE;;;;AAIA,OAAO,MAAM,KAAK,GAAwB,CAAC,YAAY,CAAC;AAExD;;;;AAIA,OAAO,MAAM,GAAG,GAAG,MACf,KAAK,CAAC,OAAO,CAAE,IAAI,IAAK,CACpB,IAAI,EACJ,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,KAAK,EACV,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAE,IAAI,IAAK,CAC3C,IAAI,EACJ,IAAI,CAAC,IAAI,EACT,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EACrB,IAAI,CAAC,KAAK,EACV,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CACzB,CAAC,CACL,CAAC","ignoreList":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Pocket Trains (game code `pt`) NBSync api endpoints.
|
|
6
|
+
*
|
|
7
|
+
* Signing: a random `salt` (signed int32) goes in the path, and `hash` is
|
|
8
|
+
* `md5(<preimage> + <game secret salt>)` with the preimage
|
|
9
|
+
* `pt/<playerId>/<salt><playerAuthKey>` (variants noted per endpoint). The
|
|
10
|
+
* secret salt is the value extracted from `NBSync._ss`.
|
|
11
|
+
*
|
|
12
|
+
* Verification (live server + Frida DTO inspection of the game, 2026-08-26):
|
|
13
|
+
* - Signing is MD5, server-validated (same scheme as Tiny Tower / Pocket
|
|
14
|
+
* Planes; the game computes SHA-256 only for the unauthenticated `register`).
|
|
15
|
+
* - Response envelopes VERIFIED by reading the game's DTO classes at runtime:
|
|
16
|
+
* register, player_details, sync/pull (NBSyncGameSaveResponse), current_version,
|
|
17
|
+
* verify_device, friend/pull_game, friend/pull_meta (meta is a flat
|
|
18
|
+
* Dictionary<String,Object> on pt), send_item (NBSyncItemsSendResponse),
|
|
19
|
+
* get_items (NBSyncItemsGetResponse: success/gifts, NO `total` unlike pp).
|
|
20
|
+
* `get_items` was also exercised live with a burnbot.
|
|
21
|
+
* - pt-specific gifting: `get_gifts_pt` -> NBSyncGetPTGiftResponse with
|
|
22
|
+
* NBSyncGetPTGift elements, plus a gift-id flow (NBSyncGetGiftIDResponse,
|
|
23
|
+
* `friend/pull_meta_gift_id`). The get_gifts_pt REQUEST params are UNCONFIRMED
|
|
24
|
+
* (the tried `/get_gifts_pt/pt/:playerId/:salt/:hash` form was rejected), so
|
|
25
|
+
* that endpoint is marked accordingly.
|
|
26
|
+
*
|
|
27
|
+
* Game-specific save/meta schemas are left as `Schema.Unknown` placeholders.
|
|
28
|
+
*
|
|
29
|
+
* @since 1.0.0
|
|
30
|
+
* @category Endpoints
|
|
31
|
+
*/
|
|
32
|
+
export * as Endpoints from "./Endpoints.ts";
|
|
33
|
+
/**
|
|
34
|
+
* Pocket Trains SDK: signed calls against Nimblebit's NBSync service.
|
|
35
|
+
*
|
|
36
|
+
* Signing reuses `@tinyburg/nimblebit-sdk` (`NimblebitAuth`): the game secret
|
|
37
|
+
* salt (from `NBSync._ss`) is provided as the auth key, and each request is
|
|
38
|
+
* `md5(<preimage> + <secret salt>)` with a random uint32 `salt` in the path.
|
|
39
|
+
* All method preimages below are the Tiny Tower formula with the `pt` game code.
|
|
40
|
+
*
|
|
41
|
+
* The methods that were exercised live against sync.nimblebit.com are marked
|
|
42
|
+
* VERIFIED; save-bearing / write paths follow the same pattern but were not
|
|
43
|
+
* exercised. Save bytes are returned raw (base64-decoded); inflating (pako) and
|
|
44
|
+
* parsing into a save schema is left to the caller.
|
|
45
|
+
*
|
|
46
|
+
* @since 1.0.0
|
|
47
|
+
* @category SDK
|
|
48
|
+
*/
|
|
49
|
+
export * as PocketTrains from "./PocketTrains.ts";
|
|
50
|
+
/**
|
|
51
|
+
* The scopes the Pocket Trains api is guarded by, as a game-rooted tree, built with
|
|
52
|
+
* `@tinyburg/nimblebit-sdk`'s `defineGame`. Only the endpoints this sdk defines
|
|
53
|
+
* are covered; areas without both a read and a write side are left out until
|
|
54
|
+
* their endpoints exist.
|
|
55
|
+
*
|
|
56
|
+
* @since 1.0.0
|
|
57
|
+
* @category Scopes
|
|
58
|
+
*/
|
|
59
|
+
export * as Scopes from "./Scopes.ts";
|
|
60
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAA;AAEjD;;;;;;;;GAQG;AACH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Pocket Trains (game code `pt`) NBSync api endpoints.
|
|
6
|
+
*
|
|
7
|
+
* Signing: a random `salt` (signed int32) goes in the path, and `hash` is
|
|
8
|
+
* `md5(<preimage> + <game secret salt>)` with the preimage
|
|
9
|
+
* `pt/<playerId>/<salt><playerAuthKey>` (variants noted per endpoint). The
|
|
10
|
+
* secret salt is the value extracted from `NBSync._ss`.
|
|
11
|
+
*
|
|
12
|
+
* Verification (live server + Frida DTO inspection of the game, 2026-08-26):
|
|
13
|
+
* - Signing is MD5, server-validated (same scheme as Tiny Tower / Pocket
|
|
14
|
+
* Planes; the game computes SHA-256 only for the unauthenticated `register`).
|
|
15
|
+
* - Response envelopes VERIFIED by reading the game's DTO classes at runtime:
|
|
16
|
+
* register, player_details, sync/pull (NBSyncGameSaveResponse), current_version,
|
|
17
|
+
* verify_device, friend/pull_game, friend/pull_meta (meta is a flat
|
|
18
|
+
* Dictionary<String,Object> on pt), send_item (NBSyncItemsSendResponse),
|
|
19
|
+
* get_items (NBSyncItemsGetResponse: success/gifts, NO `total` unlike pp).
|
|
20
|
+
* `get_items` was also exercised live with a burnbot.
|
|
21
|
+
* - pt-specific gifting: `get_gifts_pt` -> NBSyncGetPTGiftResponse with
|
|
22
|
+
* NBSyncGetPTGift elements, plus a gift-id flow (NBSyncGetGiftIDResponse,
|
|
23
|
+
* `friend/pull_meta_gift_id`). The get_gifts_pt REQUEST params are UNCONFIRMED
|
|
24
|
+
* (the tried `/get_gifts_pt/pt/:playerId/:salt/:hash` form was rejected), so
|
|
25
|
+
* that endpoint is marked accordingly.
|
|
26
|
+
*
|
|
27
|
+
* Game-specific save/meta schemas are left as `Schema.Unknown` placeholders.
|
|
28
|
+
*
|
|
29
|
+
* @since 1.0.0
|
|
30
|
+
* @category Endpoints
|
|
31
|
+
*/
|
|
32
|
+
export * as Endpoints from "./Endpoints.js";
|
|
33
|
+
/**
|
|
34
|
+
* Pocket Trains SDK: signed calls against Nimblebit's NBSync service.
|
|
35
|
+
*
|
|
36
|
+
* Signing reuses `@tinyburg/nimblebit-sdk` (`NimblebitAuth`): the game secret
|
|
37
|
+
* salt (from `NBSync._ss`) is provided as the auth key, and each request is
|
|
38
|
+
* `md5(<preimage> + <secret salt>)` with a random uint32 `salt` in the path.
|
|
39
|
+
* All method preimages below are the Tiny Tower formula with the `pt` game code.
|
|
40
|
+
*
|
|
41
|
+
* The methods that were exercised live against sync.nimblebit.com are marked
|
|
42
|
+
* VERIFIED; save-bearing / write paths follow the same pattern but were not
|
|
43
|
+
* exercised. Save bytes are returned raw (base64-decoded); inflating (pako) and
|
|
44
|
+
* parsing into a save schema is left to the caller.
|
|
45
|
+
*
|
|
46
|
+
* @since 1.0.0
|
|
47
|
+
* @category SDK
|
|
48
|
+
*/
|
|
49
|
+
export * as PocketTrains from "./PocketTrains.js";
|
|
50
|
+
/**
|
|
51
|
+
* The scopes the Pocket Trains api is guarded by, as a game-rooted tree, built with
|
|
52
|
+
* `@tinyburg/nimblebit-sdk`'s `defineGame`. Only the endpoints this sdk defines
|
|
53
|
+
* are covered; areas without both a read and a write side are left out until
|
|
54
|
+
* their endpoints exist.
|
|
55
|
+
*
|
|
56
|
+
* @since 1.0.0
|
|
57
|
+
* @category Scopes
|
|
58
|
+
*/
|
|
59
|
+
export * as Scopes from "./Scopes.js";
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,OAAO,KAAK,SAAS,MAAM,gBAAgB;AAE3C;;;;;;;;;;;;;;;;AAgBA,OAAO,KAAK,YAAY,MAAM,mBAAmB;AAEjD;;;;;;;;;AASA,OAAO,KAAK,MAAM,MAAM,aAAa","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinyburg/pocket-trains-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "api for the mobile game Pocket Trains by Nimblebit",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"nimblebit",
|
|
7
|
+
"pockettrains"
|
|
8
|
+
],
|
|
9
|
+
"homepage": "https://github.com/leonitousconforti/tinyburg",
|
|
10
|
+
"license": "GPL-3.0-only",
|
|
11
|
+
"author": "Leo Conforti <leo@leoconforti.us> (https://leoconforti.us)",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/leonitousconforti/tinyburg.git",
|
|
15
|
+
"directory": "packages/pocket-trains-sdk"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"src/**/*.ts",
|
|
19
|
+
"dist/**/*.js",
|
|
20
|
+
"dist/**/*.js.map",
|
|
21
|
+
"dist/**/*.d.ts",
|
|
22
|
+
"dist/**/*.d.ts.map"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"exports": {
|
|
27
|
+
"./package.json": "./package.json",
|
|
28
|
+
".": "./dist/index.js",
|
|
29
|
+
"./*": "./dist/*.js",
|
|
30
|
+
"./internal/*": null
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@tinyburg/nimblebit-sdk": "0.2.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@yielded/auth": "0.1.0-beta.47",
|
|
40
|
+
"effect": "4.1.1"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@yielded/auth": "0.1.0-beta.47",
|
|
44
|
+
"effect": "4.1.1"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc -b tsconfig.build.json && babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
|
|
48
|
+
"check": "tsc -b tsconfig.json",
|
|
49
|
+
"codegen": "build-utils prepare-v4"
|
|
50
|
+
}
|
|
6
51
|
}
|