@valoranchi/riot-client 0.3.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.
Files changed (283) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +644 -0
  3. package/dist/RiotClient.d.ts +36 -0
  4. package/dist/RiotClient.d.ts.map +1 -0
  5. package/dist/RiotClient.js +115 -0
  6. package/dist/RiotClient.js.map +1 -0
  7. package/dist/bin.d.ts +3 -0
  8. package/dist/bin.d.ts.map +1 -0
  9. package/dist/bin.js +4 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/catalogue/Catalogue.d.ts +69 -0
  12. package/dist/catalogue/Catalogue.d.ts.map +1 -0
  13. package/dist/catalogue/Catalogue.js +206 -0
  14. package/dist/catalogue/Catalogue.js.map +1 -0
  15. package/dist/catalogue/CatalogueStore.d.ts +14 -0
  16. package/dist/catalogue/CatalogueStore.d.ts.map +1 -0
  17. package/dist/catalogue/CatalogueStore.js +38 -0
  18. package/dist/catalogue/CatalogueStore.js.map +1 -0
  19. package/dist/catalogue/ValorantApi.d.ts +26 -0
  20. package/dist/catalogue/ValorantApi.d.ts.map +1 -0
  21. package/dist/catalogue/ValorantApi.js +126 -0
  22. package/dist/catalogue/ValorantApi.js.map +1 -0
  23. package/dist/catalogue/types.d.ts +173 -0
  24. package/dist/catalogue/types.d.ts.map +1 -0
  25. package/dist/catalogue/types.js +2 -0
  26. package/dist/catalogue/types.js.map +1 -0
  27. package/dist/cli.d.ts +18 -0
  28. package/dist/cli.d.ts.map +1 -0
  29. package/dist/cli.js +912 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/client/AccountService.d.ts +61 -0
  32. package/dist/client/AccountService.d.ts.map +1 -0
  33. package/dist/client/AccountService.js +319 -0
  34. package/dist/client/AccountService.js.map +1 -0
  35. package/dist/client/AccountValidator.d.ts +15 -0
  36. package/dist/client/AccountValidator.d.ts.map +1 -0
  37. package/dist/client/AccountValidator.js +49 -0
  38. package/dist/client/AccountValidator.js.map +1 -0
  39. package/dist/client/ChatValidator.d.ts +40 -0
  40. package/dist/client/ChatValidator.d.ts.map +1 -0
  41. package/dist/client/ChatValidator.js +154 -0
  42. package/dist/client/ChatValidator.js.map +1 -0
  43. package/dist/client/ClientContext.d.ts +16 -0
  44. package/dist/client/ClientContext.d.ts.map +1 -0
  45. package/dist/client/ClientContext.js +12 -0
  46. package/dist/client/ClientContext.js.map +1 -0
  47. package/dist/client/EventsService.d.ts +11 -0
  48. package/dist/client/EventsService.d.ts.map +1 -0
  49. package/dist/client/EventsService.js +54 -0
  50. package/dist/client/EventsService.js.map +1 -0
  51. package/dist/client/LiveMatchService.d.ts +18 -0
  52. package/dist/client/LiveMatchService.d.ts.map +1 -0
  53. package/dist/client/LiveMatchService.js +84 -0
  54. package/dist/client/LiveMatchService.js.map +1 -0
  55. package/dist/client/LoadoutValidator.d.ts +28 -0
  56. package/dist/client/LoadoutValidator.d.ts.map +1 -0
  57. package/dist/client/LoadoutValidator.js +330 -0
  58. package/dist/client/LoadoutValidator.js.map +1 -0
  59. package/dist/client/MatchService.d.ts +80 -0
  60. package/dist/client/MatchService.d.ts.map +1 -0
  61. package/dist/client/MatchService.js +199 -0
  62. package/dist/client/MatchService.js.map +1 -0
  63. package/dist/client/MatchValidator.d.ts +29 -0
  64. package/dist/client/MatchValidator.d.ts.map +1 -0
  65. package/dist/client/MatchValidator.js +81 -0
  66. package/dist/client/MatchValidator.js.map +1 -0
  67. package/dist/client/PartyService.d.ts +111 -0
  68. package/dist/client/PartyService.d.ts.map +1 -0
  69. package/dist/client/PartyService.js +460 -0
  70. package/dist/client/PartyService.js.map +1 -0
  71. package/dist/client/PartyValidator.d.ts +93 -0
  72. package/dist/client/PartyValidator.d.ts.map +1 -0
  73. package/dist/client/PartyValidator.js +390 -0
  74. package/dist/client/PartyValidator.js.map +1 -0
  75. package/dist/client/SessionManager.d.ts +28 -0
  76. package/dist/client/SessionManager.d.ts.map +1 -0
  77. package/dist/client/SessionManager.js +104 -0
  78. package/dist/client/SessionManager.js.map +1 -0
  79. package/dist/client/SocialService.d.ts +63 -0
  80. package/dist/client/SocialService.d.ts.map +1 -0
  81. package/dist/client/SocialService.js +185 -0
  82. package/dist/client/SocialService.js.map +1 -0
  83. package/dist/client/StoreService.d.ts +25 -0
  84. package/dist/client/StoreService.d.ts.map +1 -0
  85. package/dist/client/StoreService.js +88 -0
  86. package/dist/client/StoreService.js.map +1 -0
  87. package/dist/client/StoreValidator.d.ts +32 -0
  88. package/dist/client/StoreValidator.d.ts.map +1 -0
  89. package/dist/client/StoreValidator.js +111 -0
  90. package/dist/client/StoreValidator.js.map +1 -0
  91. package/dist/client/api.d.ts +323 -0
  92. package/dist/client/api.d.ts.map +1 -0
  93. package/dist/client/api.js +2 -0
  94. package/dist/client/api.js.map +1 -0
  95. package/dist/collection/AccountProgressionBuilder.d.ts +12 -0
  96. package/dist/collection/AccountProgressionBuilder.d.ts.map +1 -0
  97. package/dist/collection/AccountProgressionBuilder.js +132 -0
  98. package/dist/collection/AccountProgressionBuilder.js.map +1 -0
  99. package/dist/collection/CollectionBuilder.d.ts +19 -0
  100. package/dist/collection/CollectionBuilder.d.ts.map +1 -0
  101. package/dist/collection/CollectionBuilder.js +199 -0
  102. package/dist/collection/CollectionBuilder.js.map +1 -0
  103. package/dist/collection/ContentBuilder.d.ts +6 -0
  104. package/dist/collection/ContentBuilder.d.ts.map +1 -0
  105. package/dist/collection/ContentBuilder.js +36 -0
  106. package/dist/collection/ContentBuilder.js.map +1 -0
  107. package/dist/collection/CustomGameConfigsBuilder.d.ts +9 -0
  108. package/dist/collection/CustomGameConfigsBuilder.d.ts.map +1 -0
  109. package/dist/collection/CustomGameConfigsBuilder.js +49 -0
  110. package/dist/collection/CustomGameConfigsBuilder.js.map +1 -0
  111. package/dist/collection/FriendsBuilder.d.ts +12 -0
  112. package/dist/collection/FriendsBuilder.d.ts.map +1 -0
  113. package/dist/collection/FriendsBuilder.js +89 -0
  114. package/dist/collection/FriendsBuilder.js.map +1 -0
  115. package/dist/collection/GameSessionBuilder.d.ts +6 -0
  116. package/dist/collection/GameSessionBuilder.d.ts.map +1 -0
  117. package/dist/collection/GameSessionBuilder.js +11 -0
  118. package/dist/collection/GameSessionBuilder.js.map +1 -0
  119. package/dist/collection/LeaderboardBuilder.d.ts +9 -0
  120. package/dist/collection/LeaderboardBuilder.d.ts.map +1 -0
  121. package/dist/collection/LeaderboardBuilder.js +31 -0
  122. package/dist/collection/LeaderboardBuilder.js.map +1 -0
  123. package/dist/collection/LiveMatchBuilder.d.ts +22 -0
  124. package/dist/collection/LiveMatchBuilder.d.ts.map +1 -0
  125. package/dist/collection/LiveMatchBuilder.js +154 -0
  126. package/dist/collection/LiveMatchBuilder.js.map +1 -0
  127. package/dist/collection/LoadoutBuilder.d.ts +12 -0
  128. package/dist/collection/LoadoutBuilder.d.ts.map +1 -0
  129. package/dist/collection/LoadoutBuilder.js +126 -0
  130. package/dist/collection/LoadoutBuilder.js.map +1 -0
  131. package/dist/collection/LoadoutWriter.d.ts +32 -0
  132. package/dist/collection/LoadoutWriter.d.ts.map +1 -0
  133. package/dist/collection/LoadoutWriter.js +48 -0
  134. package/dist/collection/LoadoutWriter.js.map +1 -0
  135. package/dist/collection/MatchBuilder.d.ts +22 -0
  136. package/dist/collection/MatchBuilder.d.ts.map +1 -0
  137. package/dist/collection/MatchBuilder.js +209 -0
  138. package/dist/collection/MatchBuilder.js.map +1 -0
  139. package/dist/collection/MessagesBuilder.d.ts +11 -0
  140. package/dist/collection/MessagesBuilder.d.ts.map +1 -0
  141. package/dist/collection/MessagesBuilder.js +89 -0
  142. package/dist/collection/MessagesBuilder.js.map +1 -0
  143. package/dist/collection/MmrBuilder.d.ts +16 -0
  144. package/dist/collection/MmrBuilder.d.ts.map +1 -0
  145. package/dist/collection/MmrBuilder.js +134 -0
  146. package/dist/collection/MmrBuilder.js.map +1 -0
  147. package/dist/collection/PartyBuilder.d.ts +14 -0
  148. package/dist/collection/PartyBuilder.d.ts.map +1 -0
  149. package/dist/collection/PartyBuilder.js +37 -0
  150. package/dist/collection/PartyBuilder.js.map +1 -0
  151. package/dist/collection/PlayerSettingsBuilder.d.ts +6 -0
  152. package/dist/collection/PlayerSettingsBuilder.d.ts.map +1 -0
  153. package/dist/collection/PlayerSettingsBuilder.js +41 -0
  154. package/dist/collection/PlayerSettingsBuilder.js.map +1 -0
  155. package/dist/collection/QueueConfigBuilder.d.ts +6 -0
  156. package/dist/collection/QueueConfigBuilder.d.ts.map +1 -0
  157. package/dist/collection/QueueConfigBuilder.js +14 -0
  158. package/dist/collection/QueueConfigBuilder.js.map +1 -0
  159. package/dist/collection/RankResolver.d.ts +18 -0
  160. package/dist/collection/RankResolver.d.ts.map +1 -0
  161. package/dist/collection/RankResolver.js +91 -0
  162. package/dist/collection/RankResolver.js.map +1 -0
  163. package/dist/collection/StoreBuilder.d.ts +20 -0
  164. package/dist/collection/StoreBuilder.d.ts.map +1 -0
  165. package/dist/collection/StoreBuilder.js +153 -0
  166. package/dist/collection/StoreBuilder.js.map +1 -0
  167. package/dist/collection/StoreItemResolver.d.ts +14 -0
  168. package/dist/collection/StoreItemResolver.d.ts.map +1 -0
  169. package/dist/collection/StoreItemResolver.js +138 -0
  170. package/dist/collection/StoreItemResolver.js.map +1 -0
  171. package/dist/collection/StoreOffersBuilder.d.ts +12 -0
  172. package/dist/collection/StoreOffersBuilder.d.ts.map +1 -0
  173. package/dist/collection/StoreOffersBuilder.js +46 -0
  174. package/dist/collection/StoreOffersBuilder.js.map +1 -0
  175. package/dist/errors.d.ts +27 -0
  176. package/dist/errors.d.ts.map +1 -0
  177. package/dist/errors.js +52 -0
  178. package/dist/errors.js.map +1 -0
  179. package/dist/events/RiotEvents.d.ts +78 -0
  180. package/dist/events/RiotEvents.d.ts.map +1 -0
  181. package/dist/events/RiotEvents.js +284 -0
  182. package/dist/events/RiotEvents.js.map +1 -0
  183. package/dist/events/TypedEmitter.d.ts +10 -0
  184. package/dist/events/TypedEmitter.d.ts.map +1 -0
  185. package/dist/events/TypedEmitter.js +30 -0
  186. package/dist/events/TypedEmitter.js.map +1 -0
  187. package/dist/index.d.ts +11 -0
  188. package/dist/index.d.ts.map +1 -0
  189. package/dist/index.js +9 -0
  190. package/dist/index.js.map +1 -0
  191. package/dist/local/ChatApi.d.ts +21 -0
  192. package/dist/local/ChatApi.d.ts.map +1 -0
  193. package/dist/local/ChatApi.js +89 -0
  194. package/dist/local/ChatApi.js.map +1 -0
  195. package/dist/local/Lockfile.d.ts +10 -0
  196. package/dist/local/Lockfile.d.ts.map +1 -0
  197. package/dist/local/Lockfile.js +37 -0
  198. package/dist/local/Lockfile.js.map +1 -0
  199. package/dist/local/Presence.d.ts +4 -0
  200. package/dist/local/Presence.d.ts.map +1 -0
  201. package/dist/local/Presence.js +118 -0
  202. package/dist/local/Presence.js.map +1 -0
  203. package/dist/local/RegionResolver.d.ts +12 -0
  204. package/dist/local/RegionResolver.d.ts.map +1 -0
  205. package/dist/local/RegionResolver.js +51 -0
  206. package/dist/local/RegionResolver.js.map +1 -0
  207. package/dist/local/RiotClientLocalApi.d.ts +48 -0
  208. package/dist/local/RiotClientLocalApi.d.ts.map +1 -0
  209. package/dist/local/RiotClientLocalApi.js +218 -0
  210. package/dist/local/RiotClientLocalApi.js.map +1 -0
  211. package/dist/local/RiotSocket.d.ts +56 -0
  212. package/dist/local/RiotSocket.d.ts.map +1 -0
  213. package/dist/local/RiotSocket.js +196 -0
  214. package/dist/local/RiotSocket.js.map +1 -0
  215. package/dist/local/chatTypes.d.ts +115 -0
  216. package/dist/local/chatTypes.d.ts.map +1 -0
  217. package/dist/local/chatTypes.js +2 -0
  218. package/dist/local/chatTypes.js.map +1 -0
  219. package/dist/model/index.d.ts +756 -0
  220. package/dist/model/index.d.ts.map +1 -0
  221. package/dist/model/index.js +2 -0
  222. package/dist/model/index.js.map +1 -0
  223. package/dist/raw.d.ts +25 -0
  224. package/dist/raw.d.ts.map +1 -0
  225. package/dist/raw.js +24 -0
  226. package/dist/raw.js.map +1 -0
  227. package/dist/riot/HttpGateway.d.ts +14 -0
  228. package/dist/riot/HttpGateway.d.ts.map +1 -0
  229. package/dist/riot/HttpGateway.js +87 -0
  230. package/dist/riot/HttpGateway.js.map +1 -0
  231. package/dist/riot/ResponseCache.d.ts +15 -0
  232. package/dist/riot/ResponseCache.d.ts.map +1 -0
  233. package/dist/riot/ResponseCache.js +75 -0
  234. package/dist/riot/ResponseCache.js.map +1 -0
  235. package/dist/riot/RiotApi.d.ts +87 -0
  236. package/dist/riot/RiotApi.d.ts.map +1 -0
  237. package/dist/riot/RiotApi.js +305 -0
  238. package/dist/riot/RiotApi.js.map +1 -0
  239. package/dist/riot/Session.d.ts +24 -0
  240. package/dist/riot/Session.d.ts.map +1 -0
  241. package/dist/riot/Session.js +41 -0
  242. package/dist/riot/Session.js.map +1 -0
  243. package/dist/riot/types.d.ts +676 -0
  244. package/dist/riot/types.d.ts.map +1 -0
  245. package/dist/riot/types.js +17 -0
  246. package/dist/riot/types.js.map +1 -0
  247. package/package.json +68 -0
  248. package/schema/AccountXp.json +86 -0
  249. package/schema/BlockedPlayer.json +22 -0
  250. package/schema/ClientInfo.json +41 -0
  251. package/schema/Content.json +83 -0
  252. package/schema/ContractProgress.json +69 -0
  253. package/schema/Conversation.json +49 -0
  254. package/schema/CustomGameConfigs.json +64 -0
  255. package/schema/CustomGameSettings.json +46 -0
  256. package/schema/Favourite.json +22 -0
  257. package/schema/Friend.json +215 -0
  258. package/schema/FriendRequest.json +26 -0
  259. package/schema/GameSession.json +25 -0
  260. package/schema/Leaderboard.json +103 -0
  261. package/schema/LeaderboardEntry.json +75 -0
  262. package/schema/LiveMatch.json +354 -0
  263. package/schema/Loadout.json +241 -0
  264. package/schema/Match.json +494 -0
  265. package/schema/MatchSummary.json +38 -0
  266. package/schema/Message.json +48 -0
  267. package/schema/Mission.json +31 -0
  268. package/schema/Mmr.json +172 -0
  269. package/schema/Offer.json +163 -0
  270. package/schema/Order.json +177 -0
  271. package/schema/OwnedItems.json +308 -0
  272. package/schema/Participant.json +50 -0
  273. package/schema/Party.json +185 -0
  274. package/schema/PartyInvite.json +45 -0
  275. package/schema/PartyRequest.json +42 -0
  276. package/schema/Penalty.json +22 -0
  277. package/schema/Player.json +31 -0
  278. package/schema/PlayerSettings.json +76 -0
  279. package/schema/Premier.json +19 -0
  280. package/schema/QueueConfig.json +34 -0
  281. package/schema/RankChange.json +89 -0
  282. package/schema/Store.json +455 -0
  283. package/schema/Wallet.json +22 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matias Obezzi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,644 @@
