Summary
DistributorClient.getUserStats and getTokenStats extract actualUser/actualToken from the parameter, then discard the extracted value and pass the raw parameter to addressToString. The JSDoc on both methods promises an { user: ... } / { token: ... } wrapper-object input form that the type signature (AddressParam = string | Address) does not support and that the body would not handle correctly even if it did.
Where
packages/sdk/src/DistributorClient.ts:106-137
/**
* Get stats for a specific user.
* @param user The address of the user, or an object containing the user address.
*/
public async getUserStats(
user: AddressParam
): Promise<AssembledTransaction<UserStats | undefined>> {
const actualUser = typeof user === "object" ? user.user : user; // ← computed and never used
return executeWithErrorHandling(
() =>
this.client.get_user_stats({ user: addressToString(user) }) as Promise< // ← uses raw `user`
AssembledTransaction<UserStats | undefined>
>,
"Get user statistics"
);
}
getTokenStats (lines 125-137) has the same dead-code shape with actualToken.
Why this is a real bug, not just lint noise
- The JSDoc lies. Consumers who pass
{ user: 'G...' } (per the docstring) will see TypeScript reject it; if they cast around the type, runtime hits addressToString({ user: 'G...' }), which throws or returns garbage.
typeof user === 'object' is true for Address instances, so actualUser becomes (addressInstance as any).user (undefined) — a footgun if the unused variable is ever wired up later.
- The dead destructure suggests this was supposed to be the parameter unwrapping logic and was abandoned mid-refactor — easy to misread on next-touch.
The other Distributor methods (distributeEqual, distributeWeighted, setAdmin, etc., lines 50-83 / 200+) accept AddressParam and call addressToString(...) directly with no destructure. That's the correct shape; getUserStats/getTokenStats should match.
Fix
Pick one of:
Option A — drop the dead code (recommended, minimal change):
public async getUserStats(user: AddressParam) {
return executeWithErrorHandling(
() => this.client.get_user_stats({ user: addressToString(user) }) as Promise<...>,
"Get user statistics"
);
}
Update the JSDoc to remove the "or an object containing the user address" claim. Apply the same to getTokenStats.
Option B — actually support the wrapper form by widening AddressParam to string | Address | { user: AddressParam } (and likewise for token). Adds API surface; only worth it if there's a real caller asking for it.
Acceptance criteria
Summary
DistributorClient.getUserStatsandgetTokenStatsextractactualUser/actualTokenfrom the parameter, then discard the extracted value and pass the raw parameter toaddressToString. The JSDoc on both methods promises an{ user: ... }/{ token: ... }wrapper-object input form that the type signature (AddressParam = string | Address) does not support and that the body would not handle correctly even if it did.Where
packages/sdk/src/DistributorClient.ts:106-137getTokenStats(lines 125-137) has the same dead-code shape withactualToken.Why this is a real bug, not just lint noise
{ user: 'G...' }(per the docstring) will see TypeScript reject it; if they cast around the type, runtime hitsaddressToString({ user: 'G...' }), which throws or returns garbage.typeof user === 'object'is true forAddressinstances, soactualUserbecomes(addressInstance as any).user(undefined) — a footgun if the unused variable is ever wired up later.The other
Distributormethods (distributeEqual,distributeWeighted,setAdmin, etc., lines 50-83 / 200+) acceptAddressParamand calladdressToString(...)directly with no destructure. That's the correct shape;getUserStats/getTokenStatsshould match.Fix
Pick one of:
Option A — drop the dead code (recommended, minimal change):
Update the JSDoc to remove the "or an object containing the user address" claim. Apply the same to
getTokenStats.Option B — actually support the wrapper form by widening
AddressParamtostring | Address | { user: AddressParam }(and likewise for token). Adds API surface; only worth it if there's a real caller asking for it.Acceptance criteria
actualUser/actualTokenlocals.string | Addressinput form.