Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions core/src/exchanges/opinion/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,10 @@ export interface OpinionRawOrder {
// ----------------------------------------------------------------------------

interface OpinionApiResponse<T> {
errno: number;
errmsg: string;
code?: number;
msg?: string;
errno?: number;
errmsg?: string;
result: T;
}

Expand Down Expand Up @@ -589,9 +591,10 @@ export class OpinionFetcher implements IExchangeFetcher<OpinionRawMarket, Opinio
* Validates that the API response envelope indicates success (code === 0).
*/
private assertSuccess(data: OpinionApiResponse<any>): void {
if (data.errno !== 0) {
const code = data.code ?? data.errno;
if (code !== 0) {
throw new Error(
`Opinion API error (errno ${data.errno}): ${data.errmsg || 'Unknown error'}`,
`Opinion API error (code ${code ?? 'unknown'}): ${data.msg || data.errmsg || 'Unknown error'}`,
);
}
}
Expand Down
12 changes: 8 additions & 4 deletions core/src/exchanges/opinion/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,11 @@ export class OpinionExchange extends PredictionMarketExchange {
const client = await auth.getClobClient();
const response = await client.placeOrder(built.raw);

if (response.errno !== 0) {
const errorCode = response.code ?? response.errno;
const errorMessage = response.msg || response.errmsg || 'Unknown error';
if (errorCode !== 0) {
throw new Error(
`Order submission failed: ${response.errmsg} (errno: ${response.errno})`,
`Order submission failed: ${errorMessage} (code: ${errorCode ?? 'unknown'})`,
);
}

Expand Down Expand Up @@ -437,9 +439,11 @@ export class OpinionExchange extends PredictionMarketExchange {

const response = await client.cancelOrder(orderId);

if (response.errno !== 0) {
const errorCode = response.code ?? response.errno;
const errorMessage = response.msg || response.errmsg || 'Unknown error';
if (errorCode !== 0) {
throw new Error(
`Order cancellation failed: ${response.errmsg} (errno: ${response.errno})`,
`Order cancellation failed: ${errorMessage} (code: ${errorCode ?? 'unknown'})`,
);
}

Expand Down
46 changes: 46 additions & 0 deletions core/test/exchanges/opinion-fetcher-envelope.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { OpinionFetcher } from '../../src/exchanges/opinion/fetcher';
import { FetcherContext } from '../../src/exchanges/interfaces';

function makeFetcher(data: unknown) {
const get = jest.fn(async () => ({ data }));
const ctx: FetcherContext = {
http: { get } as any,
callApi: jest.fn() as any,
getHeaders: jest.fn(() => ({ Authorization: 'Bearer test' })),
};
return new OpinionFetcher(ctx, 'https://api.opinion.test');
}

describe('OpinionFetcher response envelopes', () => {
it('accepts documented code/msg success envelopes', async () => {
const rawMarket = { id: 42, question: 'Will it work?' } as any;
const fetcher = makeFetcher({
code: 0,
msg: 'success',
result: { data: rawMarket },
});

await expect(fetcher.fetchRawMarketById(42)).resolves.toBe(rawMarket);
});

it('rejects documented code/msg error envelopes', async () => {
const fetcher = makeFetcher({
code: 123,
msg: 'bad request',
result: null,
});

await expect(fetcher.fetchRawMarketById(42)).rejects.toThrow('Opinion API error (code 123): bad request');
});

it('continues to accept legacy errno/errmsg envelopes', async () => {
const rawMarket = { id: 43, question: 'Legacy?' } as any;
const fetcher = makeFetcher({
errno: 0,
errmsg: 'success',
result: { data: rawMarket },
});

await expect(fetcher.fetchRawMarketById(43)).resolves.toBe(rawMarket);
});
});
Loading