@basedone/core 0.2.2 → 0.2.4

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.
@@ -789,3 +789,97 @@ export interface FlashSale {
789
789
  items: FlashSaleItem[];
790
790
  }
791
791
 
792
+ // ============================================
793
+ // SHIPPING ENTITIES
794
+ // ============================================
795
+
796
+ /**
797
+ * Merchant shipping settings entity
798
+ */
799
+ export interface MerchantShippingSettings extends BaseEntity {
800
+ /** Merchant ID */
801
+ merchantId: string;
802
+ /** Default handling fee in USDC */
803
+ defaultHandlingFee: number;
804
+ /** Default processing time in days */
805
+ defaultProcessingDays: number;
806
+ /** Default product weight in kg */
807
+ defaultWeightKg: number;
808
+ /** Free shipping enabled globally */
809
+ freeShippingEnabled: boolean;
810
+ /** Free shipping threshold in USDC */
811
+ freeShippingThreshold: number | null;
812
+ /** Show estimated delivery to customers */
813
+ showEstimatedDelivery: boolean;
814
+ }
815
+
816
+ /**
817
+ * Shipping zone entity
818
+ */
819
+ export interface ShippingZone extends BaseEntity {
820
+ /** Merchant ID */
821
+ merchantId: string;
822
+ /** Zone name */
823
+ name: string;
824
+ /** Country codes (ISO 2-letter codes) */
825
+ countries: string[];
826
+ /** Is default zone for unlisted countries */
827
+ isDefault: boolean;
828
+ /** Is zone active */
829
+ isActive: boolean;
830
+ /** Priority (higher = checked first) */
831
+ priority: number;
832
+ /** Number of rates in this zone */
833
+ rateCount?: number;
834
+ /** Associated shipping rates */
835
+ rates?: ShippingRate[];
836
+ }
837
+
838
+ /**
839
+ * Shipping rate entity
840
+ */
841
+ export interface ShippingRate extends BaseEntity {
842
+ /** Zone ID */
843
+ zoneId: string;
844
+ /** Zone name (for display) */
845
+ zoneName?: string;
846
+ /** Merchant ID */
847
+ merchantId: string;
848
+ /** Rate name (e.g., "Standard", "Express") */
849
+ name: string;
850
+ /** Base shipping rate in USDC */
851
+ baseRate: number;
852
+ /** Per kg rate in USDC */
853
+ perKgRate: number;
854
+ /** Minimum weight in kg */
855
+ minWeightKg: number | null;
856
+ /** Maximum weight in kg */
857
+ maxWeightKg: number | null;
858
+ /** Minimum delivery days */
859
+ minDeliveryDays: number | null;
860
+ /** Maximum delivery days */
861
+ maxDeliveryDays: number | null;
862
+ /** Free shipping above this amount */
863
+ freeAboveAmount: number | null;
864
+ /** Is rate active */
865
+ isActive: boolean;
866
+ /** Sort order */
867
+ sortOrder: number;
868
+ }
869
+
870
+ /**
871
+ * Shipping option (calculated for checkout)
872
+ */
873
+ export interface ShippingOption {
874
+ /** Rate ID */
875
+ id: string;
876
+ /** Rate name */
877
+ name: string;
878
+ /** Calculated cost in USDC */
879
+ cost: number;
880
+ /** Estimated delivery string */
881
+ estimatedDelivery: string;
882
+ /** Zone name */
883
+ zoneName: string;
884
+ }
885
+
@@ -32,8 +32,12 @@ export enum OrderStatus {
32
32
  * Payment method enum
33
33
  */
34
34
  export enum PaymentMethod {
35
- /** USDC payment via Hyperliquid escrow */
35
+ /** USDC payment via Hyperliquid SpotTransfer */
36
36
  USDC_ESCROW = "USDC_ESCROW",
37
+ /** BasedPay external ledger payment */
38
+ BASEDPAY = "BASEDPAY",
39
+ /** Stripe card payment */
40
+ STRIPE = "STRIPE",
37
41
  /** Points-based payment */
38
42
  POINTS = "POINTS",
39
43
  }
@@ -254,6 +258,8 @@ export enum ProductSortBy {
254
258
  POPULAR = "popular",
255
259
  /** Sort by featured status */
256
260
  FEATURED = "featured",
261
+ /** Sort by proximity to user location (requires lat/lng) */
262
+ NEARBY = "nearby",
257
263
  }
258
264
 
259
265
  /**
@@ -54,6 +54,12 @@ export interface ListProductsParams extends PaginationParams {
54
54
  sortBy?: ProductSortBy;
55
55
  /** Filter by active status */
56
56
  isActive?: boolean;
57
+ /** Filter by destination country (ISO 2-letter code) - only show products from merchants that ship here */
58
+ country?: string;
59
+ /** User latitude for proximity sorting (used with sortBy=nearby) */
60
+ lat?: number;
61
+ /** User longitude for proximity sorting (used with sortBy=nearby) */
62
+ lng?: number;
57
63
  }
