From cd3ea734e3ccbf79eddf6c21ddffa38f42e34e65 Mon Sep 17 00:00:00 2001 From: david Date: Fri, 28 Aug 2026 09:27:53 +0200 Subject: [PATCH] fix: run Surplus seller continuously --- supplier/.env.example | 7 ++++--- supplier/src/surplus/config.ts | 4 ++-- supplier/src/surplus/controller.ts | 21 ++++++++++++++++++--- tests/unit/surplus-controller.test.ts | 10 +++++----- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/supplier/.env.example b/supplier/.env.example index 08a8476..6bb6449 100644 --- a/supplier/.env.example +++ b/supplier/.env.example @@ -145,9 +145,10 @@ OPENROUTER_CAPACITY_BASE_URL=https://openrouter.ai/api SURPLUS_SELLER_WALLET=0x0000000000000000000000000000000000000000 SURPLUS_PAYOUT_ADDRESS=0x0000000000000000000000000000000000000000 # The controller discovers all fixed-price text models and selects one by -# current demand. It keeps only one active proof offer. -SURPLUS_PER_OFFER_CAP_USD=1.00 -SURPLUS_AGGREGATE_CAP_USD=1.00 +# current demand. It keeps only one active offer. At the default 490 bps +# recovery floor, a $0.05 seller cap bounds upstream spend near $1.02 per day. +SURPLUS_PER_OFFER_CAP_USD=0.05 +SURPLUS_AGGREGATE_CAP_USD=0.05 SURPLUS_OPENROUTER_RESERVE_USD=1.00 SURPLUS_OPENROUTER_MAX_LIMIT_USD=20.00 SURPLUS_MIN_RECOVERY_BPS=490 diff --git a/supplier/src/surplus/config.ts b/supplier/src/surplus/config.ts index e0bd30c..16ac21e 100644 --- a/supplier/src/surplus/config.ts +++ b/supplier/src/surplus/config.ts @@ -72,11 +72,11 @@ export function loadSurplusManagerConfig( providerBaseUrl, capacityBaseUrl, perOfferCapUsd: usd( - env.SURPLUS_PER_OFFER_CAP_USD ?? "1.00", + env.SURPLUS_PER_OFFER_CAP_USD ?? "0.05", "SURPLUS_PER_OFFER_CAP_USD", ), aggregateCapUsd: usd( - env.SURPLUS_AGGREGATE_CAP_USD ?? "1.00", + env.SURPLUS_AGGREGATE_CAP_USD ?? "0.05", "SURPLUS_AGGREGATE_CAP_USD", ), sellerWallet, diff --git a/supplier/src/surplus/controller.ts b/supplier/src/surplus/controller.ts index e04e508..67031f2 100644 --- a/supplier/src/surplus/controller.ts +++ b/supplier/src/surplus/controller.ts @@ -212,7 +212,12 @@ export class SurplusSellerController { } const allowance = await this.allowance.readAllowance(); - this.assertAllowance(allowance, parseUsdDecimal(this.config.aggregateCapUsd, "ceil")); + this.assertAllowance( + allowance, + this.providerExposureUsdNanos( + parseUsdDecimal(this.config.aggregateCapUsd, "ceil"), + ), + ); const [discovered, markets] = await Promise.all([ this.client.discoverModels( this.config.providerApiKey, @@ -444,7 +449,9 @@ export class SurplusSellerController { const allowance = await this.allowance.readAllowance(); this.assertAllowance( allowance, - parseUsdDecimal(this.config.perOfferCapUsd, "ceil"), + this.providerExposureUsdNanos( + parseUsdDecimal(this.config.perOfferCapUsd, "ceil"), + ), ); const baselineAllowance = BigInt( currentState.intent.baselineRemainingUsdNanos, @@ -452,7 +459,9 @@ export class SurplusSellerController { const providerSpend = baselineAllowance > allowance.remainingUsdNanos ? baselineAllowance - allowance.remainingUsdNanos : 0n; - const spendCap = parseUsdDecimal(this.config.perOfferCapUsd, "ceil"); + const spendCap = this.providerExposureUsdNanos( + parseUsdDecimal(this.config.perOfferCapUsd, "ceil"), + ); if (this.config.stopAfterTrades > 0 && providerSpend >= spendCap) { const stopping: SurplusControllerState = { version: 1, @@ -684,6 +693,12 @@ export class SurplusSellerController { } } + private providerExposureUsdNanos(sellerCapUsdNanos: bigint): bigint { + const numerator = sellerCapUsdNanos * 10_000n; + const denominator = BigInt(this.config.recoveryBps); + return (numerator + denominator - 1n) / denominator; + } + private assertAllowance( allowance: OpenRouterKeyAllowance, exposureUsdNanos: bigint, diff --git a/tests/unit/surplus-controller.test.ts b/tests/unit/surplus-controller.test.ts index 0cbe800..52740e9 100644 --- a/tests/unit/surplus-controller.test.ts +++ b/tests/unit/surplus-controller.test.ts @@ -27,8 +27,8 @@ function config(): SurplusManagerConfig { providerApiKey: "sk-or-v1-test", providerBaseUrl: "https://openrouter.ai/api/v1", capacityBaseUrl: "https://openrouter.ai/api", - perOfferCapUsd: "1.00", - aggregateCapUsd: "1.00", + perOfferCapUsd: "0.05", + aggregateCapUsd: "0.05", sellerWallet: SELLER_WALLET, payoutAddress: SELLER_WALLET, maxCandidateOrderBooks: 10, @@ -236,7 +236,7 @@ describe("SurplusSellerController", () => { expect(client.createdPayload).toMatchObject({ model: "beta-model", costMultiplier: 0.04995, - dailyCapUsd: 1, + dailyCapUsd: 0.05, payoutAddress: SELLER_WALLET, }); expect(store.state.phase).toBe("active"); @@ -316,7 +316,7 @@ describe("SurplusSellerController", () => { model: "beta-model", sellerBaseUrl: "https://openrouter.ai/api/v1", status: "inactive", - capDailyUsd: 1, + capDailyUsd: 0.05, costMultiplierPpm: 49_950, inputMicroUsdPer1m: 3_972, outputMicroUsdPer1m: 7_944, @@ -331,7 +331,7 @@ describe("SurplusSellerController", () => { costMultiplierPpm: 49_950, inputMicroUsdPer1m: 3_972, outputMicroUsdPer1m: 7_944, - dailyCapUsd: 1, + dailyCapUsd: 0.05, baselineRemainingUsdNanos: "20000000000", idempotencyKey: "create-1", createdAt: "2026-08-27T10:00:00.000Z",