@evefrontier/dapp-kit 0.1.0
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/README.md +53 -0
- package/config/dapp-kit.ts +20 -0
- package/config/index.ts +1 -0
- package/docs/api/.nojekyll +1 -0
- package/docs/api/assets/hierarchy.js +1 -0
- package/docs/api/assets/highlight.css +120 -0
- package/docs/api/assets/icons.js +18 -0
- package/docs/api/assets/icons.svg +1 -0
- package/docs/api/assets/main.js +60 -0
- package/docs/api/assets/navigation.js +1 -0
- package/docs/api/assets/search.js +1 -0
- package/docs/api/assets/style.css +1633 -0
- package/docs/api/classes/WalletNoAccountSelectedError.html +3 -0
- package/docs/api/classes/WalletNotConnectedError.html +3 -0
- package/docs/api/classes/WalletSponsoredTransactionNotSupportedError.html +5 -0
- package/docs/api/enums/ActionTypes.html +6 -0
- package/docs/api/enums/Assemblies.html +7 -0
- package/docs/api/enums/QueryParams.html +3 -0
- package/docs/api/enums/Severity.html +5 -0
- package/docs/api/enums/SponsoredTransactionActions.html +7 -0
- package/docs/api/enums/State.html +6 -0
- package/docs/api/enums/TYPEIDS.html +15 -0
- package/docs/api/functions/EveFrontierProvider.html +11 -0
- package/docs/api/functions/NotificationProvider.html +2 -0
- package/docs/api/functions/SmartObjectProvider.html +10 -0
- package/docs/api/functions/VaultProvider.html +1 -0
- package/docs/api/functions/abbreviateAddress.html +11 -0
- package/docs/api/functions/assertAssemblyType.html +9 -0
- package/docs/api/functions/clickToCopy.html +1 -0
- package/docs/api/functions/executeGraphQLQuery.html +12 -0
- package/docs/api/functions/findOwnerByAddress.html +5 -0
- package/docs/api/functions/formatDuration.html +8 -0
- package/docs/api/functions/formatM3.html +8 -0
- package/docs/api/functions/getAssemblyType.html +4 -0
- package/docs/api/functions/getAssemblyTypeApiString.html +2 -0
- package/docs/api/functions/getAssemblyWithOwner.html +18 -0
- package/docs/api/functions/getCharacterOwnerCapType.html +3 -0
- package/docs/api/functions/getCommonItems.html +1 -0
- package/docs/api/functions/getDappUrl.html +7 -0
- package/docs/api/functions/getDatahubGameInfo.html +13 -0
- package/docs/api/functions/getEnv.html +1 -0
- package/docs/api/functions/getEveWorldPackageId.html +4 -0
- package/docs/api/functions/getObjectByAddress.html +9 -0
- package/docs/api/functions/getObjectId.html +4 -0
- package/docs/api/functions/getObjectOwnerAndOwnedObjectsByType.html +10 -0
- package/docs/api/functions/getObjectRegistryType.html +3 -0
- package/docs/api/functions/getObjectWithDynamicFields.html +10 -0
- package/docs/api/functions/getObjectWithJson.html +9 -0
- package/docs/api/functions/getObjectsByType.html +12 -0
- package/docs/api/functions/getOwnedObjectsByPackage.html +10 -0
- package/docs/api/functions/getOwnedObjectsByType.html +10 -0
- package/docs/api/functions/getRegistryAddress.html +3 -0
- package/docs/api/functions/getSingletonObjectByType.html +9 -0
- package/docs/api/functions/getSponsoredTransactionFeature.html +11 -0
- package/docs/api/functions/getSuiGraphqlEndpoint.html +4 -0
- package/docs/api/functions/getTxUrl.html +8 -0
- package/docs/api/functions/getVolumeM3.html +5 -0
- package/docs/api/functions/hasSponsoredTransactionFeature.html +3 -0
- package/docs/api/functions/isOwner.html +10 -0
- package/docs/api/functions/parseErrorFromMessage.html +1 -0
- package/docs/api/functions/parseStatus.html +2 -0
- package/docs/api/functions/parseURL.html +1 -0
- package/docs/api/functions/removeTrailingZeros.html +1 -0
- package/docs/api/functions/transformToAssembly.html +5 -0
- package/docs/api/functions/transformToCharacter.html +2 -0
- package/docs/api/functions/useConnection.html +21 -0
- package/docs/api/functions/useNotification.html +28 -0
- package/docs/api/functions/useSmartObject.html +26 -0
- package/docs/api/functions/useSponsoredTransaction.html +50 -0
- package/docs/api/functions/walletSupportsSponsoredTransaction.html +13 -0
- package/docs/api/hierarchy.html +1 -0
- package/docs/api/index.html +26 -0
- package/docs/api/interfaces/AddressOwner.html +2 -0
- package/docs/api/interfaces/AddressOwnerWithJson.html +2 -0
- package/docs/api/interfaces/AssemblyProperties.html +14 -0
- package/docs/api/interfaces/CharacterInfo.html +8 -0
- package/docs/api/interfaces/DatahubGameInfo.html +30 -0
- package/docs/api/interfaces/DetailedAssemblyResponse.html +14 -0
- package/docs/api/interfaces/DetailedSmartCharacterResponse.html +7 -0
- package/docs/api/interfaces/DynamicFieldNode.html +3 -0
- package/docs/api/interfaces/EphemeralInventory.html +6 -0
- package/docs/api/interfaces/EveFrontierSponsoredTransactionFeature.html +7 -0
- package/docs/api/interfaces/GameTypeResponse.html +13 -0
- package/docs/api/interfaces/GateModule.html +5 -0
- package/docs/api/interfaces/GetObjectByAddressResponse.html +2 -0
- package/docs/api/interfaces/GetObjectOwnerAndOwnedObjectsResponse.html +2 -0
- package/docs/api/interfaces/GetObjectOwnerAndOwnedObjectsWithJsonResponse.html +2 -0
- package/docs/api/interfaces/GetObjectResponse.html +2 -0
- package/docs/api/interfaces/GetObjectWithJsonResponse.html +2 -0
- package/docs/api/interfaces/GetObjectsByTypeResponse.html +2 -0
- package/docs/api/interfaces/GetOwnedObjectsByPackageResponse.html +2 -0
- package/docs/api/interfaces/GetOwnedObjectsByTypeResponse.html +2 -0
- package/docs/api/interfaces/GetSingletonObjectByTypeResponse.html +2 -0
- package/docs/api/interfaces/GraphQLResponse.html +3 -0
- package/docs/api/interfaces/InventoryItem.html +8 -0
- package/docs/api/interfaces/ManufacturingModule.html +2 -0
- package/docs/api/interfaces/MoveObjectContents.html +4 -0
- package/docs/api/interfaces/MoveObjectData.html +3 -0
- package/docs/api/interfaces/NetworkNodeModule.html +7 -0
- package/docs/api/interfaces/NotificationContextType.html +4 -0
- package/docs/api/interfaces/NotificationState.html +6 -0
- package/docs/api/interfaces/Notify.html +6 -0
- package/docs/api/interfaces/ObjectWithContentsNode.html +4 -0
- package/docs/api/interfaces/OwnedObjectAddressNode.html +2 -0
- package/docs/api/interfaces/OwnedObjectFullNode.html +4 -0
- package/docs/api/interfaces/OwnedObjectNode.html +3 -0
- package/docs/api/interfaces/OwnedObjectNodeWithJson.html +4 -0
- package/docs/api/interfaces/OwnerCapData.html +5 -0
- package/docs/api/interfaces/PageInfo.html +3 -0
- package/docs/api/interfaces/RawCharacterData.html +8 -0
- package/docs/api/interfaces/RawSuiObjectData.html +17 -0
- package/docs/api/interfaces/RefineryModule.html +2 -0
- package/docs/api/interfaces/SmartAssemblyResponse.html +11 -0
- package/docs/api/interfaces/SmartObjectContextType.html +8 -0
- package/docs/api/interfaces/SponsoredTransactionInput.html +15 -0
- package/docs/api/interfaces/SponsoredTransactionOutput.html +8 -0
- package/docs/api/interfaces/StorageModule.html +4 -0
- package/docs/api/interfaces/SuiObjectResponse.html +5 -0
- package/docs/api/interfaces/TransformOptions.html +6 -0
- package/docs/api/interfaces/TurretModule.html +2 -0
- package/docs/api/interfaces/VaultContextType.html +7 -0
- package/docs/api/modules.html +1 -0
- package/docs/api/types/AssemblyType.html +1 -0
- package/docs/api/types/ErrorType.html +5 -0
- package/docs/api/types/SendSponsoredTransactionFn.html +1 -0
- package/docs/api/types/SponsoredTransactionArgs.html +2 -0
- package/docs/api/types/SponsoredTransactionAssemblyType.html +2 -0
- package/docs/api/types/SponsoredTransactionMethod.html +2 -0
- package/docs/api/types/UseSponsoredTransactionArgs.html +3 -0
- package/docs/api/types/UseSponsoredTransactionError.html +2 -0
- package/docs/api/types/UseSponsoredTransactionMutationOptions.html +2 -0
- package/docs/api/variables/ERRORS.html +1 -0
- package/docs/api/variables/ERROR_MESSAGES.html +1 -0
- package/docs/api/variables/EVEFRONTIER_SPONSORED_TRANSACTION.html +4 -0
- package/docs/api/variables/EXCLUDED_TYPEIDS.html +1 -0
- package/docs/api/variables/GET_OBJECTS_BY_TYPE.html +3 -0
- package/docs/api/variables/GET_OBJECT_BY_ADDRESS.html +3 -0
- package/docs/api/variables/GET_OBJECT_OWNER_AND_OWNED_OBJECTS_BY_TYPE.html +4 -0
- package/docs/api/variables/GET_OBJECT_OWNER_AND_OWNED_OBJECTS_WITH_JSON.html +3 -0
- package/docs/api/variables/GET_OBJECT_WITH_DYNAMIC_FIELDS.html +4 -0
- package/docs/api/variables/GET_OBJECT_WITH_JSON.html +3 -0
- package/docs/api/variables/GET_OWNED_OBJECTS_BY_PACKAGE.html +3 -0
- package/docs/api/variables/GET_OWNED_OBJECTS_BY_TYPE.html +3 -0
- package/docs/api/variables/GET_SINGLETON_OBJECT_BY_TYPE.html +3 -0
- package/docs/api/variables/NotificationContext.html +1 -0
- package/docs/api/variables/ONE_M3.html +2 -0
- package/docs/api/variables/POLLING_INTERVAL.html +2 -0
- package/docs/api/variables/STORAGE_KEYS.html +2 -0
- package/docs/api/variables/SmartObjectContext.html +1 -0
- package/docs/api/variables/VaultContext.html +1 -0
- package/docs/api/variables/dAppKit.html +2 -0
- package/graphql/client.ts +480 -0
- package/graphql/index.ts +73 -0
- package/graphql/queries.ts +371 -0
- package/graphql/types.ts +443 -0
- package/hooks/index.ts +14 -0
- package/hooks/useConnection.ts +58 -0
- package/hooks/useNotification.ts +80 -0
- package/hooks/useSmartObject.ts +78 -0
- package/hooks/useSponsoredTransaction.ts +323 -0
- package/index.ts +162 -0
- package/package.json +48 -0
- package/providers/EveFrontierProvider.tsx +41 -0
- package/providers/NotificationProvider.tsx +115 -0
- package/providers/SmartObjectProvider.tsx +282 -0
- package/providers/VaultProvider.tsx +114 -0
- package/providers/index.ts +17 -0
- package/tsconfig.json +22 -0
- package/typedoc.json +38 -0
- package/types/global.d.ts +7 -0
- package/types/index.ts +4 -0
- package/types/sponsoredTransaction.ts +26 -0
- package/types/types.ts +113 -0
- package/types/worldApiReturnTypes.ts +166 -0
- package/utils/__tests__/mapping.test.ts +441 -0
- package/utils/constants.ts +96 -0
- package/utils/datahub.ts +76 -0
- package/utils/errors.ts +171 -0
- package/utils/index.ts +38 -0
- package/utils/mapping.ts +115 -0
- package/utils/transforms.ts +258 -0
- package/utils/utils.ts +270 -0
- package/vite-env.d.ts +16 -0
- package/wallet/features.ts +165 -0
- package/wallet/index.ts +28 -0
- package/wallet/utils.ts +117 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { State, AssemblyType, Assemblies } from "./types";
|
|
2
|
+
|
|
3
|
+
// =========================================
|
|
4
|
+
// Inventory Related Types
|
|
5
|
+
// =========================================
|
|
6
|
+
|
|
7
|
+
/** @category Types */
|
|
8
|
+
export interface InventoryItem {
|
|
9
|
+
id: string;
|
|
10
|
+
item_id: string;
|
|
11
|
+
location: { location_hash: string };
|
|
12
|
+
quantity: number;
|
|
13
|
+
tenant: string;
|
|
14
|
+
type_id: number;
|
|
15
|
+
name: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** @category Types */
|
|
19
|
+
export interface EphemeralInventory {
|
|
20
|
+
ownerId: string;
|
|
21
|
+
ownerName: string;
|
|
22
|
+
storageCapacity: bigint;
|
|
23
|
+
usedCapacity: bigint;
|
|
24
|
+
ephemeralInventoryItems: InventoryItem[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// =========================================
|
|
28
|
+
// Module Types
|
|
29
|
+
// =========================================
|
|
30
|
+
|
|
31
|
+
/** @category Types */
|
|
32
|
+
export interface StorageModule {
|
|
33
|
+
mainInventory: {
|
|
34
|
+
capacity: string;
|
|
35
|
+
usedCapacity: string;
|
|
36
|
+
items: InventoryItem[];
|
|
37
|
+
};
|
|
38
|
+
ephemeralInventories: EphemeralInventory[];
|
|
39
|
+
isParentNodeOnline: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** @category Types */
|
|
43
|
+
export interface TurretModule {
|
|
44
|
+
isParentNodeOnline: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** @category Types */
|
|
48
|
+
export interface ManufacturingModule {
|
|
49
|
+
isParentNodeOnline: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** @category Types */
|
|
53
|
+
export interface RefineryModule {
|
|
54
|
+
isParentNodeOnline: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** @category Types */
|
|
58
|
+
export interface GateModule {
|
|
59
|
+
linked: boolean;
|
|
60
|
+
destinationId: string | undefined;
|
|
61
|
+
inRange: AssemblyType<Assemblies.SmartGate>[];
|
|
62
|
+
isParentNodeOnline: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** @category Types */
|
|
66
|
+
export interface NetworkNodeModule {
|
|
67
|
+
fuel: FuelResponse;
|
|
68
|
+
burn: BurnResponse;
|
|
69
|
+
energyProduction: number;
|
|
70
|
+
energyMaxCapacity: number;
|
|
71
|
+
totalReservedEnergy: number;
|
|
72
|
+
linkedAssemblies: SmartAssemblyResponse[];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// =========================================
|
|
76
|
+
// Fuel Related Types
|
|
77
|
+
// =========================================
|
|
78
|
+
|
|
79
|
+
/** @category Types @internal */
|
|
80
|
+
export interface FuelResponse {
|
|
81
|
+
amount: number;
|
|
82
|
+
burnRateInMs: number;
|
|
83
|
+
efficiency: number;
|
|
84
|
+
unitVolume: number;
|
|
85
|
+
typeId: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** @category Types @internal */
|
|
89
|
+
export interface BurnResponse {
|
|
90
|
+
isBurning: boolean;
|
|
91
|
+
startTime: string;
|
|
92
|
+
previousCycleElapsedTimeInSec: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// =========================================
|
|
96
|
+
// Location Related Types
|
|
97
|
+
// =========================================
|
|
98
|
+
|
|
99
|
+
/** @category Types @internal */
|
|
100
|
+
export interface SolarSystem {
|
|
101
|
+
id: number;
|
|
102
|
+
name: string;
|
|
103
|
+
location: {
|
|
104
|
+
x: number;
|
|
105
|
+
y: number;
|
|
106
|
+
z: number;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// =========================================
|
|
111
|
+
// Character Related Types
|
|
112
|
+
// =========================================
|
|
113
|
+
|
|
114
|
+
/** @category Types @internal */
|
|
115
|
+
export interface SmartCharacterResponse {
|
|
116
|
+
address: string;
|
|
117
|
+
id: string;
|
|
118
|
+
name: string;
|
|
119
|
+
tribeId: number;
|
|
120
|
+
characterId: number;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// =========================================
|
|
124
|
+
// Assembly Related Types
|
|
125
|
+
// =========================================
|
|
126
|
+
|
|
127
|
+
/** @category Types */
|
|
128
|
+
export interface SmartAssemblyResponse {
|
|
129
|
+
id: string;
|
|
130
|
+
item_id: number;
|
|
131
|
+
type: Assemblies;
|
|
132
|
+
typeDetails?: GameTypeResponse;
|
|
133
|
+
name: string;
|
|
134
|
+
state: State;
|
|
135
|
+
character?: SmartCharacterResponse;
|
|
136
|
+
solarSystem?: SolarSystem;
|
|
137
|
+
energyUsage: number;
|
|
138
|
+
typeId: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** @category Types */
|
|
142
|
+
export interface DetailedAssemblyResponse extends SmartAssemblyResponse {
|
|
143
|
+
location: {
|
|
144
|
+
x: number;
|
|
145
|
+
y: number;
|
|
146
|
+
z: number;
|
|
147
|
+
};
|
|
148
|
+
description: string;
|
|
149
|
+
dappURL: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** @category Types */
|
|
153
|
+
export interface GameTypeResponse {
|
|
154
|
+
categoryId: number;
|
|
155
|
+
categoryName: string;
|
|
156
|
+
description: string;
|
|
157
|
+
groupId: number;
|
|
158
|
+
groupName: string;
|
|
159
|
+
iconUrl: string;
|
|
160
|
+
id: number;
|
|
161
|
+
mass: number;
|
|
162
|
+
name: string;
|
|
163
|
+
portionSize: number;
|
|
164
|
+
radius: number;
|
|
165
|
+
volume: number;
|
|
166
|
+
}
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { bcs } from "@mysten/sui/bcs";
|
|
3
|
+
import { deriveObjectID } from "@mysten/sui/utils";
|
|
4
|
+
import { parseStatus, getAssemblyType } from "../mapping";
|
|
5
|
+
import { Assemblies, State } from "../../types";
|
|
6
|
+
import { getObjectRegistryType } from "../constants";
|
|
7
|
+
|
|
8
|
+
// Mock env vars for testing
|
|
9
|
+
const TEST_EVE_WORLD_PACKAGE_ID =
|
|
10
|
+
"0x2ff3e06b96eb830bdcffbc6cae9b8fe43f005c3b94cef05d9ec23057df16f107";
|
|
11
|
+
const TEST_SUI_GRAPHQL_ENDPOINT = "https://graphql.testnet.sui.io/graphql";
|
|
12
|
+
|
|
13
|
+
// Mock the GraphQL client (only for getObjectId/getRegistryAddress tests)
|
|
14
|
+
vi.mock("../../graphql/client", () => ({
|
|
15
|
+
getSingletonObjectByType: vi.fn(),
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
import { getSingletonObjectByType } from "../../graphql/client";
|
|
19
|
+
|
|
20
|
+
describe("mapping utilities", () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
vi.clearAllMocks();
|
|
23
|
+
// Stub environment variables for tests
|
|
24
|
+
vi.stubEnv("VITE_EVE_WORLD_PACKAGE_ID", TEST_EVE_WORLD_PACKAGE_ID);
|
|
25
|
+
vi.stubEnv("VITE_SUI_GRAPHQL_ENDPOINT", TEST_SUI_GRAPHQL_ENDPOINT);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
vi.restoreAllMocks();
|
|
30
|
+
vi.unstubAllEnvs();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// parseStatus Tests
|
|
35
|
+
// ============================================================================
|
|
36
|
+
describe("parseStatus", () => {
|
|
37
|
+
it("returns State.ONLINE for 'ONLINE' status", () => {
|
|
38
|
+
expect(parseStatus("ONLINE")).toBe(State.ONLINE);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("returns State.ONLINE for lowercase 'online' status", () => {
|
|
42
|
+
expect(parseStatus("online")).toBe(State.ONLINE);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("returns State.ANCHORED for 'OFFLINE' status", () => {
|
|
46
|
+
expect(parseStatus("OFFLINE")).toBe(State.ANCHORED);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("returns State.ANCHORED for 'ANCHORED' status", () => {
|
|
50
|
+
expect(parseStatus("ANCHORED")).toBe(State.ANCHORED);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("returns State.UNANCHORED for 'UNANCHORED' status", () => {
|
|
54
|
+
expect(parseStatus("UNANCHORED")).toBe(State.UNANCHORED);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("returns State.NULL for undefined status", () => {
|
|
58
|
+
expect(parseStatus(undefined)).toBe(State.NULL);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("returns State.NULL for empty string", () => {
|
|
62
|
+
expect(parseStatus("")).toBe(State.NULL);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// getAssemblyType Tests
|
|
68
|
+
// ============================================================================
|
|
69
|
+
describe("getAssemblyType", () => {
|
|
70
|
+
it("returns SmartStorageUnit for storage_unit type", () => {
|
|
71
|
+
expect(
|
|
72
|
+
getAssemblyType(
|
|
73
|
+
`${TEST_EVE_WORLD_PACKAGE_ID}::storage_unit::StorageUnit<...>`,
|
|
74
|
+
),
|
|
75
|
+
).toBe(Assemblies.SmartStorageUnit);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("returns SmartTurret for turret type", () => {
|
|
79
|
+
expect(
|
|
80
|
+
getAssemblyType(`${TEST_EVE_WORLD_PACKAGE_ID}::turret::Turret<...>`),
|
|
81
|
+
).toBe(Assemblies.SmartTurret);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("returns SmartGate for gate type", () => {
|
|
85
|
+
expect(
|
|
86
|
+
getAssemblyType(`${TEST_EVE_WORLD_PACKAGE_ID}::gate::Gate<...>`),
|
|
87
|
+
).toBe(Assemblies.SmartGate);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("returns NetworkNode for network_node type", () => {
|
|
91
|
+
expect(
|
|
92
|
+
getAssemblyType(
|
|
93
|
+
`${TEST_EVE_WORLD_PACKAGE_ID}::network_node::NetworkNode<...>`,
|
|
94
|
+
),
|
|
95
|
+
).toBe(Assemblies.NetworkNode);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("returns SmartStorageUnit as default for unknown type", () => {
|
|
99
|
+
expect(getAssemblyType("unknown::type::Unknown")).toBe(
|
|
100
|
+
Assemblies.SmartStorageUnit,
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("handles type strings with different package IDs", () => {
|
|
105
|
+
expect(
|
|
106
|
+
getAssemblyType("0xabc123::storage_unit::StorageUnit<SomeType>"),
|
|
107
|
+
).toBe(Assemblies.SmartStorageUnit);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// getRegistryAddress Tests
|
|
113
|
+
// ============================================================================
|
|
114
|
+
describe("getRegistryAddress", () => {
|
|
115
|
+
const mockAssemblyRegistryAddress =
|
|
116
|
+
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
|
|
117
|
+
const mockCharacterRegistryAddress =
|
|
118
|
+
"0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321";
|
|
119
|
+
|
|
120
|
+
beforeEach(() => {
|
|
121
|
+
vi.resetModules();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("fetches assembly registry address from GraphQL", async () => {
|
|
125
|
+
vi.mocked(getSingletonObjectByType).mockResolvedValueOnce({
|
|
126
|
+
data: {
|
|
127
|
+
objects: {
|
|
128
|
+
nodes: [{ address: mockAssemblyRegistryAddress }],
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const { getRegistryAddress } = await import("../mapping");
|
|
134
|
+
const address = await getRegistryAddress();
|
|
135
|
+
|
|
136
|
+
expect(getSingletonObjectByType).toHaveBeenCalledWith(
|
|
137
|
+
getObjectRegistryType(),
|
|
138
|
+
);
|
|
139
|
+
expect(address).toBe(mockAssemblyRegistryAddress);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("fetches character registry address from GraphQL", async () => {
|
|
143
|
+
vi.mocked(getSingletonObjectByType).mockResolvedValueOnce({
|
|
144
|
+
data: {
|
|
145
|
+
objects: {
|
|
146
|
+
nodes: [{ address: mockCharacterRegistryAddress }],
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const { getRegistryAddress } = await import("../mapping");
|
|
152
|
+
const address = await getRegistryAddress();
|
|
153
|
+
|
|
154
|
+
expect(getSingletonObjectByType).toHaveBeenCalledWith(
|
|
155
|
+
getObjectRegistryType(),
|
|
156
|
+
);
|
|
157
|
+
expect(address).toBe(mockCharacterRegistryAddress);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("caches assembly registry address after first fetch", async () => {
|
|
161
|
+
vi.mocked(getSingletonObjectByType).mockResolvedValueOnce({
|
|
162
|
+
data: {
|
|
163
|
+
objects: {
|
|
164
|
+
nodes: [{ address: mockAssemblyRegistryAddress }],
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const { getRegistryAddress } = await import("../mapping");
|
|
170
|
+
|
|
171
|
+
const address = await getRegistryAddress();
|
|
172
|
+
|
|
173
|
+
expect(getSingletonObjectByType).toHaveBeenCalledTimes(1);
|
|
174
|
+
expect(address).toBe(mockAssemblyRegistryAddress);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("throws error when registry address is not found", async () => {
|
|
178
|
+
vi.mocked(getSingletonObjectByType).mockResolvedValueOnce({
|
|
179
|
+
data: {
|
|
180
|
+
objects: {
|
|
181
|
+
nodes: [],
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const { getRegistryAddress } = await import("../mapping");
|
|
187
|
+
|
|
188
|
+
await expect(getRegistryAddress()).rejects.toThrow(
|
|
189
|
+
`ObjectRegistry not found for type: ${getObjectRegistryType()}`,
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("throws error when GraphQL response has no data", async () => {
|
|
194
|
+
vi.mocked(getSingletonObjectByType).mockResolvedValueOnce({
|
|
195
|
+
data: undefined,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const { getRegistryAddress } = await import("../mapping");
|
|
199
|
+
|
|
200
|
+
await expect(getRegistryAddress()).rejects.toThrow(
|
|
201
|
+
`ObjectRegistry not found for type: ${getObjectRegistryType()}`,
|
|
202
|
+
);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// ============================================================================
|
|
207
|
+
describe("deriveObjectID derivation", () => {
|
|
208
|
+
const TenantItemIdBcs = bcs.struct("TenantItemId", {
|
|
209
|
+
item_id: bcs.u64(),
|
|
210
|
+
tenant: bcs.string(),
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it("works with primitive string (from Sui docs)", () => {
|
|
214
|
+
const result = deriveObjectID(
|
|
215
|
+
"0xc0ffee",
|
|
216
|
+
"0x1::string::String",
|
|
217
|
+
bcs.String.serialize("foo").toBytes(),
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
expect(result).toBe(
|
|
221
|
+
"0x699219f4a2b6cfb8640bb853fc4ab4f497da038ec0614bfa2835aa27993399db",
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("works with primitive u8 (from Sui docs)", () => {
|
|
226
|
+
const result = deriveObjectID(
|
|
227
|
+
"0x2",
|
|
228
|
+
"u8",
|
|
229
|
+
bcs.u8().serialize(1).toBytes(),
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
expect(result).toBe(
|
|
233
|
+
"0x4de7696edddfb592a8dc7c8b66053b1557eb4fa1a9194322562aabf3da9e9239",
|
|
234
|
+
);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("works with primitive u32 (from old Character contract)", () => {
|
|
238
|
+
const result = deriveObjectID(
|
|
239
|
+
"0xbe0c6bf206ff70ed30ef367dc46f8d47fa20263c3d3c04e0b08312b291a4755d",
|
|
240
|
+
"u32",
|
|
241
|
+
bcs.u32().serialize(1003).toBytes(),
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
expect(result).toBe(
|
|
245
|
+
"0xba2beac06dfcebe1963dea11ad37b4b851dd8060b6510c57e160e84280ed8b4c",
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it("works with TenantItemId struct", () => {
|
|
250
|
+
const key = TenantItemIdBcs.serialize({
|
|
251
|
+
item_id: 204305,
|
|
252
|
+
tenant: "yanns-macbook-pro.local",
|
|
253
|
+
}).toBytes();
|
|
254
|
+
|
|
255
|
+
const result = deriveObjectID(
|
|
256
|
+
"0x72ad8a9f876b922fb244761da022b328a8d487708d821f4d991414f320749c41",
|
|
257
|
+
"0xe938ed4a360f86554fda6f4493866b0732cdd996d80e1cee429ad35d0a03deee::game_id::TenantItemId",
|
|
258
|
+
key,
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
expect(result).toBe(
|
|
262
|
+
"0xac1edc9cd64eb00ee3f98a583d7f7c94a39493c984706e6b3afe2668c4c8fb4c",
|
|
263
|
+
);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("works with TenantItemId struct in test tenant (sample #1 from contracts)", () => {
|
|
267
|
+
const key = TenantItemIdBcs.serialize({
|
|
268
|
+
item_id: 691735,
|
|
269
|
+
tenant: "test",
|
|
270
|
+
}).toBytes();
|
|
271
|
+
|
|
272
|
+
const result = deriveObjectID(
|
|
273
|
+
"0x70c704eb8ee89c910a31ecf550a85514d5a4d3d2742cc2fbd5b2131c3513b79c",
|
|
274
|
+
"0x8941524ae368d91a7f9ee95466d3e60b75ddc16de3c3b9233dc11f85ce86c258::game_id::TenantItemId",
|
|
275
|
+
key,
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
expect(result).toBe(
|
|
279
|
+
"0xccee853995609e171763798b6faaf635793a9a88d79211d6486bfdd268d3fd73",
|
|
280
|
+
);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it("works with TenantItemId struct in test tenant (sample #2 from contracts)", () => {
|
|
284
|
+
const key = TenantItemIdBcs.serialize({
|
|
285
|
+
item_id: 625814,
|
|
286
|
+
tenant: "test",
|
|
287
|
+
}).toBytes();
|
|
288
|
+
|
|
289
|
+
const result = deriveObjectID(
|
|
290
|
+
"0x70c704eb8ee89c910a31ecf550a85514d5a4d3d2742cc2fbd5b2131c3513b79c",
|
|
291
|
+
"0x8941524ae368d91a7f9ee95466d3e60b75ddc16de3c3b9233dc11f85ce86c258::game_id::TenantItemId",
|
|
292
|
+
key,
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
expect(result).toBe(
|
|
296
|
+
"0x4b63016cb24af75235f8ab7c43b9fdfa52bb87a0f99c8f6d3d58c228d6fdc4c5",
|
|
297
|
+
);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it("works with new SSUID", () => {
|
|
301
|
+
const key = TenantItemIdBcs.serialize({
|
|
302
|
+
item_id: 1000000012533,
|
|
303
|
+
tenant: "testevenet",
|
|
304
|
+
}).toBytes();
|
|
305
|
+
|
|
306
|
+
const result = deriveObjectID(
|
|
307
|
+
"0x226c1a6e456f7438f4a2bc83808df75fb3e47fea4b11ef220f9a2df8fb91a97c",
|
|
308
|
+
"0x2ff3e06b96eb830bdcffbc6cae9b8fe43f005c3b94cef05d9ec23057df16f107::in_game_id::TenantItemId",
|
|
309
|
+
key,
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
expect(result).toBe(
|
|
313
|
+
"0x4c2d7222607d8d46bb6fe03a58e4488a79b598a6c2931d87f933d86dc0557233",
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it("produces different results for different tenants", () => {
|
|
318
|
+
const key1 = TenantItemIdBcs.serialize({
|
|
319
|
+
item_id: 12345,
|
|
320
|
+
tenant: "tenant1",
|
|
321
|
+
}).toBytes();
|
|
322
|
+
|
|
323
|
+
const key2 = TenantItemIdBcs.serialize({
|
|
324
|
+
item_id: 12345,
|
|
325
|
+
tenant: "tenant2",
|
|
326
|
+
}).toBytes();
|
|
327
|
+
|
|
328
|
+
const parentId =
|
|
329
|
+
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
|
|
330
|
+
const keyType = "0x1234::game_id::TenantItemId";
|
|
331
|
+
|
|
332
|
+
const result1 = deriveObjectID(parentId, keyType, key1);
|
|
333
|
+
const result2 = deriveObjectID(parentId, keyType, key2);
|
|
334
|
+
|
|
335
|
+
expect(result1).not.toBe(result2);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it("produces different results for different parent IDs", () => {
|
|
339
|
+
const key = TenantItemIdBcs.serialize({
|
|
340
|
+
item_id: 12345,
|
|
341
|
+
tenant: "test",
|
|
342
|
+
}).toBytes();
|
|
343
|
+
|
|
344
|
+
const keyType = "0x1234::game_id::TenantItemId";
|
|
345
|
+
|
|
346
|
+
const result1 = deriveObjectID(
|
|
347
|
+
"0x1111111111111111111111111111111111111111111111111111111111111111",
|
|
348
|
+
keyType,
|
|
349
|
+
key,
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
const result2 = deriveObjectID(
|
|
353
|
+
"0x2222222222222222222222222222222222222222222222222222222222222222",
|
|
354
|
+
keyType,
|
|
355
|
+
key,
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
expect(result1).not.toBe(result2);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// ============================================================================
|
|
363
|
+
// getObjectId Tests (mocked)
|
|
364
|
+
// ============================================================================
|
|
365
|
+
describe("getObjectId", () => {
|
|
366
|
+
const mockRegistryAddress =
|
|
367
|
+
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
|
|
368
|
+
|
|
369
|
+
beforeEach(() => {
|
|
370
|
+
vi.resetModules();
|
|
371
|
+
|
|
372
|
+
vi.mocked(getSingletonObjectByType).mockResolvedValue({
|
|
373
|
+
data: {
|
|
374
|
+
objects: {
|
|
375
|
+
nodes: [{ address: mockRegistryAddress }],
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it("fetches registry address and derives object ID", async () => {
|
|
382
|
+
const { getObjectId } = await import("../mapping");
|
|
383
|
+
const itemId = "12345";
|
|
384
|
+
|
|
385
|
+
const objectId = await getObjectId(itemId, "testevenet");
|
|
386
|
+
|
|
387
|
+
expect(getSingletonObjectByType).toHaveBeenCalledWith(
|
|
388
|
+
getObjectRegistryType(),
|
|
389
|
+
);
|
|
390
|
+
expect(typeof objectId).toBe("string");
|
|
391
|
+
expect(objectId.startsWith("0x")).toBe(true);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it("uses OBJECT registry type when specified", async () => {
|
|
395
|
+
const { getObjectId } = await import("../mapping");
|
|
396
|
+
|
|
397
|
+
await getObjectId("12345", "testevenet");
|
|
398
|
+
|
|
399
|
+
expect(getSingletonObjectByType).toHaveBeenCalledWith(
|
|
400
|
+
getObjectRegistryType(),
|
|
401
|
+
);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it("uses default OBJECT registry type when not specified", async () => {
|
|
405
|
+
const { getObjectId } = await import("../mapping");
|
|
406
|
+
|
|
407
|
+
await getObjectId("12345", "testevenet");
|
|
408
|
+
|
|
409
|
+
expect(getSingletonObjectByType).toHaveBeenCalledWith(
|
|
410
|
+
getObjectRegistryType(),
|
|
411
|
+
);
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
it("propagates errors when registry address not found", async () => {
|
|
415
|
+
vi.mocked(getSingletonObjectByType).mockResolvedValueOnce({
|
|
416
|
+
data: {
|
|
417
|
+
objects: {
|
|
418
|
+
nodes: [],
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
const { getObjectId } = await import("../mapping");
|
|
424
|
+
|
|
425
|
+
await expect(getObjectId("12345", "testevenet")).rejects.toThrow(
|
|
426
|
+
`ObjectRegistry not found for type: ${getObjectRegistryType()}`,
|
|
427
|
+
);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it("caches registry address across multiple calls", async () => {
|
|
431
|
+
const { getObjectId } = await import("../mapping");
|
|
432
|
+
|
|
433
|
+
await getObjectId("12345", "testevenet");
|
|
434
|
+
await getObjectId("67890", "testevenet");
|
|
435
|
+
await getObjectId("11111", "testevenet");
|
|
436
|
+
|
|
437
|
+
// Should only fetch registry once (cached)
|
|
438
|
+
expect(getSingletonObjectByType).toHaveBeenCalledTimes(1);
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Environment Variable Helpers
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get a required environment variable, throwing if not set.
|
|
7
|
+
* @param name - The environment variable name (e.g., "VITE_SUI_GRAPHQL_ENDPOINT")
|
|
8
|
+
* @throws {Error} If the environment variable is not set
|
|
9
|
+
*/
|
|
10
|
+
function getEnvVar(name: string): string {
|
|
11
|
+
const value = import.meta.env[name];
|
|
12
|
+
if (!value) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`Missing required environment variable: ${name}. ` +
|
|
15
|
+
`Please set it in your .env file.`,
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Environment-Based Configuration
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the Sui GraphQL endpoint URL from environment.
|
|
27
|
+
* @returns The GraphQL endpoint URL
|
|
28
|
+
* @throws {Error} If VITE_SUI_GRAPHQL_ENDPOINT is not set
|
|
29
|
+
* @category Utilities
|
|
30
|
+
*/
|
|
31
|
+
export const getSuiGraphqlEndpoint = (): string =>
|
|
32
|
+
getEnvVar("VITE_SUI_GRAPHQL_ENDPOINT");
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get the EVE World package ID from environment.
|
|
36
|
+
* @returns The package ID (0x-prefixed address)
|
|
37
|
+
* @throws {Error} If VITE_EVE_WORLD_PACKAGE_ID is not set
|
|
38
|
+
* @category Utilities
|
|
39
|
+
*/
|
|
40
|
+
export const getEveWorldPackageId = (): string =>
|
|
41
|
+
getEnvVar("VITE_EVE_WORLD_PACKAGE_ID");
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get the Character OwnerCap type string (derived from package ID).
|
|
45
|
+
* @returns The fully qualified type string for Character OwnerCap
|
|
46
|
+
* @category Utilities
|
|
47
|
+
*/
|
|
48
|
+
export const getCharacterOwnerCapType = (): string => {
|
|
49
|
+
const pkg = getEveWorldPackageId();
|
|
50
|
+
return `${pkg}::access::OwnerCap<${pkg}::character::Character>`;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get the ObjectRegistry type string (derived from package ID).
|
|
55
|
+
* @returns The fully qualified type string for ObjectRegistry
|
|
56
|
+
* @category Utilities
|
|
57
|
+
*/
|
|
58
|
+
export const getObjectRegistryType = (): string =>
|
|
59
|
+
`${getEveWorldPackageId()}::object_registry::ObjectRegistry`;
|
|
60
|
+
|
|
61
|
+
/** Polling interval in milliseconds (10 seconds). @category Utilities */
|
|
62
|
+
export const POLLING_INTERVAL = 10000;
|
|
63
|
+
|
|
64
|
+
/** Local storage keys. @category Utilities */
|
|
65
|
+
export const STORAGE_KEYS = {
|
|
66
|
+
CONNECTED: "eve-dapp-connected",
|
|
67
|
+
} as const;
|
|
68
|
+
|
|
69
|
+
/** Type IDs for in-game items. @category Utilities */
|
|
70
|
+
/* eslint-disable @typescript-eslint/no-loss-of-precision */
|
|
71
|
+
export enum TYPEIDS {
|
|
72
|
+
LENS = 77518,
|
|
73
|
+
TRANSACTION_CHIP = 79193,
|
|
74
|
+
COMMON_ORE = 77800,
|
|
75
|
+
METAL_RICH_ORE = 77810,
|
|
76
|
+
SMART_STORAGE_UNIT = 77917,
|
|
77
|
+
PROTOCOL_DEPOT = 85249,
|
|
78
|
+
GATEKEEPER = 83907,
|
|
79
|
+
SALT = 83839,
|
|
80
|
+
NETWORK_NODE = 88092,
|
|
81
|
+
PORTABLE_REFINERY = 87161,
|
|
82
|
+
PORTABLE_PRINTER = 87162,
|
|
83
|
+
PORTABLE_STORAGE = 87566,
|
|
84
|
+
REFUGE = 87160,
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** @category Utilities */
|
|
88
|
+
export const EXCLUDED_TYPEIDS = [
|
|
89
|
+
TYPEIDS.PORTABLE_REFINERY,
|
|
90
|
+
TYPEIDS.PORTABLE_PRINTER,
|
|
91
|
+
TYPEIDS.PORTABLE_STORAGE,
|
|
92
|
+
TYPEIDS.REFUGE,
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
/** Volume - from wei units to m3. @category Utilities */
|
|
96
|
+
export const ONE_M3 = 1000000000000000000;
|