Skip to content

Commit 17b0b5b

Browse files
committed
feat: add lpv3 error codes to sdk
1 parent 41301ea commit 17b0b5b

6 files changed

Lines changed: 352 additions & 18 deletions

File tree

packages/core/src/lib/light_push/light_push.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { PeerId, Stream } from "@libp2p/interface";
22
import {
33
type IEncoder,
44
type IMessage,
5+
inferProtocolVersion,
56
isSuccess as isV3Success,
67
type Libp2p,
78
type LightPushCoreResult,
@@ -217,6 +218,9 @@ export class LightPushCore {
217218
};
218219
}
219220

221+
// Determine protocol version for response handling
222+
const protocolVersion = inferProtocolVersion(response.statusCode !== undefined);
223+
220224
if (protocol === LightPushCodecV3 && response.statusCode !== undefined) {
221225
if (!isV3Success(response.statusCode)) {
222226
const error = toLightPushError(response.statusCode);
@@ -229,7 +233,8 @@ export class LightPushCore {
229233
error,
230234
peerId: peerId,
231235
statusCode: response.statusCode,
232-
statusDesc: response.statusDesc || response.info
236+
statusDesc: response.statusDesc || response.info,
237+
protocolVersion
233238
}
234239
};
235240
}
@@ -247,7 +252,8 @@ export class LightPushCore {
247252
success: null,
248253
failure: {
249254
error: LightPushError.RLN_PROOF_GENERATION,
250-
peerId: peerId
255+
peerId: peerId,
256+
protocolVersion
251257
}
252258
};
253259
}
@@ -259,7 +265,8 @@ export class LightPushCore {
259265
failure: {
260266
error: LightPushError.REMOTE_PEER_REJECTED,
261267
peerId: peerId,
262-
statusDesc: response.info
268+
statusDesc: response.info,
269+
protocolVersion
263270
}
264271
};
265272
}

packages/interfaces/src/light_push.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,28 @@ export function getStatusDescription(
112112
`Unknown status code: ${statusCode}`
113113
);
114114
}
115+
116+
/**
117+
* Maps a protocol codec string to a version identifier
118+
* @param codec - The protocol codec string (e.g., "/vac/waku/lightpush/3.0.0")
119+
* @returns Version string (e.g., "v3", "v2") or "unknown" if not recognized
120+
*/
121+
export function getProtocolVersion(codec: string): string {
122+
if (codec.includes('3.0.0')) {
123+
return 'v3';
124+
}
125+
if (codec.includes('2.0.0')) {
126+
return 'v2';
127+
}
128+
return 'unknown';
129+
}
130+
131+
/**
132+
* Determines protocol version from status code presence
133+
* v3 protocols include statusCode, v2 protocols do not
134+
* @param hasStatusCode - Whether the response includes a status code
135+
* @returns Version string ("v3" or "v2")
136+
*/
137+
export function inferProtocolVersion(hasStatusCode: boolean): string {
138+
return hasStatusCode ? 'v3' : 'v2';
139+
}

packages/interfaces/src/protocols.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ export interface LightPushFailure {
188188
peerId?: PeerId;
189189
statusCode?: number;
190190
statusDesc?: string;
191+
/** Protocol version used when the failure occurred (v2, v3, etc.) */
192+
protocolVersion?: string;
191193
}
192194

193195
export interface FilterFailure {
@@ -218,7 +220,13 @@ export type LightPushSDKResult = ThisAndThat<
218220
PeerId[],
219221
"failures",
220222
LightPushFailure[]
221-
>;
223+
> & {
224+
/**
225+
* Protocol versions used per peer during this send operation
226+
* Key: peer ID string, Value: protocol version (e.g., "v2", "v3")
227+
*/
228+
protocolVersions?: Record<string, string>;
229+
};
222230

223231
export type FilterSDKResult = ThisAndThat<
224232
"successes",

packages/sdk/src/light_push/light_push.spec.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
Libp2p,
1212
LightPushError,
1313
LightPushStatusCode,
14-
ProtocolError,
14+
toLightPushError,
1515
toProtocolError
1616
} from "@waku/interfaces";
1717
import { utf8ToBytes } from "@waku/utils/bytes";
@@ -153,8 +153,13 @@ describe("LightPush SDK", () => {
153153

154154
expect(isSuccess(LightPushStatusCode.SUCCESS)).to.be.true;
155155
expect(isSuccess(LightPushStatusCode.BAD_REQUEST)).to.be.false;
156+
// Test the new v3 error mapping function
157+
expect(toLightPushError(LightPushStatusCode.PAYLOAD_TOO_LARGE)).to.eq(
158+
LightPushError.PAYLOAD_TOO_LARGE
159+
);
160+
// Test backward compatibility with the deprecated function
156161
expect(toProtocolError(LightPushStatusCode.PAYLOAD_TOO_LARGE)).to.eq(
157-
ProtocolError.SIZE_TOO_BIG
162+
LightPushError.PAYLOAD_TOO_LARGE
158163
);
159164
});
160165

