diff --git a/wallet/src/ui/app/ApiProvider.ts b/wallet/src/ui/app/ApiProvider.ts index 5aab4a47d3eb1..039a474dc8bbb 100644 --- a/wallet/src/ui/app/ApiProvider.ts +++ b/wallet/src/ui/app/ApiProvider.ts @@ -3,16 +3,40 @@ import { JsonRpcProvider } from '@mysten/sui.js'; -// const DEFAULT_API_ENDPOINT = 'https://gateway.devnet.sui.io'; -const DEFAULT_API_ENDPOINT = 'http://127.0.0.1:5001'; +export enum API_ENV { + local = 'local', + devNet = 'devNet', +} + +export const ENV_TO_API: Record = { + [API_ENV.local]: process.env.API_ENDPOINT_LOCAL, + [API_ENV.devNet]: process.env.API_ENDPOINT_DEV_NET, +}; + +function getDefaultApiEnv() { + const apiEnv = process.env.API_ENV; + if (apiEnv && !Object.keys(API_ENV).includes(apiEnv)) { + throw new Error(`Unknown environment variable API_ENV, ${apiEnv}`); + } + return apiEnv ? API_ENV[apiEnv as keyof typeof API_ENV] : API_ENV.devNet; +} + +function getDefaultAPI(env: API_ENV) { + const apiEndpoint = ENV_TO_API[env]; + if (!apiEndpoint) { + throw new Error(`API endpoint not found for API_ENV ${env}`); + } + return apiEndpoint; +} + +export const DEFAULT_API_ENV = getDefaultApiEnv(); +export const DEFAULT_API_ENDPOINT = getDefaultAPI(DEFAULT_API_ENV); export default class ApiProvider { private _apiProvider: JsonRpcProvider; constructor() { - // TODO: allow overriding default endpoint - const apiEndpoint = DEFAULT_API_ENDPOINT; - this._apiProvider = new JsonRpcProvider(apiEndpoint); + this._apiProvider = new JsonRpcProvider(DEFAULT_API_ENDPOINT); } public get instance() { diff --git a/wallet/src/ui/app/components/sui-object/SuiObject.module.scss b/wallet/src/ui/app/components/sui-object/SuiObject.module.scss index 5bbcf1f940e13..77d13dfc8ec6c 100644 --- a/wallet/src/ui/app/components/sui-object/SuiObject.module.scss +++ b/wallet/src/ui/app/components/sui-object/SuiObject.module.scss @@ -70,3 +70,13 @@ overflow-y: auto; max-height: 100%; } + +.explorer-link { + position: absolute; + bottom: 0; + right: 0; + font-size: 10px; + padding: 5px; + color: #43b0e6; + text-decoration: none; +} diff --git a/wallet/src/ui/app/components/sui-object/index.tsx b/wallet/src/ui/app/components/sui-object/index.tsx index e236f63192923..57c852ec133f9 100644 --- a/wallet/src/ui/app/components/sui-object/index.tsx +++ b/wallet/src/ui/app/components/sui-object/index.tsx @@ -2,11 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import { isSuiMoveObject, isSuiMovePackage } from '@mysten/sui.js'; -import { memo } from 'react'; +import { memo, useMemo } from 'react'; import Field from './field'; +import BsIcon from '_components/bs-icon'; import CopyToClipboard from '_components/copy-to-clipboard'; import { useMiddleEllipsis, useMediaUrl, useSuiObjectFields } from '_hooks'; +import { Explorer } from '_redux/slices/sui-objects/Explorer'; import type { SuiObject as SuiObjectType } from '@mysten/sui.js'; @@ -17,7 +19,8 @@ export type SuiObjectProps = { }; function SuiObject({ obj }: SuiObjectProps) { - const shortId = useMiddleEllipsis(obj.reference.objectId); + const { objectId } = obj.reference; + const shortId = useMiddleEllipsis(objectId); const objType = (isSuiMoveObject(obj.data) && obj.data.type) || 'Move Package'; const imgUrl = useMediaUrl(obj.data); @@ -25,12 +28,14 @@ function SuiObject({ obj }: SuiObjectProps) { const suiMoveObjectFields = isSuiMoveObject(obj.data) ? obj.data.fields : null; + const explorerUrl = useMemo( + () => Explorer.getObjectUrl(objectId), + [objectId] + ); return (
- - - {shortId} - + + {shortId} {objType}
@@ -60,6 +65,17 @@ function SuiObject({ obj }: SuiObjectProps) { ) : null}
+ + + ); } diff --git a/wallet/src/ui/app/redux/slices/sui-objects/Explorer.ts b/wallet/src/ui/app/redux/slices/sui-objects/Explorer.ts new file mode 100644 index 0000000000000..2620b6b04a74c --- /dev/null +++ b/wallet/src/ui/app/redux/slices/sui-objects/Explorer.ts @@ -0,0 +1,29 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import { API_ENV, DEFAULT_API_ENV } from '_app/ApiProvider'; + +import type { ObjectId } from '@mysten/sui.js'; + +const API_ENV_TO_EXPLORER_URL: Record = { + [API_ENV.local]: process.env.EXPLORER_URL_LOCAL, + [API_ENV.devNet]: process.env.EXPLORER_URL_DEV_NET, +}; + +function getDefaultUrl() { + const url = API_ENV_TO_EXPLORER_URL[DEFAULT_API_ENV]; + if (!url) { + throw new Error(`Url for API_ENV ${DEFAULT_API_ENV} is not defined`); + } + return url; +} + +const DEFAULT_EXPLORER_URL = getDefaultUrl(); + +export class Explorer { + private static _url = DEFAULT_EXPLORER_URL; + + public static getObjectUrl(objectID: ObjectId) { + return new URL(`/objects/${objectID}`, Explorer._url).href; + } +}