@gala-chain/launchpad-sdk 8.1.0 → 9.0.0-rc.1

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 (372) hide show
  1. package/CHANGELOG.md +837 -0
  2. package/EXAMPLES.md +95 -681
  3. package/MIGRATING-TO-9.0.md +343 -0
  4. package/README.md +46 -17
  5. package/dist/LaunchpadSDK.d.ts +536 -616
  6. package/dist/LaunchpadSDK.d.ts.map +1 -1
  7. package/dist/api/LaunchpadAPI.d.ts +6 -176
  8. package/dist/api/LaunchpadAPI.d.ts.map +1 -1
  9. package/dist/auth/SessionAuthService.d.ts +32 -2
  10. package/dist/auth/SessionAuthService.d.ts.map +1 -1
  11. package/dist/auth/SignatureAuth.d.ts +2 -2
  12. package/dist/auth/SignatureAuth.d.ts.map +1 -1
  13. package/dist/auth/session.d.ts +59 -0
  14. package/dist/auth/session.d.ts.map +1 -0
  15. package/dist/auth/types.d.ts +7 -2
  16. package/dist/auth/types.d.ts.map +1 -1
  17. package/dist/config/environments.d.ts +7 -2
  18. package/dist/config/environments.d.ts.map +1 -1
  19. package/dist/constants/decimals.d.ts +0 -23
  20. package/dist/constants/decimals.d.ts.map +1 -1
  21. package/dist/constants/endpoints.d.ts +19 -8
  22. package/dist/constants/endpoints.d.ts.map +1 -1
  23. package/dist/constants/enums.d.ts +19 -0
  24. package/dist/constants/enums.d.ts.map +1 -1
  25. package/dist/constants/version.generated.d.ts +1 -1
  26. package/dist/constants/version.generated.d.ts.map +1 -1
  27. package/dist/errors/LaunchpadSDKError.d.ts +18 -0
  28. package/dist/errors/LaunchpadSDKError.d.ts.map +1 -1
  29. package/dist/helpers/sdk.d.ts.map +1 -1
  30. package/dist/index.browser.d.ts +40 -45
  31. package/dist/index.browser.d.ts.map +1 -1
  32. package/dist/index.browser.esm.js +1 -1
  33. package/dist/index.cjs +1 -1
  34. package/dist/index.esm.js +1 -1
  35. package/dist/index.js +1 -1
  36. package/dist/index.node.d.ts +4 -5
  37. package/dist/index.node.d.ts.map +1 -1
  38. package/dist/launchpad/bundle-submission.d.ts +57 -10
  39. package/dist/launchpad/bundle-submission.d.ts.map +1 -1
  40. package/dist/launchpad/create-sale-validation.d.ts +19 -0
  41. package/dist/launchpad/create-sale-validation.d.ts.map +1 -0
  42. package/dist/launchpad/transport.d.ts +33 -2
  43. package/dist/launchpad/transport.d.ts.map +1 -1
  44. package/dist/launchpad/writes.d.ts +37 -11
  45. package/dist/launchpad/writes.d.ts.map +1 -1
  46. package/dist/native.cjs +1 -1
  47. package/dist/native.d.ts +4 -5
  48. package/dist/native.d.ts.map +1 -1
  49. package/dist/native.esm.js +1 -1
  50. package/dist/schemas/launchpad.d.ts +3 -2
  51. package/dist/schemas/launchpad.d.ts.map +1 -1
  52. package/dist/schemas/primitives.d.ts +12 -2
  53. package/dist/schemas/primitives.d.ts.map +1 -1
  54. package/dist/schemas/user.d.ts +3 -18
  55. package/dist/schemas/user.d.ts.map +1 -1
  56. package/dist/schemas/validators.d.ts +3 -3
  57. package/dist/services/AbstractCacheService.d.ts +2 -2
  58. package/dist/services/ApiKeyService.d.ts +1 -1
  59. package/dist/services/BanService.d.ts +1 -1
  60. package/dist/services/ChartService.d.ts.map +1 -1
  61. package/dist/services/ContentReactionService.d.ts +6 -18
  62. package/dist/services/ContentReactionService.d.ts.map +1 -1
  63. package/dist/services/EventsQueryService.d.ts +47 -0
  64. package/dist/services/EventsQueryService.d.ts.map +1 -0
  65. package/dist/services/GalaChainBalanceService.d.ts +17 -89
  66. package/dist/services/GalaChainBalanceService.d.ts.map +1 -1
  67. package/dist/services/GalaChainLockService.d.ts +19 -20
  68. package/dist/services/GalaChainLockService.d.ts.map +1 -1
  69. package/dist/services/GalaChainService.d.ts +28 -15
  70. package/dist/services/GalaChainService.d.ts.map +1 -1
  71. package/dist/services/GalaChainTokenService.d.ts +25 -53
  72. package/dist/services/GalaChainTokenService.d.ts.map +1 -1
  73. package/dist/services/GalaChainTransferService.d.ts +42 -41
  74. package/dist/services/GalaChainTransferService.d.ts.map +1 -1
  75. package/dist/services/HealthService.d.ts +33 -0
  76. package/dist/services/HealthService.d.ts.map +1 -0
  77. package/dist/services/ImageService.d.ts +3 -3
  78. package/dist/services/ImageService.d.ts.map +1 -1
  79. package/dist/services/LaunchpadPriceService.d.ts +66 -0
  80. package/dist/services/LaunchpadPriceService.d.ts.map +1 -0
  81. package/dist/services/LaunchpadService.d.ts +34 -42
  82. package/dist/services/LaunchpadService.d.ts.map +1 -1
  83. package/dist/services/MessagesService.d.ts +12 -44
  84. package/dist/services/MessagesService.d.ts.map +1 -1
  85. package/dist/services/ModeratorService.d.ts +2 -2
  86. package/dist/services/ModeratorService.d.ts.map +1 -1
  87. package/dist/services/NftCollectionService.d.ts +22 -6
  88. package/dist/services/NftCollectionService.d.ts.map +1 -1
  89. package/dist/services/OverseerService.d.ts +3 -3
  90. package/dist/services/OverseerService.d.ts.map +1 -1
  91. package/dist/services/PlatformStatsService.d.ts +1 -2
  92. package/dist/services/PlatformStatsService.d.ts.map +1 -1
  93. package/dist/services/PoolService.d.ts +28 -65
  94. package/dist/services/PoolService.d.ts.map +1 -1
  95. package/dist/services/RestrictedNamesService.d.ts +1 -1
  96. package/dist/services/RestrictedNamesService.d.ts.map +1 -1
  97. package/dist/services/StreamChatService.d.ts +8 -19
  98. package/dist/services/StreamChatService.d.ts.map +1 -1
  99. package/dist/services/StreamTokenServiceBase.d.ts +2 -1
  100. package/dist/services/StreamTokenServiceBase.d.ts.map +1 -1
  101. package/dist/services/StreamWebSocketService.d.ts +423 -451
  102. package/dist/services/StreamWebSocketService.d.ts.map +1 -1
  103. package/dist/services/StreamingService.d.ts +14 -15
  104. package/dist/services/StreamingService.d.ts.map +1 -1
  105. package/dist/services/TokenBanService.d.ts +1 -1
  106. package/dist/services/TokenResolverService.d.ts +5 -5
  107. package/dist/services/TokenResolverService.d.ts.map +1 -1
  108. package/dist/services/TradeService.d.ts +13 -9
  109. package/dist/services/TradeService.d.ts.map +1 -1
  110. package/dist/services/TradingQuotesService.d.ts.map +1 -1
  111. package/dist/services/UserService.d.ts +64 -20
  112. package/dist/services/UserService.d.ts.map +1 -1
  113. package/dist/services/gateway-transport.d.ts +32 -0
  114. package/dist/services/gateway-transport.d.ts.map +1 -0
  115. package/dist/services/gateway-writes.d.ts +83 -0
  116. package/dist/services/gateway-writes.d.ts.map +1 -0
  117. package/dist/services/realtime/event-catalog.d.ts +456 -0
  118. package/dist/services/realtime/event-catalog.d.ts.map +1 -0
  119. package/dist/services/shared/pagination-helpers.d.ts +22 -5
  120. package/dist/services/shared/pagination-helpers.d.ts.map +1 -1
  121. package/dist/services/shared/service-validators.d.ts.map +1 -1
  122. package/dist/signing/index.d.ts +2 -3
  123. package/dist/signing/index.d.ts.map +1 -1
  124. package/dist/signing/signers.d.ts +64 -9
  125. package/dist/signing/signers.d.ts.map +1 -1
  126. package/dist/signing/types.d.ts +7 -10
  127. package/dist/signing/types.d.ts.map +1 -1
  128. package/dist/types/api-key.dto.d.ts +1 -1
  129. package/dist/types/ban.dto.d.ts +21 -16
  130. package/dist/types/ban.dto.d.ts.map +1 -1
  131. package/dist/types/burn.dto.d.ts +4 -2
  132. package/dist/types/burn.dto.d.ts.map +1 -1
  133. package/dist/types/chat-messages.dto.d.ts +10 -72
  134. package/dist/types/chat-messages.dto.d.ts.map +1 -1
  135. package/dist/types/comments.dto.d.ts +8 -78
  136. package/dist/types/comments.dto.d.ts.map +1 -1
  137. package/dist/types/common.d.ts +42 -85
  138. package/dist/types/common.d.ts.map +1 -1
  139. package/dist/types/constraints.d.ts +47 -23
  140. package/dist/types/constraints.d.ts.map +1 -1
  141. package/dist/types/content-flag.dto.d.ts +5 -1
  142. package/dist/types/content-flag.dto.d.ts.map +1 -1
  143. package/dist/types/content-reactions.dto.d.ts +0 -4
  144. package/dist/types/content-reactions.dto.d.ts.map +1 -1
  145. package/dist/types/dto.d.ts +0 -5
  146. package/dist/types/dto.d.ts.map +1 -1
  147. package/dist/types/engagement-stats.dto.d.ts +16 -27
  148. package/dist/types/engagement-stats.dto.d.ts.map +1 -1
  149. package/dist/types/events.dto.d.ts +89 -0
  150. package/dist/types/events.dto.d.ts.map +1 -1
  151. package/dist/types/global-feed.dto.d.ts +23 -164
  152. package/dist/types/global-feed.dto.d.ts.map +1 -1
  153. package/dist/types/health.dto.d.ts +32 -0
  154. package/dist/types/health.dto.d.ts.map +1 -0
  155. package/dist/types/launchpad.dto.d.ts +77 -323
  156. package/dist/types/launchpad.dto.d.ts.map +1 -1
  157. package/dist/types/lock.dto.d.ts +12 -7
  158. package/dist/types/lock.dto.d.ts.map +1 -1
  159. package/dist/types/messages.dto.d.ts +168 -118
  160. package/dist/types/messages.dto.d.ts.map +1 -1
  161. package/dist/types/moderator.dto.d.ts +1 -1
  162. package/dist/types/options.dto.d.ts +8 -36
  163. package/dist/types/options.dto.d.ts.map +1 -1
  164. package/dist/types/overseer.dto.d.ts +2 -1
  165. package/dist/types/overseer.dto.d.ts.map +1 -1
  166. package/dist/types/platform-stats.dto.d.ts +3 -3
  167. package/dist/types/realtime-events.dto.d.ts +340 -0
  168. package/dist/types/realtime-events.dto.d.ts.map +1 -0
  169. package/dist/types/restricted-names.dto.d.ts +2 -2
  170. package/dist/types/restricted-names.dto.d.ts.map +1 -1
  171. package/dist/types/stream-chat.dto.d.ts +15 -14
  172. package/dist/types/stream-chat.dto.d.ts.map +1 -1
  173. package/dist/types/streaming.dto.d.ts +73 -104
  174. package/dist/types/streaming.dto.d.ts.map +1 -1
  175. package/dist/types/token-ban.dto.d.ts.map +1 -1
  176. package/dist/types/token-config.dto.d.ts +34 -19
  177. package/dist/types/token-config.dto.d.ts.map +1 -1
  178. package/dist/types/trades-query.dto.d.ts +8 -24
  179. package/dist/types/trades-query.dto.d.ts.map +1 -1
  180. package/dist/types/user.dto.d.ts +133 -112
  181. package/dist/types/user.dto.d.ts.map +1 -1
  182. package/dist/types/websocket-events.dto.d.ts +5 -5
  183. package/dist/types/websocket-events.dto.d.ts.map +1 -1
  184. package/dist/utils/address-formatter.d.ts +25 -2
  185. package/dist/utils/address-formatter.d.ts.map +1 -1
  186. package/dist/utils/agent-config.d.ts +9 -4
  187. package/dist/utils/agent-config.d.ts.map +1 -1
  188. package/dist/utils/auto-pagination.d.ts +7 -240
  189. package/dist/utils/auto-pagination.d.ts.map +1 -1
  190. package/dist/utils/bignumber-helpers.d.ts +3 -2
  191. package/dist/utils/bignumber-helpers.d.ts.map +1 -1
  192. package/dist/utils/delimiter-parser.d.ts +0 -13
  193. package/dist/utils/delimiter-parser.d.ts.map +1 -1
  194. package/dist/utils/error-factories.d.ts +4 -3
  195. package/dist/utils/error-factories.d.ts.map +1 -1
  196. package/dist/utils/error-patterns.d.ts +0 -47
  197. package/dist/utils/error-patterns.d.ts.map +1 -1
  198. package/dist/utils/error-wrapper.d.ts +5 -5
  199. package/dist/utils/errors.d.ts +53 -318
  200. package/dist/utils/errors.d.ts.map +1 -1
  201. package/dist/utils/http.d.ts +36 -3
  202. package/dist/utils/http.d.ts.map +1 -1
  203. package/dist/utils/message-validators.d.ts.map +1 -1
  204. package/dist/utils/pagination-helpers.d.ts +17 -0
  205. package/dist/utils/pagination-helpers.d.ts.map +1 -1
  206. package/dist/utils/pagination-validation.d.ts +2 -2
  207. package/dist/utils/response-handlers.d.ts.map +1 -1
  208. package/dist/utils/service-validators.d.ts +6 -6
  209. package/dist/utils/service-validators.d.ts.map +1 -1
  210. package/dist/utils/token-format-converter.d.ts +1 -1
  211. package/dist/utils/token-parser.d.ts +6 -127
  212. package/dist/utils/token-parser.d.ts.map +1 -1
  213. package/dist/utils/token-stringification.d.ts +7 -7
  214. package/dist/utils/token-stringification.d.ts.map +1 -1
  215. package/dist/utils/tokenNameNormalizer.d.ts +2 -2
  216. package/dist/utils/tokenNormalizer.d.ts +5 -29
  217. package/dist/utils/tokenNormalizer.d.ts.map +1 -1
  218. package/dist/utils/unique-key-generator.d.ts +7 -134
  219. package/dist/utils/unique-key-generator.d.ts.map +1 -1
  220. package/dist/utils/validation-helpers.d.ts +21 -64
  221. package/dist/utils/validation-helpers.d.ts.map +1 -1
  222. package/dist/utils/validation.d.ts +4 -1
  223. package/dist/utils/validation.d.ts.map +1 -1
  224. package/package.json +47 -87
  225. package/dist/api/dto/BurnTokensDto.d.ts +0 -77
  226. package/dist/api/dto/BurnTokensDto.d.ts.map +0 -1
  227. package/dist/api/dto/LockTokenDto.d.ts +0 -85
  228. package/dist/api/dto/LockTokenDto.d.ts.map +0 -1
  229. package/dist/api/dto/TransferTokenDto.d.ts +0 -64
  230. package/dist/api/dto/TransferTokenDto.d.ts.map +0 -1
  231. package/dist/api/dto/UnlockTokenDto.d.ts +0 -74
  232. package/dist/api/dto/UnlockTokenDto.d.ts.map +0 -1
  233. package/dist/bridge/BridgeService.d.ts +0 -484
  234. package/dist/bridge/BridgeService.d.ts.map +0 -1
  235. package/dist/bridge/GalaConnectClient.d.ts +0 -170
  236. package/dist/bridge/GalaConnectClient.d.ts.map +0 -1
  237. package/dist/bridge/constants/index.d.ts +0 -7
  238. package/dist/bridge/constants/index.d.ts.map +0 -1
  239. package/dist/bridge/constants/tokens.d.ts +0 -212
  240. package/dist/bridge/constants/tokens.d.ts.map +0 -1
  241. package/dist/bridge/index.d.ts +0 -24
  242. package/dist/bridge/index.d.ts.map +0 -1
  243. package/dist/bridge/public-types.d.ts +0 -2
  244. package/dist/bridge/public-types.d.ts.map +0 -1
  245. package/dist/bridge/strategies/BridgeStrategy.d.ts +0 -204
  246. package/dist/bridge/strategies/BridgeStrategy.d.ts.map +0 -1
  247. package/dist/bridge/strategies/EthereumBridgeStrategy.d.ts +0 -178
  248. package/dist/bridge/strategies/EthereumBridgeStrategy.d.ts.map +0 -1
  249. package/dist/bridge/strategies/SolanaBridgeStrategy.d.ts +0 -236
  250. package/dist/bridge/strategies/SolanaBridgeStrategy.d.ts.map +0 -1
  251. package/dist/bridge/types/bridge.dto.d.ts +0 -772
  252. package/dist/bridge/types/bridge.dto.d.ts.map +0 -1
  253. package/dist/bridge/types/bridgeable-token.dto.d.ts +0 -209
  254. package/dist/bridge/types/bridgeable-token.dto.d.ts.map +0 -1
  255. package/dist/bridge/types/eip712.d.ts +0 -66
  256. package/dist/bridge/types/eip712.d.ts.map +0 -1
  257. package/dist/bridge/types/index.d.ts +0 -8
  258. package/dist/bridge/types/index.d.ts.map +0 -1
  259. package/dist/bridge/utils/RateLimiter.d.ts +0 -34
  260. package/dist/bridge/utils/RateLimiter.d.ts.map +0 -1
  261. package/dist/bridge/utils/address-formatter.d.ts +0 -25
  262. package/dist/bridge/utils/address-formatter.d.ts.map +0 -1
  263. package/dist/bridge/utils/addressValidation.d.ts +0 -200
  264. package/dist/bridge/utils/addressValidation.d.ts.map +0 -1
  265. package/dist/bridge/utils/balanceHelpers.d.ts +0 -215
  266. package/dist/bridge/utils/balanceHelpers.d.ts.map +0 -1
  267. package/dist/bridge/utils/bridgeErrors.d.ts +0 -98
  268. package/dist/bridge/utils/bridgeErrors.d.ts.map +0 -1
  269. package/dist/bridge/utils/bridgeOutHelpers.d.ts +0 -68
  270. package/dist/bridge/utils/bridgeOutHelpers.d.ts.map +0 -1
  271. package/dist/bridge/utils/bridgePayload.d.ts +0 -98
  272. package/dist/bridge/utils/bridgePayload.d.ts.map +0 -1
  273. package/dist/bridge/utils/bridgeStatusParser.d.ts +0 -76
  274. package/dist/bridge/utils/bridgeStatusParser.d.ts.map +0 -1
  275. package/dist/bridge/utils/eip712Helpers.d.ts +0 -66
  276. package/dist/bridge/utils/eip712Helpers.d.ts.map +0 -1
  277. package/dist/bridge/utils/index.d.ts +0 -19
  278. package/dist/bridge/utils/index.d.ts.map +0 -1
  279. package/dist/bridge/utils/retry.d.ts +0 -112
  280. package/dist/bridge/utils/retry.d.ts.map +0 -1
  281. package/dist/bridge/utils/strategyDelegation.d.ts +0 -126
  282. package/dist/bridge/utils/strategyDelegation.d.ts.map +0 -1
  283. package/dist/bridge/utils/tokenIdUtils.d.ts +0 -86
  284. package/dist/bridge/utils/tokenIdUtils.d.ts.map +0 -1
  285. package/dist/bridge/utils/tokenMath.d.ts +0 -39
  286. package/dist/bridge/utils/tokenMath.d.ts.map +0 -1
  287. package/dist/bridge/utils/tokenMetadataResolver.d.ts +0 -97
  288. package/dist/bridge/utils/tokenMetadataResolver.d.ts.map +0 -1
  289. package/dist/helpers/wallet.d.ts +0 -151
  290. package/dist/helpers/wallet.d.ts.map +0 -1
  291. package/dist/react/WalletContext.d.ts +0 -60
  292. package/dist/react/WalletContext.d.ts.map +0 -1
  293. package/dist/react/index.d.ts +0 -65
  294. package/dist/react/index.d.ts.map +0 -1
  295. package/dist/react/types.d.ts +0 -76
  296. package/dist/react/types.d.ts.map +0 -1
  297. package/dist/react/useWallet.d.ts +0 -123
  298. package/dist/react/useWallet.d.ts.map +0 -1
  299. package/dist/react/useWalletConnection.d.ts +0 -89
  300. package/dist/react/useWalletConnection.d.ts.map +0 -1
  301. package/dist/react/useWalletDetection.d.ts +0 -81
  302. package/dist/react/useWalletDetection.d.ts.map +0 -1
  303. package/dist/react.cjs +0 -1
  304. package/dist/react.esm.js +0 -1
  305. package/dist/services/AbstractTokenFetchService.d.ts +0 -150
  306. package/dist/services/AbstractTokenFetchService.d.ts.map +0 -1
  307. package/dist/services/BatchedCacheService.d.ts +0 -133
  308. package/dist/services/BatchedCacheService.d.ts.map +0 -1
  309. package/dist/services/BridgeableTokenCache.d.ts +0 -120
  310. package/dist/services/BridgeableTokenCache.d.ts.map +0 -1
  311. package/dist/services/BridgeableTokenService.d.ts +0 -218
  312. package/dist/services/BridgeableTokenService.d.ts.map +0 -1
  313. package/dist/services/DexService.d.ts +0 -440
  314. package/dist/services/DexService.d.ts.map +0 -1
  315. package/dist/services/NetworkKeyedCacheService.d.ts +0 -185
  316. package/dist/services/NetworkKeyedCacheService.d.ts.map +0 -1
  317. package/dist/services/PriceHistoryService.d.ts +0 -209
  318. package/dist/services/PriceHistoryService.d.ts.map +0 -1
  319. package/dist/services/StreamingEventService.d.ts +0 -441
  320. package/dist/services/StreamingEventService.d.ts.map +0 -1
  321. package/dist/services/WrapService.d.ts +0 -171
  322. package/dist/services/WrapService.d.ts.map +0 -1
  323. package/dist/services/WrappableTokenCache.d.ts +0 -100
  324. package/dist/services/WrappableTokenCache.d.ts.map +0 -1
  325. package/dist/services/WrappableTokenService.d.ts +0 -130
  326. package/dist/services/WrappableTokenService.d.ts.map +0 -1
  327. package/dist/setup.d.ts +0 -8
  328. package/dist/setup.d.ts.map +0 -1
  329. package/dist/tokens/transfers.d.ts +0 -95
  330. package/dist/tokens/transfers.d.ts.map +0 -1
  331. package/dist/types/comment.dto.d.ts +0 -176
  332. package/dist/types/comment.dto.d.ts.map +0 -1
  333. package/dist/types/galachain-api.types.d.ts +0 -297
  334. package/dist/types/galachain-api.types.d.ts.map +0 -1
  335. package/dist/types/priceHistory.dto.d.ts +0 -134
  336. package/dist/types/priceHistory.dto.d.ts.map +0 -1
  337. package/dist/types/streaming-events.dto.d.ts +0 -605
  338. package/dist/types/streaming-events.dto.d.ts.map +0 -1
  339. package/dist/types/token.types.d.ts +0 -359
  340. package/dist/types/token.types.d.ts.map +0 -1
  341. package/dist/types/wrappable-token.dto.d.ts +0 -305
  342. package/dist/types/wrappable-token.dto.d.ts.map +0 -1
  343. package/dist/utils/crypto-compat.d.ts +0 -40
  344. package/dist/utils/crypto-compat.d.ts.map +0 -1
  345. package/dist/utils/load-env.d.ts +0 -31
  346. package/dist/utils/load-env.d.ts.map +0 -1
  347. package/dist/utils/token-instance-key.d.ts +0 -57
  348. package/dist/utils/token-instance-key.d.ts.map +0 -1
  349. package/dist/utils/wallet.d.ts +0 -166
  350. package/dist/utils/wallet.d.ts.map +0 -1
  351. package/dist/wallet/ExternalWalletProvider.d.ts +0 -90
  352. package/dist/wallet/ExternalWalletProvider.d.ts.map +0 -1
  353. package/dist/wallet/GalaWalletProvider.d.ts +0 -122
  354. package/dist/wallet/GalaWalletProvider.d.ts.map +0 -1
  355. package/dist/wallet/PrivateKeyProvider.d.ts +0 -90
  356. package/dist/wallet/PrivateKeyProvider.d.ts.map +0 -1
  357. package/dist/wallet/detection.d.ts +0 -107
  358. package/dist/wallet/detection.d.ts.map +0 -1
  359. package/dist/wallet/event-handlers.d.ts +0 -50
  360. package/dist/wallet/event-handlers.d.ts.map +0 -1
  361. package/dist/wallet/index.d.ts +0 -51
  362. package/dist/wallet/index.d.ts.map +0 -1
  363. package/dist/wallet/signing-operation.d.ts +0 -19
  364. package/dist/wallet/signing-operation.d.ts.map +0 -1
  365. package/dist/wallet/typed-data-helpers.d.ts +0 -68
  366. package/dist/wallet/typed-data-helpers.d.ts.map +0 -1
  367. package/dist/wallet/types.d.ts +0 -267
  368. package/dist/wallet/types.d.ts.map +0 -1
  369. package/dist/wallet/utils.d.ts +0 -117
  370. package/dist/wallet/utils.d.ts.map +0 -1
  371. package/dist/wallet.cjs +0 -1
  372. package/dist/wallet.esm.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,842 @@
