mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
feat: integrate luxnet SDK for P-chain API calls
Replace hand-rolled JSON-RPC fetch client with [email protected].0 SDK. P-chain hooks now use PlatformVMAPI methods directly.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import Lux from 'luxnet';
|
||||
|
||||
import { getEnvValue } from 'configs/app/utils';
|
||||
|
||||
const CCHAIN_RPC_PATTERN = /\/ext\/bc\/C\/rpc$/;
|
||||
const HTTPS_PORT = 443;
|
||||
const HTTP_PORT = 80;
|
||||
|
||||
function parseRpcUrl(): { host: string; port: number; protocol: string } {
|
||||
const rpcUrl = getEnvValue('NEXT_PUBLIC_NETWORK_RPC_URL');
|
||||
if (!rpcUrl) {
|
||||
throw new Error('NEXT_PUBLIC_NETWORK_RPC_URL is not configured');
|
||||
}
|
||||
|
||||
const base = rpcUrl.replace(CCHAIN_RPC_PATTERN, '');
|
||||
const url = new URL(base);
|
||||
const defaultPort = url.protocol === 'https:' ? HTTPS_PORT : HTTP_PORT;
|
||||
|
||||
return {
|
||||
host: url.hostname,
|
||||
port: url.port ? Number(url.port) : defaultPort,
|
||||
protocol: url.protocol.replace(':', ''),
|
||||
};
|
||||
}
|
||||
|
||||
let instance: Lux | undefined;
|
||||
|
||||
export function getLux(): Lux {
|
||||
if (!instance) {
|
||||
const { host, port, protocol } = parseRpcUrl();
|
||||
instance = new Lux(host, port, protocol);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
@@ -1,73 +1,13 @@
|
||||
// Low-level P-chain JSON-RPC client.
|
||||
// Derives the P-chain URL from NEXT_PUBLIC_NETWORK_RPC_URL by replacing the
|
||||
// C-chain path (/ext/bc/C/rpc) with the P-chain path (/ext/bc/P).
|
||||
import { getLux } from 'lib/api/luxnet/instance';
|
||||
|
||||
import type { JsonRpcRequest, JsonRpcResponse } from './types';
|
||||
|
||||
import { getEnvValue } from 'configs/app/utils';
|
||||
|
||||
const PCHAIN_PATH = '/ext/bc/P';
|
||||
const CCHAIN_PATH_PATTERN = /\/ext\/bc\/C\/rpc$/;
|
||||
|
||||
let requestId = 0;
|
||||
|
||||
function getPChainUrl(): string {
|
||||
const rpcUrl = getEnvValue('NEXT_PUBLIC_NETWORK_RPC_URL');
|
||||
|
||||
if (!rpcUrl) {
|
||||
throw new Error('NEXT_PUBLIC_NETWORK_RPC_URL is not configured');
|
||||
}
|
||||
|
||||
// Replace C-chain path with P-chain path
|
||||
if (CCHAIN_PATH_PATTERN.test(rpcUrl)) {
|
||||
return rpcUrl.replace(CCHAIN_PATH_PATTERN, PCHAIN_PATH);
|
||||
}
|
||||
|
||||
// Fallback: strip trailing slash and append P-chain path
|
||||
const base = rpcUrl.replace(/\/+$/, '');
|
||||
try {
|
||||
const url = new URL(base);
|
||||
return `${ url.origin }${ PCHAIN_PATH }`;
|
||||
} catch {
|
||||
throw new Error(`Invalid NEXT_PUBLIC_NETWORK_RPC_URL: ${ rpcUrl }`);
|
||||
}
|
||||
export function getPChain() {
|
||||
return getLux().PChain();
|
||||
}
|
||||
|
||||
export async function pchainRpc<TResult>(
|
||||
method: string,
|
||||
params?: Record<string, unknown>,
|
||||
): Promise<TResult> {
|
||||
const url = getPChainUrl();
|
||||
requestId += 1;
|
||||
|
||||
const body: JsonRpcRequest = {
|
||||
jsonrpc: '2.0',
|
||||
id: requestId,
|
||||
method,
|
||||
...(params !== undefined ? { params } : {}),
|
||||
};
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`P-chain RPC error: HTTP ${ response.status }`);
|
||||
}
|
||||
|
||||
const json = await response.json() as JsonRpcResponse<TResult>;
|
||||
|
||||
if (json.error) {
|
||||
throw new Error(`P-chain RPC error: ${ json.error.message } (code ${ json.error.code })`);
|
||||
}
|
||||
|
||||
if (json.result === undefined) {
|
||||
throw new Error('P-chain RPC error: missing result in response');
|
||||
}
|
||||
|
||||
return json.result;
|
||||
export function getInfo() {
|
||||
return getLux().Info();
|
||||
}
|
||||
|
||||
export { getPChainUrl };
|
||||
export function getHealth() {
|
||||
return getLux().Health();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// P-chain API hooks and types.
|
||||
|
||||
export { pchainRpc, getPChainUrl } from './client';
|
||||
export { getPChain, getInfo, getHealth } from './client';
|
||||
export { useCurrentValidators } from './useCurrentValidators';
|
||||
export { useBlockchains } from './useBlockchains';
|
||||
export { useSubnets } from './useSubnets';
|
||||
@@ -15,9 +15,6 @@ export type {
|
||||
GetBlockchainsResponse,
|
||||
GetSubnetsResponse,
|
||||
ValidatorStats,
|
||||
JsonRpcRequest,
|
||||
JsonRpcResponse,
|
||||
JsonRpcError,
|
||||
} from './types';
|
||||
|
||||
export type { UseCurrentValidatorsResult } from './useCurrentValidators';
|
||||
|
||||
@@ -67,25 +67,3 @@ export interface ValidatorStats {
|
||||
readonly totalDelegatedStake: bigint;
|
||||
readonly averageUptime: number;
|
||||
}
|
||||
|
||||
// JSON-RPC envelope types
|
||||
|
||||
export interface JsonRpcRequest {
|
||||
readonly jsonrpc: '2.0';
|
||||
readonly id: number;
|
||||
readonly method: string;
|
||||
readonly params?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface JsonRpcResponse<TResult> {
|
||||
readonly jsonrpc: '2.0';
|
||||
readonly id: number;
|
||||
readonly result?: TResult;
|
||||
readonly error?: JsonRpcError;
|
||||
}
|
||||
|
||||
export interface JsonRpcError {
|
||||
readonly code: number;
|
||||
readonly message: string;
|
||||
readonly data?: unknown;
|
||||
}
|
||||
|
||||
@@ -4,24 +4,17 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
|
||||
import type {
|
||||
GetBlockchainsResponse,
|
||||
PChainBlockchain,
|
||||
} from './types';
|
||||
import type { PChainBlockchain } from './types';
|
||||
|
||||
import { pchainRpc } from './client';
|
||||
import { getPChain } from './client';
|
||||
|
||||
const BLOCKCHAINS_STALE_TIME_MS = 300_000;
|
||||
const BLOCKCHAINS_QUERY_KEY = 'pchain:blockchains' as const;
|
||||
const EMPTY_BLOCKCHAINS: ReadonlyArray<PChainBlockchain> = [];
|
||||
|
||||
async function fetchBlockchains(): Promise<ReadonlyArray<PChainBlockchain>> {
|
||||
const response = await pchainRpc<GetBlockchainsResponse>(
|
||||
'platform.getBlockchains',
|
||||
{},
|
||||
);
|
||||
|
||||
return response.blockchains;
|
||||
const blockchains = await getPChain().getBlockchains();
|
||||
return blockchains as unknown as ReadonlyArray<PChainBlockchain>;
|
||||
}
|
||||
|
||||
export function useBlockchains() {
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
ValidatorStats,
|
||||
} from './types';
|
||||
|
||||
import { pchainRpc } from './client';
|
||||
import { getPChain } from './client';
|
||||
|
||||
const VALIDATORS_STALE_TIME_MS = 60_000;
|
||||
const VALIDATORS_QUERY_KEY = 'pchain:currentValidators' as const;
|
||||
@@ -63,12 +63,8 @@ export interface UseCurrentValidatorsResult {
|
||||
}
|
||||
|
||||
async function fetchCurrentValidators(): Promise<UseCurrentValidatorsResult> {
|
||||
const response = await pchainRpc<GetCurrentValidatorsResponse>(
|
||||
'platform.getCurrentValidators',
|
||||
{},
|
||||
);
|
||||
|
||||
const validators = response.validators;
|
||||
const result = await getPChain().getCurrentValidators() as GetCurrentValidatorsResponse;
|
||||
const validators = result.validators;
|
||||
const stats = computeValidatorStats(validators);
|
||||
|
||||
return { validators, stats };
|
||||
|
||||
@@ -4,24 +4,17 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
|
||||
import type {
|
||||
GetSubnetsResponse,
|
||||
PChainSubnet,
|
||||
} from './types';
|
||||
import type { PChainSubnet } from './types';
|
||||
|
||||
import { pchainRpc } from './client';
|
||||
import { getPChain } from './client';
|
||||
|
||||
const SUBNETS_STALE_TIME_MS = 300_000;
|
||||
const SUBNETS_QUERY_KEY = 'pchain:subnets' as const;
|
||||
const EMPTY_SUBNETS: ReadonlyArray<PChainSubnet> = [];
|
||||
|
||||
async function fetchSubnets(): Promise<ReadonlyArray<PChainSubnet>> {
|
||||
const response = await pchainRpc<GetSubnetsResponse>(
|
||||
'platform.getSubnets',
|
||||
{},
|
||||
);
|
||||
|
||||
return response.subnets;
|
||||
const subnets = await getPChain().getSubnets();
|
||||
return subnets as unknown as ReadonlyArray<PChainSubnet>;
|
||||
}
|
||||
|
||||
export function useSubnets() {
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
"graphql": "^16.8.1",
|
||||
"graphql-ws": "^5.11.3",
|
||||
"js-cookie": "^3.0.1",
|
||||
"luxnet": "3.16.0",
|
||||
"magic-bytes.js": "1.8.0",
|
||||
"mixpanel-browser": "2.67.0",
|
||||
"monaco-editor": "^0.34.1",
|
||||
|
||||
Generated
+853
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user