Skip to content

Commit ea36831

Browse files
authored
Merge pull request #436 from EmberAGI/feature/435-perpetual-core-contracts
feat(registry): adopt canonical perpetual contracts
2 parents 634ba89 + 58d1e85 commit ea36831

File tree

7 files changed

+422
-26
lines changed

7 files changed

+422
-26
lines changed
Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,42 @@
11
import type {
2-
ClosePerpetualsOrdersRequest,
3-
ClosePerpetualsOrdersResponse,
4-
CreatePerpetualsPositionRequest,
5-
CreatePerpetualsPositionResponse,
2+
CreatePerpetualsDecreasePlanRequest,
3+
CreatePerpetualsDecreasePlanResponse,
4+
CreatePerpetualsDecreaseQuoteRequest,
5+
CreatePerpetualsDecreaseQuoteResponse,
6+
CreatePerpetualsIncreasePlanRequest,
7+
CreatePerpetualsIncreasePlanResponse,
8+
CreatePerpetualsIncreaseQuoteRequest,
9+
CreatePerpetualsIncreaseQuoteResponse,
10+
CreatePerpetualsOrderCancelPlanRequest,
11+
CreatePerpetualsOrderCancelPlanResponse,
612
} from '../schemas/perpetuals.js';
713

8-
export type PerpetualsCreateShortPositionCallback = (
9-
request: CreatePerpetualsPositionRequest
10-
) => Promise<CreatePerpetualsPositionResponse>;
14+
export type PerpetualsIncreaseQuoteCallback = (
15+
request: CreatePerpetualsIncreaseQuoteRequest
16+
) => Promise<CreatePerpetualsIncreaseQuoteResponse>;
1117

12-
export type PerpetualsCreateLongPositionCallback = (
13-
request: CreatePerpetualsPositionRequest
14-
) => Promise<CreatePerpetualsPositionResponse>;
18+
export type PerpetualsIncreasePlanCallback = (
19+
request: CreatePerpetualsIncreasePlanRequest
20+
) => Promise<CreatePerpetualsIncreasePlanResponse>;
1521

16-
export type PerpetualsCloseOrdersCallback = (
17-
request: ClosePerpetualsOrdersRequest
18-
) => Promise<ClosePerpetualsOrdersResponse>;
22+
export type PerpetualsDecreaseQuoteCallback = (
23+
request: CreatePerpetualsDecreaseQuoteRequest
24+
) => Promise<CreatePerpetualsDecreaseQuoteResponse>;
1925

20-
export type PerpetualsActions = 'perpetuals-short' | 'perpetuals-long' | 'perpetuals-close';
26+
export type PerpetualsDecreasePlanCallback = (
27+
request: CreatePerpetualsDecreasePlanRequest
28+
) => Promise<CreatePerpetualsDecreasePlanResponse>;
29+
30+
export type PerpetualsOrderCancelPlanCallback = (
31+
request: CreatePerpetualsOrderCancelPlanRequest
32+
) => Promise<CreatePerpetualsOrderCancelPlanResponse>;
33+
34+
export const PerpetualsActionTypes = [
35+
'perpetuals-increase-quote',
36+
'perpetuals-increase-plan',
37+
'perpetuals-decrease-quote',
38+
'perpetuals-decrease-plan',
39+
'perpetuals-orders-cancel-plan',
40+
] as const;
41+
42+
export type PerpetualsActions = (typeof PerpetualsActionTypes)[number];
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { PerpetualsActionTypes } from './perpetuals.js';
4+
5+
describe('PerpetualsActions', () => {
6+
it('exposes canonical action keys and excludes legacy action keys', () => {
7+
expect(PerpetualsActionTypes).toEqual([
8+
'perpetuals-increase-quote',
9+
'perpetuals-increase-plan',
10+
'perpetuals-decrease-quote',
11+
'perpetuals-decrease-plan',
12+
'perpetuals-orders-cancel-plan',
13+
]);
14+
expect(PerpetualsActionTypes.includes('perpetuals-close')).toBe(false);
15+
});
16+
});

