@evefrontier/dapp-kit 0.1.1 → 0.1.3
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/CHANGELOG.md +12 -0
- package/README.md +2 -2
- package/docs/api/assets/hierarchy.js +1 -1
- package/docs/api/assets/navigation.js +1 -1
- package/docs/api/assets/search.js +1 -1
- package/docs/api/classes/WalletNoAccountSelectedError.html +3 -3
- package/docs/api/classes/WalletNotConnectedError.html +3 -3
- package/docs/api/classes/WalletSponsoredTransactionNotSupportedError.html +3 -3
- package/docs/api/enums/ActionTypes.html +2 -2
- package/docs/api/enums/Assemblies.html +3 -2
- package/docs/api/enums/QueryParams.html +2 -2
- package/docs/api/enums/Severity.html +2 -2
- package/docs/api/enums/SponsoredTransactionActions.html +3 -3
- package/docs/api/enums/State.html +2 -2
- package/docs/api/enums/SupportedWallets.html +2 -2
- package/docs/api/enums/TYPEIDS.html +3 -3
- package/docs/api/functions/EveFrontierProvider.html +2 -2
- package/docs/api/functions/NotificationProvider.html +2 -2
- package/docs/api/functions/SmartObjectProvider.html +4 -4
- package/docs/api/functions/VaultProvider.html +1 -1
- package/docs/api/functions/abbreviateAddress.html +2 -2
- package/docs/api/functions/assertAssemblyType.html +2 -2
- package/docs/api/functions/clickToCopy.html +1 -1
- package/docs/api/functions/executeGraphQLQuery.html +2 -2
- package/docs/api/functions/findOwnerByAddress.html +2 -2
- package/docs/api/functions/formatDuration.html +2 -2
- package/docs/api/functions/formatM3.html +2 -2
- package/docs/api/functions/getAdjustedBurnRate.html +6 -0
- package/docs/api/functions/getAssemblyType.html +2 -2
- package/docs/api/functions/getAssemblyTypeApiString.html +2 -2
- package/docs/api/functions/getAssemblyWithOwner.html +3 -3
- package/docs/api/functions/getCharacterAndOwnedObjects.html +3 -0
- package/docs/api/functions/getCharacterOwnedObjects.html +5 -0
- package/docs/api/functions/getCharacterOwnedObjectsJson.html +5 -0
- package/docs/api/functions/getCharacterOwnerCapType.html +2 -2
- package/docs/api/functions/getCharacterPlayerProfileType.html +3 -0
- package/docs/api/functions/getCommonItems.html +1 -1
- package/docs/api/functions/getDappUrl.html +2 -2
- package/docs/api/functions/getDatahubGameInfo.html +2 -2
- package/docs/api/functions/getEnergyConfig.html +4 -0
- package/docs/api/functions/getEnergyConfigType.html +3 -0
- package/docs/api/functions/getEnergyUsageForType.html +5 -0
- package/docs/api/functions/getEnv.html +1 -1
- package/docs/api/functions/getEveWorldPackageId.html +2 -2
- package/docs/api/functions/getFuelEfficiencyConfig.html +4 -0
- package/docs/api/functions/getFuelEfficiencyConfigType.html +3 -0
- package/docs/api/functions/getFuelEfficiencyForType.html +5 -0
- package/docs/api/functions/getObjectByAddress.html +2 -2
- package/docs/api/functions/getObjectId.html +2 -2
- package/docs/api/functions/getObjectOwnerAndOwnedObjectsByType.html +2 -2
- package/docs/api/functions/getObjectOwnerAndOwnedObjectsWithJson.html +7 -0
- package/docs/api/functions/getObjectRegistryType.html +2 -2
- package/docs/api/functions/getObjectWithDynamicFields.html +2 -2
- package/docs/api/functions/getObjectWithJson.html +2 -2
- package/docs/api/functions/getObjectsByType.html +2 -2
- package/docs/api/functions/getOwnedObjectsByPackage.html +2 -2
- package/docs/api/functions/getOwnedObjectsByType.html +2 -2
- package/docs/api/functions/getRegistryAddress.html +2 -2
- package/docs/api/functions/getSingletonObjectByType.html +2 -2
- package/docs/api/functions/getSponsoredTransactionFeature.html +2 -2
- package/docs/api/functions/getSuiGraphqlEndpoint.html +2 -2
- package/docs/api/functions/getTxUrl.html +2 -2
- package/docs/api/functions/getVolumeM3.html +2 -2
- package/docs/api/functions/getWalletCharacters.html +3 -0
- package/docs/api/functions/hasSponsoredTransactionFeature.html +2 -2
- package/docs/api/functions/isOwner.html +3 -3
- package/docs/api/functions/parseCharacterFromJson.html +5 -0
- package/docs/api/functions/parseErrorFromMessage.html +1 -1
- package/docs/api/functions/parseStatus.html +2 -2
- package/docs/api/functions/parseURL.html +1 -1
- package/docs/api/functions/removeTrailingZeros.html +1 -1
- package/docs/api/functions/transformToAssembly.html +2 -2
- package/docs/api/functions/transformToCharacter.html +2 -2
- package/docs/api/functions/useConnection.html +2 -2
- package/docs/api/functions/useNotification.html +2 -2
- package/docs/api/functions/useSmartObject.html +4 -9
- package/docs/api/functions/useSponsoredTransaction.html +5 -5
- package/docs/api/functions/walletSupportsSponsoredTransaction.html +2 -2
- package/docs/api/hierarchy.html +1 -1
- package/docs/api/index.html +3 -5
- package/docs/api/interfaces/AddressOwner.html +2 -2
- package/docs/api/interfaces/AddressOwnerWithJson.html +2 -2
- package/docs/api/interfaces/AddressWithObjects.html +3 -0
- package/docs/api/interfaces/AdjustedBurnRate.html +8 -0
- package/docs/api/interfaces/AsMoveObjectRef.html +3 -0
- package/docs/api/interfaces/AssemblyProperties.html +6 -3
- package/docs/api/interfaces/CharacterAndOwnedObjectsNode.html +2 -0
- package/docs/api/interfaces/CharacterInfo.html +3 -3
- package/docs/api/interfaces/CharacterOwnerNode.html +3 -0
- package/docs/api/interfaces/ConfigExtractDynamicFieldNode.html +3 -0
- package/docs/api/interfaces/ContentsBcs.html +2 -0
- package/docs/api/interfaces/ContentsJsonAndBcs.html +3 -0
- package/docs/api/interfaces/ContentsJsonOnly.html +3 -0
- package/docs/api/interfaces/ContentsTypeAndBcs.html +3 -0
- package/docs/api/interfaces/ContentsTypeJsonAndBcs.html +4 -0
- package/docs/api/interfaces/DatahubGameInfo.html +14 -16
- package/docs/api/interfaces/DetailedAssemblyResponse.html +6 -3
- package/docs/api/interfaces/DetailedSmartCharacterResponse.html +2 -2
- package/docs/api/interfaces/DynamicFieldNode.html +2 -2
- package/docs/api/interfaces/EphemeralInventory.html +2 -2
- package/docs/api/interfaces/EveFrontierSponsoredTransactionFeature.html +3 -3
- package/docs/api/interfaces/ExtractAsMoveObjectNode.html +4 -0
- package/docs/api/interfaces/GateModule.html +2 -5
- package/docs/api/interfaces/GetCharacterAndOwnedObjectsResponse.html +2 -0
- package/docs/api/interfaces/GetObjectAndCharacterOwnerResponse.html +2 -0
- package/docs/api/interfaces/GetObjectByAddressResponse.html +2 -2
- package/docs/api/interfaces/GetObjectOwnerAndOwnedObjectsResponse.html +2 -2
- package/docs/api/interfaces/GetObjectOwnerAndOwnedObjectsWithJsonResponse.html +2 -2
- package/docs/api/interfaces/GetObjectResponse.html +2 -2
- package/docs/api/interfaces/GetObjectWithJsonResponse.html +2 -2
- package/docs/api/interfaces/GetObjectsByTypeResponse.html +2 -2
- package/docs/api/interfaces/GetOwnedObjectsByPackageResponse.html +2 -2
- package/docs/api/interfaces/GetOwnedObjectsByTypeResponse.html +2 -2
- package/docs/api/interfaces/GetSingletonConfigObjectByTypeResponse.html +2 -0
- package/docs/api/interfaces/GetSingletonObjectByTypeResponse.html +2 -2
- package/docs/api/interfaces/GetWalletCharactersResponse.html +2 -0
- package/docs/api/interfaces/GraphQLResponse.html +2 -2
- package/docs/api/interfaces/InventoryItem.html +2 -2
- package/docs/api/interfaces/ManufacturingModule.html +1 -2
- package/docs/api/interfaces/MoveObjectContents.html +2 -2
- package/docs/api/interfaces/MoveObjectData.html +2 -2
- package/docs/api/interfaces/NetworkNodeModule.html +2 -2
- package/docs/api/interfaces/NotificationContextType.html +2 -2
- package/docs/api/interfaces/NotificationState.html +2 -2
- package/docs/api/interfaces/Notify.html +2 -2
- package/docs/api/interfaces/ObjectNodes.html +2 -0
- package/docs/api/interfaces/ObjectWithContentsNode.html +2 -2
- package/docs/api/interfaces/OwnedObjectAddressNode.html +2 -2
- package/docs/api/interfaces/OwnedObjectFullNode.html +2 -2
- package/docs/api/interfaces/OwnedObjectNode.html +2 -2
- package/docs/api/interfaces/OwnedObjectNodeWithJson.html +2 -2
- package/docs/api/interfaces/OwnerCapData.html +3 -3
- package/docs/api/interfaces/PageInfo.html +2 -2
- package/docs/api/interfaces/PreviousTransaction.html +2 -0
- package/docs/api/interfaces/RawCharacterData.html +3 -3
- package/docs/api/interfaces/RawSuiObjectData.html +10 -6
- package/docs/api/interfaces/RefineryModule.html +1 -2
- package/docs/api/interfaces/SmartAssemblyResponse.html +6 -2
- package/docs/api/interfaces/SmartObjectContextType.html +4 -6
- package/docs/api/interfaces/SponsoredTransactionInput.html +6 -7
- package/docs/api/interfaces/SponsoredTransactionOutput.html +5 -5
- package/docs/api/interfaces/StorageModule.html +2 -3
- package/docs/api/interfaces/SuiObjectResponse.html +2 -2
- package/docs/api/interfaces/TransformOptions.html +8 -4
- package/docs/api/interfaces/TurretModule.html +1 -2
- package/docs/api/interfaces/TypeRepr.html +2 -0
- package/docs/api/interfaces/TypeReprWithLayout.html +3 -0
- package/docs/api/interfaces/VaultContextType.html +3 -3
- package/docs/api/modules.html +1 -1
- package/docs/api/types/AssemblyType.html +1 -1
- package/docs/api/types/ContentsTypeAndJson.html +2 -0
- package/docs/api/types/ErrorType.html +2 -2
- package/docs/api/types/MoveObjectRefWithJson.html +2 -0
- package/docs/api/types/SendSponsoredTransactionFn.html +1 -1
- package/docs/api/types/SponsoredTransactionArgs.html +2 -2
- package/docs/api/types/SponsoredTransactionAssemblyType.html +2 -2
- package/docs/api/types/SponsoredTransactionMethod.html +2 -2
- package/docs/api/types/UseSponsoredTransactionArgs.html +2 -2
- package/docs/api/types/UseSponsoredTransactionError.html +2 -2
- package/docs/api/types/UseSponsoredTransactionMutationOptions.html +2 -2
- package/docs/api/variables/ASSEMBLY_TYPE_API_STRING.html +2 -2
- package/docs/api/variables/ERRORS.html +1 -1
- package/docs/api/variables/ERROR_MESSAGES.html +1 -1
- package/docs/api/variables/EVEFRONTIER_SPONSORED_TRANSACTION.html +2 -2
- package/docs/api/variables/EXCLUDED_TYPEIDS.html +1 -1
- package/docs/api/variables/GET_OBJECTS_BY_TYPE.html +2 -2
- package/docs/api/variables/GET_OBJECT_BY_ADDRESS.html +2 -2
- package/docs/api/variables/GET_OBJECT_OWNER_AND_OWNED_OBJECTS_BY_TYPE.html +2 -2
- package/docs/api/variables/GET_OBJECT_OWNER_AND_OWNED_OBJECTS_WITH_JSON.html +2 -2
- package/docs/api/variables/GET_OBJECT_WITH_DYNAMIC_FIELDS.html +2 -2
- package/docs/api/variables/GET_OBJECT_WITH_JSON.html +2 -2
- package/docs/api/variables/GET_OWNED_OBJECTS_BY_PACKAGE.html +2 -2
- package/docs/api/variables/GET_OWNED_OBJECTS_BY_TYPE.html +2 -2
- package/docs/api/variables/GET_SINGLETON_CONFIG_OBJECT_BY_TYPE.html +2 -0
- package/docs/api/variables/GET_SINGLETON_OBJECT_BY_TYPE.html +2 -2
- package/docs/api/variables/GET_WALLET_CHARACTERS.html +3 -0
- package/docs/api/variables/NotificationContext.html +1 -1
- package/docs/api/variables/ONE_M3.html +2 -2
- package/docs/api/variables/POLLING_INTERVAL.html +2 -2
- package/docs/api/variables/STORAGE_KEYS.html +2 -2
- package/docs/api/variables/SmartObjectContext.html +1 -1
- package/docs/api/variables/VaultContext.html +1 -1
- package/docs/api/variables/dAppKit.html +2 -2
- package/graphql/client.ts +119 -24
- package/graphql/index.ts +5 -39
- package/graphql/queries.ts +166 -1
- package/graphql/types.ts +192 -167
- package/hooks/index.ts +1 -0
- package/hooks/useSmartObject.ts +2 -12
- package/hooks/useSponsoredTransaction.ts +60 -9
- package/index.ts +7 -71
- package/package.json +1 -1
- package/providers/SmartObjectProvider.tsx +84 -57
- package/types/contexts.ts +1 -3
- package/types/sponsoredTransaction.ts +1 -0
- package/types/types.ts +52 -10
- package/types/worldApiReturnTypes.ts +13 -37
- package/utils/__tests__/burnRate.test.ts +121 -0
- package/utils/__tests__/character.test.ts +112 -0
- package/utils/__tests__/characterOwnedObjects.test.ts +222 -0
- package/utils/__tests__/config.test.ts +424 -0
- package/utils/__tests__/mapping.test.ts +2 -2
- package/utils/burnRate.ts +46 -0
- package/utils/character.ts +46 -0
- package/utils/characterOwnedObjects.ts +52 -0
- package/utils/config.ts +151 -0
- package/utils/constants.ts +39 -5
- package/utils/datahub.ts +3 -41
- package/utils/errors.ts +1 -1
- package/utils/index.ts +10 -1
- package/utils/mapping.ts +5 -2
- package/utils/transforms.ts +34 -31
- package/vite-env.d.ts +2 -2
- package/wallet/features.ts +7 -2
- package/docs/api/interfaces/GameTypeResponse.html +0 -13
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MoveObjectData, RawSuiObjectData } from "../graphql/types";
|
|
2
|
+
import { TransformOptions } from "../utils";
|
|
3
|
+
import { State, Assemblies, type DatahubGameInfo } from "./types";
|
|
2
4
|
|
|
3
5
|
// =========================================
|
|
4
6
|
// Inventory Related Types
|
|
@@ -36,30 +38,21 @@ export interface StorageModule {
|
|
|
36
38
|
items: InventoryItem[];
|
|
37
39
|
};
|
|
38
40
|
ephemeralInventories: EphemeralInventory[];
|
|
39
|
-
isParentNodeOnline: boolean;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
/** @category Types */
|
|
43
|
-
export interface TurretModule {
|
|
44
|
-
isParentNodeOnline: boolean;
|
|
45
|
-
}
|
|
44
|
+
export interface TurretModule {}
|
|
46
45
|
|
|
47
46
|
/** @category Types */
|
|
48
|
-
export interface ManufacturingModule {
|
|
49
|
-
isParentNodeOnline: boolean;
|
|
50
|
-
}
|
|
47
|
+
export interface ManufacturingModule {}
|
|
51
48
|
|
|
52
49
|
/** @category Types */
|
|
53
|
-
export interface RefineryModule {
|
|
54
|
-
isParentNodeOnline: boolean;
|
|
55
|
-
}
|
|
50
|
+
export interface RefineryModule {}
|
|
56
51
|
|
|
57
52
|
/** @category Types */
|
|
58
53
|
export interface GateModule {
|
|
59
|
-
linked: boolean;
|
|
60
54
|
destinationId: string | undefined;
|
|
61
|
-
|
|
62
|
-
isParentNodeOnline: boolean;
|
|
55
|
+
destinationGate: RawSuiObjectData | null;
|
|
63
56
|
}
|
|
64
57
|
|
|
65
58
|
/** @category Types */
|
|
@@ -78,7 +71,7 @@ export interface NetworkNodeModule {
|
|
|
78
71
|
/** @category Types @internal */
|
|
79
72
|
export interface FuelResponse {
|
|
80
73
|
quantity: number;
|
|
81
|
-
|
|
74
|
+
burnTimeInMs: number;
|
|
82
75
|
burnStartTime: number;
|
|
83
76
|
isBurning: boolean;
|
|
84
77
|
lastUpdated: number;
|
|
@@ -131,38 +124,21 @@ export interface SmartAssemblyResponse {
|
|
|
131
124
|
id: string;
|
|
132
125
|
item_id: number;
|
|
133
126
|
type: Assemblies;
|
|
134
|
-
typeDetails?:
|
|
127
|
+
typeDetails?: DatahubGameInfo;
|
|
135
128
|
name: string;
|
|
136
129
|
state: State;
|
|
137
130
|
character?: SmartCharacterResponse;
|
|
138
131
|
solarSystem?: SolarSystem;
|
|
132
|
+
isParentNodeOnline?: boolean;
|
|
133
|
+
energySourceId?: string;
|
|
139
134
|
energyUsage: number;
|
|
140
135
|
typeId: number;
|
|
136
|
+
_raw?: MoveObjectData;
|
|
137
|
+
_options?: TransformOptions;
|
|
141
138
|
}
|
|
142
139
|
|
|
143
140
|
/** @category Types */
|
|
144
141
|
export interface DetailedAssemblyResponse extends SmartAssemblyResponse {
|
|
145
|
-
location: {
|
|
146
|
-
x: number;
|
|
147
|
-
y: number;
|
|
148
|
-
z: number;
|
|
149
|
-
};
|
|
150
142
|
description: string;
|
|
151
143
|
dappURL: string;
|
|
152
144
|
}
|
|
153
|
-
|
|
154
|
-
/** @category Types */
|
|
155
|
-
export interface GameTypeResponse {
|
|
156
|
-
categoryId: number;
|
|
157
|
-
categoryName: string;
|
|
158
|
-
description: string;
|
|
159
|
-
groupId: number;
|
|
160
|
-
groupName: string;
|
|
161
|
-
iconUrl: string;
|
|
162
|
-
id: number;
|
|
163
|
-
mass: number;
|
|
164
|
-
name: string;
|
|
165
|
-
portionSize: number;
|
|
166
|
-
radius: number;
|
|
167
|
-
volume: number;
|
|
168
|
-
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getAdjustedBurnRate } from "../burnRate";
|
|
3
|
+
|
|
4
|
+
describe("getAdjustedBurnRate", () => {
|
|
5
|
+
const MS_PER_HOUR = 3600000;
|
|
6
|
+
|
|
7
|
+
it("returns ~1.11 units/hour when raw is 1h and efficiency is 90%", () => {
|
|
8
|
+
const raw = MS_PER_HOUR;
|
|
9
|
+
const result = getAdjustedBurnRate(raw, 90);
|
|
10
|
+
expect(result.burnTimePerUnitMs).toBe(3240000); // 3600000 * 0.9
|
|
11
|
+
expect(result.unitsPerHour).toBeCloseTo(1.111111, 4);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("returns burnTimePerUnitMs = raw and 1 unit/hour when efficiency is 100% and raw is 1h", () => {
|
|
15
|
+
const raw = MS_PER_HOUR;
|
|
16
|
+
const result = getAdjustedBurnRate(raw, 100);
|
|
17
|
+
expect(result.burnTimePerUnitMs).toBe(raw);
|
|
18
|
+
expect(result.unitsPerHour).toBe(1);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("returns 2.5 units/hour when raw is 1h and efficiency is 40%", () => {
|
|
22
|
+
const raw = MS_PER_HOUR;
|
|
23
|
+
const result = getAdjustedBurnRate(raw, 40);
|
|
24
|
+
expect(result.burnTimePerUnitMs).toBe(1440000); // 3600000 * 0.4
|
|
25
|
+
expect(result.unitsPerHour).toBe(2.5);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("returns 1.25 units/hour when raw is 1h and efficiency is 80%", () => {
|
|
29
|
+
const raw = MS_PER_HOUR;
|
|
30
|
+
const result = getAdjustedBurnRate(raw, 80);
|
|
31
|
+
expect(result.burnTimePerUnitMs).toBe(2880000); // 3600000 * 0.8
|
|
32
|
+
expect(result.unitsPerHour).toBe(1.25);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("returns ~6.67 units/hour when raw is 1h and efficiency is 15%", () => {
|
|
36
|
+
const raw = MS_PER_HOUR;
|
|
37
|
+
const result = getAdjustedBurnRate(raw, 15);
|
|
38
|
+
expect(result.burnTimePerUnitMs).toBe(540000); // 3600000 * 0.15
|
|
39
|
+
expect(result.unitsPerHour).toBeCloseTo(6.666667, 4);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("returns 10 units/hour when raw is 1h and efficiency is 10%", () => {
|
|
43
|
+
const raw = MS_PER_HOUR;
|
|
44
|
+
const result = getAdjustedBurnRate(raw, 10);
|
|
45
|
+
expect(result.burnTimePerUnitMs).toBe(360000); // 3600000 * 0.1
|
|
46
|
+
expect(result.unitsPerHour).toBe(10);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("uses raw as burn time and derives unitsPerHour when efficiency is null", () => {
|
|
50
|
+
const raw = MS_PER_HOUR;
|
|
51
|
+
const result = getAdjustedBurnRate(raw, null);
|
|
52
|
+
expect(result.burnTimePerUnitMs).toBe(raw);
|
|
53
|
+
expect(result.unitsPerHour).toBe(1);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("uses raw as burn time when efficiency is undefined", () => {
|
|
57
|
+
const raw = 1800000;
|
|
58
|
+
const result = getAdjustedBurnRate(raw, undefined);
|
|
59
|
+
expect(result.burnTimePerUnitMs).toBe(raw);
|
|
60
|
+
expect(result.unitsPerHour).toBe(2);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("uses raw as burn time when efficiency is 0", () => {
|
|
64
|
+
const raw = MS_PER_HOUR;
|
|
65
|
+
const result = getAdjustedBurnRate(raw, 0);
|
|
66
|
+
expect(result.burnTimePerUnitMs).toBe(raw);
|
|
67
|
+
expect(result.unitsPerHour).toBe(1);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("returns unitsPerHour 0 when raw is 0", () => {
|
|
71
|
+
const result = getAdjustedBurnRate(0, 90);
|
|
72
|
+
expect(result.burnTimePerUnitMs).toBe(0);
|
|
73
|
+
expect(result.unitsPerHour).toBe(0);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("normalizes invalid raw (NaN) to 0 and returns (0, 0)", () => {
|
|
77
|
+
const result = getAdjustedBurnRate(Number.NaN, 90);
|
|
78
|
+
expect(result.burnTimePerUnitMs).toBe(0);
|
|
79
|
+
expect(result.unitsPerHour).toBe(0);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("normalizes invalid raw (Infinity) to 0 and returns (0, 0)", () => {
|
|
83
|
+
const result = getAdjustedBurnRate(Number.POSITIVE_INFINITY, 90);
|
|
84
|
+
expect(result.burnTimePerUnitMs).toBe(0);
|
|
85
|
+
expect(result.unitsPerHour).toBe(0);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("normalizes invalid raw (negative) to 0 and returns (0, 0)", () => {
|
|
89
|
+
const result = getAdjustedBurnRate(-1000, 90);
|
|
90
|
+
expect(result.burnTimePerUnitMs).toBe(0);
|
|
91
|
+
expect(result.unitsPerHour).toBe(0);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("handles negative efficiency by using raw (fallback)", () => {
|
|
95
|
+
const raw = MS_PER_HOUR;
|
|
96
|
+
const result = getAdjustedBurnRate(raw, -10);
|
|
97
|
+
expect(result.burnTimePerUnitMs).toBe(raw);
|
|
98
|
+
expect(result.unitsPerHour).toBe(1);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("handles NaN efficiency by using raw", () => {
|
|
102
|
+
const raw = MS_PER_HOUR;
|
|
103
|
+
const result = getAdjustedBurnRate(raw, Number.NaN);
|
|
104
|
+
expect(result.burnTimePerUnitMs).toBe(raw);
|
|
105
|
+
expect(result.unitsPerHour).toBe(1);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("treats efficiency > 100 as invalid and uses raw (fallback)", () => {
|
|
109
|
+
const raw = MS_PER_HOUR;
|
|
110
|
+
const result = getAdjustedBurnRate(raw, 250);
|
|
111
|
+
expect(result.burnTimePerUnitMs).toBe(raw);
|
|
112
|
+
expect(result.unitsPerHour).toBe(1);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("computes correct unitsPerHour for 10 units/hour (6 min per unit)", () => {
|
|
116
|
+
const sixMinutesMs = 6 * 60 * 1000;
|
|
117
|
+
const result = getAdjustedBurnRate(sixMinutesMs, 100);
|
|
118
|
+
expect(result.burnTimePerUnitMs).toBe(sixMinutesMs);
|
|
119
|
+
expect(result.unitsPerHour).toBe(10);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { parseCharacterFromJson } from "../character";
|
|
3
|
+
|
|
4
|
+
describe("parseCharacterFromJson", () => {
|
|
5
|
+
const validCharacterJson = {
|
|
6
|
+
id: "0x65916b0c872aa5e29b0e9ec66a29fa18cd5f85b188d48914d4437d42abc4f800",
|
|
7
|
+
character_address: "0x82da5c79037b5cb544ed89725f61a577d17c55a14941ea992a8d18cc476893d7",
|
|
8
|
+
tribe_id: 17,
|
|
9
|
+
key: { item_id: "12345", tenant: "default" },
|
|
10
|
+
metadata: {
|
|
11
|
+
name: "Test Character",
|
|
12
|
+
description: "",
|
|
13
|
+
url: "",
|
|
14
|
+
assembly_id: "0xassembly",
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
it("returns null when json is null", () => {
|
|
19
|
+
expect(parseCharacterFromJson(null)).toBeNull();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("returns null when json is undefined", () => {
|
|
23
|
+
expect(parseCharacterFromJson(undefined)).toBeNull();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("returns null when json is a string", () => {
|
|
27
|
+
expect(parseCharacterFromJson("not an object")).toBeNull();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("returns null when json is an array", () => {
|
|
31
|
+
expect(parseCharacterFromJson([])).toBeNull();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("returns CharacterInfo with all fields when given valid object", () => {
|
|
35
|
+
const result = parseCharacterFromJson(validCharacterJson);
|
|
36
|
+
expect(result).not.toBeNull();
|
|
37
|
+
expect(result!.id).toBe(validCharacterJson.id);
|
|
38
|
+
expect(result!.address).toBe(validCharacterJson.character_address);
|
|
39
|
+
expect(result!.name).toBe(validCharacterJson.metadata.name);
|
|
40
|
+
expect(result!.tribeId).toBe(17);
|
|
41
|
+
expect(result!.characterId).toBe(12345);
|
|
42
|
+
expect(result!._raw).toBe(validCharacterJson);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("parses tribe_id when it is a string", () => {
|
|
46
|
+
const result = parseCharacterFromJson({
|
|
47
|
+
...validCharacterJson,
|
|
48
|
+
tribe_id: "42",
|
|
49
|
+
});
|
|
50
|
+
expect(result).not.toBeNull();
|
|
51
|
+
expect(result!.tribeId).toBe(42);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("parses key.item_id when it is a string", () => {
|
|
55
|
+
const result = parseCharacterFromJson({
|
|
56
|
+
...validCharacterJson,
|
|
57
|
+
key: { item_id: "999", tenant: "x" },
|
|
58
|
+
});
|
|
59
|
+
expect(result).not.toBeNull();
|
|
60
|
+
expect(result!.characterId).toBe(999);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns 0 for tribeId when tribe_id is missing", () => {
|
|
64
|
+
const { tribe_id: _, ...withoutTribe } = validCharacterJson;
|
|
65
|
+
const result = parseCharacterFromJson(withoutTribe);
|
|
66
|
+
expect(result).not.toBeNull();
|
|
67
|
+
expect(result!.tribeId).toBe(0);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("returns 0 for characterId when key is missing", () => {
|
|
71
|
+
const { key: _, ...withoutKey } = validCharacterJson;
|
|
72
|
+
const result = parseCharacterFromJson(withoutKey);
|
|
73
|
+
expect(result).not.toBeNull();
|
|
74
|
+
expect(result!.characterId).toBe(0);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("returns empty string for name when metadata is not an object", () => {
|
|
78
|
+
const result = parseCharacterFromJson({
|
|
79
|
+
...validCharacterJson,
|
|
80
|
+
metadata: "invalid",
|
|
81
|
+
});
|
|
82
|
+
expect(result).not.toBeNull();
|
|
83
|
+
expect(result!.name).toBe("");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("returns empty string for name when metadata.name is missing", () => {
|
|
87
|
+
const result = parseCharacterFromJson({
|
|
88
|
+
...validCharacterJson,
|
|
89
|
+
metadata: { description: "", url: "", assembly_id: "0x" },
|
|
90
|
+
});
|
|
91
|
+
expect(result).not.toBeNull();
|
|
92
|
+
expect(result!.name).toBe("");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("returns empty strings for id and address when missing or wrong type", () => {
|
|
96
|
+
const result = parseCharacterFromJson({
|
|
97
|
+
tribe_id: 0,
|
|
98
|
+
key: {},
|
|
99
|
+
metadata: {},
|
|
100
|
+
});
|
|
101
|
+
expect(result).not.toBeNull();
|
|
102
|
+
expect(result!.id).toBe("");
|
|
103
|
+
expect(result!.address).toBe("");
|
|
104
|
+
expect(result!.name).toBe("");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("stores original json as _raw", () => {
|
|
108
|
+
const input = { ...validCharacterJson };
|
|
109
|
+
const result = parseCharacterFromJson(input);
|
|
110
|
+
expect(result!._raw).toBe(input);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import type { GetCharacterAndOwnedObjectsResponse } from "../../graphql/types";
|
|
3
|
+
import {
|
|
4
|
+
getCharacterOwnedObjectsJson,
|
|
5
|
+
getCharacterOwnedObjects,
|
|
6
|
+
} from "../characterOwnedObjects";
|
|
7
|
+
|
|
8
|
+
vi.mock("../../graphql/client", () => ({
|
|
9
|
+
getCharacterAndOwnedObjects: vi.fn(),
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
import { getCharacterAndOwnedObjects } from "../../graphql/client";
|
|
13
|
+
|
|
14
|
+
/** Minimal owned object node shape (Gate/Assembly/Character/NetworkNode). */
|
|
15
|
+
function ownedObjectNode(json: Record<string, unknown>, typeRepr: string) {
|
|
16
|
+
return {
|
|
17
|
+
contents: {
|
|
18
|
+
extract: {
|
|
19
|
+
asAddress: {
|
|
20
|
+
asObject: {
|
|
21
|
+
asMoveObject: {
|
|
22
|
+
contents: { type: { repr: typeRepr }, json },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Builds a valid GetCharacterAndOwnedObjectsResponse with the given owned-object json payloads. */
|
|
32
|
+
function buildResponse(
|
|
33
|
+
ownedJsons: Record<string, unknown>[],
|
|
34
|
+
typeRepr = "0x2::example::Object",
|
|
35
|
+
): GetCharacterAndOwnedObjectsResponse {
|
|
36
|
+
const nodes = ownedJsons.map((json) => ownedObjectNode(json, typeRepr));
|
|
37
|
+
return {
|
|
38
|
+
address: {
|
|
39
|
+
address: "0xwallet",
|
|
40
|
+
objects: {
|
|
41
|
+
nodes: [
|
|
42
|
+
{
|
|
43
|
+
contents: {
|
|
44
|
+
extract: {
|
|
45
|
+
asAddress: {
|
|
46
|
+
asObject: {
|
|
47
|
+
asMoveObject: {
|
|
48
|
+
contents: {
|
|
49
|
+
type: { repr: "0x2::character::Character" },
|
|
50
|
+
json: { id: "0xchar", metadata: {} },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
objects: { nodes },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
describe("getCharacterOwnedObjectsJson", () => {
|
|
66
|
+
it("returns undefined when data is undefined", () => {
|
|
67
|
+
expect(getCharacterOwnedObjectsJson(undefined)).toBeUndefined();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("returns undefined when data is null", () => {
|
|
71
|
+
expect(getCharacterOwnedObjectsJson(null as unknown as undefined)).toBeUndefined();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("returns undefined when address is missing", () => {
|
|
75
|
+
expect(
|
|
76
|
+
getCharacterOwnedObjectsJson(
|
|
77
|
+
{} as unknown as GetCharacterAndOwnedObjectsResponse,
|
|
78
|
+
),
|
|
79
|
+
).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("returns undefined when address.objects is missing", () => {
|
|
83
|
+
expect(
|
|
84
|
+
getCharacterOwnedObjectsJson({
|
|
85
|
+
address: { address: "0x" },
|
|
86
|
+
} as unknown as GetCharacterAndOwnedObjectsResponse),
|
|
87
|
+
).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("returns undefined when address.objects.nodes is missing", () => {
|
|
91
|
+
expect(
|
|
92
|
+
getCharacterOwnedObjectsJson({
|
|
93
|
+
address: { address: "0x", objects: {} },
|
|
94
|
+
} as unknown as GetCharacterAndOwnedObjectsResponse),
|
|
95
|
+
).toBeUndefined();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("returns undefined when address.objects.nodes is empty", () => {
|
|
99
|
+
expect(
|
|
100
|
+
getCharacterOwnedObjectsJson({
|
|
101
|
+
address: { address: "0x", objects: { nodes: [] } },
|
|
102
|
+
}),
|
|
103
|
+
).toBeUndefined();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("returns undefined when first node has no contents.extract.asAddress.objects", () => {
|
|
107
|
+
const data = {
|
|
108
|
+
address: {
|
|
109
|
+
address: "0x",
|
|
110
|
+
objects: {
|
|
111
|
+
nodes: [
|
|
112
|
+
{
|
|
113
|
+
contents: {
|
|
114
|
+
extract: {
|
|
115
|
+
asAddress: {
|
|
116
|
+
/* objects missing – path ends here */
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
} as unknown as GetCharacterAndOwnedObjectsResponse;
|
|
125
|
+
expect(getCharacterOwnedObjectsJson(data)).toBeUndefined();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("returns undefined when objects.nodes is empty", () => {
|
|
129
|
+
const data = buildResponse([]);
|
|
130
|
+
expect(getCharacterOwnedObjectsJson(data)).toBeUndefined();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("extracts json array from full deep GraphQL shape (single object)", () => {
|
|
134
|
+
const json1 = { id: "0xobj1", type_id: "123", owner_cap_id: "0xcap" };
|
|
135
|
+
const data = buildResponse([json1]);
|
|
136
|
+
const result = getCharacterOwnedObjectsJson(data);
|
|
137
|
+
expect(result).toEqual([json1]);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("extracts json array from full deep GraphQL shape (multiple objects)", () => {
|
|
141
|
+
const json1 = { id: "0xgate", type_id: "gate" };
|
|
142
|
+
const json2 = { id: "0xasm", type_id: "assembly", metadata: {} };
|
|
143
|
+
const json3 = { id: "0xchar", tribe_id: 17, character_address: "0xaddr" };
|
|
144
|
+
const data = buildResponse([json1, json2, json3]);
|
|
145
|
+
const result = getCharacterOwnedObjectsJson(data);
|
|
146
|
+
expect(result).toEqual([json1, json2, json3]);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("preserves exact json payloads (regression: deep path must match GraphQL shape)", () => {
|
|
150
|
+
const nested = {
|
|
151
|
+
id: "0xnode",
|
|
152
|
+
fuel: { quantity: "100", is_burning: false },
|
|
153
|
+
connected_assembly_ids: ["0xa", "0xb"],
|
|
154
|
+
};
|
|
155
|
+
const data = buildResponse([nested]);
|
|
156
|
+
const result = getCharacterOwnedObjectsJson(data);
|
|
157
|
+
expect(result).toHaveLength(1);
|
|
158
|
+
expect(result![0]).toEqual(nested);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe("getCharacterOwnedObjects", () => {
|
|
163
|
+
beforeEach(() => {
|
|
164
|
+
vi.clearAllMocks();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
afterEach(() => {
|
|
168
|
+
vi.restoreAllMocks();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("returns extracted json array when response has data with owned objects", async () => {
|
|
172
|
+
const payloads = [
|
|
173
|
+
{ id: "0x1", type_id: "gate" },
|
|
174
|
+
{ id: "0x2", type_id: "assembly" },
|
|
175
|
+
];
|
|
176
|
+
const responseData = buildResponse(payloads);
|
|
177
|
+
vi.mocked(getCharacterAndOwnedObjects).mockResolvedValue({
|
|
178
|
+
data: responseData,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const result = await getCharacterOwnedObjects("0xwallet");
|
|
182
|
+
|
|
183
|
+
expect(getCharacterAndOwnedObjects).toHaveBeenCalledWith("0xwallet");
|
|
184
|
+
expect(result).toEqual(payloads);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("returns undefined when response.data is undefined", async () => {
|
|
188
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
189
|
+
vi.mocked(getCharacterAndOwnedObjects).mockResolvedValue({});
|
|
190
|
+
|
|
191
|
+
const result = await getCharacterOwnedObjects("0xwallet");
|
|
192
|
+
|
|
193
|
+
expect(result).toBeUndefined();
|
|
194
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
195
|
+
"[Dapp] No data returned from getCharacterAndOwnedObjects",
|
|
196
|
+
);
|
|
197
|
+
warnSpy.mockRestore();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("returns undefined when response.data has no owned objects (empty nodes)", async () => {
|
|
201
|
+
const responseData = buildResponse([]);
|
|
202
|
+
vi.mocked(getCharacterAndOwnedObjects).mockResolvedValue({
|
|
203
|
+
data: responseData,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const result = await getCharacterOwnedObjects("0xwallet");
|
|
207
|
+
|
|
208
|
+
expect(result).toBeUndefined();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("returns undefined when response.data.address is missing", async () => {
|
|
212
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
213
|
+
vi.mocked(getCharacterAndOwnedObjects).mockResolvedValue({
|
|
214
|
+
data: {} as GetCharacterAndOwnedObjectsResponse,
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const result = await getCharacterOwnedObjects("0xwallet");
|
|
218
|
+
|
|
219
|
+
expect(result).toBeUndefined();
|
|
220
|
+
warnSpy.mockRestore();
|
|
221
|
+
});
|
|
222
|
+
});
|