@@ -204,9 +209,18 @@ describe("LightPush SDK", () => {
204209
];
205210

206211
statusCodes.forEach((code) => {
207-
const protocolError = toProtocolError(code);
208-
expect(protocolError).to.be.a("string");
209-
expect(Object.values(ProtocolError)).to.include(protocolError);
212+
// Test the new v3 mapping function
213+
const lightPushError = toLightPushError(code);
214+
expect(lightPushError).to.be.a("string");
215+
expect(Object.values(LightPushError)).to.include(lightPushError);
216+
217+
// Test backward compatibility - deprecated function now returns LightPushError values
218+
const deprecatedError = toProtocolError(code);
219+
expect(deprecatedError).to.be.a("string");
220+
expect(Object.values(LightPushError)).to.include(deprecatedError);
221+
222+
// Both functions should return the same value for consistency
223+
expect(lightPushError).to.eq(deprecatedError);
210224
});
211225
});
212226
});

packages/sdk/src/light_push/light_push.ts

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ConnectionManager, LightPushCore } from "@waku/core";
33
import {
44
type IEncoder,
55
ILightPush,
6+
inferProtocolVersion,
67
type IMessage,
78
type ISendOptions,
89
type Libp2p,
@@ -62,6 +63,26 @@ export class LightPush implements ILightPush {
6263
return this.protocol.multicodec;
6364
}
6465

66+
/**
67+
* Get all supported protocol codecs
68+
* @returns Array of supported protocol codec strings
69+
*/
70+
public get multicodecs(): string[] {
71+
return this.protocol.multicodecs;
72+
}
73+
74+
/**
75+
* Get supported protocol versions
76+
* @returns Array of supported version strings (e.g., ['v2', 'v3'])
77+
*/
78+
public get supportedVersions(): string[] {
79+
return this.protocol.multicodecs.map(codec => {
80+
if (codec.includes('3.0.0')) return 'v3';
81+
if (codec.includes('2.0.0')) return 'v2';
82+
return 'unknown';
83+
});
84+
}
85+
6586
public start(): void {
6687
this.retryManager.start();
6788
}
@@ -100,17 +121,63 @@ export class LightPush implements ILightPush {
100121
pubsubTopic: encoder.pubsubTopic
101122
});
102123

124+
// Track protocol versions used per peer
125+
const protocolVersions: Record<string, string> = {};
126+
103127
const coreResults: LightPushCoreResult[] =
104128
peerIds?.length > 0
105129
? await Promise.all(
106-
peerIds.map((peerId) =>
107-
this.protocol.send(encoder, message, peerId).catch((_e) => ({
108-
success: null,
109-
failure: {
110-
error: LightPushError.GENERIC_FAIL
130+
peerIds.map(async (peerId) => {
131+
try {
132+
const result = await this.protocol.send(encoder, message, peerId);
133+
134+
// Enhanced error logging with protocol version information
135+
if (result.failure) {
136+
const peerIdStr = peerId.toString();
137+
const protocolVersion = result.failure.protocolVersion || inferProtocolVersion(result.failure.statusCode !== undefined);
138+
protocolVersions[peerIdStr] = protocolVersion;
139+
140+
log.warn(
141+
`Failed to send to peer ${peerIdStr} (${protocolVersion}): ${result.failure.error}`,
142+
{
143+
peerId: peerIdStr,
144+
protocolVersion,
145+
error: result.failure.error,
146+
statusCode: result.failure.statusCode,
147+
statusDesc: result.failure.statusDesc
148+
}
149+
);
150+
151+
// Ensure protocolVersion is set in failure
152+
if (!result.failure.protocolVersion) {
153+
result.failure.protocolVersion = protocolVersion;
154+
}
155+
} else if (result.success) {
156+
// For successful sends, we need to infer protocol version from peer capabilities
157+
// This is a best-effort approach since success responses don't always contain version info
158+
const peerIdStr = peerId.toString();
159+
protocolVersions[peerIdStr] = 'v3'; // Assume v3 for successful sends (will be corrected if needed)
160+
161+
log.info(`Successfully sent to peer ${peerIdStr}`);
111162
}
112-
}))
113-
)
163+
164+
return result;
165+
} catch (error) {
166+
const peerIdStr = peerId.toString();
167+
protocolVersions[peerIdStr] = 'unknown';
168+
169+
log.error(`Exception sending to peer ${peerIdStr}:`, error);
170+
171+
return {
172+
success: null,
173+
failure: {
174+
error: LightPushError.GENERIC_FAIL,
175+
peerId,
176+
protocolVersion: 'unknown'
177+
}
178+
};
179+
}
180+
})
114181
)
115182
: [];
116183

@@ -121,15 +188,17 @@ export class LightPush implements ILightPush {
121188
.map((v) => v.success) as PeerId[],
122189
failures: coreResults
123190
.filter((v) => v.failure)
124-
.map((v) => v.failure) as LightPushFailure[]
191+
.map((v) => v.failure) as LightPushFailure[],
192+
protocolVersions
125193
}
126194
: {
127195
successes: [],
128196
failures: [
129197
{
130198
error: LightPushError.NO_PEER_AVAILABLE
131199
}
132-
]
200+
],
201+
protocolVersions: {}
133202
};
134203

135204
if (options.autoRetry && results.successes.length === 0) {

0 commit comments

Comments
 (0)