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
197 changes: 193 additions & 4 deletions docs/all.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,7 @@ paths:
description: Type of the tractor order
enum:
- SOW_V0
- CONVERT_UP_V0
betweenTimes:
type: array
description: Date range for snapshot time filtering
Expand Down Expand Up @@ -1371,6 +1372,9 @@ paths:
snapshotBlock:
type: integer
description: Block number when the snapshot was taken
season:
type: integer
description: Season number of this snapshot
totalPintoSown:
type: string
description: (SOW_V0) Cumulative amount of Pinto sown at snapshot time
Expand All @@ -1383,18 +1387,41 @@ paths:
totalCascadeFundedAnyTemp:
type: string
description: (SOW_V0) Total funded amount that can be executed at any temperature
totalBeansConverted:
type: string
description: (CONVERT_UP_V0) Cumulative amount of Beans converted at snapshot time
totalGsBonusStalk:
type: string
description: (CONVERT_UP_V0) Total Grown Stalk bonus received from conversions
totalGsBonusBdv:
type: string
description: (CONVERT_UP_V0) Total BDV associated with Grown Stalk bonuses
totalGsPenaltyStalk:
type: string
description: (CONVERT_UP_V0) Total Grown Stalk penalty from conversions
totalGsPenaltyBdv:
type: string
description: (CONVERT_UP_V0) Total BDV associated with Grown Stalk penalties
totalCascadeFunded:
type: string
description: (CONVERT_UP_V0) Total amount funded in cascade
totalCascadeFundedExecutable:
type: string
description: (CONVERT_UP_V0) Total funded amount that is currently executable
totalTipsPaid:
type: string
description: (SOW_V0) Cumulative tips paid at snapshot time
description: Cumulative tips paid to this order type at snapshot time
currentMaxTip:
type: string
description: (SOW_V0) Current maximum tip at snapshot time
description: Current maximum tip of this order type at snapshot time
totalExecutions:
type: integer
description: (SOW_V0) Cumulative number of executions at snapshot time
description: Cumulative number of executions of this order type at snapshot time
uniquePublishers:
type: integer
description: Number of unique publishers of this order type at snapshot time
example:
lastUpdated: 29374836
totalRecords: 25
snapshots:
- id: 172
snapshotTimestamp: "2025-04-23T23:00:01.000Z"
Expand All @@ -1406,6 +1433,7 @@ paths:
totalTipsPaid: "26700000"
currentMaxTip: "910000"
totalExecutions: 71
totalRecords: 25
'400':
description: Bad Request
content:
Expand All @@ -1416,6 +1444,167 @@ paths:
error:
type: string
example: "Invalid date range provided."
/tractor/v2/snapshots:
post:
tags:
- Tractor
summary: Get tractor state snapshots (v2)
description: Returns historical snapshots of tractor metrics for multiple order types. This endpoint allows querying multiple order types at once and returns them organized by order type.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
orderTypes:
type: array
description: Array of tractor order types to query. If omitted, all order types are returned.
items:
type: string
enum:
- SOW_V0
- CONVERT_UP_V0
betweenTimes:
type: array
description: Date range for snapshot time filtering
items:
type: string
format: date-time
minItems: 2
maxItems: 2
betweenSeasons:
type: array
description: Season range for snapshot time filtering
items:
type: integer
minItems: 2
maxItems: 2
limit:
type: number
description: Maximum number of snapshots to return per order type
skip:
type: number
description: Number of snapshots to skip (for pagination)
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
lastUpdated:
type: integer
description: Block number of the last update
maxRecords:
type: integer
description: Maximum number of total records across all queried order types
snapshots:
type: object
description: Snapshots organized by order type
additionalProperties:
type: array
items:
type: object
properties:
snapshotTimestamp:
type: string
format: date-time
description: When the snapshot was taken
snapshotBlock:
type: integer
description: Block number when the snapshot was taken
season:
type: integer
description: Season number of this snapshot
totalPintoSown:
type: string
description: (SOW_V0) Cumulative amount of Pinto sown at snapshot time
totalPodsMinted:
type: string
description: (SOW_V0) Cumulative number of pods minted at snapshot time
totalCascadeFundedBelowTemp:
type: string
description: (SOW_V0) Total funded amount that can be executed at the current temperature
totalCascadeFundedAnyTemp:
type: string
description: (SOW_V0) Total funded amount that can be executed at any temperature
totalBeansConverted:
type: string
description: (CONVERT_UP_V0) Cumulative amount of Beans converted at snapshot time
totalGsBonusStalk:
type: string
description: (CONVERT_UP_V0) Total Grown Stalk bonus received from conversions
totalGsBonusBdv:
type: string
description: (CONVERT_UP_V0) Total BDV associated with Grown Stalk bonuses
totalGsPenaltyStalk:
type: string
description: (CONVERT_UP_V0) Total Grown Stalk penalty from conversions
totalGsPenaltyBdv:
type: string
description: (CONVERT_UP_V0) Total BDV associated with Grown Stalk penalties
totalCascadeFunded:
type: string
description: (CONVERT_UP_V0) Total amount funded in cascade
totalCascadeFundedExecutable:
type: string
description: (CONVERT_UP_V0) Total funded amount that is currently executable
totalTipsPaid:
type: string
description: Cumulative tips paid to this order type at snapshot time
currentMaxTip:
type: string
description: Current maximum tip of this order type at snapshot time
totalExecutions:
type: integer
description: Cumulative number of executions of this order type at snapshot time
uniquePublishers:
type: integer
description: Number of unique publishers of this order type at snapshot time
example:
lastUpdated: 29374836
snapshots:
SOW_V0:
- id: 172
snapshotTimestamp: "2025-04-23T23:00:01.000Z"
snapshotBlock: 29329927
season: 3700
totalPintoSown: "25114326676"
totalPodsMinted: "368220397685"
totalCascadeFundedBelowTemp: "24198821026"
totalCascadeFundedAnyTemp: "69015496855"
totalTipsPaid: "26700000"
currentMaxTip: "910000"
totalExecutions: 71
uniquePublishers: 4
CONVERT_UP_V0:
- snapshotTimestamp: "2025-11-06T09:00:01.000Z"
snapshotBlock: 37815127
season: 8426
totalBeansConverted: "12000000"
totalGsBonusStalk: "184994244374079"
totalGsBonusBdv: "90266"
totalGsPenaltyStalk: "0"
totalGsPenaltyBdv: "0"
totalCascadeFunded: "4153289614"
totalCascadeFundedExecutable: "0"
totalTipsPaid: "300000"
currentMaxTip: "0"
totalExecutions: 2
uniquePublishers: 4
maxRecords: 25
'400':
description: Bad Request
content:
application/json:
schema:
type: object
properties:
error:
type: string
example: "Invalid orderType provided."
/seasons:
get:
tags:
Expand Down
47 changes: 47 additions & 0 deletions src/routes/tractor-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ router.post('/executions', async (ctx) => {

/**
* Returns all tractor state snapshots matching the requested criteria.
* @deprecated use v2 instead
*/
router.post('/snapshots', async (ctx) => {
/** @type {import('../../types/types').TractorSnapshotsRequest} */
Expand Down Expand Up @@ -129,4 +130,50 @@ router.post('/snapshots', async (ctx) => {
ctx.body = results;
});

/**
* Returns all tractor state snapshots matching the requested criteria.
*/
router.post('/v2/snapshots', async (ctx) => {
/** @type {import('../../types/types').TractorV2SnapshotsRequest} */
const body = ctx.request.body;

if (
(body.orderTypes && !Array.isArray(body.orderTypes)) ||
(body.limit !== undefined && typeof body.limit !== 'number') ||
(body.skip !== undefined && typeof body.skip !== 'number')
) {
throw new InputError('Invalid type provided for body parameter.');
}

const orderTypes = body.orderTypes ?? Object.keys(TractorOrderType);
if (orderTypes.some((type) => !TractorOrderType[type])) {
throw new InputError('Invalid orderType provided.');
}

body.between = body.between?.map((v) => new Date(v));
RestParsingUtil.dateRangeValidation(body.between);

RestParsingUtil.numberRangeValidation(body.betweenSeasons);

const results = await Promise.all(
orderTypes.map(async (type) => {
if (type === 'SOW_V0') {
return await SnapshotSowV0Service.getSnapshots(body);
} else if (type === 'CONVERT_UP_V0') {
return await SnapshotConvertUpV0Service.getSnapshots(body);
}
})
);

/** @type {import('../../types/types').TractorV2SnapshotsResult} */
ctx.body = {
lastUpdated: results[0].lastUpdated,
snapshots: results.reduce((acc, next, idx) => {
acc[orderTypes[idx]] = next.snapshots;
return acc;
}, {}),
maxRecords: results.reduce((max, result) => Math.max(max, result.totalRecords), 0)
};
});

module.exports = router;
33 changes: 27 additions & 6 deletions types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import SowV0OrderDto from '../src/repository/dto/tractor/SowV0OrderDto';
import SowV0ExecutionDto from '../src/repository/dto/tractor/SowV0ExecutionDto';
import { TractorOrderType } from '../src/repository/postgres/models/types/types';
import SnapshotSowV0Dto from '../src/repository/dto/tractor/SnapshotSowV0Dto';
import SnapshotConvertUpV0Dto from '../src/repository/dto/tractor/SnapshotConvertUpV0Dto';
import CombinedInflowSnapshotDto from '../src/repository/dto/inflow/CombinedInflowSnapshotDto';
import ConvertUpV0ExecutionDto from '../src/repository/dto/tractor/ConvertUpV0ExecutionDto';
import ConvertUpV0OrderDto from '../src/repository/dto/tractor/ConvertUpV0OrderDto';

export type DepositYield = {
// Percentage growth in deposit's bdv
Expand Down Expand Up @@ -121,11 +124,14 @@ type SowV0ExecutionRequestParams = {
usedToken?: string;
};

type ConvertUpV0OrderRequestParams = SowV0OrderRequestParams;
type ConvertUpV0ExecutionRequestParams = SowV0ExecutionRequestParams;

// Union types for all possible blueprint-specific values
type BlueprintOrderRequestParams = SowV0OrderRequestParams;
type BlueprintOrderResponse = SowV0OrderDto;
type BlueprintExecutionRequestParams = SowV0ExecutionRequestParams;
type BlueprintExecutionResponse = SowV0ExecutionDto;
type BlueprintOrderRequestParams = SowV0OrderRequestParams | ConvertUpV0OrderRequestParams;
type BlueprintOrderResponse = SowV0OrderDto | ConvertUpV0OrderDto;
type BlueprintExecutionRequestParams = SowV0ExecutionRequestParams | ConvertUpV0ExecutionRequestParams;
type BlueprintExecutionResponse = SowV0ExecutionDto | ConvertUpV0ExecutionDto;

export type TractorOrderRequest = {
orderType?: keyof TractorOrderType | 'KNOWN' | 'UKNOWN';
Expand Down Expand Up @@ -178,15 +184,15 @@ export type TractorExecutionsResult = {
};

export type TractorSnapshotsRequest = {
orderType?: keyof TractorOrderType | 'KNOWN' | 'UKNOWN';
orderType: keyof TractorOrderType;
betweenTimes?: [Date, Date];
betweenSeasons?: [number, number];
limit?: number;
skip?: number;
};

// Potential union type as more are added
type SnapshotResponse = SnapshotSowV0Dto;
type SnapshotResponse = SnapshotSowV0Dto | SnapshotConvertUpV0Dto;
export type TractorSnapshotsResult = {
// Block number
lastUpdated: number;
Expand All @@ -206,3 +212,18 @@ export type CombinedInflowSnapshotsResult = {
snapshots: CombinedInflowSnapshotResponse[];
totalRecords: number;
};

export type TractorV2SnapshotsRequest = {
orderTypes?: Array<keyof TractorOrderType>;
betweenTimes?: [Date, Date];
betweenSeasons?: [number, number];
limit?: number;
skip?: number;
};

export type TractorV2SnapshotsResult = {
// Block number
lastUpdated: number;
snapshots: Record<keyof TractorOrderType, SnapshotResponse[]>;
maxRecords: number;
};