Skip to content

Commit ead00ba

Browse files
Christian Shearerclaude
andcommitted
Fix pool tests to match equal-allocation retirement rewrite
Tests were still asserting 50/30/20 credit type splits and single txHash returns, but the pool service was rewritten on Mar 12 to allocate equally across all eligible batches with per-batch transactions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7016ef0 commit ead00ba

File tree

1 file changed

+40
-34
lines changed

1 file changed

+40
-34
lines changed

src/__tests__/pool.test.ts

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,25 @@ vi.mock("../config.js", () => ({
2525
isWalletConfigured: vi.fn(() => true),
2626
}));
2727

28-
// Mock order-selector
29-
vi.mock("../services/order-selector.js", () => ({
30-
selectBestOrders: vi.fn(async (_creditType: unknown, quantity: number, _denom: unknown, _abbrevs: unknown) => ({
31-
orders: [
32-
{
33-
sellOrderId: "1",
34-
batchDenom: "C01-001",
35-
quantity: String(Math.min(quantity, 10)),
36-
askAmount: "1000000",
37-
askDenom: "uregen",
38-
costMicro: BigInt(Math.ceil(Math.min(quantity, 10) * 1000000)),
39-
},
40-
],
41-
totalQuantity: String(Math.min(quantity, 10).toFixed(6)),
42-
totalCostMicro: BigInt(Math.ceil(Math.min(quantity, 10) * 1000000)),
43-
paymentDenom: "uregen",
44-
displayDenom: "REGEN",
45-
exponent: 6,
46-
insufficientSupply: quantity > 10,
47-
})),
28+
// Mock ledger — sell orders, credit classes, allowed denoms
29+
vi.mock("../services/ledger.js", () => ({
30+
listSellOrders: vi.fn(async () => [
31+
{ id: "1", seller: "regen1seller", batch_denom: "C02-001-20210101-20211231-001", quantity: "100", ask_denom: "uregen", ask_amount: "1000000", disable_auto_retire: false, expiration: null },
32+
{ id: "2", seller: "regen1seller", batch_denom: "C02-002-20220101-20221231-001", quantity: "100", ask_denom: "uregen", ask_amount: "1000000", disable_auto_retire: false, expiration: null },
33+
{ id: "3", seller: "regen1seller", batch_denom: "BT01-001-20210101-20211231-001", quantity: "100", ask_denom: "uregen", ask_amount: "1000000", disable_auto_retire: false, expiration: null },
34+
{ id: "4", seller: "regen1seller", batch_denom: "BT01-002-20220101-20221231-001", quantity: "100", ask_denom: "uregen", ask_amount: "1000000", disable_auto_retire: false, expiration: null },
35+
{ id: "5", seller: "regen1seller", batch_denom: "USS01-001-20210101-20211231-001", quantity: "100", ask_denom: "uregen", ask_amount: "1000000", disable_auto_retire: false, expiration: null },
36+
{ id: "6", seller: "regen1seller", batch_denom: "KSH01-001-20210101-20211231-001", quantity: "100", ask_denom: "uregen", ask_amount: "1000000", disable_auto_retire: false, expiration: null },
37+
]),
38+
listCreditClasses: vi.fn(async () => [
39+
{ id: "C02", credit_type_abbrev: "C" },
40+
{ id: "BT01", credit_type_abbrev: "BT" },
41+
{ id: "USS01", credit_type_abbrev: "USS" },
42+
{ id: "KSH01", credit_type_abbrev: "KSH" },
43+
]),
44+
getAllowedDenoms: vi.fn(async () => [
45+
{ bank_denom: "uregen", display_denom: "REGEN", exponent: 6 },
46+
]),
4847
}));
4948

5049
// Mock email service
@@ -64,8 +63,8 @@ vi.mock("../server/db.js", async () => {
6463

6564
import { executePoolRun, type PoolRunResult } from "../services/pool.js";
6665
import { signAndBroadcast } from "../services/wallet.js";
67-
import { selectBestOrders } from "../services/order-selector.js";
6866
import { loadConfig } from "../config.js";
67+
import { listSellOrders } from "../services/ledger.js";
6968

7069
let db: Database.Database;
7170

@@ -239,17 +238,19 @@ describe("Pool Service", () => {
239238
.toBe(result.totalRevenueCents);
240239
});
241240

242-
it("calculates correct 50/30/20 credit type allocation within credits budget", async () => {
241+
it("allocates credit budget equally across all eligible batches", async () => {
243242
addTestSubscribers(10, 1000); // $100 total, 75% = $75 credits budget (monthly)
244243

245244
const result = await executePoolRun({ dryRun: true });
246245

247-
// 50% of 7500 = 3750
248-
expect(result.carbon.budgetCents).toBe(3750);
249-
// 30% of 7500 = 2250
250-
expect(result.biodiversity.budgetCents).toBe(2250);
251-
// Remainder = 7500 - 3750 - 2250 = 1500
252-
expect(result.uss.budgetCents).toBe(1500);
246+
// 6 eligible batches, equal allocation: floor(7500 / 6) = 1250 per batch
247+
// Carbon: 2 batches (C02-001, C02-002) = 2 * 1250 = 2500 (+ 0 remainder to first batch overall)
248+
// Biodiversity: 2 batches (BT01-001, BT01-002) = 2 * 1250 = 2500
249+
// USS: 2 batches (USS01-001, KSH01-001) = 2 * 1250 = 2500
250+
expect(result.batches.length).toBe(6);
251+
expect(result.carbon.budgetCents).toBe(2500);
252+
expect(result.biodiversity.budgetCents).toBe(2500);
253+
expect(result.uss.budgetCents).toBe(2500);
253254

254255
// Credit type budgets sum to credits budget
255256
expect(result.carbon.budgetCents + result.biodiversity.budgetCents + result.uss.budgetCents)
@@ -276,9 +277,11 @@ describe("Pool Service", () => {
276277
const result = await executePoolRun({ dryRun: false });
277278

278279
expect(result.dryRun).toBe(false);
279-
// signAndBroadcast should have been called for each credit type
280-
expect(signAndBroadcast).toHaveBeenCalled();
281-
expect(result.carbon.txHash).toBe("AABB1122");
280+
// signAndBroadcast should have been called for each eligible batch (6 batches)
281+
expect(signAndBroadcast).toHaveBeenCalledTimes(6);
282+
// Each category aggregates txHashes from its batches (comma-separated)
283+
// Carbon has 2 batches, each returning "AABB1122"
284+
expect(result.carbon.txHash).toBe("AABB1122,AABB1122");
282285
});
283286

284287
it("records per-subscriber fractional attributions", async () => {
@@ -315,10 +318,11 @@ describe("Pool Service", () => {
315318
}
316319
});
317320

318-
it("handles partial fill when one credit type fails", async () => {
321+
it("handles partial fill when one batch fails", async () => {
319322
addTestSubscribers(1, 1000);
320323

321-
// Make signAndBroadcast fail on second call
324+
// Make signAndBroadcast fail on second call (BT01-002, the second sorted batch)
325+
// Sorted batches: BT01-001, BT01-002, C02-001, C02-002, KSH01-001, USS01-001
322326
let callCount = 0;
323327
vi.mocked(signAndBroadcast).mockImplementation(async () => {
324328
callCount++;
@@ -340,7 +344,9 @@ describe("Pool Service", () => {
340344
const result = await executePoolRun({ dryRun: false });
341345

342346
expect(result.status).toBe("partial");
343-
expect(result.carbon.txHash).toBe("TX1");
347+
// Carbon: 2 batches (calls 3 & 4) both succeed
348+
expect(result.carbon.txHash).toBe("TX3,TX4");
349+
// Biodiversity: call 1 succeeds (TX1), call 2 fails
344350
expect(result.biodiversity.error).toContain("broadcast failed");
345351
expect(result.errors.length).toBeGreaterThan(0);
346352
});

0 commit comments

Comments
 (0)