1
1
  # Changelog
2
2
 
3
+ ## 9.0.0-rc.1
4
+
5
+ Since 9.0.0-rc.0 (published): the sections "App-owned session" through "The stream socket" below
6
+ (the app-session, browser-wallet, bundle-confirmation, error-answer, path-parameter, `PageInfo`,
7
+ `fetchPools`, admin/overseer, trades/tokens/users/streaming and stream-socket contracts) and the
8
+ later entries of "BREAKING CHANGES" and "Fixes" are new in rc.1; everything else in this section is
9
+ rc.0's. Core peer floor is `>=1.0.0-rc.6 <2`.
10
+
11
+ launchpad-sdk is launchpad-only. Everything that speaks to the GalaChain gateway generically is
12
+ `@gala-chain/gala-core-sdk`'s (a peer dependency: install it beside launchpad-sdk); everything that
13
+ speaks to the swap backend (dex-backend) is `@gala-chain/gswap-sdk`'s, and launchpad-sdk no longer
14
+ depends on it in any way. **[MIGRATING-TO-9.0.md](./MIGRATING-TO-9.0.md)** lists every export and
15
+ `LaunchpadSDK` member 8.1.0 had that 9.0.0 does not, with its new home; it is generated from the
16
+ built declarations of both versions (`pnpm docs:migration`).
17
+
18
+ ### BREAKING CHANGES (9.0 cut)
19
+
20
+ - **The `Sign` header goes to the launchpad backend only.** The clients for the GalaChain gateway,
21
+ dex-api (referrals, bridgeable and wrappable token lists), the swap backend (prices) and the
22
+ bundler no longer send it: none of those hosts reads it (the gateway's own signature is in each
23
+ write's body; dex-api reads `x-wallet-address`), and every header cost a wallet signature per
24
+ request, a prompt for browser wallets. The clients keep the wallet identity (`getAddress`,
25
+ `signTypedData`) services read from them. `HttpClient` takes `{ signRequests }` as its third
26
+ constructor argument (default true: the launchpad backend client). Gateway read goldens
27
+ (`gateway-reads`, `token-discovery`) lost exactly their recorded `Sign` header and nothing else;
28
+ `tests/http-client-sign-header.test.ts` pins both behaviours.
29
+ - **No DEX at all, not even as a devDependency.** The 46 DEX demos and their npm scripts (`demo:dex*`,
30
+ `demo:liquidity*`, `demo:fees*`, the pool watchers, `test:demos:dex`, `test:demos:fees`) moved to
31
+ `packages/gswap-sdk/examples/demos` (on gswap-sdk's own client, type-checked by its
32
+ `check:examples`), and the stage live test's DEX checks to gswap-sdk's live test.
33
+ `tests/product-boundary.test.ts` scans `src`, `tests`, `examples` and `scripts` with the TypeScript
34
+ scanner, refuses gswap-sdk in every dependency field and resolves it from the package with plain
35
+ Node (MODULE_NOT_FOUND); the CI dist check refuses it in every bundle.
36
+ - **Prices: launchpad tokens only.** Of the two swap-backend price readers launchpad-sdk had, only the
37
+ launchpad-token one stays: `fetchTokenPrice({ tokenName })` (the bonding-curve price, or the
38
+ token's swap-backend price once it graduated; GALA's USD price and a graduated token's price are
39
+ read with a thin `GET /market/price` documented as launchpad-backend-adjacent). REMOVED, as
40
+ generic swap-backend reads that gswap-sdk's `market` already makes:
41
+ `fetchTokenPrice({ tokenId })` (a `tokenId` is now refused with a `ValidationError` before
42
+ anything is sent) and its 400/404 "launchpad fallback" (the recorded golden vector shows it never
43
+ fired: the 404 was wrapped before the check), `fetchGalaPrice()`, `fetchPriceHistory()`,
44
+ `fetchAllPriceHistory()` and their types (`FetchPriceHistoryOptions`, `PriceHistoryResult`,
45
+ `PriceSnapshot`, `PriceSortOrder`). Use `gSwap.market.getPrice(tokenId)` and
46
+ `gSwap.market.getPriceSeries(await sdk.resolveTokenClassKey(name), timeframe)`.
47
+ Decision and evidence (callers grepped in mcp-server, the apps, examples and docs): the only
48
+ callers of the removed reads were the MCP price tools, the examples and the docs. The MCP tools
49
+ (`gala_launchpad_fetch_token_spot_price` with `tokenId`, `..._fetch_gala_spot_price`,
50
+ `..._fetch_price_history`, `..._fetch_all_price_history`) keep their names, inputs and outputs on
51
+ the MCP server's own GSwap client, and replay the 13 recorded 8.1 vectors of these reads (same
52
+ endpoint and query, same outputs). What differs on the wire: no launchpad `Sign` header on these
53
+ public reads, the `$` of a class key sent as `%24`, and a backend failure's inner text (gswap-sdk's).
54
+ - **Dependencies are the source's import graph** (`tests/dependency-graph.test.ts`): `@gala-chain/api`,
55
+ `axios`, `bignumber.js`, `ethers`, `socket.io-client`, `uuid`, `web-file-polyfill`; peers
56
+ `@gala-chain/gala-core-sdk` (`>=1.0.0-rc.3 <2`), `zod` (now `^4.3.6`: the peer said `^3` while the
57
+ schemas are zod 4, and it is no longer also a dependency) and the shared libraries. No longer
58
+ dependencies: `@solana/web3.js`, `@solana/spl-token`, `dotenv`, `@modelcontextprotocol/sdk` (and,
59
+ since the bridge move, `bs58` and `json-stringify-deterministic`).
60
+ - **Bridging is explicit: the `bridge` loader.** The bridge, balance-on-chain, token-list and wrap
61
+ methods run on `@gala-chain/gala-core-sdk/bridge` (the one core entry that loads `ethers`,
62
+ `@solana/web3.js` and `@solana/spl-token`, core's optional peers), which the app hands over:
63
+ `new LaunchpadSDK({ ..., bridge: () => import('@gala-chain/gala-core-sdk/bridge') })` (type
64
+ `CoreBridgeLoader`; a page without a bundler passes a function resolving to the module it loaded
65
+ itself). The UMD bundle no longer looks for a `GalaCoreSDKBridge` global. launchpad-sdk
66
+ names neither that module nor Solana in any built bundle: a bundler (Vite, webpack, Metro)
67
+ resolves every load it sees, a lazy `import()` included, so the earlier `import()` inside the SDK
68
+ made every app's build need Solana (an app's Vite build failed with 13 `MISSING_EXPORT` errors on
69
+ `@solana/web3.js` / `@solana/spl-token`). Without the loader a bridge or wrap call is a
70
+ `ConfigurationError` (`field: 'bridge'`) naming it; with it, the module is loaded once per SDK at
71
+ the first such call, and a failed load (the peers are not installed) is a `ConfigurationError`
72
+ naming them, tried again at the next call. `check:pack` scans every built bundle of the packed
73
+ package for a `@gala-chain/gala-core-sdk/bridge` or `@solana/*` load (`scripts/runtime-specifiers.ts`).
74
+ A bridge or wrap call made with one wallet is refused (`ConfigurationError`, nothing sent) if
75
+ `setWallet` / `setWalletProvider` runs while `/bridge` loads, rather than running as the next
76
+ wallet. `getSupportedBridgeTokens()` is `async`.
77
+ - **The public surface re-exports nothing** (`tests/public-surface.test.ts` pins both entries' export
78
+ lists and fails on any export declared outside `src/`). Removed from the main and `/native`
79
+ entries: `generateEIP712Types` and `GalaChainSigner` (core's), the duplicate EIP-712 types
80
+ `EIP712Types`, `EIP712TypeField`, `EIP712Domain` (core's `EIP712Types`, `EIP712DomainValue`),
81
+ `HttpRequestor` (the bundler transport takes core's `HttpRequestor` type), `GALA_TOKEN_CLASS_KEY`
82
+ (core's), `generateUniqueKey` (core's `createUniqueKey`), and the demo `.env` loaders `getEnv`,
83
+ `getEnvOrThrow`, `loadEnvWithFallback`.
84
+
85
+ ### App-owned session (a browser app's httpOnly-cookie JWT session)
86
+
87
+ - **`session` in `LaunchpadSDKConfig`.** A browser app (launchpad-frontend-v3) keeps its own JWT
88
+ session: the refresh token is an httpOnly cookie the backend sets for `cookieSession: true`
89
+ logins, and the app is the one token authority. With `session: { accessToken, onUnauthorized,
90
+ credentials? }` every launchpad-backend request takes its bearer from `accessToken()` (awaited per
91
+ request), a 401 goes to `onUnauthorized(rejectedToken)` and is retried once with the token it
92
+ returns (`null`: the 401 stands), the launchpad-backend client sends credentials (unless
93
+ `credentials: 'omit'`), and the SDK stores no token (services that attach "the JWT" attach
94
+ nothing; the client adds the session's bearer). No other host (gateway, bundler, dex-api, swap
95
+ backend) ever sees the session or credentials. Exclusive with `accessToken`. Pair it with
96
+ `signer` + `walletAddress`: `wallet` / `walletProvider` sign every launchpad request (`Sign`).
97
+ - **`loginWithSignature({ address, message, signature, publicKey? })`**: `POST /auth/login` with a
98
+ signature the caller made (a browser wallet signs `Sign in to Launchpad t:<ms>` itself); with a
99
+ session it asks for the cookie session and stores nothing. **`loginWithDevBypass(address)`**: the
100
+ backend's non-production signature bypass.
101
+ - With a session, `refreshToken()` is `POST /auth/refresh` with `{}`, no bearer and the cookie;
102
+ `logout({ allDevices, accessToken })` always revokes on the server (bearer as handed over, never
103
+ refreshed); `ensureValidToken()` is the session's current token. Auth-endpoint failures are an
104
+ `AuthError` with the backend's `statusCode` (401/403: the session was rejected; 429/5xx/none:
105
+ transient). `tests/app-session.test.ts` drives each through a real axios instance.
106
+
107
+ ### Browser-app wallet signing
108
+
109
+ - **`BrowserWalletSigner.fromEip1193(provider, keyAddress, options?)`**: a browser app holds the
110
+ wallet's raw EIP-1193 provider, not an ethers one. The factory builds the ethers `BrowserProvider`
111
+ the typed-data path reads the network and the selected account from, keeps the raw `request` for
112
+ `signObject`, and takes the key as `0x` or `eth|` (a `client|` alias is refused: it names no key).
113
+ The bytes are those of the constructor path (bundler-typed-data and wallet-providers goldens
114
+ unchanged; `tests/wallet-signers-app.test.ts` compares both paths over a real `BrowserProvider`).
115
+ - **`WALLET_ACCOUNT_CHANGED`** (`LaunchpadSDKError`, `details.walletAccount` / `signerAccount`):
116
+ `BrowserWalletSigner` refuses to sign when the wallet's selected account is not its key. Same
117
+ message as before; it was a plain `Error`, which the bundler transport rewrapped as
118
+ `LAUNCHPAD_SIGNING_FAILED`.
119
+ - **`WALLET_USER_REJECTED`**: the bundler transport tells a decline in the wallet (gala-core-sdk's
120
+ `isWalletUserRejection`: `4001`, `ACTION_REJECTED`, Gala Wallet's decline, core's
121
+ `SIGNING_FAILED`/`user_rejected`) apart from other signing failures, with the wallet's code in
122
+ `details.walletCode`. Other failures stay `LAUNCHPAD_SIGNING_FAILED`; an SDK error passes through.
123
+ - **Gala Wallet typed data selects the account.** `GalaWalletSigner.signTypedData` switches the
124
+ extension (`setAddress`, where it offers it) to `selectAddress`, else the Ethereum account the
125
+ request names, inside gala-core-sdk's per-wallet select-then-sign queue
126
+ (`withGalaWalletIdentity`), and signs through the `wallet` option when one is given (it read
127
+ `window.gala` even then, while `signObject` used the option).
128
+ - **`GalaWalletSigner` option `verifyActiveAccount` (default `false`)**: the app's check before a Gala
129
+ Wallet signature. On, the signer reads the wallet's active account (`wallet.address`, else
130
+ `eth_accounts` when the wallet has not reported one since the page loaded) and refuses with
131
+ `WALLET_ACCOUNT_CHANGED` (`details.walletAccount` null when none was reported) unless it is the
132
+ signer's key; the RPC order is that check, `setAddress`, `eth_signTypedData`. Off by default so the
133
+ six recorded `galaWalletEthAddress` vectors of `bundler-typed-data.golden.json` are unchanged (the
134
+ check adds an `eth_accounts` request); the opt-in sequences are pinned by the new
135
+ `tests/golden/gala-wallet-verify-account.golden.json`. A signer that names no Ethereum key
136
+ (`client|` alias without an Ethereum `selectAddress`) is refused at construction
137
+ (`INVALID_SIGNER_OPTIONS`). `BrowserWalletSigner` needs no option: it always compares the wallet's
138
+ selected account with its key.
139
+
140
+ ### Bundle confirmation for a browser app
141
+
142
+ - **`bundleSocketFactory` in `LaunchpadSDKConfig`** (passed to `BundlerTransport`): the app's own
143
+ bundler socket, with its reconnect settings. Each `wait()` adds its listener for the bundle's
144
+ event on the socket the factory returns and removes it when the wait ends; that socket is never
145
+ disconnected (a socket the transport opens itself still is).
146
+ - **`sdk.launchpad.attach({ bundleId, method, uniqueKey, tokenName? })`** (and
147
+ `BundlerTransport.attach`): a `BundleSubmission` for a bundle sent before a reload, whose `wait()`
148
+ confirms exactly as the original's (socket event raced against the REST confirmation, which also
149
+ answers for a bundle that settled while nobody listened). Nothing is signed or sent until
150
+ `wait()`. Refused with `INVALID_BUNDLE_ATTACHMENT` (`details.field`): empty `bundleId` /
151
+ `uniqueKey`, a method the bundler does not accept, a `CreateSale` without `tokenName`. New exports:
152
+ `LAUNCHPAD_WRITE_METHODS` (`LaunchpadWriteMethod` is now derived from it), types
153
+ `BundleAttachment`, `BundleSocket`, `SocketFactory`. `LaunchpadWriteTransport` gains `attach`.
154
+ - The bundler (bundler-backend origin/main, `src/socket/socket.gateway.ts`) emits only
155
+ `{ status, data }` (lowercase; `PENDING` / `PROCESSED` / `FAILED`), never `{ Status, Data }`, so
156
+ `parseBundleResult` is unchanged.
157
+
158
+ ### The backend's error answer on `NetworkError`
159
+
160
+ - **`serverMessage`, `serverError`, `details`, `body`** (type `NetworkErrorServerAnswer`) beside
161
+ `statusCode`. Before, an HTTP failure was `NetworkError("HTTP <M> <url>: Request failed with status
162
+ code N")` and the backend's body survived only on `originalError.launchpadError`. The launchpad
163
+ backend (origin/main `GlobalExceptionFilter`) answers `{ status, error: true, message }`
164
+ (HttpException: validation pipe, `sendResult`, guards) or `{ statusCode, message }` (CustomError,
165
+ 413, unhandled 500): `serverMessage` is that `message` (an array is joined with `,`, as
166
+ `String(array)` shows it), `serverError` is a string `error` only (`true` is not one), `body` the
167
+ whole body (or the text of a non-JSON answer). Messages are unchanged.
168
+ - **A wrapped NetworkError keeps them**: `new NetworkError(msg, status?, originalError?, answer?)`
169
+ takes the answer of `originalError` (an axios error's response, or another NetworkError) when
170
+ not given, and `handleNetworkError` (the `error-wrapper` `withErrorHandling` wrap services put
171
+ around the client's error) also takes the wrapped NetworkError's status: it was `undefined`
172
+ there. (A bare `createNetworkError(msg, undefined, inner)` does not take the status: the
173
+ gateway-reads golden pins `statusCode` absent on the GalaChain balance read's wrapped 400.)
174
+ `createNetworkError` takes the answer as an optional fourth argument;
175
+ `response-handlers.assertResponseSuccess` puts a 2xx error envelope's body on it.
176
+ - Paths that turned the client's NetworkError into another error now keep it a NetworkError, same
177
+ message: `PoolService.fetchToken`'s 404 "Token not found: <name>" (was a plain `Error`),
178
+ `UserService.uploadProfileImage`'s "Profile image upload failed: ..." for an HTTP refusal (was a
179
+ `ValidationError` `UPLOAD_FAILED`; other failures still are), and `LaunchpadPriceService`'s spot
180
+ price failure now wraps the original.
181
+ - The response interceptor's `launchpadError.error` is set only when the body's `error` is a string
182
+ (it cast the backend's `true` to a string).
183
+
184
+ ### Path parameters are spelled as the backend compares them
185
+
186
+ - `buildEndpoint` (every `StreamTokenServiceBase` service) lowercased EVERY path value. It now
187
+ follows `PATH_PARAM_CASING`, decided per parameter from launchpad-backend origin/main's routes:
188
+ `tokenName` (the pool lookup's `normalizeTokenName`), `address` and `userAddress`
189
+ (`normalizeAddress`) stay lowercased; `assetId` and `targetId` (Mux ids, mixed-case, compared
190
+ exactly), `id` (numeric invite ids) and `code` (invite codes, matched exactly) are sent as given.
191
+ A parameter the table does not name is refused. Changed on the wire: `getRecordingDownload` /
192
+ `deleteRecording` (`/v1/tokens/:tokenName/recordings/:assetId[/download]`) and
193
+ `removeSimulcastTarget` (`/v1/tokens/:tokenName/simulcasts/:targetId`): a mixed-case Mux id was
194
+ lowercased into one the backend does not have; the moderator and overseer `getInviteByCode`
195
+ (`/v1/{moderator,overseer}-invites/code/:code`) send the code as given (generated codes are
196
+ lowercase hex, so only a code typed in another case differs); the invite `:id` routes are
197
+ unchanged in effect (digits).
198
+
199
+ ### `PageInfo` is the backend's `pageInfo`
200
+
201
+ - **`PageInfo` = `{ hasNextPage, endCursor?, hasPreviousPage?, startCursor?, totalCount? }`**, the
202
+ backend's own keys (launchpad-backend origin/main `buildPageInfo`: `endCursor` / `startCursor`
203
+ are `string | null`). It declared `nextCursor` / `prevCursor` / `hasPrevPage`, while every list
204
+ but two passed the backend's `pageInfo` through unchanged (so at run time it was `endCursor`), and
205
+ `PoolService` / `UserService` renamed the backend's keys to the declared ones. Now no list renames:
206
+ pools and user token lists return the backend's `pageInfo` (`pageInfoOf`, which drops a field of
207
+ the wrong type), and the cursor walkers (`autoPaginateWithCursor`, `fetchAllPools`, the vault
208
+ token-name lookup) follow `endCursor` (`nextCursorOf`): `autoPaginateWithCursor` stopped after
209
+ the first page of every passed-through list. They also stop when the backend repeats the cursor
210
+ just used (`fetchAllPools` went back to page 1 on a missing cursor).
211
+ - `totalCount` is set only on results the SDK assembles from every page (`fetchAll...`): the
212
+ backend sends no count. Removed with it: `UserTokenListResult.total` (always undefined), the
213
+ dead `InternalFetchUserBalancesResponse` type, and the top-level `count` / `total` / `nextCursor`
214
+ / `prevCursor` / `hasNextPage` / `hasPrevPage` fields of the internal pool and user-list response
215
+ types (the backend answers `{ tokens | token | launches, pageInfo }`). Migration: read
216
+ `pageInfo.endCursor` (`?? undefined` for a `cursor` option) where you read `nextCursor`.
217
+
218
+ ### `fetchPools` matches `GET /v1/tokens` (launchpad-backend origin/main `FetchPoolDto`)
219
+
220
+ - **`type` and `streamStatus` in the backend's spelling, any case.** `type` RECENT / POPULAR /
221
+ RECORDINGS / SECONDS_STREAMED (`POOL_FETCH_TYPES`; the backend compares case-sensitively, so it is
222
+ sent uppercase), `streamStatus` IDLE / ACTIVE / DISABLED (`POOL_STREAM_STATUSES`). The lookup
223
+ tables were lowercase-keyed and DROPPED the app's `'POPULAR'` / `'ACTIVE'` without a word; lowercase
224
+ still works. A value the backend does not accept is a `ValidationError`, never dropped.
225
+ - **`pageSize` 1 to 100** (`POOL_LIST_MAX_PAGE_SIZE`, the backend's `MediumListQueryDto` maximum):
226
+ it was silently clamped to 20. Larger, zero or fractional is a `ValidationError`. `fetchAllPools`
227
+ reads pages of 100 (was 20). Default still 10.
228
+ - `recentlyStreamed` (integer 1 to 720), `language` (ISO 639-1) and `search` (at most 255) are
229
+ checked before sending, as the backend would refuse them.
230
+ - **`hasUpcomingShows` / `hasRecordings`: only `true` is sent.** The backend's boolean conversion
231
+ (`@Type(() => Boolean)` with implicit conversion) reads `"false"` as true, so `false` used to turn
232
+ the filter ON; it now sends nothing (no filter).
233
+ - `isGraduated` / `creatorAddress` are NOT added: origin/main's `FetchPoolDto` has neither and the
234
+ pipe forbids unknown properties (a 400).
235
+ - One pool-list reader: the private `LaunchpadAPI.fetchPools` / `fetchPoolsFromAPI` copy (used to
236
+ find a vault's token name for a sell-fee quote) is removed; that lookup reads `PoolService`. The
237
+ copy read `hasNextPage` / `nextCursor` at the top of `data`, where the backend never puts them,
238
+ so it never got past page 1. `LaunchpadService` / `fetchAllPools` take `FetchPoolsOptions` (their
239
+ inline option types still named `offset` / `limit`). The zod `poolFetchTypeSchema` takes all four
240
+ types; the public `PoolFetchType` is the one type (`'RECENT' | 'POPULAR' | 'RECORDINGS' |
241
+ 'SECONDS_STREAMED'`, it was the schema's two).
242
+
243
+ ### Admin and overseer contracts (launchpad-backend origin/main)
244
+
245
+ - **`revokeOverseerInvite` and `revokeOverseer` sent no Authorization.** The auth headers were passed
246
+ in the query-params slot of `HttpClient.delete`: the request went out unauthenticated and the
247
+ header names became query parameters. They are headers now (`tests/g3-admin-wire.test.ts`).
248
+ - **Restricted token names carry the session bearer.** `getRestrictedNames` / `updateRestrictedNames`
249
+ (Overseer-only routes) sent no Authorization. An empty `content` is accepted (the backend takes any
250
+ string; it clears the list); `UpdateRestrictedNamesResponse` is `{ content }` (the backend echoes the
251
+ stored content), it was typed `{ success: true }`.
252
+ - **Invite codes are validated like the backend**: any non-empty string up to 64 characters
253
+ (`INVITE_CODE_CONSTRAINT.MAX_LENGTH`, was 100 for overseer codes and "64 hex" for moderator codes).
254
+ An unknown code is the backend's 404, which a claim page relies on to fall through from the overseer
255
+ lookup to the moderator one; it used to be a client-side `ValidationError`.
256
+ - **`sdk.getHealth()`** (`GET /health`, public): `HealthCheckResponse` (`status` plus database, redis,
257
+ mux, rabbitmq, galachain_query, galachain_launchpad). A critical dependency down is HTTP 503 and
258
+ throws a `NetworkError`.
259
+ - **`sdk.getEventStats()`, `sdk.queryEvents(options)`** (`GET /v1/events/stats`, `GET /v1/events`,
260
+ Admin API key or Overseer): the routes answer BARE bodies, which the service reads and shape-checks.
261
+ `queryEvents` pages by `page` / `limit` (1..100). `eventTypes` / `categories` are sent as a
262
+ REPEATED key (one value is sent twice): the backend validates them with `@IsArray` behind Express 5's
263
+ simple query parser, where a comma list or `key[]=` is refused.
264
+ - **`getMessageStats` reads the bare object** `GET /v1/messages/stats` answers (it required a
265
+ `{ data }` envelope and could never succeed against the backend).
266
+
267
+ - **The flag filters validate what `GetFlagsQueryDto` takes**: the token filter is 1-50 letters and digits
268
+ (a 1-character filter threw; see the token name rules below) and the addresses
269
+ (`reporterAddress`, `reportedUserAddress`, also `createFlag`'s) are the forms `@GalaChainAddressField()`
270
+ takes after its normalisation: `eth|<40 hex>`, `0x<40 hex>`, 40 hex, `client|<24 hex>` or 24 hex
271
+ (`isBackendUserAddress` / `assertBackendUserAddress`). A bare client id is accepted now; a partial
272
+ address and `client|<name>` stay refused, because the backend answers 400 for them.
273
+ - **`updateModeratorInvite({ inviteId, description: '' })` is a valid update**: the backend's `UpdateModeratorInviteDto.description` has no minimum and its service updates on
274
+ `description !== undefined`, so `''` alone clears the label (the SDK refused it with "At least one of
275
+ role or description"). An update with neither field is still refused.
276
+
277
+ ### Trades, tokens, users and streaming contracts (launchpad-backend origin/main)
278
+
279
+ - **`fetchTrades` reaches its route.** It sent the literal `/v1/tokens/:tokenName/trades` with the
280
+ name in a query parameter; the token is now in the path (lowercased, as the backend compares it).
281
+ `TradeQueryItem` types `tokenSymbol`, which `GET /v1/trades` returns. `getTrades` already unwrapped
282
+ the `{ data }` body (verified on the wire, `tests/g3-trades-wire.test.ts`).
283
+ - **`fetchTokenStats` returns what the backend sends**: `{ holdersCount, chatMessageCount, commentCount,
284
+ roomCount }` (`TokenStatsData`, was `EngagementStatsData`). It required a `stats` wrapper the backend
285
+ has none of, and so could never succeed; `totalEngagement`, participants and activity fields were
286
+ never sent.
287
+ - **`updateTokenConfig` takes `chatEnabled`** (was `messagesEnabled`, which the backend refuses with 400:
288
+ its `UpdateTokenConfigDto` has `chatEnabled`).
289
+ - **`fetchLaunchpadFee()` returns the number** (`data.feeAmount`); it returned the `{ feeAmount }` object
290
+ typed as a number.
291
+ - **Images reach their routes.** `uploadImageByTokenName` posts to `/v1/tokens/:tokenName/image` (the
292
+ placeholder went out literally, the name in a query parameter) and `uploadProfileImage` to
293
+ `POST /v1/users/me/image` (it used the token route); the profile upload needs no address or wallet.
294
+ - **`updateProfile` sends what is given.** `address` is optional (validated, not sent), `fullName` and
295
+ `profileImage` are optional (at least one), `profileImage: ''` clears the image, and the profile is no
296
+ longer fetched first to send the old image back. `fullName` is validated like the backend's
297
+ `UpdateProfileDto` (a trimmed 2..20 letters, one optional second word) and no wallet is required, only
298
+ a JWT.
299
+ - **User token lists take pages up to 100** (`USER_PAGINATION_CONSTRAINT.MAX_LIMIT` 20 -> 100; the
300
+ backend takes up to 1000, default 50); `getManagedTokens` sends no `pageSize` unless asked, so the
301
+ backend's 50 applies (the SDK's default 10 cut a longer list off).
302
+ - **`fetchVolumeData` returns the chart**: `{ dataPoints, isPreviousData, nextTime? }` with the candles
303
+ typed as the backend sends them (`startTime`, `openPrice`, `highPrice`, `lowPrice`, `closePrice`,
304
+ `volume`); `dataPoints` held the whole `{ data, isPreviousData }` object typed as `{ timestamp, value }[]`.
305
+ - **`getTradeQuote` takes an `AbortSignal`** (`TradeQuoteParams.signal`); `PlatformStatsData` volumes are
306
+ numbers (typed as strings); `listOverseerUsers` accepts `ASC` / `DESC` (the backend reads the order
307
+ case-insensitively).
308
+ - **Recordings match `GET /v1/tokens/:tokenName/recordings`**: a bare array with no paging.
309
+ `getStreamRecordings({ tokenName })` returns `{ recordings, tokenName }` (the fabricated `page`, `limit`,
310
+ `total`, `hasNext` are gone; the old code read `data.recordings` and could never succeed). A recording is
311
+ `{ id, playbackId, status, duration, createdAt, masterAccess, aspectRatio?, assets? }` (was `assetId`,
312
+ `tokenName`, `downloadable`, `fileSize`, `thumbnailUrl`); `RECORDING_STATUS` is Mux's `preparing` /
313
+ `ready` / `errored`. An unknown token is a `NetworkError` with `statusCode` 404.
314
+ - **Simulcasts match `/v1/tokens/:tokenName/simulcasts`**: the list is a bare array behind the owner's
315
+ session bearer (it was sent without Authorization); a target is `{ id, url, status, passthrough? }`;
316
+ `addSimulcastTarget` sends `{ platform, url, streamKey, passthrough? }` with the platform in lowercase
317
+ (`'youtube' | 'twitch' | 'facebook' | 'custom'`, `SIMULCAST_PLATFORM`), as the backend's
318
+ `CreateSimulcastTargetDto` requires (it refused `rtmpUrl`, `name` and uppercase platforms), and the
319
+ URL is RTMP or RTMPS only (the SDK allowed SRT, which the backend refuses).
320
+ - **`sdk.getChatStatus(tokenName)`** (`GET /live/:tokenName/chat`, public): `{ enabled, tokenName,
321
+ reason?, slowModeSeconds?, status? }`. `ChatStatusResponse` gains `tokenName` and `slowModeSeconds`.
322
+ - **The pinned message is the backend's `PinnedMessageData`** (`messageId`, `content`, `userAddress`,
323
+ `pinnedBy`, `pinnedAt`, `user?`, `holderTier?`): `getPinnedMessage` returned a type with `id` and
324
+ `createdAt` the backend never sends, and threw when nothing was pinned (`{ data: null }`); it returns
325
+ `{ message: null }` now. `getPinnedChatMessage` / `pinChatMessage` return that message as it is, and
326
+ `unpinChatMessage` takes its `messageId`.
327
+ - **`UpdateMessageOptions.type`**: a chat edit is capped at 500 characters before it is sent when the
328
+ type is known (`updateChatMessage` passes it).
329
+ - **`PoolData` names the streaming fields the backend sends**: `muxPlaybackId`, `muxStreamAspectRatio`,
330
+ `streamLanguage` (typed `playbackId`, `aspectRatio`, `language`, which the backend does not send, so
331
+ they were always undefined); `streamEnabled`, `messagesEnabled`, `commentsEnabled` are not on a pool.
332
+ - **New `sdk.getUserGalaBalance(address)`** (`GET /v1/users/:address/gala-balance`, public: the GALA
333
+ balance and USD value the backend reads) and **`sdk.fetchReferralCode()`**
334
+ (`GET /v1/connect/users/referrals/code`, JWT: `{ code, username? }`).
335
+ - **`TradesQueryResult` is the one trades result type, and it is not deprecated.** `getTrades`,
336
+ `getRecentTrades` and `getHolderHistory` return the backend's `{ trades, pageInfo }`; the
337
+ `@deprecated` marker (it pointed at `TradesListResult`, an `items`/`meta` type no method returns) and
338
+ `TradesListResult` are gone, and the `getTrades` examples read `pageInfo` (they destructured a `meta`
339
+ the result never had).
340
+ - **`UpdateTokenConfigOptions` is one type.** The package root exported a `token-config.dto` interface
341
+ (social links `string` only) while `updateTokenConfig` took a second one declared beside the message
342
+ types (`string | null`). The backend's `UpdateTokenConfigDto` takes `null` to clear a social link, so
343
+ the one type is the `string | null` form, declared in `token-config.dto` with
344
+ `validateUpdateTokenConfigOptions` (moved with it), and the dead duplicate
345
+ `InternalUpdateTokenConfigResponse` of `messages.dto` is gone.
346
+ - **The pin and invite result types are exported, one meaning per name.** `pinMessage` / `unpinMessage`
347
+ return `PinMessageResult` (`{ success }`) and `getPinnedMessage` returns `PinnedMessageResult`
348
+ (`{ message }`), both now exported from the root; the root's old `PinMessageResult`
349
+ (`{ tokenName, pinnedMessage }`, the shape of a removed REST route) is gone and
350
+ `getPinnedChatMessage` / `pinChatMessage` return `GetPinnedMessageResult`
351
+ (`pinnedMessage` is `null` when another moderator unpinned between the pin and the read back; it was
352
+ cast to non-null). `InviteScope`, `UpdateInviteRoleOptions` and `UpdateInviteRoleResult` are exported;
353
+ the identical `InviteScope` of `streaming.dto` and `ModeratedTokenInviteScope` are the one
354
+ `InviteScope`.
355
+ - **`fetchProfile` is typed and unwrapped.** `fetchProfile(address)` returned the whole
356
+ `{ status, error, message, data }` envelope typed `unknown`; it returns `PublicUserProfile` (the
357
+ backend's `ProfileResponse`: `address`, nullable `fullName` / `profileImage` / `bio`, `stats`
358
+ (`ProfileStats`), the four `BadgeStatus[]` ladders, `isLiveStreaming`, `liveStreamToken`) and a body
359
+ that is not that shape is a `NetworkError` (`Malformed profile response`). The service's no-address
360
+ form (`GET /v1/users/me/profile`, JWT) returns `CurrentUserProfile`. `BadgeStatus`, `ProfileStats`,
361
+ `PublicUserProfile` and `CurrentUserProfile` are exported.
362
+ - **`PoolData` types `badges`** (`PoolBadges`: the `volume` and `engagement` `BadgeStatus[]` ladders the
363
+ backend builds for `GET /v1/tokens` and `/:tokenName`) and the stored `volumeBadge` / `engagementBadge`
364
+ columns. The pool route sends no `chatEnabled`, `streamingEnabled` or `tokenSymbol` (they are not in
365
+ its attribute list), so `PoolData` does not declare them.
366
+ - **Message, comment and chat types are the backend's five shapes** (`GET /v1/messages` and the four write
367
+ answers differ; the SDK typed one invented `BaseContentItem` for all of them). `Message` is the list
368
+ item of `fetchMessages`, `getComments` and `getChatMessages`: `id` and `messageId` (the same string),
369
+ `user` / `userProfile` (the same non-null `{ fullName, profileImage }`), `updatedAt` `string | null`,
370
+ `reactions: { counts, userReacted? }` (was a plain `Record<string, number>`), and no `type`,
371
+ `holderTier` or `isPinned` (the backend sends none of them on a list item). Writes: `sendChatMessage`
372
+ returns `SentChatMessage` (no database id, `holderTier?`), `createComment` / `updateComment` return
373
+ `WrittenComment` (numeric `id` AND `messageId`, no `tokenName`), `updateChatMessage` returns
374
+ `EditedChatMessage` (numeric `id`, `reactions?` as `ReactionData`); `createMessage` / `updateMessage`
375
+ infer the result from `options.type`. `BaseContentItem`, `CommentItem`, `ChatMessageItem`,
376
+ `isChatMessageItem` and the dead `/v1/comments` result types (`CommentData`, `FetchCommentsResult`,
377
+ `PostCommentResult`, `FetchCommentsOptions`, `PostCommentOptions`, `DeleteCommentOptions`, file
378
+ `comment.dto.ts`) are gone; `isMessage` checks the real shape (it needed a `type` no item has, so it
379
+ was false for every item). Each id the examples took from a write (`result.comment.id`, a number, or
380
+ `result.message.id`, undefined) is the `messageId`.
381
+ - **Each method validates the token name of ITS backend route** (launchpad-backend origin/main). The SDK
382
+ refused names the routes take (3-20 everywhere, 2-20 on messages, 50 on trades) and sent names a route
383
+ refuses. Five rules, exported as `TOKEN_NAME_*_CONSTRAINT` (and `TokenNameConstraint`), replace
384
+ `LAUNCHPAD_TOKEN_NAME_CONSTRAINT`, `RELAXED_TOKEN_NAME_CONSTRAINT`, `EXTENDED_TOKEN_NAME_CONSTRAINT`
385
+ and the helpers' silent 3-20 default (`validateTokenName(name, field, constraint)`,
386
+ `isValidTokenName(name, constraint)`, `validateOptionalTokenName(...)` now take the route's rule):
387
+ `DTO` 1-20 letters and digits (`@TokenNameField()` request fields: `fetchPools` filter, `fetchVolumeData`,
388
+ `fetchTokenDistribution`, `fetchUserHolderContext`, `fetchMessages`, `createMessage`, `getTrades`,
389
+ flag create, moderator invites, `banToken`), `FILTER` 1-50 (the flag lists), `PATH` letters and digits
390
+ 1-255 (a raw `:tokenName` the pool lookup resolves, no format check: `fetchToken`, `fetchTokenStats`,
391
+ `updateTokenConfig`, `getTokenConfig`, image upload, every stream, recording, simulcast, ban and chat
392
+ method, `getPinnedMessage`, the user token list filter), `AVAILABILITY` 1-50 characters, any
393
+ (`validateToken`, `checkPool`: `ValidateTokenDto`), `EVENT` 1-100 characters without HTML (the
394
+ `WebSocketAdminService` emits). The root helpers `validateTokenName(name, field, constraint)`,
395
+ `isValidTokenName(name, constraint)` and `validateOptionalTokenName(name, field, constraint)` take the
396
+ rule of the route you name (they had a silent 3-20 default). The chain's launch rule (letters and
397
+ digits, 1+, no cap; what the launch form and `createSale` take) is `tokenNameSchema`,
398
+ `launchTokenDataSchema` and `imageUploadOptionsSchema`; `graphDataOptionsSchema` and
399
+ `graduateTokenOptionsSchema` use the DTO rule (`dtoTokenNameSchema`) and `checkPoolOptionsSchema` the
400
+ availability rule (`availabilityTokenNameSchema`). `TRADES_QUERY_CONSTRAINTS` (a deprecated
401
+ composite) is gone.
402
+ - **The reaction routes take no token name.** `AddReactionDto` is `{ messageId, reactionType }` and the
403
+ backend refuses any other property (whitelist + forbidNonWhitelisted), so `addContentReaction` with a
404
+ `tokenName` answered 400; `AddContentReactionOptions` / `RemoveContentReactionOptions` lose
405
+ `tokenName` and nothing is validated or sent for it.
406
+ - **`uploadTokenImage` and `uploadProfileImage` work on a signer-plus-address SDK.** The facade threw
407
+ "Wallet is required" (and `uploadProfileImage` defaulted the address from the wallet) though
408
+ `POST /v1/tokens/:tokenName/image` and `POST /v1/users/me/image` read the user from the session JWT and
409
+ need nothing else; an app configured with `{ signer, walletAddress, session }` and no `wallet` uploads
410
+ with the session bearer (`tests/g7-uploads-wire.test.ts`). `uploadProfileImage` no longer invents an
411
+ address: one that is given is validated and left out of the request. Their JSDoc described
412
+ `imagePath` options and a Node-only API that do not exist (the options are `{ file }`).
413
+ - **Image uploads send multipart, not JSON.** Both uploads put the `FormData` through an axios instance
414
+ that carries `Content-Type: application/json` as an instance default; the request-level header was only
415
+ left out, so the default survived the merge and axios serialised the body as JSON
416
+ (`{"image":{}}`, the file lost; the 400 the backend answers was the only sign). `HttpClient` now
417
+ clears the Content-Type for a `FormData` body per request (an explicit `undefined`), so the transport
418
+ sets `multipart/form-data` with its boundary (axios' Node adapter, the browser's XHR). The existing
419
+ wire tests swapped the whole instance for one without the default and could not see it;
420
+ `tests/image-upload-multipart-wire.test.ts` (Node, real server) and
421
+ `tests/image-upload-multipart-browser-wire.test.ts` (jsdom XHR, real server, plus the FormData as it
422
+ leaves axios) run the real `createHttpExecutor` instance and read the bytes sent. These are the only
423
+ two multipart paths in the SDK.
424
+ - **One name for an image upload.** `UploadImageByTokenNameOptions.options.tokenName` (a second name that
425
+ went into the URL without being validated) is gone; the path takes the validated `tokenName`. The dead
426
+ `LaunchpadAPI.uploadImageByTokenName` (`POST /launchpad/upload-image`) and
427
+ `LaunchpadAPI.fetchTokenDistribution` (`GET /holders/:tokenName`), routes the backend does not have, are
428
+ removed with their tests (`ImageService` and `PoolService` are the working ones).
429
+
430
+ ### The stream socket: one registry of subscribers (launchpad-backend origin/main)
431
+
432
+ `StreamWebSocketService` keeps ONE registry. `sdk.realtime` is the service of an SDK (built with
433
+ `streamWebSocketUrl`, the reconnect settings and the session's token). Every event the backend emits has a
434
+ typed entry on it (`RealtimeEventPayloads`, read from the emit sites, not from the backend's docs).
435
+
436
+ - **Any number of subscribers per event, per token, per room.** Every `subscribe*` method is synchronous,
437
+ returns that subscriber's OWN unsubscribe (a second call is harmless) and replaces nobody. The old
438
+ single callback slots (`globalCallbacks`, `roomCallbacks`, `globalFeedCallbacks`) are gone: a second
439
+ subscriber used to replace the first and the first's cleanup deleted the second's callback, and
440
+ `subscribeToStream` on a joined token wiped every other subscriber's callbacks. A subscriber that
441
+ throws or rejects is logged and skipped; the others are served. `LaunchpadSDK.watch*` are plain
442
+ subscribers (the fan-out, refcount and room bookkeeping `watchTokenRoomEvent` kept is deleted).
443
+ - **Rooms are refcounted.** A token room, a comment room, the global feed and the events firehose are
444
+ joined on the FIRST subscriber and left on the LAST; never two server subscriptions for one room. A
445
+ leave waits for the join's acknowledgement (a subscribe followed at once by an unsubscribe cannot strand
446
+ the room on the server). A subscribe before the socket is connected registers and joins on connect; with
447
+ `autoConnect` (default) it also opens the socket. It never throws `NOT_CONNECTED`.
448
+ - **Listeners are registered once per socket**, when it is created (they used to be registered again on
449
+ every `connect`, so every reconnect doubled every callback), and removed when it is closed.
450
+ - **Reconnect.** The service acts on the Socket's `connect` (the Manager's `reconnect` fires before the
451
+ socket is connected and used to run `authenticate()` too early). On every connection after the first:
452
+ re-authenticate FIRST with the token current at that moment (`tokenProvider`, never a remembered
453
+ one) if the socket was authenticated, THEN re-join every room that still has a subscriber, THEN call the
454
+ new `onReconnect(listener)` listeners (the app's version never fired, `reconnect` is a Manager event).
455
+ `onConnectionStateChange(listener)` is new. A server-side `io server disconnect` reconnects (socket.io
456
+ does not), and so do `connect()` and a new subscribe after socket.io ran out of reconnection attempts
457
+ (`socket.active` stays true then). `LaunchpadSDKConfig.streamReconnectAttempts` / `streamReconnectDelay` /
458
+ `streamReconnectDelayMax` reach socket.io (a browser app wants `Infinity`, 1000, 10000); defaults stay
459
+ 5 / 2000.
460
+ - **`authenticate(token?)` returns `Promise<boolean>`** (it returned `void` and threw `NOT_CONNECTED`
461
+ when not connected): `true` on `authenticated`; `false` on `exception`, `stream_chat_auth_error`, the
462
+ 10 s timeout, a dropped connection, no token, or a newer `authenticate` / `deauthenticate`. The same
463
+ token on the same connection sends nothing; a different token replaces the pending one and is sent after
464
+ the server answered the one in flight. `LaunchpadSDK.authenticateStreamWebSocket(token?)` takes the
465
+ app's token (or the session's) and returns the boolean. The handshake carries no token any more
466
+ (`StreamWebSocketConfig.authToken` is gone; a static token was presented, expired, on every reconnect).
467
+ - **`deauthenticate()`** (`sdk.deauthenticateStreamWebSocket()`): the server has no message that drops a
468
+ socket's identity, so an authenticated socket is closed and opened again (subscriptions stay registered;
469
+ `onReconnect` fires). `setWallet` / `setWalletProvider` call it.
470
+ - **`joinTokenRoom(token)`** holds a token's room with no listener (the room stays joined while its
471
+ listeners come and go); it returns its own release.
472
+ - **The overseers' firehose** (`subscribeEventsFirehose(listener, filters?)`): one server subscription
473
+ for all subscribers, joined once the socket is authenticated (it is overseer-only) and again after every
474
+ re-authentication. The backend's firehose takes no filters, so each subscriber's
475
+ `{ eventTypes, tokenName, userAddress }` filters are applied client-side.
476
+ - **The comment room.** `COMMENT_*` events are sent to the comment room only; `subscribeCommentCreated`
477
+ (and the new `Updated` / `Deleted`) now emit `subscribe_comment` (it never did, so it received nothing).
478
+ - **User-room and overseer events are delivered to global subscribers** (`subscribeGlobalModeratorAdded`
479
+ / `Removed` / `RoleUpdated` / `InviteCreated`, `subscribeGlobalTokenBanned` / `Unbanned`,
480
+ `subscribeContentFlagged`, `subscribeFlagResolved`, `subscribeAIModerationComplete` / `Failed`,
481
+ `subscribeUserBanned` / `Unbanned`, `subscribeBanEnforcement`, `subscribeTradeUpdateNotify`,
482
+ `subscribeBalanceUpdated(token)`, ...), not only to a token room's subscribers.
483
+ - **Feed subscribers are served whether or not the token room is joined.** The backend sends a client in
484
+ both rooms one copy of an event; the service delivers it to the token subscribers and to the feed
485
+ subscribers (it used to deliver it to the token room only, never to the feed).
486
+ - **New events with typed payloads**: `STREAM_CHAT_UPDATED`, `STREAM_CHAT_DELETED`, `SLOW_MODE_CHANGED`,
487
+ `RECORDING_STATUS`, `RECORDINGS_COUNT_UPDATED`, `SIMULCAST_STATUS`, `DOWNLOAD_READY`,
488
+ `STREAM_CONTROL_STATUS_CHANGED`, `CONTENT_REACTION_ADDED` / `REMOVED`, `COMMENT_UPDATED` / `DELETED`,
489
+ `CONTENT_FLAGGED`, `FLAG_RESOLVED`, `AI_MODERATION_COMPLETE` / `FAILED`, `POOL_CREATED`,
490
+ `TRADE_UPDATE_NOTIFY`, `AI_MODERATION_GLOBAL_STATUS`, `EVENT` (firehose), `exception`.
491
+ `STREAM_COUNTDOWN_UPDATED` / `STREAM_LANGUAGE_UPDATED` are fed from `TOKEN_CONFIG_UPDATED` (the backend no
492
+ longer emits them separately). `getSiteConfigState()` returns the latest site-wide switches.
493
+ `subscribeFeedTokenEvents(cb)` hands every feed token event over named (`{ event, data }`).
494
+ - **A second copy of one occurrence is dropped** for the events the backend sends through two rooms a
495
+ client can be in (`CONTENT_FLAGGED`, `FLAG_RESOLVED`, `AI_MODERATION_*`, `POOL_CREATED`, `OVERSEER_*`):
496
+ within 5 seconds, by id.
497
+ - **A payload with no usable `tokenName` no longer throws inside the socket listener** (`data.tokenName.trim()`,
498
+ `data.content.slice`); it reaches the subscribers of the event for every token and none of a token.
499
+ - **The 30-second replay buffer is removed.** It replayed stale events (trade deltas, candles) to a
500
+ late subscriber as if they were new, and started a timer per event per token; registration now precedes
501
+ the join, so there is no join race left for it to cover.
502
+ - **Replaced APIs (9.0.0 is unpublished: no shims).** `setGlobalCallbacks` -> `addCallbacks(callbacks)`
503
+ (adds, returns the remover); `setGlobalFeedCallbacks`, `unsubscribeFromGlobalFeed` and the Promise form
504
+ of `subscribeToGlobalFeed` -> `subscribeToGlobalFeed(callbacks)` returns an unsubscribe;
505
+ `connectStreamWebSocket(callbacks)` adds subscribers; `subscribeToStream(token, callbacks)` adds, and
506
+ `unsubscribeFromStream(token)` removes only what `subscribeToStream` added. `subscribeEngagementStatsUpdated`
507
+ takes a token. `StreamingEventService` and its `streaming-events` types are deleted: the
508
+ `LaunchpadSDK.on*` methods they backed never fired (nothing fed them); they are now subscribers of the same
509
+ registry (`onStreamChatMessage`, `onViewerCountChanged`, `onUserBanned`, ...: every occurrence the socket
510
+ receives, for any token; join rooms with the `subscribe*` methods or `subscribeToStream`).
511
+ `disconnect()` releases every subscriber, listener and timer and rejects what is pending; the service can be
512
+ used again; `dispose()` (called by `sdk.cleanup()`) is final.
513
+ - **Payload types follow the backend**: `UserBannedEvent` / `UserUnbannedEvent` / `BanEnforcementEvent`
514
+ (`isGlobal`, `isPermanent`, optional `reason` / `expiresAt` / `userAddress`; `tokenName` is `null` for a
515
+ global ban; the type guards accept the banned user's own copy, which has no address),
516
+ `TradeExecutedEvent` (+ `symbol`, `icon`), `BalanceUpdatedEvent` (the backend sends no balances),
517
+ `StreamGlobalStatusEvent` / `StreamChatGlobalStatusEvent` (`updatedAt` optional: `{ enabled }`), and the
518
+ global-feed token types are the token-room types (the feed copies named other fields). `COMMENT_DELETED`
519
+ carries `commentId`, not `messageId`.
520
+
521
+ ### Fixes
522
+
523
+ - `createSale`'s pre-flight refused launches the launch form and the deployed bundler accept (a
524
+ scheme-less link such as `t.me/x`, a lower-case symbol, a name of 2 or 21-25 characters, a
525
+ pre-buy of `5.`). It now refuses only what the bundler (fee window, bad words) or the chain
526
+ (`CreateTokenSaleDTO`, `TokenClass`) refuses: a name of letters and digits (any length), a symbol
527
+ of letters and digits in any case (the chain upper-cases it; the wire carries it as typed), no
528
+ link rules, a non-empty description (at most 1000) and image (at most 500), an integer
529
+ `saleStartTime`, and a plain-decimal pre-buy and curve portions, which are SIGNED in their
530
+ canonical spelling (`5.` -> `5`, `1.50` -> `1.5`: the chain keeps any other spelling a string
531
+ and refuses it). Bad words are still refused by the bundler after signing (it fetches the list).
532
+ `LaunchpadTradeInput`, `LaunchpadExtraFees` and `CreateSaleInput` are exported by name
533
+ (`@since 9.0.0`), and `LaunchpadTradeInput.extraFees` documents what is sent on a buy.
534
+ - `BundleSubmission.wait()` takes `{ signal?: AbortSignal }` beside `timeoutMs` / `pollIntervalMs`
535
+ (`@since 9.0.0`). An aborted wait rejects with `LaunchpadSDKError` `BUNDLE_WAIT_ABORTED`
536
+ (`details.method`, `details.bundleId`; an already aborted signal rejects before a socket is opened
537
+ or a read sent) and stops what it started: the in-flight read (the requestor gets the wait's
538
+ `AbortSignal` as `init.signal`), the pause between reads, the deadline timer, its socket listener
539
+ (an own socket is disconnected, a borrowed `bundleSocketFactory` socket never). Aborting stops
540
+ watching only; `attach` resumes the bundle. A wait that ends for any reason now stops its reads too
541
+ (they used to run on until the deadline, up to 10 minutes). Also: one failed confirmation read (an
542
+ HTTP error, a network error, an unreadable body) no longer rejects the wait with
543
+ `BUNDLE_REQUEST_FAILED` while the socket can still deliver: reads are repeated every
544
+ `pollIntervalMs` until the deadline, and only a verdict (PROCESSED / FAILED), the deadline or an
545
+ abort ends the wait. At the deadline after failing reads the error is `BUNDLE_CONFIRMATION_TIMEOUT`
546
+ with the last failed read in `details.lastReadFailure` (`{ message, status? }`); the deadline
547
+ also holds for a read that never answers.
548
+ - `graduateToken` bought `calculateBuyAmountForGraduation`'s `amount` (the GALA cost of the
549
+ remaining tokens) as the exact-buy token quantity. It buys `remainingTokens`, with the GALA cost
550
+ as `expectedAmount` (the slippage cap).
551
+ - `subscribeToTokenCreations`: an event field that is missing or not a string is its fallback
552
+ (`''`, `preBuyQuantity` `'0'`), never `undefined`; `isFinalized` is `true` only for `true`.
553
+ - Demo tooling: `demo:run` ran every selection interactively and counted failed demos as
554
+ successes (booleans tested with `!= null`); the registry maps each demo's SDK methods, leaves
555
+ the tooling out (130 demos) and `demo:run:method` / `demo:run:endpoint` exist. 131 more boolean
556
+ `!= null` tests in the demos and tests (write demos ran their transfer, wrap and unwrap whatever
557
+ their `EXECUTE_*` flag said) are plain boolean tests, and `tests/constant-boolean-null-check.test.ts`
558
+ refuses the shape.
559
+
560
+ ### The `/bundle` signing schemes (unchanged bytes; for Andy)
561
+
562
+ Two schemes post to the bundler's `/bundle`, and both have callers, so both stay:
563
+ `sdk.launchpad.buyWithNative / buyExactToken / sellWithNative / sellExactToken / createSale`
564
+ (`BundlerTransport`) signs EIP-712 typed data (`signTypedData`, the GalaChain domain; pinned by
565
+ `tests/golden/bundler-typed-data.golden.json`): what the live launchpad frontend
566
+ (launchpad-frontend-v3, `signTypedData` / `eth_signTypedData`) and the MCP trading tools send.
567
+ `sdk.buy()` / `sdk.sell()` (`BundleService.buyToken / sellToken`) sign with the signer's
568
+ `signObject` (native for a private key, personal-sign for a browser wallet): the native app calls
569
+ these (`src/sdk/facades/trade.ts`), as do the examples. Retiring `BundleService`'s trade methods
570
+ needs the native app moved to `sdk.launchpad.*` first (which changes the bytes it sends).
571
+
572
+ ### What moved to gala-core-sdk (the extraction steps, from the 8.1.0 baseline)
573
+
574
+ The gateway token writes (transfer GALA, transfer a token, burn, lock, unlock) moved to
575
+ `@gala-chain/gala-core-sdk` 1.0.0-rc.1 (`GatewayWrites`). `transferGala`, `transferToken`,
576
+ `burnTokens`, `lockTokens` and `unlockTokens` keep their names, signatures, input checks, result
577
+ shapes and error classes and delegate to it; their requests are byte-identical (golden vectors)
578
+ and still go through the SDK's gateway `HttpClient` (the `Sign` header included).
579
+
580
+ The gateway token READS moved to `@gala-chain/gala-core-sdk` 1.0.0-rc.2 (`GatewayReads`):
581
+ `fetchGalaBalance`, `fetchTokenBalance` (tokenId and MUSIC/GMUSIC routes), `fetchTokenDetails`,
582
+ `fetchTokenClassesWithSupply` and the NFT reads keep their names and signatures and delegate to it,
583
+ through the same clients as before (balances and NFT reads through the gateway `HttpClient` with
584
+ its `Sign` header, token classes through the unauthenticated gateway axios instance). The core peer
585
+ range is now `>=1.0.0-rc.3 <2`.
586
+
587
+ The wallet providers and the React hooks moved to `@gala-chain/gala-core-sdk` 1.0.0-rc.3
588
+ (`/providers`, `/react`). `LaunchpadSDKConfig.walletProvider`, `setWalletProvider` and
589
+ `SignatureAuth` take core's `WalletProvider`; a core `PrivateKeyProvider` still gives the SDK's
590
+ services their key.
591
+
592
+ The bridge moved to `@gala-chain/gala-core-sdk` 1.0.0-rc.3 (`/bridge`): `BridgeService`, the
593
+ Ethereum and Solana strategies, `GalaConnectClient`, the bridgeable and wrappable token services
594
+ (with their caches and the offset pagination), `WrapService`, the bridge constants and types, and
595
+ `createSolanaWallet`. `src/bridge/` and those services are gone from launchpad-sdk; the SDK's
596
+ bridge, balance, token-list and wrap methods build core's services (from the SDK's wallet, its
597
+ native signer and its DEX API client) and keep their names. The bridge-out signed payloads are
598
+ byte-identical (golden vectors, unchanged); every GalaConnect request, Ethereum and Solana
599
+ transaction, token-list read and wrap request replays the recorded vectors, and
600
+ `LaunchpadSDK.wrapToken` sends exactly the recorded wrap. `/native` is 337,915 bytes (was 403,450).
601
+
602
+ #### Breaking (the moves)
603
+
604
+ - **The bridge is gala-core-sdk's.** Every bridge export of the browser and node entries is
605
+ REMOVED; import it from `@gala-chain/gala-core-sdk/bridge` (same name unless listed):
606
+
607
+ | Was (launchpad-sdk) | Now (`@gala-chain/gala-core-sdk/bridge`) |
608
+ | --- | --- |
609
+ | `BaseBridgeStrategy`, `EthereumBridgeStrategy`, `SolanaBridgeStrategy`, `GalaConnectClient`, `BridgeStatusCode`, the constants (`CHAIN_IDS`, `GALACHAIN_CHANNELS`, `ETHEREUM_TOKENS_PROD` / `_STAGE`, `DEFAULT_SOLANA_TOKENS`, `ERC20_ABI`, `BRIDGE_CONTRACT_ABI`, ...), the EIP-712 constants, the token math (`toBaseUnits`, `fromBaseUnits`, `formatTokenAmount`, `compareAmounts`), `stripHexPrefix`, and every bridge, bridgeable-token and wrappable-token type | the same name |
610
+ | `BRIDGE_TOKEN_METADATA` | `STATIC_TOKEN_METADATA` |
611
+ | `BridgeRateLimiter` | `RateLimiter` |
612
+ | `DEFAULT_ETHEREUM_TOKENS` (deprecated alias) | `ETHEREUM_TOKENS_PROD` |
613
+ | `GalaConnectHttpError` | `GalaSDKError` with code `GALACONNECT_HTTP_ERROR` (`error.status`, `params.serverMessage`) |
614
+ | `createSolanaWallet`, `GeneratedSolanaWallet` | the same name (it was in the browser and node entries) |
615
+ | `WrapUnwrapStatus`, `WrapUnwrapStatusResult` | removed: a wrap resolves only once completed |
616
+
617
+ `BridgeService`, `BridgeableTokenService`, `WrappableTokenService` and `WrapService`, which
618
+ launchpad-sdk did not export, are exported there too.
619
+ - **Bridge and wrap failures are typed `GalaSDKError`s** (`isGalaError(error, code)`), not
620
+ `ValidationError` / `NetworkError` / `TransactionError` / `GalaConnectHttpError` or a text:
621
+ `INVALID_BRIDGE_AMOUNT`, `INVALID_WALLET_ADDRESS`, `INVALID_TOKEN_REFERENCE`,
622
+ `UNSUPPORTED_BRIDGE_TOKEN`, `BRIDGE_NOT_CONFIGURED`, `INVALID_BRIDGE_OPTION`,
623
+ `INSUFFICIENT_BRIDGE_BALANCE`, `GALACONNECT_HTTP_ERROR`, `BRIDGE_REQUEST_REJECTED`,
624
+ `BRIDGE_RESPONSE_INVALID`, `BRIDGE_READ_RESPONSE_INVALID`, `BRIDGE_TOKEN_NOT_FOUND`,
625
+ `TOKEN_NOT_WRAPPABLE`, `INVALID_WRAP_DIRECTION`, `BRIDGE_CHAIN_READ_FAILED`, and, once something
626
+ may have moved (never repeat it), `BRIDGE_WRITE_OUTCOME_UNKNOWN`, `BRIDGE_OUT_OUTCOME_UNKNOWN`
627
+ (with the bridge request id and the `uniqueKey`), `BRIDGE_DEPOSIT_OUTCOME_UNKNOWN`,
628
+ `BRIDGE_STATUS_TIMEOUT`.
629
+ - **`wrapToken` / `unwrapToken` throw instead of returning `success: false`**: `WrapUnwrapResult`
630
+ is the completed result (`success: true`, `transactionId` and `completedAt` always set; `error`
631
+ and `fee` removed). Their options have no `memo` (it was never sent). **`getWrapStatus` is
632
+ REMOVED** (it always answered "completed" for any id).
633
+ - **`getBridgeStatus(hash)`** takes no chain hint (one GalaConnect read answers for either chain);
634
+ **`estimateBridgeFee`** takes no `amount` (the fee never depended on it).
635
+ - Behaviour on the way: a GalaConnect write is sent again only after a 429 (a 5xx or a failure in
636
+ transit may have been applied: outcome unknown); an `eth|0x...` recipient is accepted; the
637
+ caller's own input (token id, amount, recipient, an unconfigured chain) is refused before any
638
+ read; a malformed RPC URL, contract, wallet address or program id option is refused when the
639
+ service is built.
640
+ - `bs58` and `json-stringify-deterministic` are no longer dependencies (nor, with the 9.0 cut above,
641
+ `@solana/web3.js` and `@solana/spl-token`: core's `/bridge` loads them, at the first bridge
642
+ call). `LaunchpadSDK`'s own
643
+ declarations need no Node types (a consumer of it compiles with TypeScript 6 and 7 without
644
+ them); an app that imports `/bridge` types naming `@solana/web3.js` (e.g. `BridgeServiceConfig`)
645
+ needs Node's types, since `@solana/web3.js`'s declarations import `http` / `https`.
646
+
647
+ - **`@gala-chain/launchpad-sdk/wallet` and `@gala-chain/launchpad-sdk/react` are REMOVED**, and so
648
+ are the wallet exports of the browser entry. Import from core instead (same names unless listed):
649
+
650
+ | Was (launchpad-sdk) | Now (gala-core-sdk) |
651
+ | --- | --- |
652
+ | `/wallet` and the browser entry: `PrivateKeyProvider`, `ExternalWalletProvider`, `GalaWalletProvider`, `detectWallets`, `getWalletByRdns`, `hasAnyWallet`, `isWalletAvailable`, `subscribeToWalletChanges`, `getInjectedEip1193Provider`, `KNOWN_WALLET_RDNS`, `createWalletProvider`, `createProviderFromEip1193`, `ensureConnected`, `getPrivateKeyIfAvailable`, `isPrivateKeyProvider`, `isExternalProvider`, `isEip1193Provider` and the types (`WalletProvider`, `Eip1193Provider`, `DetectedWallet`, ...) | `@gala-chain/gala-core-sdk/providers` |
653
+ | `WalletProviderError`, `WalletProviderErrorCode` | `GalaSDKError` from `@gala-chain/gala-core-sdk`, branched with `isGalaError(error, 'WALLET_CONNECTION_FAILED' \| 'WALLET_NOT_CONNECTED' \| 'SIGNING_FAILED' \| ...)` |
654
+ | `createProviderFromWallet(wallet)`, `walletToProvider(wallet)` | `PrivateKeyProvider.fromWallet(wallet)` |
655
+ | `providerToWallet(provider)` | `isPrivateKeyProvider(p) ? new Wallet(p.exportPrivateKey()) : undefined` (ethers stays the app's) |
656
+ | `/react`: `WalletProvider`, `WalletContext`, `useWallet`, `useWalletContext`, `useWalletConnection`, `useWalletDetection`, `useWalletAddress`, `useGalaAddress`, `useWalletProvider`, `useIsWalletConnected` and their types | `@gala-chain/gala-core-sdk/react` |
657
+ | `/react`'s re-exports `detectWallets`, `ExternalWalletProvider`, `KNOWN_WALLET_RDNS`, `PrivateKeyProvider`, type `WalletProviderInterface` | `@gala-chain/gala-core-sdk/providers` (`WalletProviderInterface` is `WalletProvider`) |
658
+
659
+ A custom `WalletProvider` now needs `getSigner()` (core's interface). `react` is no longer a peer
660
+ of launchpad-sdk (it is an optional peer of core's `/react`).
661
+ - **The Ethereum wallet helpers are gala-core-sdk's.** `createWallet`, `getPublicKeyFromPrivateKey`,
662
+ `getEthereumAddressFromPrivateKey` and the type `PublicKeyResult` are REMOVED from launchpad-sdk
663
+ (browser, node and `/native` entries): import them from `@gala-chain/gala-core-sdk`. Core's
664
+ `createWallet` returns `{ privateKey, address, galaAddress, mnemonic }` without the ethers
665
+ `.wallet`: `new Wallet(createWallet(input).privateKey)`. Refusals are core `GalaSDKError`s
666
+ (`INVALID_WALLET_INPUT`, `INVALID_PRIVATE_KEY`) instead of `ValidationError` / ethers errors; the
667
+ test-mode fake key (`NODE_ENV=test`) is gone. `createSolanaWallet` moved with the bridge (above).
668
+ `AgentConfig` builds its wallets with core's `createWallet`; its wallet type is exported as
669
+ `AgentWallet` (core's wallet plus the ethers `wallet`). The internal `WalletUtils` is gone.
670
+
671
+ - **The token-class and hold types are gala-core-sdk's.** `fetchTokenClassesWithSupply` returns
672
+ `GalaChainTokenClass[]` (was `TokenClassWithSupply`, whose `authorities` were typed as objects:
673
+ GalaChain sends user refs, strings) and `fetchTokenDetails` returns `GalaChainTokenDetails` (was
674
+ launchpad's `GalaChainTokenDetails`, whose `chatEnabled` was never set: a token's chat status is
675
+ `getTokenConfig(tokenName).chatEnabled`). A hold in `TokenBalanceResult` / `LockedBalanceResult`
676
+ is `GalaChainTokenHold` (`name` and `vestingPeriodStart` are optional, as GalaChain stores them).
677
+ Removed exports: `TokenClassWithSupply`, `TokenHold`, the zod `tokenHoldSchema`; import the types
678
+ from `@gala-chain/gala-core-sdk`. A token class carries GalaChain's documented fields only (an
679
+ undocumented field is no longer passed on).
680
+ - **`TokenClassKey` and `TokenInstanceKey` REMOVED**: every signature uses gala-core-sdk's
681
+ `GalaChainTokenClassKey` / `GalaChainTokenInstanceKey` (same four fields, plus `instance`), so
682
+ import those from `@gala-chain/gala-core-sdk`. `TokenId` stays (`string | GalaChainTokenClassKey
683
+ | GalaChainTokenInstanceKey`). The bridge's `isTokenClassKey` export is removed: use core's
684
+ `isTokenClassKey` (the same check: four non-empty strings).
685
+ - `ENVIRONMENT_URLS` takes `gatewayBaseUrl` and `dexApiBaseUrl` from core's
686
+ `GALA_CHAIN_ENVIRONMENTS` (same URLs); `Environment` is core's `GalaChainEnv` (`'prod' | 'stage'`).
687
+ - **The DEX is gswap-sdk's, not launchpad-sdk's.** launchpad-sdk no longer depends on
688
+ `@gala-chain/gswap-sdk` (product SDKs never import each other). Removed: `sdk.dex` (the `GSwap`
689
+ client) and the `GSwap` re-export; the swap-backend reads `fetchAllDexSeasons`,
690
+ `fetchCurrentDexSeason`, `fetchDexLeaderboardBySeasonId`, `fetchCurrentDexLeaderboard`,
691
+ `fetchDexAggregatedVolumeSummary` and the pool poller `onDexPoolCreation`; the types `DexSeason`,
692
+ `LeaderboardEntry`, `LeaderboardResult`, `MasteryTitle`, `DexAggregatedVolumeSummary`. Migration:
693
+
694
+ ```typescript
695
+ import { PrivateKeySigner } from '@gala-chain/gala-core-sdk';
696
+ import { GSwap } from '@gala-chain/gswap-sdk';
697
+
698
+ const gSwap = new GSwap({ env, signer: new PrivateKeySigner(key), walletAddress: sdk.getAddress() });
699
+ // sdk.dex.quoting / swaps / pools / positions / symbols / assets -> gSwap.quoting / swaps / ...
700
+ // sdk.fetchAllDexSeasons() -> gSwap.leaderboard.getSeasons()
701
+ // sdk.fetchCurrentDexSeason() -> gSwap.leaderboard.getCurrentSeason()
702
+ // sdk.fetchDexLeaderboardBySeasonId(id) -> gSwap.leaderboard.getLeaderboard(id) ({ seasonId, entries })
703
+ // sdk.fetchCurrentDexLeaderboard() -> gSwap.leaderboard.getCurrentLeaderboard()
704
+ // sdk.fetchDexAggregatedVolumeSummary() -> gSwap.market.getVolumeSummary() (8 fields)
705
+ // sdk.onDexPoolCreation(cb, { minTVL }) -> gSwap.pools.watchNewPools(cb, { minTvl })
706
+ ```
707
+
708
+ The gswap reads follow the backend's real answers: an answer of another shape is an error, not
709
+ `[]`; an unusable row is skipped (reported to `onInvalidEntry`), not filled with `''` / `0`; a
710
+ leaderboard has no `totalEntries` (`entries.length`) and a wallet without an XP breakdown has
711
+ `totalXp: null` (was `'0'`). `sdk.dex` was also never rebuilt by `setWallet` (it kept the first
712
+ wallet's signer): an app's own `GSwap` is built from the signer it means.
713
+ (The price reads went with the 9.0 cut above: only `fetchTokenPrice({ tokenName })` stays.)
714
+
715
+ - **`sdk.tokens` and `TokenWrites` REMOVED**, with the types `ChainResult`, `TransferInput`,
716
+ `LockInput`, `TokenAmountInput` and `TokenIdentifier`. They were a second implementation of the
717
+ same writes. Migration:
718
+
719
+ ```typescript
720
+ // Removed
721
+ const result = await sdk.tokens.transfer({ to, tokenClassKey: 'GALA|Unit|none|none', quantity: '1' });
722
+
723
+ // Now (the SDK's wallet, or a { signer, walletAddress } SDK)
724
+ const { transactionId, blockNumber } = await sdk.transferToken({ to, tokenId: 'GALA|Unit|none|none', amount: '1' });
725
+ // sdk.tokens.burn / lock / unlock -> sdk.burnTokens / lockTokens / unlockTokens({ tokens: [...] })
726
+ ```
727
+
728
+ What the services do not take that `sdk.tokens` did: a `client|` or `eth|0x...` recipient (spell
729
+ an Ethereum recipient `eth|<40 hex>` or `0x<40 hex>`), any `uniqueKey` (transfer keys keep the
730
+ `galaswap-operation-` / `galaconnect-operation-` prefix rule), a `$`-joined `tokenId`. For
731
+ those, use `GatewayWrites` from `@gala-chain/gala-core-sdk` directly.
732
+
733
+ #### Added
734
+
735
+ - An SDK configured with `{ signer, walletAddress }` (no `wallet`) can make token writes through
736
+ the five methods: signed by that signer and made as the declared identity (an `eth|` account or
737
+ a `client|` alias). With a `wallet` nothing changed.
738
+ - `LockTokensResult`, `UnlockTokensResult` and `BurnTokensResult` carry the gateway's
739
+ `x-transaction-id` as `transactionId` (preferred over a `Data` item's id) and `blockNumber`
740
+ from `x-block-number`, like the transfer receipts.
741
+
742
+ #### Changed
743
+
744
+ - Auto-generated `uniqueKey`s are `galaconnect-operation-<uuid v4>` (58 characters, CSPRNG) instead
745
+ of `galaconnect-operation-<ms>_<26 hex>` (62). An empty `uniqueKey` means "none" (a key is
746
+ minted); it used to be signed as `""` and refused by the chain.
747
+ - A caller's `uniqueKey` on `lockTokens` / `unlockTokens` / `burnTokens` (never checked before), and
748
+ one with characters outside `A-Za-z0-9._:-` on a transfer, is refused before signing.
749
+ - Quantities must be plain decimal strings (no exponent, hex or spaces); they are still signed as
750
+ written, never scaled.
751
+ - A pipe `tokenId` with a non-decimal fifth part (`Token|Unit|X|client|launchpad`, read as instance
752
+ `launchpad`) or a `TokenInstanceKey` with a non-decimal `instance` is refused before signing
753
+ instead of being signed as a different token.
754
+ - Token writes go through the SDK's gateway `HttpClient` (axios, the `Sign` header) as the five
755
+ methods always did; `config.httpRequestor`, which `sdk.tokens` used, is not used for them (it
756
+ still serves the bundler path). An app that must send token writes through its own
757
+ requestor uses core's `GatewayWrites` (`httpRequestor` option).
758
+ - `setWallet` / `setWalletProvider` now rebuild the token-write services, so a transfer, burn,
759
+ lock or unlock signs as the new wallet (before, the services kept signing as the wallet the SDK
760
+ was constructed with); a declared `{ signer, walletAddress }` identity no longer applies once the
761
+ wallet changes.
762
+ - A refusal of the core write before anything is sent maps to the service's error class
763
+ (`SIGNING_FAILED` -> `SIGNATURE_FAILED`, a token reference -> `TOKEN_NOT_FOUND`, a quantity ->
764
+ `INVALID_AMOUNT`, others -> the validation type).
765
+
766
+ #### Fixed (wallet changes)
767
+
768
+ - After `setWallet` / `setWalletProvider` nothing signs as, or sends from, the previous wallet:
769
+ the bundle trades (`buyTokens`, `sellTokens`) are rebuilt for the new wallet (they kept the
770
+ construction wallet, so an SDK started read-only could never trade), and the bridge service, the
771
+ wrap service and the GalaConnect client (built at first use with that wallet's address and key,
772
+ then kept forever) are dropped and rebuilt for the new wallet at their next use.
773
+ - An identity declared at construction (`walletAddress`, `galaChainAddress`, e.g. a `client|`
774
+ alias) named the construction key and is dropped on a wallet change: `getAddress()` was still
775
+ the old one, so the rebuilt services would have paired the new key with the old identity.
776
+ - `SignatureAuth.setWalletProvider` with a key-holding provider (`PrivateKeyProvider`) knows the
777
+ address at once, as `setWallet` does (the synchronous getters threw until `cacheAddress()`); a
778
+ wallet-backed provider still needs `cacheAddress()` and never reports the previous account.
779
+
780
+ #### Fixed (gateway reads)
781
+
782
+ - `fetchGalaBalance` and `fetchTokenBalance` (tokenId and MUSIC/GMUSIC routes) work against the
783
+ real gateway again: their `FetchBalances` body carried `instance: "0"`, which mainnet and testnet
784
+ refuse with HTTP 400 ("whitelistValidation: property instance should not exist", recorded
785
+ 2026-10-13), so every such call threw a `NetworkError`. The body is now the chain DTO
786
+ (`owner, collection, category, type, additionalKey`).
787
+ - A balance record of another owner than the one asked for is never reported as theirs (the read
788
+ answers `null`); a missing owner is refused instead of reading every owner's balances.
789
+ - `availableQuantity` / `lockedQuantity` / `inUseQuantity` are never in exponent form
790
+ (`0.00000001`, not `1e-8`).
791
+ - `fetchNftCollections`, `isNftCollectionAvailable`, `fetchNftTokenClasses` and `fetchNftBalances`
792
+ read GalaChain (`FetchNftCollectionAuthorizationsWithPagination`,
793
+ `FetchTokenClassesWithPagination`, `FetchBalances`, page by page and bounded); they were
794
+ placeholders that always answered `[]` / `true`. `isNftCollectionAvailable` throws when the read
795
+ fails (never "available"), so `claimNftCollection` refuses a name that is already claimed. The
796
+ NFT writes (`claimNftCollection`, `createNftTokenClass`, `mintNft`) still do not reach GalaChain:
797
+ they return a locally made transaction id with status `pending`.
798
+
799
+ #### Fixed (price history; these reads are now the MCP server's, on gswap-sdk, which keeps the fixes)
800
+
801
+ - `fetchAllPriceHistory` reads the series once. It paged it through `fetchPriceHistory` with the
802
+ page NUMBER as the offset (0, 1, 2, ... with 50 per page), so a series over 50 points was
803
+ refetched in full per page (a 120-point series: about 100 requests) and came back with
804
+ overlapping, repeated snapshots; a series that changed between two requests shifted the pages.
805
+ A caller's `offset` / `limit` do not apply to it.
806
+ - `fetchPriceHistory` refuses a `limit` or `pageSize` outside 1-50 and a negative or fractional
807
+ `offset` before any request (`ValidationError`). A `limit` of 0 used to answer `page: NaN`,
808
+ `totalPages: Infinity` (JSON `null`).
809
+
810
+ #### Changed (gateway reads)
811
+
812
+ - A `FetchBalances` / `FetchTokenClasses` answer that is not GalaChain's (a numeric quantity, a hold
813
+ or class missing its fields) is refused whole: a balance is then `null` (as for any unusable
814
+ answer), a token class a `NetworkError`. A token-class answer without the class asked for is a
815
+ `NetworkError` ("Token not found on GalaChain", 404) instead of returning another class.
816
+ `fetchTokenClassesWithSupply` answers one class per key in the order asked (1 to 1000 keys).
817
+
818
+ #### Removed (internal)
819
+
820
+ - `api/dto/{TransferTokenDto,BurnTokensDto,LockTokenDto,UnlockTokenDto}` (and with them
821
+ `@gala-chain/api`'s `ChainCallDTO` on these paths), `utils/token-instance-key.ts`.
822
+ - `GalaChainBalanceService`'s `sumHoldQuantities` / `filterHolds` / `calculateAvailableQuantity`
823
+ (core totals the holds), the `GalaChainTokenBalance` / `InternalGalaChainFetchBalancesResponse` /
824
+ `InternalFetchTokenClassesWithSupplyResponse` types, `BalanceQueryParams.instance`, and
825
+ `@gala-chain/api`'s `TokenClass` on the token-class paths.
826
+ - Dead code: `utils/token-parser` `parseToken` (no caller), `isDelimited`, `isValidTokenFormat`,
827
+ `isPlainTokenSymbol` and its `isTokenClassKey`; `delimiter-parser` `validateTokenObject` (only
828
+ `parseToken` used it); `tokenNormalizer`'s `isTokenClassKeyStrict` re-export, `isTokenInstanceKey`
829
+ and `isTokenIdString`; `unique-key-generator` `generateOperationKey` (no caller; its keys held a
830
+ `|` and exceeded 64 characters); the unimported modules `types/token.types.ts` and
831
+ `types/galachain-api.types.ts` (a third and fourth `TokenClassKey` / `isTokenClassKey`).
832
+ - The GSwap error wrappers `GSwapQuoteError`, `GSwapSwapError`, `GSwapPoolError`,
833
+ `GSwapAssetError`, `GSwapPositionError`, `DexQuoteError`, `DexPoolNotFoundError` and
834
+ `handleGSwapErrorGeneric` (not exported, never thrown: gswap-sdk's `GSwapSDKError` is the DEX
835
+ error); `DexService`'s season, leaderboard and volume reads; `scripts/stage-verify-dex-reads.ts`
836
+ (`verify:stage-dex-reads`, which checked `sdk.dex`).
837
+ - `@gala-chain/gswap-sdk` was then a devDependency only (the examples and the live stage test); with
838
+ the 9.0 cut above it is no dependency of any kind.
839
+
3
840
  ## 6.0.0
4
841
 
5
842
  ### BREAKING CHANGES