typescript/onchain-actions-plugins/registry/src/core/actions/types.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import type {
1212
} from './liquidity.js';
1313
import type {
1414
PerpetualsActions,
15-
PerpetualsCloseOrdersCallback,
16-
PerpetualsCreateLongPositionCallback,
17-
PerpetualsCreateShortPositionCallback,
15+
PerpetualsDecreasePlanCallback,
16+
PerpetualsDecreaseQuoteCallback,
17+
PerpetualsIncreasePlanCallback,
18+
PerpetualsIncreaseQuoteCallback,
19+
PerpetualsOrderCancelPlanCallback,
1820
} from './perpetuals.js';
1921
import type { SwapActionCallback, SwapActions } from './swap.js';
2022
import type {
@@ -49,9 +51,11 @@ type CallbacksRecord = {
4951
'lending-withdraw': LendingWithdrawCallback;
5052
'liquidity-supply': LiquiditySupplyCallback;
5153
'liquidity-withdraw': LiquidityWithdrawCallback;
52-
'perpetuals-short': PerpetualsCreateShortPositionCallback;
53-
'perpetuals-long': PerpetualsCreateLongPositionCallback;
54-
'perpetuals-close': PerpetualsCloseOrdersCallback;
54+
'perpetuals-increase-quote': PerpetualsIncreaseQuoteCallback;
55+
'perpetuals-increase-plan': PerpetualsIncreasePlanCallback;
56+
'perpetuals-decrease-quote': PerpetualsDecreaseQuoteCallback;
57+
'perpetuals-decrease-plan': PerpetualsDecreasePlanCallback;
58+
'perpetuals-orders-cancel-plan': PerpetualsOrderCancelPlanCallback;
5559
'tokenizedYield-mintPtAndYt': TokenizedYieldMintPtAndYtCallback;
5660
'tokenizedYield-buyPt': TokenizedYieldBuyPtCallback;
5761
'tokenizedYield-buyYt': TokenizedYieldBuyYtCallback;

typescript/onchain-actions-plugins/registry/src/core/queries/perpetuals.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type {
22
GetPerpetualsMarketsOrdersRequest,
33
GetPerpetualsMarketsOrdersResponse,
4+
GetPerpetualLifecycleRequest,
5+
GetPerpetualLifecycleResponse,
46
GetPerpetualsMarketsPositionsRequest,
57
GetPerpetualsMarketsPositionsResponse,
68
GetPerpetualsMarketsRequest,
@@ -19,8 +21,20 @@ export type PerpetualsGetOrders = (
1921
request: GetPerpetualsMarketsOrdersRequest
2022
) => Promise<GetPerpetualsMarketsOrdersResponse>;
2123

24+
export type PerpetualsGetLifecycle = (
25+
request: GetPerpetualLifecycleRequest
26+
) => Promise<GetPerpetualLifecycleResponse>;
27+
28+
export const PerpetualsQueryKeys = [
29+
'getMarkets',
30+
'getPositions',
31+
'getOrders',
32+
'getLifecycle',
33+
] as const;
34+
2235
export type PerpetualsQueries = {
2336
getMarkets: PerpetualsGetMarkets;
2437
getPositions: PerpetualsGetPositions;
2538
getOrders: PerpetualsGetOrders;
39+
getLifecycle: PerpetualsGetLifecycle;
2640
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { PerpetualsQueryKeys } from './perpetuals.js';
4+
5+
describe('PerpetualsQueryKeys', () => {
6+
it('includes lifecycle lookup query key', () => {
7+
expect(PerpetualsQueryKeys).toEqual(['getMarkets', 'getPositions', 'getOrders', 'getLifecycle']);
8+
});
9+
});

typescript/onchain-actions-plugins/registry/src/core/schemas/perpetuals.ts

Lines changed: 167 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ const BaseUnitAmountSchema = z.preprocess((value) => {
116116
return value;
117117
}, z.bigint());
118118

119+
const Base10IntegerStringSchema = z
120+
.string()
121+
.regex(/^\d+$/u, 'Must be a base-10 integer string');
122+
119123
// Definition for plugin with mapped entities already in place
120124
export const CreatePerpetualsPositionRequestSchema = z.object({
121125
amount: BaseUnitAmountSchema,
@@ -170,18 +174,175 @@ export type GetPerpetualsMarketsOrdersResponse = z.infer<
170174
typeof GetPerpetualsMarketsOrdersResponseSchema
171175
>;
172176

173-
export const ClosePerpetualsOrdersRequestSchema = z.object({
174-
walletAddress: z.string().describe("User's wallet address"),
175-
key: z.string(),
177+
export const CreatePerpetualsIncreaseQuoteRequestSchema = z.object({
178+
walletAddress: z.string(),
179+
providerName: z.string(),
180+
chainId: z.string(),
181+
marketAddress: z.string(),
182+
collateralTokenAddress: z.string(),
183+
side: PositionSideSchema,
184+
collateralDeltaAmount: Base10IntegerStringSchema,
185+
sizeDeltaUsd: Base10IntegerStringSchema,
186+
slippageBps: Base10IntegerStringSchema,
187+
});
188+
export type CreatePerpetualsIncreaseQuoteRequest = z.infer<
189+
typeof CreatePerpetualsIncreaseQuoteRequestSchema
190+
>;
191+
192+
export const CreatePerpetualsIncreasePlanRequestSchema =
193+
CreatePerpetualsIncreaseQuoteRequestSchema;
194+
export type CreatePerpetualsIncreasePlanRequest = z.infer<
195+
typeof CreatePerpetualsIncreasePlanRequestSchema
196+
>;
197+
198+
const PerpetualDecreaseRequestBaseSchema = z.object({
199+
walletAddress: z.string(),
200+
providerName: z.string(),
201+
chainId: z.string(),
202+
marketAddress: z.string(),
203+
collateralTokenAddress: z.string(),
204+
side: PositionSideSchema,
205+
});
206+
207+
const PerpetualDecreaseFullRequestSchema = PerpetualDecreaseRequestBaseSchema.extend({
208+
mode: z.literal('full'),
209+
full: z.object({
210+
slippageBps: Base10IntegerStringSchema,
211+
}),
212+
});
213+
214+
const PerpetualDecreasePartialRequestSchema = PerpetualDecreaseRequestBaseSchema.extend({
215+
mode: z.literal('partial'),
216+
partial: z.object({
217+
sizeDeltaUsd: Base10IntegerStringSchema,
218+
slippageBps: Base10IntegerStringSchema,
219+
}),
220+
});
221+
222+
export const CreatePerpetualsDecreaseQuoteRequestSchema = z.discriminatedUnion('mode', [
223+
PerpetualDecreaseFullRequestSchema,
224+
PerpetualDecreasePartialRequestSchema,
225+
]);
226+
export type CreatePerpetualsDecreaseQuoteRequest = z.infer<
227+
typeof CreatePerpetualsDecreaseQuoteRequestSchema
228+
>;
229+
230+
export const CreatePerpetualsDecreasePlanRequestSchema =
231+
CreatePerpetualsDecreaseQuoteRequestSchema;
232+
export type CreatePerpetualsDecreasePlanRequest = z.infer<
233+
typeof CreatePerpetualsDecreasePlanRequestSchema
234+
>;
235+
236+
export const CreatePerpetualsOrderCancelPlanRequestSchema = z.object({
237+
walletAddress: z.string(),
238+
providerName: z.string(),
239+
chainId: z.string(),
240+
orderKey: z.string(),
176241
});
242+
export type CreatePerpetualsOrderCancelPlanRequest = z.infer<
243+
typeof CreatePerpetualsOrderCancelPlanRequestSchema
244+
>;
177245

178-
export type ClosePerpetualsOrdersRequest = z.infer<typeof ClosePerpetualsOrdersRequestSchema>;
246+
export const GetPerpetualLifecycleRequestSchema = z.object({
247+
providerName: z.string(),
248+
chainId: z.string(),
249+
txHash: z.string(),
250+
orderKey: z.string().optional(),
251+
walletAddress: z.string().optional(),
252+
});
253+
export type GetPerpetualLifecycleRequest = z.infer<typeof GetPerpetualLifecycleRequestSchema>;
179254

180-
export const ClosePerpetualsOrdersResponseSchema = z.object({
255+
export const PerpetualNumericPrecisionSchema = z.object({
256+
tokenDecimals: z.number().int().nonnegative(),
257+
priceDecimals: z.number().int().nonnegative(),
258+
usdDecimals: z.number().int().nonnegative(),
259+
});
260+
export type PerpetualNumericPrecision = z.infer<typeof PerpetualNumericPrecisionSchema>;
261+
262+
export const PerpetualQuoteResponseSchema = z.object({
263+
asOf: z.string(),
264+
ttlMs: z.number().int().nonnegative(),
265+
precision: PerpetualNumericPrecisionSchema,
266+
pricing: z.object({
267+
markPrice: Base10IntegerStringSchema,
268+
acceptablePrice: Base10IntegerStringSchema,
269+
slippageBps: Base10IntegerStringSchema,
270+
priceImpactDeltaUsd: Base10IntegerStringSchema,
271+
}),
272+
fees: z.object({
273+
positionFeeUsd: Base10IntegerStringSchema,
274+
borrowingFeeUsd: Base10IntegerStringSchema,
275+
fundingFeeUsd: Base10IntegerStringSchema,
276+
}),
277+
warnings: z.array(z.string()),
278+
});
279+
export type PerpetualQuoteResponse = z.infer<typeof PerpetualQuoteResponseSchema>;
280+
281+
export const PerpetualPlanResponseSchema = z.object({
282+
asOf: z.string(),
283+
precision: PerpetualNumericPrecisionSchema,
181284
transactions: z.array(TransactionPlanSchema),
285+
normalizedValues: z.record(z.string(), Base10IntegerStringSchema),
286+
});
287+
export type PerpetualPlanResponse = z.infer<typeof PerpetualPlanResponseSchema>;
288+
289+
export const CreatePerpetualsIncreaseQuoteResponseSchema = PerpetualQuoteResponseSchema;
290+
export type CreatePerpetualsIncreaseQuoteResponse = z.infer<
291+
typeof CreatePerpetualsIncreaseQuoteResponseSchema
292+
>;
293+
294+
export const CreatePerpetualsIncreasePlanResponseSchema = PerpetualPlanResponseSchema;
295+
export type CreatePerpetualsIncreasePlanResponse = z.infer<
296+
typeof CreatePerpetualsIncreasePlanResponseSchema
297+
>;
298+
299+
export const CreatePerpetualsDecreaseQuoteResponseSchema = PerpetualQuoteResponseSchema;
300+
export type CreatePerpetualsDecreaseQuoteResponse = z.infer<
301+
typeof CreatePerpetualsDecreaseQuoteResponseSchema
302+
>;
303+
304+
export const CreatePerpetualsDecreasePlanResponseSchema = PerpetualPlanResponseSchema;
305+
export type CreatePerpetualsDecreasePlanResponse = z.infer<
306+
typeof CreatePerpetualsDecreasePlanResponseSchema
307+
>;
308+
309+
export const CreatePerpetualsOrderCancelPlanResponseSchema = PerpetualPlanResponseSchema;
310+
export type CreatePerpetualsOrderCancelPlanResponse = z.infer<
311+
typeof CreatePerpetualsOrderCancelPlanResponseSchema
312+
>;
313+
314+
const PerpetualLifecycleDisambiguationResponseSchema = z.object({
315+
providerName: z.string(),
316+
chainId: z.string(),
317+
txHash: z.string(),
318+
needsDisambiguation: z.literal(true),
319+
candidateOrderKeys: z.array(z.string()).min(1),
320+
asOf: z.string(),
321+
});
322+
323+
const PerpetualLifecycleResolvedResponseSchema = z.object({
324+
providerName: z.string(),
325+
chainId: z.string(),
326+
txHash: z.string(),
327+
needsDisambiguation: z.literal(false).optional(),
328+
orderKey: z.string(),
329+
status: z.enum(['pending', 'executed', 'cancelled', 'failed', 'unknown']),
330+
reason: z.string().optional(),
331+
reasonBytes: z.string().optional(),
332+
requestedPrice: Base10IntegerStringSchema.optional(),
333+
observedPrice: Base10IntegerStringSchema.optional(),
334+
createTxHash: z.string().optional(),
335+
executionTxHash: z.string().optional(),
336+
cancellationTxHash: z.string().optional(),
337+
precision: PerpetualNumericPrecisionSchema,
338+
asOf: z.string(),
182339
});
183340

184-
export type ClosePerpetualsOrdersResponse = z.infer<typeof ClosePerpetualsOrdersResponseSchema>;
341+
export const GetPerpetualLifecycleResponseSchema = z.union([
342+
PerpetualLifecycleDisambiguationResponseSchema,
343+
PerpetualLifecycleResolvedResponseSchema,
344+
]);
345+
export type GetPerpetualLifecycleResponse = z.infer<typeof GetPerpetualLifecycleResponseSchema>;
185346

186347
export const GetPerpetualsMarketsRequestSchema = z.object({
187348
chainIds: z.array(z.string()),

0 commit comments

Comments
 (0)