1
+ # @valoranchi/riot-client
2
+
3
+ [![CI](https://github.com/Matias-Obezzi/valoranchi/actions/workflows/ci.yml/badge.svg)](https://github.com/Matias-Obezzi/valoranchi/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/@valoranchi/riot-client.svg)](https://www.npmjs.com/package/@valoranchi/riot-client)
5
+
6
+ A TypeScript library and command-line tool for reading the local signed-in Riot Client session and retrieving player inventory, loadout, wallet balances, friends roster, presence, chat messages, and storefront offers for VALORANT.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @valoranchi/riot-client
12
+ ```
13
+
14
+ Or run the CLI directly via npx:
15
+
16
+ ```bash
17
+ npx @valoranchi/riot-client whoami
18
+ ```
19
+
20
+ ## Node Usage
21
+
22
+ Import `RiotClient` and call any of the public view model methods:
23
+
24
+ ```ts
25
+ import { RiotClient } from "@valoranchi/riot-client";
26
+
27
+ const client = new RiotClient({ language: "en-US" });
28
+
29
+ // 1. Get signed-in player identity and region
30
+ const player = await client.account.whoami();
31
+ console.log(player);
32
+
33
+ // 2. Get full owned inventory (weapons, skins, chromas, buddies, etc.)
34
+ const collection = await client.account.ownedItems({ language: "en-US" });
35
+ console.log(collection);
36
+
37
+ // 3. Get currently equipped loadout
38
+ const loadout = await client.account.loadout();
39
+ console.log(loadout);
40
+
41
+ // 4. Get currency balances (VP, Radianite, Kingdom Credits)
42
+ const wallet = await client.account.wallet();
43
+ console.log(wallet);
44
+
45
+ // 5. Get friends roster and presence
46
+ const friends = await client.social.friends();
47
+ console.log(friends);
48
+
49
+ // 6. Get incoming/outgoing friend requests and blocked players
50
+ const requests = await client.social.friendRequests();
51
+ const blocked = await client.social.blocked();
52
+
53
+ // 7. Get conversations and messages
54
+ const conversations = await client.social.conversations();
55
+ const messages = await client.social.messages();
56
+
57
+ // 8. Get storefront rotation (daily, night market, bundles, accessories, radianite)
58
+ const store = await client.store.current({ language: "en-US" });
59
+ console.log(store);
60
+
61
+ // 9. Get recent match history summaries
62
+ const matchSummaries = await client.matches.list({ count: 5, queue: "competitive" });
63
+ console.log(matchSummaries);
64
+
65
+ // 10. Get full match details by match ID
66
+ if (matchSummaries.length > 0) {
67
+ const match = await client.matches.get(matchSummaries[0].id);
68
+ console.log(match);
69
+ }
70
+
71
+ // 11. Get competitive MMR breakdown and current rank
72
+ const mmr = await client.matches.mmr();
73
+ console.log(mmr);
74
+
75
+ // 12. Get rank change history (competitive rating updates)
76
+ const rankChanges = await client.matches.rankHistory({ count: 5 });
77
+ console.log(rankChanges);
78
+
79
+ // 13. Get live match state (pregame agent select, in-game, range, or none)
80
+ const live = await client.matches.live({ ranks: true });
81
+ console.log(live);
82
+
83
+ // 14. Get current party details and members
84
+ const party = await client.party.current();
85
+ console.log(party);
86
+
87
+ // 15. Progression and account data
88
+ const xp = await client.account.xp();
89
+ const contracts = await client.account.contracts();
90
+ const missions = await client.account.missions();
91
+ const penalties = await client.account.penalties();
92
+ const favourites = await client.account.favourites();
93
+ const session = await client.account.session();
94
+ const config = await client.account.config();
95
+
96
+ // 16. Store catalog and orders
97
+ const offers = await client.store.offers();
98
+
99
+ // 17. Matches for other players & competitive leaderboard
100
+ const otherMatches = await client.matches.listFor(puuid, { count: 5 });
101
+ const otherMmr = await client.matches.mmrFor(puuid);
102
+ const otherRankHistory = await client.matches.rankHistoryFor(puuid);
103
+ const leaderboard = await client.matches.leaderboard({ size: 10 });
104
+ const content = await client.matches.content();
105
+ const premier = await client.matches.premier();
106
+
107
+ // 18. Matchmaking queues and custom game configs
108
+ const queues = await client.party.queues();
109
+ const customGameConfigs = await client.party.customGameConfigs();
110
+
111
+ // 19. Agent select & match actions
112
+ await client.matches.selectAgent("Jett");
113
+ await client.matches.lockAgent("Jett");
114
+ await client.matches.dodge({ confirm: true });
115
+ await client.matches.leaveMatch({ confirm: true });
116
+
117
+ // 20. Party invitations & join requests
118
+ const invites = await client.party.invites();
119
+ await client.party.join(partyId);
120
+ await client.party.declineInvite(inviteId);
121
+ const requests = await client.party.requests();
122
+ await client.party.requestToJoin(partyId);
123
+ await client.party.declineRequest(requestId);
124
+
125
+ // 21. Custom games & party controls
126
+ await client.party.makeCustomGame();
127
+ await client.party.setCustomGameSettings({
128
+ map: "Ascent",
129
+ mode: "Standard",
130
+ server: "pdx",
131
+ rules: { AllowGameModifiers: true },
132
+ });
133
+ await client.party.setTeam(puuid, "TeamOne");
134
+ await client.party.startCustomGame();
135
+ await client.party.balanceTeams();
136
+ await client.party.makeDefault("competitive");
137
+ await client.party.setPreferredServers(["pdx", "sjc"]);
138
+ await client.party.setModerator(puuid, true);
139
+ await client.party.refresh();
140
+
141
+ // 22. Cloud Player Settings & Local API
142
+ const clientInfo = await client.account.client();
143
+ const participants = await client.social.participants();
144
+ const settings = await client.account.settings();
145
+ await client.account.saveSettings(settings, { confirm: true });
146
+
147
+ // 23. Raw escape hatches (unsupported surface)
148
+ const rawLocal = await client.local.get("/riotclient/region-locale");
149
+ const rawRiot = await client.riot.get("https://pd.na.a.pvp.net/account-xp/v1/players/" + puuid);
150
+
151
+ // Close the local loopback client agent when finished
152
+ await client.close();
153
+ ```
154
+
155
+ ## Migrating from 0.1
156
+
157
+ In 0.2.0, every method moved under its namespace (`account`, `social`, `store`, `matches`, `party`).
158
+
159
+ Five methods were also renamed:
160
+
161
+ - `client.store()` → `client.store.current()`
162
+ - `client.matches()` → `client.matches.list()`
163
+ - `client.match(id)` → `client.matches.get(id)`
164
+ - `client.liveMatch()` → `client.matches.live()`
165
+ - `client.party()` → `client.party.current()`
166
+
167
+ `client.events()` and `client.close()` remain on the root client.
168
+
169
+ ## Real-Time Events
170
+
171
+ Subscribe to live events emitted by the local Riot Client WebSocket: friend presence updates, friend requests, roster changes, chat messages, party changes, and game transitions (agent select, match start).
172
+
173
+ Events come from the local Riot Client loopback connection only and carry no authentication tokens.
174
+
175
+ ### Node Example
176
+
177
+ ```ts
178
+ import { RiotClient } from "@valoranchi/riot-client";
179
+
180
+ const client = new RiotClient();
181
+ const events = client.events();
182
+
183
+ events.on("connected", () => console.log("Connected to Riot Client"));
184
+ events.on("disconnected", () => console.log("Disconnected"));
185
+
186
+ events.on("friend:presence", ({ friend, change }) => {
187
+ console.log(`Friend ${friend.gameName} is now ${change} (${friend.presence.state})`);
188
+ });
189
+
190
+ events.on("message", (msg) => {
191
+ console.log(`[${msg.from.gameName}]: ${msg.body}`);
192
+ });
193
+
194
+ events.on("game", ({ phase, matchId }) => {
195
+ console.log(`Game phase: ${phase} (match ${matchId})`);
196
+ });
197
+
198
+ // Stop listening and close the local socket when finished
199
+ await client.close();
200
+ ```
201
+
202
+ ### CLI Command
203
+
204
+ Stream live events formatted as one JSON object per line until interrupted:
205
+
206
+ ```bash
207
+ riotclient watch
208
+ riotclient watch --only friend:presence,message,game
209
+ riotclient watch --raw
210
+ ```
211
+
212
+ ## CLI Usage
213
+
214
+ The package includes the `riotclient` binary.
215
+
216
+ ```bash
217
+ riotclient whoami
218
+ riotclient owned-items --language en-US --pretty
219
+ riotclient loadout
220
+ riotclient wallet
221
+ riotclient xp
222
+ riotclient contracts
223
+ riotclient missions
224
+ riotclient penalties
225
+ riotclient favourites
226
+ riotclient session
227
+ riotclient config
228
+ riotclient friends
229
+ riotclient friend-requests
230
+ riotclient blocked
231
+ riotclient conversations
232
+ riotclient messages --cid <conversation-id>
233
+ riotclient store --pretty
234
+ riotclient offers
235
+ riotclient order <order-id>
236
+ riotclient matches --count 5
237
+ riotclient match <match-id>
238
+ riotclient matches-for <puuid>
239
+ riotclient mmr --pretty
240
+ riotclient mmr-for <puuid>
241
+ riotclient rank-history --count 5
242
+ riotclient rank-history-for <puuid>
243
+ riotclient leaderboard --size 10
244
+ riotclient content
245
+ riotclient premier
246
+ riotclient party
247
+ riotclient queues
248
+ riotclient custom-game-configs
249
+ riotclient watch
250
+ ```
251
+
252
+ Example trimmed output from `riotclient whoami --pretty`:
253
+
254
+ ```json
255
+ {
256
+ "puuid": "4a7b9c1d-1234-5678-9abc-def012345678",
257
+ "gameName": "Player",
258
+ "tagLine": "NA1",
259
+ "region": "na",
260
+ "shard": "na",
261
+ "accountLevel": 128
262
+ }
263
+ ```
264
+
265
+ Example trimmed output from `riotclient live --ranks --pretty`:
266
+
267
+ ```json
268
+ {
269
+ "phase": "ingame",
270
+ "matchId": "c9284241-1234-5678-9abc-def012345678",
271
+ "queue": "competitive",
272
+ "ranked": true,
273
+ "map": {
274
+ "uuid": "7eaecc1b-4337-bbf6-6ab9-04b8f06b3319",
275
+ "name": "Ascent",
276
+ "path": "/Game/Maps/Ascent/Ascent"
277
+ },
278
+ "mode": "/Game/GameModes/Bomb/BombGameMode.BombGameMode_C",
279
+ "phaseEndsInMs": null,
280
+ "allies": [
281
+ {
282
+ "puuid": "4a7b9c1d-1234-5678-9abc-def012345678",
283
+ "gameName": "Player",
284
+ "tagLine": "NA1",
285
+ "incognito": false,
286
+ "team": "Blue",
287
+ "agent": {
288
+ "uuid": "add6443a-41bd-e414-f6ad-e58d267f4e95",
289
+ "name": "Jett",
290
+ "icon": "https://media.valorant-api.com/agents/add6443a-41bd-e414-f6ad-e58d267f4e95/displayicon.png",
291
+ "role": "Duelist"
292
+ },
293
+ "selection": "locked",
294
+ "accountLevel": 128,
295
+ "rank": {
296
+ "tier": 17,
297
+ "name": "Diamond 3",
298
+ "division": "3",
299
+ "icon": "https://media.valorant-api.com/competitivetiers/03621f52-4cd8-5e5e-4318-00a25e1144cd/17/largeicon.png",
300
+ "rating": 45
301
+ }
302
+ }
303
+ ],
304
+ "enemies": [],
305
+ "self": {
306
+ "puuid": "4a7b9c1d-1234-5678-9abc-def012345678",
307
+ "gameName": "Player",
308
+ "tagLine": "NA1",
309
+ "incognito": false,
310
+ "team": "Blue",
311
+ "agent": {
312
+ "uuid": "add6443a-41bd-e414-f6ad-e58d267f4e95",
313
+ "name": "Jett",
314
+ "icon": "https://media.valorant-api.com/agents/add6443a-41bd-e414-f6ad-e58d267f4e95/displayicon.png",
315
+ "role": "Duelist"
316
+ },
317
+ "selection": "locked",
318
+ "accountLevel": 128,
319
+ "rank": {
320
+ "tier": 17,
321
+ "name": "Diamond 3",
322
+ "division": "3",
323
+ "icon": "https://media.valorant-api.com/competitivetiers/03621f52-4cd8-5e5e-4318-00a25e1144cd/17/largeicon.png",
324
+ "rating": 45
325
+ }
326
+ }
327
+ }
328
+ ```
329
+
330
+ Example trimmed output from `riotclient store --pretty`:
331
+
332
+ ```json
333
+ {
334
+ "player": {
335
+ "puuid": "4a7b9c1d-1234-5678-9abc-def012345678",
336
+ "gameName": "Player",
337
+ "tagLine": "NA1",
338
+ "region": "na",
339
+ "shard": "na",
340
+ "accountLevel": 128
341
+ },
342
+ "fetchedAt": "2026-09-27T12:00:00.000Z",
343
+ "daily": {
344
+ "endsAt": "2026-09-28T00:00:00.000Z",
345
+ "offers": [
346
+ {
347
+ "offerId": "4324a482-47da-4521-b3b0-4dbfcfefd779",
348
+ "item": {
349
+ "kind": "skin",
350
+ "uuid": "8908f237-47b2-031a-e905-1a89c93cc8f5",
351
+ "name": "Prime Vandal",
352
+ "weapon": "Vandal",
353
+ "tier": {
354
+ "uuid": "e046854e-406c-37f4-6607-19a9ba8426fc",
355
+ "name": "Exclusive",
356
+ "rank": 5,
357
+ "icon": "https://media.valorant-api.com/contenttiers/exclusive.png"
358
+ },
359
+ "icon": "https://media.valorant-api.com/weaponskinlevels/7209796e-4f76-88c9-04fa-fb81498b5e9d/displayicon.png",
360
+ "levelUuid": "7209796e-4f76-88c9-04fa-fb81498b5e9d"
361
+ },
362
+ "cost": {
363
+ "currency": "Valorant Points",
364
+ "currencyUuid": "85ad13f7-3d1b-5128-9eb2-7cd8ee0b5741",
365
+ "amount": 1775
366
+ }
367
+ }
368
+ ]
369
+ },
370
+ "nightMarket": null,
371
+ "bundles": {
372
+ "endsAt": "2026-10-05T00:00:00.000Z",
373
+ "items": []
374
+ },
375
+ "accessories": null,
376
+ "radianite": []
377
+ }
378
+ ```
379
+
380
+ CLI exit codes:
381
+
382
+ - `0`: Success (JSON written to stdout)
383
+ - `2`: Riot Client is not running (`RIOT_CLIENT_NOT_RUNNING`)
384
+ - `3`: Riot Client is not ready yet (`RIOT_CLIENT_NOT_READY`)
385
+ - `4`: Region could not be resolved (`REGION_UNKNOWN`)
386
+ - `5`: Remote Riot API request failed (`RIOT_API_ERROR`)
387
+ - `6`: Local validation failed (`VALIDATION`)
388
+ - `1`: Unexpected failure
389
+
390
+ On failure, error information is formatted as `{ "error": { "code": string, "message": string, "reason"?: string, "details"?: object } }` and output to stderr.
391
+
392
+ ## Writes
393
+
394
+ All writes are validated locally against your inventory and catalogue before any network request reaches Riot. If an item is not owned, an instance is exhausted, a weapon mismatches, or a social target is invalid, a `ValidationError` is thrown immediately and no network request is sent.
395
+
396
+ ### Available Methods
397
+
398
+ #### Account Writes
399
+
400
+ - `client.account.equip(change: LoadoutChange): Promise<Loadout>`: Update equipped skins, skin levels, chromas, buddies, sprays, player card, title, level border, and incognito status.
401
+ - `client.account.equipCollection(skinUuids: string[]): Promise<Loadout>`: Equip a list of skin UUIDs (one per weapon) at their highest owned level and base chroma.
402
+ - `client.account.activateContract(contractId: string): Promise<ContractProgress[]>`: Activate an agent contract.
403
+ - `client.account.addFavourite(skinUuid: string): Promise<Favourite[]>`: Add weapon skin to favourites.
404
+ - `client.account.removeFavourite(skinUuid: string): Promise<Favourite[]>`: Remove weapon skin from favourites.
405
+ - `client.account.setActRankBadgeHidden(hidden: boolean): Promise<PlayerPrivacy>`: Hide or reveal act rank badge.
406
+ - `client.account.setLeaderboardAnonymized(anonymized: boolean): Promise<PlayerPrivacy>`: Anonymize or reveal leaderboard presence.
407
+
408
+ #### Social Writes
409
+
410
+ - `client.social.sendMessage(to, text): Promise<Message>`: Send a whisper or room message (target can be `{ puuid }`, `{ conversationId }`, or `{ riotId }`).
411
+ - `client.social.sendFriendRequest(riotId): Promise<FriendRequest[]>`: Send a friend request by `Name#Tag`.
412
+ - `client.social.acceptFriendRequest(puuid): Promise<Friend[]>`: Accept an incoming friend request.
413
+ - `client.social.declineFriendRequest(puuid): Promise<FriendRequest[]>`: Decline an incoming friend request.
414
+ - `client.social.cancelFriendRequest(puuid): Promise<FriendRequest[]>`: Cancel an outgoing friend request.
415
+ - `client.social.removeFriend(puuid): Promise<Friend[]>`: Remove a friend.
416
+ - `client.social.blockPlayer(target): Promise<BlockedPlayer[]>`: Block a player by PUUID or `Name#Tag`.
417
+ - `client.social.unblockPlayer(puuid): Promise<BlockedPlayer[]>`: Unblock a player.
418
+
419
+ > **Note on social player lookup**: Arbitrary player lookup by `Name#Tag` (`social.lookup`) is not supported because Riot's player-data (`pd`) service does not offer an endpoint for resolving Riot IDs without mutual friend presence or match history; this was intentionally omitted.
420
+
421
+ #### Store Writes
422
+
423
+ - `client.store.revealNightMarket(): Promise<Storefront>`: Reveal night market offers.
424
+ - `client.store.buy(target: { offerId: string } | { bundleId: string }, options: { confirm: boolean }): Promise<Order>`: Purchase a store offer or bundle.
425
+
426
+ > **WARNING: Purchasing spends real money or in-game currency (VP, Radianite, Kingdom Credits). All purchases require explicit confirmation: `{ confirm: true }` in code, or both `--yes` and `--confirm` in the CLI.**
427
+
428
+ #### Party Writes
429
+
430
+ - `client.party.invite(riotId): Promise<Party>`: Invite a player to the party by `Name#Tag`.
431
+ - `client.party.kick(puuid): Promise<Party>`: Remove a member from the party (owner only).
432
+ - `client.party.promote(puuid): Promise<Party>`: Transfer party ownership to another member.
433
+ - `client.party.createInviteCode(): Promise<Party>`: Generate an invite code for the party.
434
+ - `client.party.revokeInviteCode(): Promise<Party>`: Revoke the party's current invite code.
435
+ - `client.party.joinByCode(code): Promise<Party>`: Join a party using an alphanumeric invite code.
436
+ - `client.party.setReady(ready): Promise<Party>`: Set your ready status (`true` or `false`).
437
+ - `client.party.setQueue(queue): Promise<Party>`: Change party queue (validated against eligible queues).
438
+ - `client.party.setAccessibility(accessibility): Promise<Party>`: Set party accessibility (`"open"` or `"closed"`).
439
+ - `client.party.startMatchmaking(): Promise<Party>`: Enter matchmaking queue (requires all members ready and idle party).
440
+ - `client.party.stopMatchmaking(): Promise<Party>`: Cancel matchmaking queue.
441
+ - `client.party.leave(): Promise<Party>`: Leave your current party.
442
+
443
+ ### Account Validation Rules
444
+
445
+ - `contract-not-agent`: Thrown when attempting to activate a contract that is not an agent contract (e.g. battlepass, event).
446
+ - `agent-owned`: Thrown when activating a contract for an agent that is already unlocked.
447
+ - `contract-active`: Thrown when activating a contract that is already active.
448
+ - `not-favourite`: Thrown when removing a favourite that is not favorited.
449
+ - `already-favourite`: Thrown when adding a favourite that is already favorited.
450
+
451
+ ### Store Validation Rules
452
+
453
+ - `offer-not-in-store`: Thrown when purchasing an item/bundle not currently available in daily rotation, night market, or featured bundles.
454
+ - `already-owned`: Thrown when purchasing an item that is already owned.
455
+ - `insufficient-funds`: Thrown when account balance is lower than the offer cost.
456
+ - `confirm-required`: Thrown when purchasing without explicit confirmation (`--confirm`).
457
+ - `night-market-missing`: Thrown when revealing night market offers when no night market is active.
458
+ - `night-market-revealed`: Thrown when all night market offers are already revealed.
459
+
460
+ ### Party Validation Rules
461
+
462
+ Every party write is validated against the live party state before any request reaches Riot:
463
+
464
+ - `no-party`: Thrown when outside the client or the player has no active party.
465
+ - `not-owner`: Thrown when a non-owner attempts owner-restricted actions (`kick`, `promote`, `set-queue`, `set-accessibility`, `create-invite-code`, `revoke-invite-code`, `start-matchmaking`, `stop-matchmaking`).
466
+ - `not-a-member`: Thrown when caller is not in party, or when the kick/promote target is not in the party.
467
+ - `self-target`: Thrown when attempting to kick or promote yourself.
468
+ - `already-in-party`: Thrown when joining by code for a party the caller already belongs to.
469
+ - `queue-not-eligible`: Thrown when selecting a queue not present in `EligibleQueues`.
470
+ - `queue-restricted`: Thrown on matchmaking join when party has active queue ineligibilities.
471
+ - `party-not-idle`: Thrown when changing queue, inviting, changing accessibility, or joining matchmaking while party state is not `DEFAULT`.
472
+ - `not-matchmaking`: Thrown when stopping matchmaking while party state is not `MATCHMAKING`.
473
+ - `members-not-ready`: Thrown on matchmaking join when any party member has not set ready.
474
+ - `invalid-riot-id`: Thrown when inviting with a malformed `Name#Tag`.
475
+ - `invalid-code`: Thrown when invite code is not 6 to 12 alphanumeric characters.
476
+ - `invite-code-missing`: Thrown when revoking an invite code but none is active.
477
+ - `restricted`: Thrown on matchmaking join when party has active restriction penalty seconds.
478
+ - `invite-missing`: Thrown when joining or declining an invite that does not exist in player record.
479
+ - `request-missing`: Thrown when declining a join request that is not pending on the party.
480
+ - `not-custom-game`: Thrown when setting custom game settings, membership, or starting when party is not in custom game mode.
481
+ - `map-not-enabled`: Thrown when setting a custom game map that is not enabled in configs.
482
+ - `mode-not-enabled`: Thrown when setting a custom game mode that is not enabled in configs.
483
+ - `server-unknown`: Thrown when setting a custom game or preferred server that does not exist in ping info.
484
+ - `no-team-players`: Thrown when starting a custom game without any players on TeamOne or TeamTwo.
485
+
486
+ ### Agent Select & Match Validation Rules
487
+
488
+ - `not-in-pregame`: Thrown when selecting, locking, or dodging while not in pregame agent select.
489
+ - `unknown-agent`: Thrown when selecting or locking an agent UUID or name not present or non-playable in catalogue.
490
+ - `agent-not-owned`: Thrown when selecting or locking an agent not unlocked and not base content.
491
+ - `agent-locked-by-ally`: Thrown when attempting to select or lock an agent already locked by a teammate.
492
+ - `already-locked`: Thrown when selecting or locking after having already locked in an agent.
493
+ - `confirm-required`: Thrown when executing `dodge`, `leaveMatch`, or `saveSettings` without explicit confirmation.
494
+ - `not-in-match`: Thrown when attempting to leave a match while not in an active game.
495
+
496
+ ### Player Settings & Local API Caveats
497
+
498
+ - `game-not-running`: Thrown when accessing or saving cloud player settings without VALORANT running. The local endpoint requires basic authentication using the `-remoting-auth-token` passed to VALORANT's process launch arguments.
499
+ - **Settings synchronization**: VALORANT re-reads settings from Riot's cloud only upon process launch. Writing settings with `account.saveSettings()` updates the cloud copy, but if the in-game Settings menu is opened in a running VALORANT client, the game client will overwrite the cloud copy with its in-memory settings.
500
+ - **Own Presence Writes**: Updating own presence (`PUT /chat/v2/me`) is not supported by this client version and is skipped.
501
+ - **Raw Escape Hatches**: `client.local` and `client.riot` provide low-level HTTP access (`get`, `post`, `put`, `delete`) to local loopback and remote Riot endpoints respectively. This is provided as an escape hatch for unmodeled routes and is an unsupported surface.
502
+
503
+ ### Dry-Run by Default in CLI
504
+
505
+ In the CLI, every write command defaults to a **dry run**: it validates the operation locally, outputs the validated body (tokens excluded) as JSON to stdout, and exits 0 without executing any network mutations.
506
+
507
+ Pass `--yes` to execute the actual write:
508
+
509
+ ```bash
510
+ # Dry run: validates locally and prints the PUT body without sending
511
+ riotclient equip --card 0819fbcd-4bd4-c379-5384-52803440f2b2
512
+
513
+ # Execute the write
514
+ riotclient equip --card 0819fbcd-4bd4-c379-5384-52803440f2b2 --yes
515
+
516
+ # Store dry run: validates availability, ownership, and funds, printing purchase details
517
+ riotclient buy --offer 4324a482-47da-4521-b3b0-4dbfcfefd779
518
+
519
+ # Execute purchase (requires BOTH --yes and --confirm)
520
+ riotclient buy --offer 4324a482-47da-4521-b3b0-4dbfcfefd779 --yes --confirm
521
+ ```
522
+
523
+ If validation fails, the command exits with code `6` and writes the validation error to stderr:
524
+
525
+ ```json
526
+ {
527
+ "error": {
528
+ "code": "VALIDATION",
529
+ "reason": "card-not-owned",
530
+ "message": "Card is not owned",
531
+ "details": { "card": "00000000-0000-0000-0000-000000000000" }
532
+ }
533
+ }
534
+ ```
535
+
536
+ ## Raw Layer
537
+
538
+ Consumers that maintain their own domain models or view models can use the library's session handling, transport, raw endpoints, local API, socket, and validators without importing high-level models:
539
+
540
+ ```ts
541
+ import {
542
+ FileCatalogueStore,
543
+ HttpGateway,
544
+ MemoryCatalogueCache,
545
+ RiotApi,
546
+ SessionManager,
547
+ ValorantApi,
548
+ } from "@valoranchi/riot-client/raw";
549
+
550
+ const gateway = new HttpGateway();
551
+ const valorantApi = new ValorantApi(gateway, new MemoryCatalogueCache(), new FileCatalogueStore());
552
+ const sessions = new SessionManager({ valorantApi });
553
+
554
+ const session = await sessions.session();
555
+ const api = new RiotApi(gateway, session);
556
+
557
+ const loadout = await api.loadout();
558
+ console.log(loadout);
559
+ ```
560
+
561
+ > **Stability note**: The raw entry follows Riot's shapes and may change with the game.
562
+
563
+ ## From Other Languages
564
+
565
+ Any runtime can spawn the `riotclient` binary as a child process and parse stdout as JSON. Type definitions can be generated directly from the committed JSON Schemas in `schema/` using tools such as `quicktype`:
566
+
567
+ ```bash
568
+ npx quicktype schema/OwnedItems.json -o OwnedItems.cs --namespace Valoranchi
569
+ ```
570
+
571
+ Example C# snippet using `System.Diagnostics.Process`:
572
+
573
+ ```csharp
574
+ using System;
575
+ using System.Diagnostics;
576
+ using System.Text.Json;
577
+
578
+ var startInfo = new ProcessStartInfo
579
+ {
580
+ FileName = "riotclient",
581
+ Arguments = "whoami",
582
+ RedirectStandardOutput = true,
583
+ RedirectStandardError = true,
584
+ UseShellExecute = false,
585
+ CreateNoWindow = true,
586
+ };
587
+
588
+ using var process = Process.Start(startInfo);
589
+ string output = process.StandardOutput.ReadToEnd();
590
+ process.WaitForExit();
591
+
592
+ if (process.ExitCode == 0)
593
+ {
594
+ using var doc = JsonDocument.Parse(output);
595
+ Console.WriteLine($"Player: {doc.RootElement.GetProperty("gameName").GetString()}");
596
+ }
597
+ ```
598
+
599
+ ## How Authentication Works
600
+
601
+ 1. The local Riot Client creates a lockfile at `%LOCALAPPDATA%\Riot Games\Riot Client\Config\lockfile`.
602
+ 2. The library reads the lockfile port and basic authentication password.
603
+ 3. Credentials are exchanged with the loopback API over local TLS to obtain entitlements and access tokens.
604
+ 4. Active region and shard are resolved from product sessions or game logs.
605
+ 5. The resulting session headers authenticate subsequent requests directly to Riot PVP game servers.
606
+
607
+ ## Catalogue Cache
608
+
609
+ Names, images, bundles, and tiers come from valorant-api.com. The catalogue for each language is stored on disk, under `%LOCALAPPDATA%\valoranchi-riot-client\catalogue` on Windows and the system temp directory elsewhere, keyed by the game version, so it is downloaded once per patch. Pass `catalogueDir` to `RiotClient` to move it, or `null` to keep it in memory only.
610
+
611
+ ## Response Cache
612
+
613
+ Riot answers are fetched live by default. To reuse them for a while, pass `responseCache: { ttlMs: 60_000 }` to `RiotClient`, or `--cache 60` to the CLI. Entries are stored per player and endpoint under `%LOCALAPPDATA%\valoranchi-riot-client\responses`, hold only the response body, never a token, and are refetched once older than the TTL. Keep the TTL short: a purchase or a loadout change is invisible until it expires.
614
+
615
+ Chat data (friends, presence, friend requests, blocked players, conversations, and messages) comes directly from the local Riot Client loopback API and is never cached.
616
+
617
+ ## Token Host Rule
618
+
619
+ Access tokens and entitlements JWTs are strictly scoped. They may only ever be sent to hosts matching `*.pvp.net`, `*.riotgames.com`, or loopback `127.0.0.1`. The HTTP gateway enforces this policy and throws a `ForbiddenHostError` before sending any request that would transmit credentials to an unauthorized host. Requests to public endpoints such as `valorant-api.com` never carry authorization headers.
620
+
621
+ ## Releasing
622
+
623
+ Releases are published automatically to npm and GitHub Releases via GitHub Actions:
624
+
625
+ 1. Navigate to the **Actions** tab on GitHub and select the **Release** workflow.
626
+ 2. Click **Run workflow** (dispatch).
627
+ 3. Select the version bump (`patch`, `minor`, or `major`). You can optionally provide additional release notes.
628
+ 4. The workflow runs the full verification suite (lint, typecheck, tests, build, JSON schemas, and tarball contents).
629
+ 5. The `## [Unreleased]` section from `CHANGELOG.md` is automatically converted into the new version entry (`## [X.Y.Z] - YYYY-MM-DD`).
630
+ 6. `@valoranchi/riot-client` is published to npm with provenance first; only then the version commit and tag (`vX.Y.Z`) are pushed and a GitHub Release is created with the changelog notes. A failed publish leaves the repository untouched.
631
+
632
+ If a publish failed after the version was already committed (for example the npm token could not reach the scope), fix the cause and run the workflow again: it notices the tagged version is missing from npm and publishes it instead of bumping. The **Publish the version already in package.json** checkbox forces that mode.
633
+
634
+ The token check at the start of the workflow expects a granular npm token with **Read and write** on all packages of the `@valoranchi` organization. An npm `404` on publish means the scope does not exist for that token: the organization is missing or the token is limited to selected packages.
635
+
636
+ ## What It Does Not Do
637
+
638
+ - No automated gameplay, bots, or match orchestration
639
+ - No background telemetry or credential logging
640
+ - No unconfirmed store purchases (all purchases require explicit dual confirmation)
641
+
642
+ ## Disclaimer
643
+
644
+ This project is an unofficial tool and is not endorsed by, directly affiliated with, maintained, authorized, or sponsored by Riot Games, Inc. VALORANT and all related properties are trademarks or registered trademarks of Riot Games, Inc.