Skip to content
Merged
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
65 changes: 6 additions & 59 deletions src/__tests__/unit/v2-trading-service-init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { TradingService } from '../../services/trading-service.js';
import { RateLimiter } from '../../core/rate-limiter.js';
import { createUnifiedCache } from '../../core/unified-cache.js';
import { PolymarketSDK } from '../../index.js';

const ENV_KEY = 'POLY_BUILDER_CODE';
const VALID_PK = '0x' + '1'.repeat(64);
Expand Down Expand Up @@ -112,61 +111,9 @@ describe('TradingService V2 — builder-code gating', () => {
});
});

describe('PolymarketSDK V2 — builderCreds without builderCode is fail-fast', () => {
let prev: string | undefined;

beforeEach(() => {
prev = process.env.POLY_BUILDER_CODE;
delete process.env.POLY_BUILDER_CODE;
});

afterEach(() => {
if (prev === undefined) {
delete process.env.POLY_BUILDER_CODE;
} else {
process.env.POLY_BUILDER_CODE = prev;
}
});

it('throws clear migration error when builderCreds provided but builderCode missing', () => {
expect(
() =>
new PolymarketSDK({
privateKey: VALID_PK,
builderCreds: { key: 'k', secret: 's', passphrase: 'p' },
})
).toThrow(/builderCreds.*builderCode|POLY_BUILDER_CODE/);
});

it('does not throw when both builderCreds and builderCode are provided', () => {
expect(
() =>
new PolymarketSDK({
privateKey: VALID_PK,
builderCreds: { key: 'k', secret: 's', passphrase: 'p' },
builderCode: VALID_BUILDER_CODE,
})
).not.toThrow();
});

it('does not throw when builderCreds is omitted (relayer-less paths)', () => {
expect(
() =>
new PolymarketSDK({
privateKey: VALID_PK,
builderCode: VALID_BUILDER_CODE,
})
).not.toThrow();
});

it('accepts builderCreds when POLY_BUILDER_CODE env supplies the code', () => {
process.env.POLY_BUILDER_CODE = VALID_BUILDER_CODE;
expect(
() =>
new PolymarketSDK({
privateKey: VALID_PK,
builderCreds: { key: 'k', secret: 's', passphrase: 'p' },
})
).not.toThrow();
});
});
// NOTE: The 4 PolymarketSDK fail-fast tests covering `builderCreds` without
// `builderCode` were removed alongside the `PolymarketSDKConfig.builderCreds`
// field itself (chore/v2-cleanup-builder-creds, 2026-05-05). After the V2
// cutover that field carried no behaviour — HMAC creds are now consumed only
// by `RelayerService`, instantiated directly. The fail-fast guard had nothing
// left to guard.
21 changes: 6 additions & 15 deletions src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,27 +266,18 @@ export interface PolySDKOptions {
*/
mempoolWssUrl?: string;

/**
* Builder API credentials (HMAC three-tuple) for the **Relayer / gasless TX**
* envelope path (`@polymarket/builder-signing-sdk`). Still required after the
* 2026-04-28 V2 cutover for Safe deployment / approvals / fund movement.
*
* NOTE: V2 order signing no longer uses HMAC creds — order attribution is
* now carried by the bytes32 `builderCode` (see `builderCode` below). Pass
* both fields when running a full Builder flow.
*/
builderCreds?: {
key: string;
secret: string;
passphrase: string;
};

/**
* V2 builder code (bytes32, e.g. `0x...64hex`). Embedded in every signed
* order's `Order.builder` field for on-chain attribution. Falls back to the
* `POLY_BUILDER_CODE` env var when omitted.
*
* Required for any path that places orders post-2026-04-28 cutover.
*
* NOTE: HMAC builder creds (`{ key, secret, passphrase }`) are NO LONGER
* accepted on this config. After the V2 cutover they are only consumed by
* `RelayerService` for gasless TX envelopes (Safe deploy / wrap / transfer);
* instantiate `RelayerService` directly with `RelayerServiceConfig.builderCreds`
* if you need that path.
*/
builderCode?: string;

Expand Down
41 changes: 8 additions & 33 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,36 +647,12 @@ export class PolymarketSDK {
private _initialized = false;

constructor(config: PolymarketSDKConfig = {}) {
// -----------------------------------------------------------------------
// V2 migration guard: fail-fast if caller still relies on V1-style HMAC
// creds for order signing.
//
// Background: pre-V2, `builderCreds` (HMAC three-tuple) flowed into the
// trading path and produced a HMAC-signed builder header. Post-2026-04-28
// V2 cutover, order attribution moved to a bytes32 `builderCode` embedded
// directly in the order struct, and HMAC creds are only used for the
// Relayer / gasless TX path. TypeScript's structural typing still accepts
// an old `{ builderCreds }` config object on `PolymarketSDKConfig` (the
// field stays on `PolySDKOptions` because Relayer needs it), so without
// an explicit guard the SDK silently drops the old auth and the first
// signed order surfaces the V1→V2 drift only at runtime.
//
// We require: when `builderCreds` is supplied, `builderCode` (or the
// `POLY_BUILDER_CODE` env) MUST also be supplied. This catches the
// ambiguous "still on the V1 mental model" call sites without breaking
// pure-Relayer setups (which would normally not pass `builderCreds`
// through `PolymarketSDK`'s constructor anyway).
// -----------------------------------------------------------------------
if (config.builderCreds && !config.builderCode && !process.env.POLY_BUILDER_CODE) {
throw new Error(
'PolymarketSDK: `builderCreds` (V1 HMAC three-tuple) is no longer used ' +
'for order signing after the 2026-04-28 V2 cutover. Order attribution ' +
'is now carried by the bytes32 `builderCode` (Order.builder field). ' +
'Set the POLY_BUILDER_CODE env var (32-byte hex) or pass ' +
'`builderCode` in `PolymarketSDKConfig` alongside `builderCreds`. ' +
'See guide-polymarket-v2-migration for the full migration path.'
);
}
// V2 cutover (2026-04-28): order attribution is carried by the bytes32
// `builderCode` (Order.builder field), not by HMAC builder creds. The
// `PolymarketSDKConfig.builderCreds` field has been removed — HMAC creds
// are now only consumed by `RelayerService` directly for gasless TX
// envelopes (Safe deploy / wrap / transfer).
// See guide-polymarket-v2-migration for the full migration path.

// Initialize infrastructure
this.rateLimiter = new RateLimiter();
Expand All @@ -694,9 +670,8 @@ export class PolymarketSDK {
privateKey,
chainId: config.chainId,
credentials: config.creds,
// V2: order signing uses `builderCode` (bytes32). HMAC `builderCreds`
// are still on the SDK options (for Relayer), but no longer flow into
// the trading path.
// V2: order signing uses `builderCode` (bytes32) — HMAC creds belong
// to `RelayerService`, not the trading path.
builderCode: config.builderCode,
safeAddress: config.safeAddress,
dataApi: this.dataApi,
Expand Down
14 changes: 4 additions & 10 deletions src/services/order-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,6 @@ export interface OrderManagerConfig {
pollingInterval?: number;
/** RPC URL for Polygon provider (for settlement tracking) */
polygonRpcUrl?: string;
/**
* Builder API HMAC credentials. Retained on the OrderManager surface for
* compatibility / Relayer-side flows; **not** consumed by V2 order signing
* (use `builderCode` instead).
*/
builderCreds?: { key: string; secret: string; passphrase: string };
/**
* V2 builder code (bytes32). Embedded in every signed order's `builder`
* field on V2. Falls back to `POLY_BUILDER_CODE` env var when omitted.
Expand Down Expand Up @@ -702,7 +696,7 @@ export class OrderManager extends EventEmitter {
private polygonProvider: ethers.providers.Provider | null = null;

// ========== Configuration ==========
private config: Required<Omit<OrderManagerConfig, 'builderCreds' | 'builderCode' | 'safeAddress'>> & Pick<OrderManagerConfig, 'builderCreds' | 'builderCode' | 'safeAddress'>;
private config: Required<Omit<OrderManagerConfig, 'builderCode' | 'safeAddress'>> & Pick<OrderManagerConfig, 'builderCode' | 'safeAddress'>;
private initialized = false;

// ========== Monitoring State ==========
Expand Down Expand Up @@ -734,9 +728,9 @@ export class OrderManager extends EventEmitter {
const cache = config.cache || createUnifiedCache();

// Initialize TradingService (always needed)
// V2: order signing reads `builderCode` (bytes32)HMAC `builderCreds`
// are no longer threaded into TradingService, but remain on the
// OrderManagerConfig for upstream Relayer flows.
// V2: order signing reads `builderCode` (bytes32). HMAC creds are no
// longer threaded through OrderManager — RelayerService owns that path
// directly (gasless TX envelopes for deploy/wrap/transfer).
this.tradingService = new TradingService(
rateLimiter,
cache,
Expand Down
Loading