Skip to content

Commit 1eee8a3

Browse files
fix: update tests for security hardening changes (wallet validation, CORS deny-all, health check)
- Use valid base58 wallet addresses in tests (was 'WalletA', now fails param validation) - Update CORS tests to expect deny-all default (was allow-all) - Update health/ready test to accept additional bags dependency field - Fix BagsClient test mock to match ClaimTransaction Zod schema - Fix BagsSdkAdapter type casts (Record<string,unknown> -> direct property access)
1 parent 3a639ce commit 1eee8a3

File tree

5 files changed

+45
-44
lines changed

5 files changed

+45
-44
lines changed

backend/src/clients/BagsSdkAdapter.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -138,23 +138,23 @@ export class BagsSdkAdapter implements BagsAdapter {
138138
otherAmountThreshold: sdkQuote.minOutAmount, // SDK maps this
139139
priceImpactPct: sdkQuote.priceImpactPct,
140140
slippageBps: sdkQuote.slippageBps,
141-
routePlan: sdkQuote.routePlan?.map((leg: Record<string, unknown>) => ({
142-
venue: (leg.venue as string) ?? '',
143-
inAmount: (leg.inAmount as string) ?? '',
144-
outAmount: (leg.outAmount as string) ?? '',
145-
inputMint: (leg.inputMint as string) ?? '',
146-
outputMint: (leg.outputMint as string) ?? '',
147-
inputMintDecimals: (leg.inputMintDecimals as number) ?? 0,
148-
outputMintDecimals: (leg.outputMintDecimals as number) ?? 0,
149-
marketKey: (leg.marketKey as string) ?? '',
150-
data: (leg.data as string) ?? '',
141+
routePlan: sdkQuote.routePlan?.map((leg) => ({
142+
venue: String(leg.venue ?? ''),
143+
inAmount: String(leg.inAmount ?? ''),
144+
outAmount: String(leg.outAmount ?? ''),
145+
inputMint: String(leg.inputMint ?? ''),
146+
outputMint: String(leg.outputMint ?? ''),
147+
inputMintDecimals: Number(leg.inputMintDecimals ?? 0),
148+
outputMintDecimals: Number(leg.outputMintDecimals ?? 0),
149+
marketKey: String(leg.marketKey ?? ''),
150+
data: String(leg.data ?? ''),
151151
})) ?? [],
152152
platformFee: {
153-
amount: (sdkQuote.platformFee as Record<string, unknown>)?.amount as string ?? '0',
154-
feeBps: (sdkQuote.platformFee as Record<string, unknown>)?.feeBps as number ?? 0,
155-
feeAccount: (sdkQuote.platformFee as Record<string, unknown>)?.feeAccount as string ?? '',
156-
segmenterFeeAmount: (sdkQuote.platformFee as Record<string, unknown>)?.segmenterFeeAmount as string ?? '0',
157-
segmenterFeePct: (sdkQuote.platformFee as Record<string, unknown>)?.segmenterFeePct as number ?? 0,
153+
amount: String(sdkQuote.platformFee?.amount ?? '0'),
154+
feeBps: Number(sdkQuote.platformFee?.feeBps ?? 0),
155+
feeAccount: String(sdkQuote.platformFee?.feeAccount ?? ''),
156+
segmenterFeeAmount: String(sdkQuote.platformFee?.segmenterFeeAmount ?? '0'),
157+
segmenterFeePct: Number(sdkQuote.platformFee?.segmenterFeePct ?? 0),
158158
},
159159
outTransferFee: sdkQuote.outTransferFee ?? '0',
160160
simulatedComputeUnits: sdkQuote.simulatedComputeUnits ?? 0,

backend/tests/api-routes.test.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function createMockDb() {
3838

3939
const mockStrategy = {
4040
strategyId: 'strat-0001',
41-
ownerWallet: 'WalletA',
41+
ownerWallet: '7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL',
4242
source: 'CLAIMABLE_POSITIONS' as const,
4343
distributionToken: '',
4444
swapConfig: { slippageBps: 50, maxPriceImpactBps: 300 },
@@ -159,7 +159,7 @@ function createMockOpenRouterClient() {
159159
const mockUserKey = {
160160
keyId: 'uk-0001',
161161
strategyId: 'strat-0001',
162-
holderWallet: 'WalletA',
162+
holderWallet: '7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL',
163163
openrouterKeyHash: 'key-hash-001',
164164
spendingLimitUsd: 10,
165165
currentUsageUsd: 2.5,
@@ -277,13 +277,13 @@ describe('Strategy Routes', () => {
277277
method: 'POST',
278278
url: '/api/strategies',
279279
headers: AUTH_HEADER,
280-
payload: { ownerWallet: 'NewWallet' },
280+
payload: { ownerWallet: '9xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkNew' },
281281
});
282282
expect(res.statusCode).toBe(200);
283283
expect(res.json().strategyId).toBe('strat-new-001');
284-
expect(res.json().ownerWallet).toBe('NewWallet');
284+
expect(res.json().ownerWallet).toBe('9xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkNew');
285285
expect(deps.strategyService.create).toHaveBeenCalledWith(
286-
expect.objectContaining({ ownerWallet: 'NewWallet' }),
286+
expect.objectContaining({ ownerWallet: '9xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkNew' }),
287287
);
288288
await app.close();
289289
});
@@ -603,7 +603,7 @@ describe('Key Routes', () => {
603603
const keyResponse = res.json()[0];
604604
expect(keyResponse).not.toHaveProperty('openrouterKey');
605605
expect(keyResponse).not.toHaveProperty('openrouter_key');
606-
expect(keyResponse.holderWallet).toBe('WalletA');
606+
expect(keyResponse.holderWallet).toBe('7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL');
607607
expect(deps.keyManagerService.getKeysByStrategy).toHaveBeenCalledWith('strat-0001');
608608
await app.close();
609609
});
@@ -816,8 +816,8 @@ describe('Wallet Key Routes', () => {
816816
});
817817
expect(res.statusCode).toBe(200);
818818
expect(res.json().keyId).toBe('uk-0001');
819-
expect(res.json().holderWallet).toBe('WalletA');
820-
expect(deps.keyManagerService.getActiveKeyByWallet).toHaveBeenCalledWith('WalletA');
819+
expect(res.json().holderWallet).toBe('7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL');
820+
expect(deps.keyManagerService.getActiveKeyByWallet).toHaveBeenCalledWith('7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL');
821821
await app.close();
822822
});
823823

@@ -846,8 +846,8 @@ describe('Wallet Key Routes', () => {
846846
});
847847
expect(res.statusCode).toBe(200);
848848
expect(res.json().revoked).toBe(true);
849-
expect(res.json().wallet).toBe('WalletA');
850-
expect(deps.keyManagerService.getActiveKeyByWallet).toHaveBeenCalledWith('WalletA');
849+
expect(res.json().wallet).toBe('7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL');
850+
expect(deps.keyManagerService.getActiveKeyByWallet).toHaveBeenCalledWith('7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL');
851851
expect(deps.keyManagerService.revokeKey).toHaveBeenCalledWith('uk-0001');
852852
await app.close();
853853
});
@@ -953,7 +953,7 @@ describe('Wallet Key Routes', () => {
953953
expect(res.statusCode).toBe(200);
954954
expect(res.json()).toHaveLength(1);
955955
expect(res.json()[0].key_hash).toBe('key-hash-001');
956-
expect(deps.keyManagerService.getActiveKeyByWallet).toHaveBeenCalledWith('WalletA');
956+
expect(deps.keyManagerService.getActiveKeyByWallet).toHaveBeenCalledWith('7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL');
957957
expect(deps.usageTrackingService.getKeyUsage).toHaveBeenCalledWith('key-hash-001');
958958
await app.close();
959959
});

backend/tests/clients/BagsClient.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,10 @@ describe('BagsClient', () => {
198198
describe('getClaimTransactions', () => {
199199
it('returns claim transactions for a position', async () => {
200200
const mockTx = [
201-
{ transaction: 'base64-tx-1', computeUnits: 150000 },
201+
{
202+
tx: 'base58-encoded-tx-1',
203+
blockhash: { blockhash: 'hash-abc', lastValidBlockHeight: 1000 },
204+
},
202205
];
203206
mockPost.mockResolvedValue({ data: mockTx, headers: {} });
204207

@@ -210,7 +213,7 @@ describe('BagsClient', () => {
210213
const result = await client.getClaimTransactions('feeClaimer123', mockPosition);
211214

212215
expect(result).toHaveLength(1);
213-
expect(result[0].transaction).toBe('base64-tx-1');
216+
expect(result[0].tx).toBe('base58-encoded-tx-1');
214217
expect(mockPost).toHaveBeenCalledWith(
215218
'/fees/claim/transactions',
216219
expect.objectContaining({

backend/tests/integration/e2e-pipeline.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const mockBagsClient = {
8383
dammPoolClaimableLamportsUserShare: 0,
8484
dammPoolAddress: 'damm-address',
8585
claimableDisplayAmount: 10,
86-
user: 'e2e-wallet',
86+
user: '5xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkE2E',
8787
claimerIndex: 0,
8888
userBps: 10000,
8989
customFeeVault: '',
@@ -137,7 +137,7 @@ const mockSignAndSendSwap = vi.fn().mockResolvedValue('mock-swap-sig');
137137

138138
const mockStrategy = {
139139
strategyId: STRATEGY_ID,
140-
ownerWallet: 'e2e-wallet',
140+
ownerWallet: '5xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkE2E',
141141
source: 'CLAIMABLE_POSITIONS' as const,
142142
distributionToken: 'mint-abc',
143143
swapConfig: { slippageBps: 50, maxPriceImpactBps: 300 },
@@ -475,14 +475,14 @@ describe('E2E: Full pipeline integration (7 phases)', () => {
475475
url: '/api/strategies',
476476
headers: AUTH_HEADER,
477477
payload: {
478-
ownerWallet: 'e2e-wallet',
478+
ownerWallet: '5xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkE2E',
479479
distributionToken: 'mint-abc',
480480
},
481481
});
482482

483483
expect(res.statusCode).toBe(200);
484484
const body = res.json();
485-
expect(body.ownerWallet).toBe('e2e-wallet');
485+
expect(body.ownerWallet).toBe('5xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkE2E');
486486
expect(body.strategyId).toBe(STRATEGY_ID);
487487
});
488488

@@ -566,7 +566,7 @@ describe('E2E: Full pipeline integration (7 phases)', () => {
566566

567567
it('verify mocks were called with correct data flow', () => {
568568
// BagsClient called to get claimable positions
569-
expect(mockBagsClient.getClaimablePositions).toHaveBeenCalledWith('e2e-wallet');
569+
expect(mockBagsClient.getClaimablePositions).toHaveBeenCalledWith('5xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkE2E');
570570

571571
// In dry-run mode, claim phase returns early before fetching claim transactions.
572572
// Only verify positions were queried.

backend/tests/server.test.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ describe('GET /health/ready', () => {
276276
expect(body.status).toBe('ok');
277277
expect(body).toHaveProperty('timestamp');
278278
expect(body).toHaveProperty('uptime');
279-
expect(body.dependencies).toEqual({ openrouter: true, database: true });
279+
expect(body.dependencies.openrouter).toBe(true);
280+
expect(body.dependencies.database).toBe(true);
280281
expect(body).toHaveProperty('responseTimeMs');
281282

282283
await app.close();
@@ -580,7 +581,7 @@ describe('Request logging', () => {
580581
// ─── CORS configuration tests ───────────────────────────────────
581582

582583
describe('CORS configuration', () => {
583-
it('allows all origins by default (corsOrigins not set)', async () => {
584+
it('denies all origins by default (corsOrigins not set)', async () => {
584585
const deps = createDeps();
585586
const app = await buildApp(deps);
586587

@@ -593,11 +594,8 @@ describe('CORS configuration', () => {
593594
},
594595
});
595596

596-
// With origin: true, the Vary header should be set to Origin
597-
// and the response should indicate CORS is allowed
598-
expect(response.headers['vary']?.toLowerCase()).toContain('origin');
599-
// origin: true echoes the requesting origin back
600-
expect(response.headers['access-control-allow-origin']).toBe('https://evil-site.com');
597+
// With origin: false (deny-all default), no CORS header echoed
598+
expect(response.headers['access-control-allow-origin']).toBeUndefined();
601599

602600
await app.close();
603601
});
@@ -641,7 +639,7 @@ describe('CORS configuration', () => {
641639
await app.close();
642640
});
643641

644-
it('handles empty corsOrigins string as allow-all', async () => {
642+
it('handles empty corsOrigins string as deny-all', async () => {
645643
const deps = createDeps();
646644
deps.corsOrigins = '';
647645
const app = await buildApp(deps);
@@ -655,8 +653,8 @@ describe('CORS configuration', () => {
655653
},
656654
});
657655

658-
// Empty string should still allow all origins (dev default)
659-
expect(response.headers['access-control-allow-origin']).toBe('https://any-origin.com');
656+
// Empty string = deny-all (production safe default)
657+
expect(response.headers['access-control-allow-origin']).toBeUndefined();
660658

661659
await app.close();
662660
});
@@ -748,7 +746,7 @@ describe('Error detail leakage prevention', () => {
748746
const mockKey = {
749747
keyId: 'or-key-123',
750748
strategyId: 'test-strategy',
751-
holderWallet: 'WalletA',
749+
holderWallet: '7xKpPqREhiP1B6d3wTgs8MTwbLj5GhXFsJAiGbrZkQbL',
752750
openrouterKeyHash: 'abc123',
753751
spendingLimitUsd: 10,
754752
currentUsageUsd: 0,

0 commit comments

Comments
 (0)