58
64
 
59
65
  /**
@@ -144,6 +150,14 @@ export interface CreateOrderRequest {
144
150
  couponCode?: string;
145
151
  /** Idempotency key */
146
152
  idempotencyKey?: string;
153
+ /** Selected shipping method name (e.g., "Standard", "Express") */
154
+ shippingMethod?: string;
155
+ /** Calculated shipping cost in USDC */
156
+ shippingCost?: number;
157
+ /** Shipping zone name for reference */
158
+ shippingZone?: string;
159
+ /** Estimated delivery time (e.g., "5-7 business days") */
160
+ estimatedDelivery?: string;
147
161
  }
148
162
 
149
163
  /**
@@ -602,3 +616,140 @@ export interface ListFollowingParams extends PaginationParams {
602
616
  sortBy?: "recent" | "name";
603
617
  }
604
618
 
619
+ // ============================================
620
+ // SHIPPING REQUESTS
621
+ // ============================================
622
+
623
+ /**
624
+ * Update shipping settings request
625
+ */
626
+ export interface UpdateShippingSettingsRequest {
627
+ /** Default handling fee in USDC */
628
+ defaultHandlingFee?: number;
629
+ /** Default processing time in days */
630
+ defaultProcessingDays?: number;
631
+ /** Default product weight in kg */
632
+ defaultWeightKg?: number;
633
+ /** Free shipping enabled globally */
634
+ freeShippingEnabled?: boolean;
635
+ /** Free shipping threshold in USDC */
636
+ freeShippingThreshold?: number | null;
637
+ /** Show estimated delivery to customers */
638
+ showEstimatedDelivery?: boolean;
639
+ }
640
+
641
+ /**
642
+ * Create shipping zone request
643
+ */
644
+ export interface CreateShippingZoneRequest {
645
+ /** Zone name */
646
+ name: string;
647
+ /** Country codes (ISO 2-letter codes) */
648
+ countries: string[];
649
+ /** Is default zone for unlisted countries */
650
+ isDefault?: boolean;
651
+ /** Is zone active */
652
+ isActive?: boolean;
653
+ /** Priority (higher = checked first) */
654
+ priority?: number;
655
+ }
656
+
657
+ /**
658
+ * Update shipping zone request
659
+ */
660
+ export interface UpdateShippingZoneRequest extends Partial<CreateShippingZoneRequest> {}
661
+
662
+ /**
663
+ * Create shipping rate request
664
+ */
665
+ export interface CreateShippingRateRequest {
666
+ /** Zone ID */
667
+ zoneId: string;
668
+ /** Rate name (e.g., "Standard", "Express") */
669
+ name: string;
670
+ /** Base shipping rate in USDC */
671
+ baseRate: number;
672
+ /** Per kg rate in USDC */
673
+ perKgRate?: number;
674
+ /** Minimum weight in kg */
675
+ minWeightKg?: number | null;
676
+ /** Maximum weight in kg */
677
+ maxWeightKg?: number | null;
678
+ /** Minimum delivery days */
679
+ minDeliveryDays?: number | null;
680
+ /** Maximum delivery days */
681
+ maxDeliveryDays?: number | null;
682
+ /** Free shipping above this amount */
683
+ freeAboveAmount?: number | null;
684
+ /** Is rate active */
685
+ isActive?: boolean;
686
+ /** Sort order */
687
+ sortOrder?: number;
688
+ }
689
+
690
+ /**
691
+ * Update shipping rate request
692
+ */
693
+ export interface UpdateShippingRateRequest extends Partial<Omit<CreateShippingRateRequest, "zoneId">> {}
694
+
695
+ /**
696
+ * Calculate shipping options request
697
+ */
698
+ export interface CalculateShippingRequest {
699
+ /** Merchant ID */
700
+ merchantId: string;
701
+ /** Cart items */
702
+ cartItems: CartItem[];
703
+ /** Destination country code (ISO 2-letter) */
704
+ destinationCountry: string;
705
+ /** Order subtotal in USDC */
706
+ orderSubtotal: number;
707
+ }
708
+
709
+ // ============================================================================
710
+ // GEM System Requests
711
+ // ============================================================================
712
+
713
+ /**
714
+ * Gem history type filter
715
+ */
716
+ export type GemHistoryTypeFilter = "earn" | "spend" | "all";
717
+
718
+ /**
719
+ * Get gem history parameters
720
+ */
721
+ export interface GetGemHistoryParams extends PaginationParams {
722
+ /** Filter by transaction type */
723
+ type?: GemHistoryTypeFilter;
724
+ }
725
+
726
+ /**
727
+ * Get expiring gems parameters
728
+ */
729
+ export interface GetExpiringGemsParams {
730
+ /** Number of days ahead to check (default: 30, max: 180) */
731
+ days?: number;
732
+ }
733
+
734
+ // ============================================================================
735
+ // Browsing Location Requests
736
+ // ============================================================================
737
+
738
+ /**
739
+ * Save browsing location request
740
+ */
741
+ export interface SaveBrowsingLocationRequest {
742
+ /** Full display address from Google Places */
743
+ formattedAddress: string;
744
+ /** City name */
745
+ city: string;
746
+ /** State/Province (optional) */
747
+ stateProvince?: string;
748
+ /** ISO 2-letter country code (e.g., "SG", "US") */
749
+ country: string;
750
+ /** Latitude coordinate */
751
+ latitude: number;
752
+ /** Longitude coordinate */
753
+ longitude: number;
754
+ }
755
+
@@ -951,3 +951,317 @@ export interface ActiveFlashSalesResponse {
951
951
  serverTime: string;
952
952
  }
