-
Notifications
You must be signed in to change notification settings - Fork 476
SelectSubnet
, SelectBlockchain
, inputSubnetId
& useAvaCloudSDK
#2531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
5420897
initial component layout
navillanueva 03eb2a8
improved UI - AvaCloud getSubnetById method missing data
navillanueva 0e517eb
upgraded latest Avacloud SDK version + improved UI
navillanueva 7ce6a2e
fixed Validator Manager latest Avacloud SDK version changes
navillanueva 3a7486b
spacing on succesful subnet creation + fixed compilation errors
navillanueva f3dbb0b
created InputSubnetId component
navillanueva 7479acf
fix build error
navillanueva 2b9037a
`SelectBlockchain` and refactored ChainID to BlockchainId (#2557)
navillanueva 5f89b2c
Merge remote-tracking branch 'origin/master' into refactor-selectSubn…
navillanueva 9727a59
removed unused imports
navillanueva 3ae6c84
merged main and resolved conflicts
navillanueva be65328
resolved AvacloudSDK v1.12.1 build errros
navillanueva 8977c27
updating serverURL init for Avacloud SDK
navillanueva 1a905bf
fetching VM ID and warning user - pending correctly creating docker c…
navillanueva 0391636
fixed Ilya's comments
navillanueva cf9eb57
fixed build errors
navillanueva e6f2ede
added testing changes
navillanueva 190a450
removed unused files
navillanueva f65740a
fixin component UI + input subnet ID on create chain
navillanueva e23d1a6
fix aggregate signature
navillanueva b4bb603
fix aggregate signature pending buffer issue
navillanueva fa48fe5
fix build errors
navillanueva 8281f1d
fix build errors
navillanueva d1cf715
added justification to complete validator removal
navillanueva 8422237
adding justification to the complete sign aggregate
navillanueva ad67d7e
Merge remote-tracking branch 'origin/master' into refactor-selectSubn…
navillanueva File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
"use client" | ||
|
||
import { Input, type Suggestion } from "./Input"; | ||
import { useL1ListStore } from "../stores/l1ListStore"; | ||
import { useCreateChainStore } from "../stores/createChainStore"; | ||
import { useMemo, useState, useCallback, useEffect } from "react"; | ||
import { utils } from "@avalabs/avalanchejs"; | ||
import { useAvaCloudSDK } from "../stores/useAvaCloudSDK"; | ||
|
||
// Primary network subnet ID | ||
export const PRIMARY_NETWORK_SUBNET_ID = "11111111111111111111111111111111LpoYY"; | ||
|
||
export default function InputSubnetId({ | ||
value, | ||
onChange, | ||
error, | ||
label = "Subnet ID", | ||
hidePrimaryNetwork = true, | ||
helperText, | ||
id, | ||
validationDelayMs = 500, | ||
readOnly = false, | ||
hideSuggestions = false, | ||
placeholder | ||
}: { | ||
value: string, | ||
onChange: (value: string) => void, | ||
error?: string | null, | ||
label?: string, | ||
hidePrimaryNetwork?: boolean | ||
helperText?: string | null | ||
id?: string | ||
validationDelayMs?: number | ||
readOnly?: boolean | ||
hideSuggestions?: boolean | ||
placeholder?: string | ||
}) { | ||
const createChainStoreSubnetId = useCreateChainStore()(state => state.subnetId); | ||
const { l1List } = useL1ListStore()(); | ||
const { getSubnetById } = useAvaCloudSDK(); | ||
|
||
const [validationError, setValidationError] = useState<string | null>(null); | ||
|
||
// Validate subnet ID format and checksum using Base58Check | ||
const validateBase58Format = (subnetId: string): boolean => { | ||
try { | ||
// Validate Base58Check format and checksum (last 4 bytes) | ||
utils.base58check.decode(subnetId); | ||
return true; | ||
} catch (error) { | ||
return false; | ||
} | ||
}; | ||
|
||
// Validate subnet ID using AvaCloud SDK | ||
const validateSubnetId = useCallback(async (subnetId: string) => { | ||
if (!subnetId || subnetId.length < 10) { | ||
setValidationError(null); | ||
return; | ||
} | ||
|
||
// First validate Base58Check format and checksum | ||
if (!validateBase58Format(subnetId)) { | ||
setValidationError("Invalid subnet ID format or checksum"); | ||
return; | ||
} | ||
|
||
try { | ||
setValidationError(null); | ||
|
||
await getSubnetById({ subnetId }); | ||
|
||
// If we get here, the subnet exists | ||
setValidationError(null); | ||
} catch (error) { | ||
// Show validation error for invalid subnet IDs | ||
setValidationError("Subnet ID not found or invalid"); | ||
} | ||
}, [getSubnetById]); | ||
|
||
// Validate when value changes | ||
useEffect(() => { | ||
const timeoutId = setTimeout(() => { | ||
if (value) { | ||
validateSubnetId(value); | ||
} else { | ||
setValidationError(null); | ||
} | ||
}, validationDelayMs); // Wait for subnet to be available before validation | ||
|
||
return () => clearTimeout(timeoutId); | ||
}, [value, validateSubnetId, validationDelayMs]); | ||
|
||
const subnetIdSuggestions: Suggestion[] = useMemo(() => { | ||
const result: Suggestion[] = []; | ||
const seen = new Set<string>(); | ||
|
||
// Add subnet from create chain store first | ||
if (createChainStoreSubnetId && !(hidePrimaryNetwork && createChainStoreSubnetId === PRIMARY_NETWORK_SUBNET_ID)) { | ||
result.push({ | ||
title: createChainStoreSubnetId, | ||
value: createChainStoreSubnetId, | ||
description: "The Subnet that you have just created in the \"Create Chain\" tool" | ||
}); | ||
seen.add(createChainStoreSubnetId); | ||
} | ||
|
||
// Add subnets from L1 list | ||
for (const l1 of l1List) { | ||
const { subnetId, name } = l1; | ||
|
||
if (!subnetId || seen.has(subnetId)) continue; | ||
|
||
if (hidePrimaryNetwork && subnetId === PRIMARY_NETWORK_SUBNET_ID) { | ||
continue; | ||
} | ||
|
||
result.push({ | ||
title: `${name} (${subnetId})`, | ||
value: subnetId, | ||
description: l1.description || "A subnet that was added to your L1 list.", | ||
}); | ||
|
||
seen.add(subnetId); | ||
} | ||
|
||
return result; | ||
}, [createChainStoreSubnetId, l1List, hidePrimaryNetwork]); | ||
|
||
// Combine validation error with passed error | ||
const combinedError = error || validationError; | ||
|
||
return ( | ||
<Input | ||
id={id} | ||
label={label} | ||
value={value} | ||
onChange={onChange} | ||
suggestions={readOnly || hideSuggestions ? [] : subnetIdSuggestions} | ||
error={combinedError} | ||
helperText={helperText} | ||
placeholder={ | ||
readOnly | ||
? "Automatically filled from Blockchain ID" | ||
: placeholder || "Enter subnet ID" | ||
} | ||
disabled={readOnly} | ||
/> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
"use client" | ||
|
||
import SelectBlockchainId from "./SelectBlockchainId"; | ||
import { useState, useCallback } from "react"; | ||
import { useWalletStore } from "../stores/walletStore"; | ||
import { networkIDs } from "@avalabs/avalanchejs"; | ||
|
||
// API Response type from AvaCloud - matches the official API response | ||
export type BlockchainApiResponse = { | ||
createBlockTimestamp: number; | ||
createBlockNumber: string; | ||
blockchainId: string; | ||
vmId: string; | ||
subnetId: string; | ||
blockchainName: string; | ||
evmChainId: number; | ||
} | ||
|
||
// Extended type with additional metadata | ||
export type BlockchainInfo = BlockchainApiResponse & { | ||
isTestnet: boolean; | ||
} | ||
|
||
export type BlockchainSelection = { | ||
blockchainId: string; | ||
blockchain: BlockchainInfo | null; | ||
} | ||
|
||
// Import the unified details display component | ||
import BlockchainDetailsDisplay from "./BlockchainDetailsDisplay"; | ||
|
||
export default function SelectBlockchain({ | ||
value, | ||
onChange, | ||
error, | ||
label = "Select Avalanche Blockchain ID" | ||
}: { | ||
value: string, | ||
onChange: (selection: BlockchainSelection) => void, | ||
error?: string | null, | ||
label?: string | ||
}) { | ||
const { avalancheNetworkID } = useWalletStore(); | ||
const [blockchainDetails, setBlockchainDetails] = useState<Record<string, BlockchainInfo>>({}); | ||
const [isLoading, setIsLoading] = useState(false); | ||
|
||
// Network names for API calls | ||
const networkNames: Record<number, string> = { | ||
[networkIDs.MainnetID]: "mainnet", | ||
[networkIDs.FujiID]: "fuji", | ||
}; | ||
|
||
// Fetch blockchain details when needed | ||
const fetchBlockchainDetails = useCallback(async (blockchainId: string) => { | ||
if (!blockchainId || blockchainDetails[blockchainId]) return; | ||
|
||
try { | ||
const network = networkNames[Number(avalancheNetworkID)]; | ||
if (!network) return; | ||
|
||
setIsLoading(true); | ||
|
||
// Use direct API call as shown in AvaCloud documentation | ||
// https://developers.avacloud.io/data-api/primary-network/get-blockchain-details-by-id | ||
const response = await fetch(`https://glacier-api.avax.network/v1/networks/${network}/blockchains/${blockchainId}`, { | ||
method: 'GET', | ||
headers: { | ||
'accept': 'application/json', | ||
}, | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(`Failed to fetch blockchain details: ${response.statusText}`); | ||
} | ||
|
||
const blockchain: BlockchainApiResponse = await response.json(); | ||
|
||
setBlockchainDetails(prev => ({ | ||
...prev, | ||
[blockchainId]: { | ||
...blockchain, | ||
isTestnet: network === "fuji" | ||
} | ||
})); | ||
} catch (error) { | ||
console.error(`Error fetching blockchain details for ${blockchainId}:`, error); | ||
} finally { | ||
setIsLoading(false); | ||
} | ||
}, [avalancheNetworkID, networkNames, blockchainDetails]); | ||
|
||
// Handle value change and fetch details if needed | ||
const handleValueChange = useCallback((newValue: string) => { | ||
if (newValue && !blockchainDetails[newValue]) { | ||
fetchBlockchainDetails(newValue); | ||
} | ||
|
||
onChange({ | ||
blockchainId: newValue, | ||
blockchain: blockchainDetails[newValue] || null | ||
}); | ||
}, [fetchBlockchainDetails, blockchainDetails, onChange]); | ||
|
||
// Get current blockchain details for display | ||
const currentBlockchain = value ? blockchainDetails[value] || null : null; | ||
const isLoadingCurrent = value && !blockchainDetails[value] && isLoading; | ||
|
||
return ( | ||
<div> | ||
<SelectBlockchainId | ||
value={value} | ||
onChange={handleValueChange} | ||
error={error} | ||
label={label} | ||
/> | ||
|
||
{/* Display blockchain details when a blockchain is selected */} | ||
{value && <BlockchainDetailsDisplay blockchain={currentBlockchain} isLoading={!!isLoadingCurrent} />} | ||
</div> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.