@basedone/core 0.2.8 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-NKSQEISP.mjs → chunk-35WGIB5F.mjs} +149 -1
- package/dist/{chunk-VBC6EQ7Q.mjs → chunk-OZPAOG43.mjs} +4 -1
- package/dist/{client-DMVXX1Gw.d.mts → client-1sWFpTpK.d.mts} +22 -2
- package/dist/{client-DMVXX1Gw.d.ts → client-1sWFpTpK.d.ts} +22 -2
- package/dist/ecommerce.d.mts +122 -2
- package/dist/ecommerce.d.ts +122 -2
- package/dist/ecommerce.js +158 -0
- package/dist/ecommerce.mjs +1 -1
- package/dist/index.d.mts +119 -3
- package/dist/index.d.ts +119 -3
- package/dist/index.js +348 -3
- package/dist/index.mjs +176 -5
- package/dist/react.d.mts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +4 -1
- package/dist/react.mjs +1 -1
- package/index.ts +3 -0
- package/lib/abstraction/api.ts +106 -0
- package/lib/abstraction/index.ts +3 -0
- package/lib/abstraction/ratio.ts +61 -0
- package/lib/abstraction/types.ts +73 -0
- package/lib/constants/admin.ts +39 -0
- package/lib/ecommerce/client/customer.ts +42 -0
- package/lib/ecommerce/index.ts +14 -0
- package/lib/ecommerce/types/entities.ts +14 -0
- package/lib/ecommerce/types/enums.ts +5 -1
- package/lib/ecommerce/types/responses.ts +28 -0
- package/lib/ecommerce/utils/orderStateMachine.ts +197 -0
- package/lib/hip3/market-info.ts +66 -3
- package/lib/instrument/client.ts +7 -0
- package/lib/meta/types.ts +4 -0
- package/lib/types.ts +29 -0
- package/package.json +2 -2
|
@@ -286,6 +286,10 @@ export interface ValidateDiscountResponse {
|
|
|
286
286
|
/** Discount amount */
|
|
287
287
|
discountAmount: number;
|
|
288
288
|
};
|
|
289
|
+
/** Merchant ID the discount belongs to */
|
|
290
|
+
merchantId?: string;
|
|
291
|
+
/** Merchant name the discount belongs to */
|
|
292
|
+
merchantName?: string | null;
|
|
289
293
|
/** Subtotal */
|
|
290
294
|
subtotal?: number;
|
|
291
295
|
/** Total */
|
|
@@ -1325,6 +1329,30 @@ export interface CashAccountBalanceResponse {
|
|
|
1325
1329
|
currency: string;
|
|
1326
1330
|
}
|
|
1327
1331
|
|
|
1332
|
+
// ============================================================================
|
|
1333
|
+
// Customer Notification Responses
|
|
1334
|
+
// ============================================================================
|
|
1335
|
+
|
|
1336
|
+
export interface CustomerNotification {
|
|
1337
|
+
id: string;
|
|
1338
|
+
type: string;
|
|
1339
|
+
title: string;
|
|
1340
|
+
message: string;
|
|
1341
|
+
metadata: Record<string, any> | null;
|
|
1342
|
+
isRead: boolean;
|
|
1343
|
+
createdAt: string;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
export interface CustomerNotificationsResponse {
|
|
1347
|
+
notifications: CustomerNotification[];
|
|
1348
|
+
stats: { unread: number };
|
|
1349
|
+
pagination: { total: number; limit: number; offset: number; hasMore: boolean };
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
export interface MarkNotificationsReadResponse {
|
|
1353
|
+
updated: number;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1328
1356
|
export interface DeliveryAddressResponse {
|
|
1329
1357
|
name: string;
|
|
1330
1358
|
phoneNumber: string;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { OrderStatus } from "../types/enums";
|
|
2
|
+
|
|
3
|
+
/** Detect pickup / on-site-collection shipping methods (normalised matching) */
|
|
4
|
+
export function isPickupOrder(
|
|
5
|
+
shippingMethod?: string | null,
|
|
6
|
+
shippingRateId?: string | null
|
|
7
|
+
): boolean {
|
|
8
|
+
// Primary check: shippingRateId === "PICKUP" (from mobile app)
|
|
9
|
+
if (shippingRateId && shippingRateId.trim().toUpperCase() === "PICKUP") {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!shippingMethod) return false;
|
|
14
|
+
const normalized = shippingMethod
|
|
15
|
+
.trim()
|
|
16
|
+
.toLowerCase()
|
|
17
|
+
.replace(/[\s-]+/g, " ");
|
|
18
|
+
return (
|
|
19
|
+
normalized === "pickup" ||
|
|
20
|
+
normalized === "on site collection" ||
|
|
21
|
+
normalized === "onsite collection"
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Canonical order status transitions.
|
|
27
|
+
*
|
|
28
|
+
* Buyer-protected escrow flow:
|
|
29
|
+
* CREATED → PAYMENT_RESERVED → MERCHANT_ACCEPTED → SHIPPED → DELIVERED → SETTLED
|
|
30
|
+
*
|
|
31
|
+
* Cancellation is allowed from any non-terminal state except DELIVERED (already in settlement).
|
|
32
|
+
*/
|
|
33
|
+
export const ORDER_STATUS_TRANSITIONS: Partial<Record<OrderStatus, OrderStatus[]>> = {
|
|
34
|
+
[OrderStatus.CREATED]: [
|
|
35
|
+
OrderStatus.PAYMENT_RESERVED,
|
|
36
|
+
OrderStatus.MERCHANT_ACCEPTED,
|
|
37
|
+
OrderStatus.CANCELLED,
|
|
38
|
+
],
|
|
39
|
+
[OrderStatus.PAYMENT_RESERVED]: [
|
|
40
|
+
OrderStatus.MERCHANT_ACCEPTED,
|
|
41
|
+
OrderStatus.CANCELLED,
|
|
42
|
+
],
|
|
43
|
+
[OrderStatus.MERCHANT_ACCEPTED]: [
|
|
44
|
+
OrderStatus.SHIPPED,
|
|
45
|
+
OrderStatus.CANCELLED,
|
|
46
|
+
],
|
|
47
|
+
// Backward compat for existing SETTLED orders created before escrow change
|
|
48
|
+
// Note: CANCELLED removed — settled orders have funds paid out, no clawback mechanism
|
|
49
|
+
[OrderStatus.SETTLED]: [OrderStatus.SHIPPED],
|
|
50
|
+
[OrderStatus.SHIPPED]: [OrderStatus.DELIVERED, OrderStatus.CANCELLED],
|
|
51
|
+
// Settlement triggered on delivery (buyer-protected escrow)
|
|
52
|
+
[OrderStatus.DELIVERED]: [OrderStatus.SETTLED],
|
|
53
|
+
// Terminal states
|
|
54
|
+
[OrderStatus.CANCELLED]: [],
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Validate whether transitioning from `currentStatus` to `newStatus` is allowed.
|
|
59
|
+
*
|
|
60
|
+
* For pickup / on-site-collection orders, MERCHANT_ACCEPTED → DELIVERED and
|
|
61
|
+
* SETTLED → DELIVERED are permitted (skipping SHIPPED).
|
|
62
|
+
*/
|
|
63
|
+
export function validateStatusTransition(
|
|
64
|
+
currentStatus: string,
|
|
65
|
+
newStatus: string,
|
|
66
|
+
options?: {
|
|
67
|
+
shippingMethod?: string | null;
|
|
68
|
+
shippingRateId?: string | null;
|
|
69
|
+
}
|
|
70
|
+
): { valid: boolean; error?: string } {
|
|
71
|
+
// Pickup orders can skip SHIPPED and go directly to DELIVERED
|
|
72
|
+
if (
|
|
73
|
+
isPickupOrder(options?.shippingMethod, options?.shippingRateId) &&
|
|
74
|
+
(currentStatus === OrderStatus.MERCHANT_ACCEPTED ||
|
|
75
|
+
currentStatus === OrderStatus.SETTLED) &&
|
|
76
|
+
newStatus === OrderStatus.DELIVERED
|
|
77
|
+
) {
|
|
78
|
+
return { valid: true };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const allowed =
|
|
82
|
+
ORDER_STATUS_TRANSITIONS[currentStatus as OrderStatus] ?? [];
|
|
83
|
+
if (!allowed.includes(newStatus as OrderStatus)) {
|
|
84
|
+
if (allowed.length === 0) {
|
|
85
|
+
return {
|
|
86
|
+
valid: false,
|
|
87
|
+
error: `Cannot change status from ${currentStatus} — this is a final state`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
valid: false,
|
|
92
|
+
error: `Cannot transition from ${currentStatus} to ${newStatus}. Allowed: ${allowed.join(", ")}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return { valid: true };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Return the list of statuses reachable from `currentStatus`.
|
|
101
|
+
* For pickup orders, DELIVERED is added when on MERCHANT_ACCEPTED or SETTLED.
|
|
102
|
+
*/
|
|
103
|
+
export function getNextStatuses(
|
|
104
|
+
currentStatus: string,
|
|
105
|
+
options?: {
|
|
106
|
+
shippingMethod?: string | null;
|
|
107
|
+
shippingRateId?: string | null;
|
|
108
|
+
}
|
|
109
|
+
): string[] {
|
|
110
|
+
const base = [
|
|
111
|
+
...(ORDER_STATUS_TRANSITIONS[currentStatus as OrderStatus] ?? []),
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
isPickupOrder(options?.shippingMethod, options?.shippingRateId) &&
|
|
116
|
+
(currentStatus === OrderStatus.MERCHANT_ACCEPTED ||
|
|
117
|
+
currentStatus === OrderStatus.SETTLED) &&
|
|
118
|
+
!base.includes(OrderStatus.DELIVERED)
|
|
119
|
+
) {
|
|
120
|
+
base.push(OrderStatus.DELIVERED);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return base;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Human-readable label for a status. */
|
|
127
|
+
export function getStatusLabel(status: string): string {
|
|
128
|
+
const labels: Record<string, string> = {
|
|
129
|
+
CREATED: "Created",
|
|
130
|
+
PAYMENT_RESERVED: "Payment Reserved",
|
|
131
|
+
MERCHANT_ACCEPTED: "Accepted",
|
|
132
|
+
SETTLED: "Completed (Paid)",
|
|
133
|
+
SHIPPED: "Shipped",
|
|
134
|
+
DELIVERED: "Delivered",
|
|
135
|
+
CANCELLED: "Cancelled",
|
|
136
|
+
};
|
|
137
|
+
return labels[status] || status;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** UI colour key for a status. */
|
|
141
|
+
export function getStatusColor(status: string): string {
|
|
142
|
+
const colors: Record<string, string> = {
|
|
143
|
+
CREATED: "gray",
|
|
144
|
+
PAYMENT_RESERVED: "blue",
|
|
145
|
+
MERCHANT_ACCEPTED: "purple",
|
|
146
|
+
SETTLED: "indigo",
|
|
147
|
+
SHIPPED: "yellow",
|
|
148
|
+
DELIVERED: "green",
|
|
149
|
+
CANCELLED: "red",
|
|
150
|
+
};
|
|
151
|
+
return colors[status] || "gray";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Whether the order can be cancelled from its current status. */
|
|
155
|
+
export function canCancelOrder(currentStatus: string): boolean {
|
|
156
|
+
return (
|
|
157
|
+
ORDER_STATUS_TRANSITIONS[currentStatus as OrderStatus]?.includes(
|
|
158
|
+
OrderStatus.CANCELLED
|
|
159
|
+
) ?? false
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Whether tracking info is required for a status change. */
|
|
164
|
+
export function requiresTrackingInfo(
|
|
165
|
+
newStatus: string,
|
|
166
|
+
options?: {
|
|
167
|
+
shippingMethod?: string | null;
|
|
168
|
+
shippingRateId?: string | null;
|
|
169
|
+
}
|
|
170
|
+
): boolean {
|
|
171
|
+
if (newStatus !== OrderStatus.SHIPPED) return false;
|
|
172
|
+
return !isPickupOrder(options?.shippingMethod, options?.shippingRateId);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Whether a status change should trigger customer notification. */
|
|
176
|
+
export function shouldNotifyCustomer(newStatus: string): boolean {
|
|
177
|
+
return [
|
|
178
|
+
OrderStatus.MERCHANT_ACCEPTED,
|
|
179
|
+
OrderStatus.SHIPPED,
|
|
180
|
+
OrderStatus.DELIVERED,
|
|
181
|
+
OrderStatus.CANCELLED,
|
|
182
|
+
].includes(newStatus as OrderStatus);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** Status progression percentage (for progress bars). */
|
|
186
|
+
export function getStatusProgress(status: string): number {
|
|
187
|
+
const progressMap: Record<string, number> = {
|
|
188
|
+
CREATED: 10,
|
|
189
|
+
PAYMENT_RESERVED: 25,
|
|
190
|
+
MERCHANT_ACCEPTED: 40,
|
|
191
|
+
SETTLED: 50,
|
|
192
|
+
SHIPPED: 75,
|
|
193
|
+
DELIVERED: 100,
|
|
194
|
+
CANCELLED: 0,
|
|
195
|
+
};
|
|
196
|
+
return progressMap[status] || 0;
|
|
197
|
+
}
|
package/lib/hip3/market-info.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { InfoClient, PerpsAssetCtx, MarginTables, PerpDex as LegacyPerpDex } from "@nktkas/hyperliquid";
|
|
2
2
|
|
|
3
|
+
/** Payload entries from Hyperliquid `info` → `{ type: "perpConciseAnnotations" }`. */
|
|
4
|
+
export interface PerpConciseAnnotationMeta {
|
|
5
|
+
category?: string;
|
|
6
|
+
displayName?: string;
|
|
7
|
+
keywords?: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type PerpConciseAnnotations = [string, PerpConciseAnnotationMeta][];
|
|
11
|
+
|
|
3
12
|
export interface PerpsMeta {
|
|
4
13
|
collateralToken: number;
|
|
5
14
|
/** Trading universes available for perpetual trading. */
|
|
@@ -32,6 +41,10 @@ export interface PerpsUniverse {
|
|
|
32
41
|
growthMode?: "enabled";
|
|
33
42
|
/** Margin mode for the universe. */
|
|
34
43
|
marginMode?: "strictIsolated" | "noCross";
|
|
44
|
+
/** From `perpConciseAnnotations` when present (search/display). */
|
|
45
|
+
category?: string;
|
|
46
|
+
displayName?: string;
|
|
47
|
+
keywords?: string[];
|
|
35
48
|
}
|
|
36
49
|
|
|
37
50
|
export interface PerpDex extends LegacyPerpDex {
|
|
@@ -40,10 +53,60 @@ export interface PerpDex extends LegacyPerpDex {
|
|
|
40
53
|
|
|
41
54
|
export type AllPerpsMeta = PerpsMeta[];
|
|
42
55
|
|
|
56
|
+
export async function getPerpConciseAnnotations(
|
|
57
|
+
infoClient: InfoClient,
|
|
58
|
+
): Promise<PerpConciseAnnotations> {
|
|
59
|
+
return infoClient.transport.request<PerpConciseAnnotations>("info", {
|
|
60
|
+
type: "perpConciseAnnotations",
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Merges `perpConciseAnnotations` into each universe row by matching `name`.
|
|
66
|
+
*/
|
|
67
|
+
export function enrichAllPerpsMetaWithAnnotations(
|
|
68
|
+
metas: AllPerpsMeta,
|
|
69
|
+
annotations: PerpConciseAnnotations,
|
|
70
|
+
): AllPerpsMeta {
|
|
71
|
+
const map = new Map<string, PerpConciseAnnotationMeta>(annotations);
|
|
72
|
+
|
|
73
|
+
return metas.map((meta) => ({
|
|
74
|
+
...meta,
|
|
75
|
+
universe: meta.universe.map((u) => {
|
|
76
|
+
const ann = map.get(u.name);
|
|
77
|
+
if (!ann) return u;
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
...u,
|
|
81
|
+
...(ann.category != null && ann.category !== ""
|
|
82
|
+
? { category: ann.category }
|
|
83
|
+
: {}),
|
|
84
|
+
...(ann.displayName != null && ann.displayName !== ""
|
|
85
|
+
? { displayName: ann.displayName }
|
|
86
|
+
: {}),
|
|
87
|
+
...(ann.keywords != null && ann.keywords.length > 0
|
|
88
|
+
? { keywords: ann.keywords }
|
|
89
|
+
: {}),
|
|
90
|
+
};
|
|
91
|
+
}),
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
|
|
43
95
|
export async function getAllPerpsMeta(
|
|
44
96
|
infoClient: InfoClient,
|
|
45
97
|
): Promise<AllPerpsMeta> {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
98
|
+
const [metas, annotations] = await Promise.all([
|
|
99
|
+
infoClient.transport.request<AllPerpsMeta>("info", {
|
|
100
|
+
type: "allPerpMetas",
|
|
101
|
+
}),
|
|
102
|
+
getPerpConciseAnnotations(infoClient).catch((): PerpConciseAnnotations => {
|
|
103
|
+
return [];
|
|
104
|
+
}),
|
|
105
|
+
]);
|
|
106
|
+
|
|
107
|
+
if (!annotations.length) {
|
|
108
|
+
return metas;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return enrichAllPerpsMetaWithAnnotations(metas, annotations);
|
|
49
112
|
}
|
package/lib/instrument/client.ts
CHANGED
|
@@ -17,6 +17,10 @@ export interface PerpsInstrument extends BaseInstrument {
|
|
|
17
17
|
collateralTokenSymbol: string;
|
|
18
18
|
dex?: string; // HIP3 dex name (e.g., "xyz" for "xyz:MSTR")
|
|
19
19
|
collateralTokenIndex?: number;
|
|
20
|
+
/** From merged `perpConciseAnnotations` (display/search). */
|
|
21
|
+
category?: string;
|
|
22
|
+
displayName?: string;
|
|
23
|
+
keywords?: string[];
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
// Spot-specific types (metadata only - no asset context data)
|
|
@@ -280,6 +284,9 @@ export class InstrumentClient {
|
|
|
280
284
|
isDelisted: info.isDelisted,
|
|
281
285
|
dex: AssetIdUtils.extractDexName(info.name),
|
|
282
286
|
collateralTokenIndex: perpMeta.collateralToken,
|
|
287
|
+
category: info.category,
|
|
288
|
+
displayName: info.displayName,
|
|
289
|
+
keywords: info.keywords,
|
|
283
290
|
};
|
|
284
291
|
|
|
285
292
|
this.addInstrument(instrument);
|
package/lib/meta/types.ts
CHANGED
|
@@ -33,4 +33,8 @@ export interface PerpsUniverse {
|
|
|
33
33
|
growthMode?: "enabled";
|
|
34
34
|
/** Margin mode for the universe. */
|
|
35
35
|
marginMode?: "strictIsolated" | "noCross";
|
|
36
|
+
/** From Hyperliquid `perpConciseAnnotations` when merged into meta. */
|
|
37
|
+
category?: string;
|
|
38
|
+
displayName?: string;
|
|
39
|
+
keywords?: string[];
|
|
36
40
|
}
|
package/lib/types.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { UserAbstractionMode } from "./abstraction";
|
|
2
|
+
|
|
3
|
+
export interface PerpDexState {
|
|
4
|
+
totalVaultEquity: number;
|
|
5
|
+
perpsAtOpenInterestCap?: Array<string>;
|
|
6
|
+
leadingVaults?: Array<LeadingVault>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// Additional undocumented fields in WebData3 will be removed on a future update
|
|
11
|
+
export interface WsWebData3 {
|
|
12
|
+
userState: {
|
|
13
|
+
abstraction: UserAbstractionMode;
|
|
14
|
+
agentAddress: string | null;
|
|
15
|
+
agentValidUntil: number | null;
|
|
16
|
+
serverTime: number;
|
|
17
|
+
cumLedger: number;
|
|
18
|
+
isVault: boolean;
|
|
19
|
+
user: string;
|
|
20
|
+
optOutOfSpotDusting?: boolean;
|
|
21
|
+
dexAbstractionEnabled?: boolean;
|
|
22
|
+
};
|
|
23
|
+
perpDexStates: Array<PerpDexState>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface LeadingVault {
|
|
27
|
+
address: string;
|
|
28
|
+
name: string;
|
|
29
|
+
}
|
package/package.json
CHANGED