953
953
 
954
+ // ============================================
955
+ // SHIPPING RESPONSES
956
+ // ============================================
957
+
958
+ import type {
959
+ MerchantShippingSettings,
960
+ ShippingZone,
961
+ ShippingRate,
962
+ ShippingOption,
963
+ } from "./entities";
964
+
965
+ /**
966
+ * Get shipping settings response
967
+ */
968
+ export interface ShippingSettingsResponse {
969
+ /** Shipping settings */
970
+ settings: MerchantShippingSettings | {
971
+ defaultHandlingFee: number;
972
+ defaultProcessingDays: number;
973
+ freeShippingEnabled: boolean;
974
+ freeShippingThreshold: number | null;
975
+ defaultWeightKg: number;
976
+ showEstimatedDelivery: boolean;
977
+ };
978
+ }
979
+
980
+ /**
981
+ * List shipping zones response
982
+ */
983
+ export interface ListShippingZonesResponse {
984
+ /** Shipping zones */
985
+ zones: ShippingZone[];
986
+ }
987
+
988
+ /**
989
+ * Shipping zone response
990
+ */
991
+ export interface ShippingZoneResponse {
992
+ /** Shipping zone */
993
+ zone: ShippingZone;
994
+ }
995
+
996
+ /**
997
+ * List shipping rates response
998
+ */
999
+ export interface ListShippingRatesResponse {
1000
+ /** Shipping rates */
1001
+ rates: ShippingRate[];
1002
+ }
1003
+
1004
+ /**
1005
+ * Shipping rate response
1006
+ */
1007
+ export interface ShippingRateResponse {
1008
+ /** Shipping rate */
1009
+ rate: ShippingRate;
1010
+ }
1011
+
1012
+ /**
1013
+ * Calculate shipping options response
1014
+ */
1015
+ export interface CalculateShippingResponse {
1016
+ /** Available shipping options */
1017
+ shippingOptions: ShippingOption[];
1018
+ }
1019
+
1020
+ // ============================================================================
1021
+ // Payment Method Responses
1022
+ // ============================================================================
1023
+
1024
+ /**
1025
+ * Payment method info for display
1026
+ */
1027
+ export interface PaymentMethodInfo {
1028
+ /** Payment method ID (e.g., "USDC_ESCROW") */
1029
+ id: string;
1030
+ /** Display name (e.g., "USDC (Hyperliquid)") */
1031
+ name: string;
1032
+ /** Description of the payment method */
1033
+ description: string;
1034
+ /** Icon identifier */
1035
+ icon?: string;
1036
+ /** Whether the payment requires user signature (e.g., blockchain) */
1037
+ requiresSignature?: boolean;
1038
+ /** Whether refunds are supported */
1039
+ supportsRefund?: boolean;
1040
+ }
1041
+
1042
+ /**
1043
+ * Get payment methods response
1044
+ */
1045
+ export interface GetPaymentMethodsResponse {
1046
+ /** Whether the request was successful */
1047
+ success: boolean;
1048
+ /** Whether payments are globally enabled */
1049
+ paymentsEnabled: boolean;
1050
+ /** List of enabled payment methods */
1051
+ methods: PaymentMethodInfo[];
1052
+ /** Optional message (e.g., when payments are disabled) */
1053
+ message?: string;
1054
+ }
1055
+
1056
+ /**
1057
+ * Process payment request
1058
+ */
1059
+ export interface ProcessPaymentRequest {
1060
+ /** Order ID to pay for */
1061
+ orderId: string;
1062
+ /** Payment method to use */
1063
+ paymentMethod: string;
1064
+ /** Amount in USDC */
1065
+ amount: number;
1066
+ /** Pre-signed action for USDC_ESCROW */
1067
+ signedAction?: {
1068
+ action: unknown;
1069
+ nonce: number;
1070
+ signature: unknown;
1071
+ };
1072
+ /** Stripe payment method ID */
1073
+ stripePaymentMethodId?: string;
1074
+ /** BasedPay account ID */
1075
+ basedPayAccountId?: string;
1076
+ /** Points to spend */
1077
+ pointsAmount?: number;
1078
+ }
1079
+
1080
+ /**
1081
+ * Process payment response
1082
+ */
1083
+ export interface ProcessPaymentResponse {
1084
+ /** Whether the payment was successful */
1085
+ success: boolean;
1086
+ /** Payment transaction ID */
1087
+ transactionId?: string;
1088
+ /** Blockchain transaction hash (for crypto payments) */
1089
+ transactionHash?: string;
1090
+ /** Payment status */
1091
+ status: "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELLED" | "REFUNDED";
1092
+ /** Amount charged */
1093
+ amount: number;
1094
+ /** Currency */
1095
+ currency: string;
1096
+ /** Error message if failed */
1097
+ error?: string;
1098
+ /** Error code */
1099
+ errorCode?: string;
1100
+ }
1101
+
1102
+ // ============================================================================
1103
+ // GEM System Responses
1104
+ // ============================================================================
1105
+
1106
+ /**
1107
+ * Gem source type - how gems were earned
1108
+ */
1109
+ export type GemSource =
1110
+ | "BUILDER_CODE"
1111
+ | "PREDICTION"
1112
+ | "CARD_SPEND"
1113
+ | "MALL_SPEND"
1114
+ | "ADMIN"
1115
+ | "REFUND";
1116
+
1117
+ /**
1118
+ * Get gem balance response
1119
+ */
1120
+ export interface GetGemBalanceResponse {
1121
+ /** User ID */
1122
+ userId: string;
1123
+ /** Total gems owned */
1124
+ totalGems: number;
1125
+ /** Available gems (not reserved) */
1126
+ availableGems: number;
1127
+ /** Gems expiring within 30 days */
1128
+ expiringSoon: number;
1129
+ /** Last balance update timestamp */
1130
+ lastUpdated: string;
1131
+ /** USD equivalent (totalGems / 100) */
1132
+ usdEquivalent: number;
1133
+ /** Conversion rate (gems per $1) */
1134
+ conversionRate: number;
1135
+ }
1136
+
1137
+ /**
1138
+ * Gem history item type
1139
+ */
1140
+ export type GemHistoryType = "earn" | "spend" | "expire";
1141
+
1142
+ /**
1143
+ * Gem history item
1144
+ */
1145
+ export interface GemHistoryItem {
1146
+ /** Transaction ID */
1147
+ id: string;
1148
+ /** Type of transaction */
1149
+ type: GemHistoryType;
1150
+ /** Amount of gems (positive for earn, negative for spend) */
1151
+ amount: number;
1152
+ /** Source type (for earn transactions) */
1153
+ source?: GemSource;
1154
+ /** Reason description (for spend transactions) */
1155
+ reason?: string;
1156
+ /** When the transaction occurred */
1157
+ createdAt: string;
1158
+ /** When the gems expire (for earn transactions) */
1159
+ expiresAt?: string;
1160
+ }
1161
+
1162
+ /**
1163
+ * Get gem history response
1164
+ */
1165
+ export interface GetGemHistoryResponse {
1166
+ /** History items */
1167
+ items: GemHistoryItem[];
1168
+ /** Total count of items */
1169
+ total: number;
1170
+ /** Pagination info */
1171
+ pagination: {
1172
+ /** Items per page */
1173
+ limit: number;
1174
+ /** Current offset */
1175
+ offset: number;
1176
+ /** Whether more items exist */
1177
+ hasMore: boolean;
1178
+ };
1179
+ }
1180
+
1181
+ /**
1182
+ * Expiring gem batch
1183
+ */
1184
+ export interface ExpiringGemBatch {
1185
+ /** Batch ID */
1186
+ id: string;
1187
+ /** Remaining gems in batch */
1188
+ amount: number;
1189
+ /** How the gems were earned */
1190
+ source: GemSource;
1191
+ /** When the batch expires */
1192
+ expiresAt: string;
1193
+ /** When the batch was created */
1194
+ createdAt: string;
1195
+ /** Days until expiry */
1196
+ daysUntilExpiry: number;
1197
+ }
1198
+
1199
+ /**
1200
+ * Get expiring gems response
1201
+ */
1202
+ export interface GetExpiringGemsResponse {
1203
+ /** Total gems expiring within the query period */
1204
+ totalExpiring: number;
1205
+ /** Expiring batches */
1206
+ batches: ExpiringGemBatch[];
1207
+ /** Query parameters used */
1208
+ queryParams: {
1209
+ /** Days ahead that were queried */
1210
+ days: number;
1211
+ };
1212
+ }
1213
+
1214
+ // ============================================================================
1215
+ // Browsing Location Responses
1216
+ // ============================================================================
1217
+
1218
+ /**
1219
+ * User's browsing location for geo-based product filtering
1220
+ */
1221
+ export interface BrowsingLocation {
1222
+ /** Location ID */
1223
+ id: string;
1224
+ /** Full display address */
1225
+ formattedAddress: string;
1226
+ /** City name */
1227
+ city: string;
1228
+ /** State/Province (if applicable) */
1229
+ stateProvince?: string | null;
1230
+ /** ISO 2-letter country code */
1231
+ country: string;
1232
+ /** Latitude coordinate */
1233
+ latitude: number;
1234
+ /** Longitude coordinate */
1235
+ longitude: number;
1236
+ /** Last updated timestamp */
1237
+ updatedAt: string;
1238
+ }
1239
+
1240
+ /**
1241
+ * Get browsing location response
1242
+ */
1243
+ export interface GetBrowsingLocationResponse {
1244
+ /** User's saved browsing location (null if not set) */
1245
+ location: BrowsingLocation | null;
1246
+ }
1247
+
1248
+ /**
1249
+ * Save browsing location response
1250
+ */
1251
+ export interface SaveBrowsingLocationResponse {
1252
+ /** Whether the operation was successful */
1253
+ success: boolean;
1254
+ /** The saved location */
1255
+ location: BrowsingLocation;
1256
+ }
1257
+
1258
+ /**
1259
+ * Delete browsing location response
1260
+ */
1261
+ export interface DeleteBrowsingLocationResponse {
1262
+ /** Whether the operation was successful */
1263
+ success: boolean;
1264
+ /** Success message */
1265
+ message: string;
1266
+ }
1267
+
@@ -80,7 +80,7 @@ export const formatSizeForOrder = ({
80
80
  sz,
81
81
  szDecimals,
82
82
  }: {
83
- sz: number;
83
+ sz: number | string;
84
84
  szDecimals: number;
85
85
  }) => {
86
86
  return new Decimal(sz).toDP(szDecimals, Decimal.ROUND_DOWN).toNumber();
package/lib/utils/time.ts CHANGED
@@ -49,3 +49,27 @@ export function getLatestCompletedWeek(
49
49
  return { weekNumber, startDate, endDate };
50
50
  }
51
51
 
52
+ /**
53
+ * Gets week information from a week number.
54
+ * This is the inverse of getLatestCompletedWeek - it converts a week number to start/end dates.
55
+ *
56
+ * @param weekNumber - The week number (1-based, where week 1 starts at WEEK1_START_DATE)
57
+ * @param weekStartsOn - Day of week the week should start on. Defaults to Thursday.
58
+ * @returns WeekInfo with weekNumber, startDate, and endDate
59
+ */
60
+ export function getWeekInfoFromNumber(
61
+ weekNumber: number,
62
+ weekStartsOn: DayOfWeek = DayOfWeek.Thursday
63
+ ): WeekInfo {
64
+ // Using a fixed point in time for week 1 calculation for consistency
65
+ const week1StartDate = new Date(process.env.WEEK1_START_DATE || "2025-12-04T00:00:00Z");
66
+
67
+ // Calculate start date: week 1 starts at week1StartDate, week N starts at week1StartDate + (N-1) weeks
68
+ const startDate = new Date(week1StartDate.getTime() + (weekNumber - 1) * WEEK_IN_MS);
69
+
70
+ // End date is 7 days after start date
71
+ const endDate = new Date(startDate.getTime() + WEEK_IN_MS);
72
+
73
+ return { weekNumber, startDate, endDate };
74
+ }
75
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basedone/core",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Core utilities for Based One",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -36,17 +36,18 @@
36
36
  "devDependencies": {
37
37
  "@types/node": "^20.0.0",
38
38
  "@types/react": "^18.0.0",
39
+ "axios": "^1.6.0",
39
40
  "tsup": "^8.5.0",
40
41
  "tsx": "^4.19.2",
41
42
  "typescript": "^5.0.0",
42
43
  "vitest": "^3.2.4"
43
44
  },
44
45
  "dependencies": {
45
- "axios": "^1.6.0",
46
46
  "decimal.js": "^10.6.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@nktkas/hyperliquid": "^0.24.3",
50
+ "axios": "^1.6.0",
50
51
  "react": "^18.0.0 || ^19.0.0"
51
52
  },
52
53
  "peerDependenciesMeta": {