diff --git a/src/components/CCIP/TutorialBlockchainSelector/ContractVerificationStep.module.css b/src/components/CCIP/TutorialBlockchainSelector/ContractVerificationStep.module.css new file mode 100644 index 00000000000..e58bf00bc85 --- /dev/null +++ b/src/components/CCIP/TutorialBlockchainSelector/ContractVerificationStep.module.css @@ -0,0 +1,243 @@ +.verificationIntro { + margin-bottom: var(--space-4x); +} + +.verificationSteps { + list-style: decimal; + padding-left: var(--space-4x); + margin: var(--space-4x) 0; + display: flex; + flex-direction: column; + gap: var(--space-4x); +} + +.stepTitle { + display: block; + font-weight: 600; + font-size: var(--font-size-lg); + color: var(--color-text-primary); + margin-bottom: var(--space-3x); +} + +.stepContent { + color: var(--color-text); +} + +/* Explorer Section */ +.explorerSection { + background: var(--color-background-secondary); + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + padding: var(--space-4x); +} + +.explorerUrl { + display: flex; + align-items: center; + gap: var(--space-2x); + flex-wrap: wrap; + margin-bottom: var(--space-3x); +} + +.explorerUrl span { + color: var(--color-text-secondary); + font-size: var(--font-size-sm); +} + +.contractSection { + border-top: 1px solid var(--color-border); + padding-top: var(--space-3x); + display: flex; + flex-direction: column; + gap: var(--space-3x); +} + +.contractInfo { + display: flex; + align-items: center; + gap: var(--space-2x); + flex-wrap: wrap; +} + +.contractInfo span { + color: var(--color-text-secondary); + font-size: var(--font-size-sm); +} + +.address { + font-family: var(--font-mono); + background: var(--color-background); + padding: var(--space-1x) var(--space-2x); + border-radius: var(--border-radius); + font-size: var(--font-size-sm); +} + +/* Verification Options */ +.verificationOptions { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: var(--space-4x); + margin: var(--space-2x) 0; +} + +.verificationOption { + background: var(--color-background-secondary); + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + padding: var(--space-4x); + display: flex; + flex-direction: column; + height: 100%; +} + +.optionHeader { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--space-2x); +} + +.optionTitle { + font-weight: 600; + font-size: var(--font-size-base); + color: var(--color-text-primary); +} + +.optionTag { + font-size: var(--font-size-xs); + font-weight: 500; + padding: var(--space-1x) var(--space-2x); + border-radius: var(--border-radius); + background: var(--color-background); + color: var(--color-text-secondary); +} + +.optionDescription { + color: var(--color-text-secondary); + font-size: var(--font-size-sm); + margin-bottom: var(--space-3x); + flex-grow: 1; +} + +.optionLink { + display: inline-flex; + align-items: center; + color: var(--color-accent); + text-decoration: none; + font-size: var(--font-size-base); + font-weight: 500; + gap: var(--space-1x); + margin-top: auto; +} + +.optionLink:hover { + text-decoration: underline; +} + +/* Buttons */ +.viewContractButton, +.verifyButton { + display: inline-flex; + align-items: center; + justify-content: center; + background: var(--color-accent); + color: white; + padding: var(--space-2x) var(--space-3x); + border-radius: var(--border-radius); + text-decoration: none; + font-weight: 500; + gap: var(--space-2x); + transition: background-color 0.2s ease; +} + +.viewContractButton:hover, +.verifyButton:hover { + background: var(--color-accent-dark); +} + +/* Confirmation Steps */ +.subSteps { + list-style: lower-alpha; + padding-left: var(--space-4x); + margin: var(--space-3x) 0; +} + +.subSteps li { + margin-bottom: var(--space-2x); + color: var(--color-text-secondary); +} + +.externalIcon { + font-size: 0.8em; +} + +/* Verification Actions */ +.verificationActions { + margin-top: var(--space-4x); + display: flex; + flex-direction: column; + gap: var(--space-3x); +} + +.verificationUrl { + display: flex; + flex-direction: column; + gap: var(--space-2x); +} + +.verificationUrl span { + color: var(--color-text-secondary); + font-size: var(--font-size-sm); +} + +.urlDisplay { + font-family: var(--font-mono); + background: var(--color-background-secondary); + padding: var(--space-2x); + border-radius: var(--border-radius); + font-size: var(--font-size-sm); + word-break: break-all; + color: var(--color-text); + border: 1px solid var(--color-border); +} + +/* New styles for placeholders and verification link */ +.placeholderMessage { + color: var(--color-text-secondary); + font-size: var(--font-size-sm); + padding: var(--space-3x); + background: var(--color-background-secondary); + border: 1px solid var(--color-border); + border-radius: var(--border-radius); +} + +.verificationLink { + margin-top: var(--space-4x); + padding: var(--space-3x); + background: var(--color-background-secondary); + border: 1px solid var(--color-border); + border-radius: var(--border-radius); +} + +.verificationLink span { + display: block; + color: var(--color-text-secondary); + font-size: var(--font-size-sm); + margin-bottom: var(--space-2x); +} + +.contractLink { + display: block; + font-family: var(--font-mono); + color: var(--color-accent); + text-decoration: none; + word-break: break-all; + font-size: var(--font-size-sm); + padding: var(--space-2x); + background: var(--color-background); + border-radius: var(--border-radius); +} + +.contractLink:hover { + text-decoration: underline; +} diff --git a/src/components/CCIP/TutorialBlockchainSelector/ContractVerificationStep.tsx b/src/components/CCIP/TutorialBlockchainSelector/ContractVerificationStep.tsx new file mode 100644 index 00000000000..82db05dc37f --- /dev/null +++ b/src/components/CCIP/TutorialBlockchainSelector/ContractVerificationStep.tsx @@ -0,0 +1,142 @@ +import { TutorialStep } from "../TutorialSetup/TutorialStep" +import { Callout } from "../TutorialSetup/Callout" +import type { Network } from "@config/data/ccip/types" +import styles from "./ContractVerificationStep.module.css" + +interface ContractVerificationStepProps { + stepId: string + network: Network | null + contractAddress?: string + contractType: "token" | "pool" +} + +export const ContractVerificationStep = ({ + stepId, + network, + contractAddress, + contractType, +}: ContractVerificationStepProps) => { + // Debug values + console.log("ContractVerificationStep Props:", { + network, + contractAddress, + contractType, + hasNetwork: !!network?.explorerUrl, + hasAddress: !!contractAddress, + }) + + const explorerContractUrl = + contractAddress && network?.explorerUrl ? `${network.explorerUrl}/address/${contractAddress}#code` : undefined + + return ( + + + + Contract verification makes your {contractType} contract's source code public on the blockchain explorer. + This: + + Builds trust by allowing anyone to audit your code + Enables direct interaction through the blockchain explorer + Helps other developers understand and integrate with your contract + + + + + + + Access the Blockchain Explorer + + {network?.explorerUrl ? ( + + + Blockchain Explorer: + + {network.explorerUrl} ↗ + + + + ) : ( + + Blockchain explorer information will be available once you select a network. + + )} + + + + + Verify Using Remix IDE + + + + + Remix IDE Guide + + + Official guide for verifying contracts using the Remix IDE verification plugin + + + View Guide ↗ + + + + + + Chainlink Tutorial + + + Step-by-step tutorial for contract verification on blockchain explorers + + + View Tutorial ↗ + + + + + + + + Confirm Verification + + + Return to your contract on the blockchain explorer + Look for a green checkmark ✓ or "Verified" status + You should now see your contract's source code in the "Code" tab + + + {!network?.explorerUrl ? ( + + Contract verification link will be available once you select a network. + + ) : !contractAddress ? ( + + Contract verification link will be available after deployment. + + ) : ( + + Verify your contract at: + + {explorerContractUrl} + + + )} + + + + + ) +} diff --git a/src/components/CCIP/TutorialBlockchainSelector/DeployPoolStep.module.css b/src/components/CCIP/TutorialBlockchainSelector/DeployPoolStep.module.css index bf7138b46f6..b347f97b232 100644 --- a/src/components/CCIP/TutorialBlockchainSelector/DeployPoolStep.module.css +++ b/src/components/CCIP/TutorialBlockchainSelector/DeployPoolStep.module.css @@ -174,3 +174,36 @@ grid-template-columns: 1fr; } } + +.verificationIntro { + margin-bottom: 1rem; +} + +.verificationSteps { + list-style-type: decimal; + padding-left: 1.5rem; + margin-bottom: 1.5rem; +} + +.verificationSteps li { + margin-bottom: 0.75rem; + line-height: 1.5; +} + +.explorerLink { + display: inline-flex; + align-items: center; + color: var(--primary-color); + text-decoration: none; + margin-left: 0.5rem; + font-size: 0.9em; +} + +.explorerLink:hover { + text-decoration: underline; +} + +.externalIcon { + margin-left: 0.25rem; + font-size: 0.8em; +} diff --git a/src/components/CCIP/TutorialBlockchainSelector/DeployPoolStep.tsx b/src/components/CCIP/TutorialBlockchainSelector/DeployPoolStep.tsx index eda4330c840..711affa4061 100644 --- a/src/components/CCIP/TutorialBlockchainSelector/DeployPoolStep.tsx +++ b/src/components/CCIP/TutorialBlockchainSelector/DeployPoolStep.tsx @@ -8,17 +8,51 @@ import { NetworkCheck } from "../TutorialSetup/NetworkCheck" import { SolidityParam } from "../TutorialSetup/SolidityParam" import { StoredContractAddress } from "./StoredContractAddress" import { NetworkAddress } from "./NetworkAddress" +import { ContractVerificationStep } from "./ContractVerificationStep" +import type { LaneState, DeployedContracts } from "@stores/lanes" import styles from "./DeployPoolStep.module.css" interface DeployPoolStepProps { chain: "source" | "destination" } +// Extend LaneState to include the properties we need +interface ExtendedLaneState extends Omit { + tokenPoolAddress?: { + [key in "source" | "destination"]?: string + } + sourceContracts: { + tokenPool?: string + } & DeployedContracts + destinationContracts: { + tokenPool?: string + } & DeployedContracts +} + export const DeployPoolStep = ({ chain }: DeployPoolStepProps) => { const [poolType, setPoolType] = useState<"lock" | "burn">("burn") - const state = useStore(laneStore) + const state = useStore(laneStore) as ExtendedLaneState + + // Debug store values + console.log("DeployPoolStep Store:", { + chain, + poolAddress: state.tokenPoolAddress, + sourceContract: state.sourceContracts?.tokenPool, + destContract: state.destinationContracts?.tokenPool, + chainPoolAddress: state.tokenPoolAddress?.[chain], + network: state.sourceNetwork, + stateKeys: Object.keys(state), + }) + const network = chain === "source" ? state.sourceNetwork : state.destinationNetwork - const networkInfo = network ? { name: network.name, logo: network.logo } : { name: "loading..." } + const contractAddress = chain === "source" ? state.sourceContracts?.tokenPool : state.destinationContracts?.tokenPool + + const networkInfo = network + ? { + name: network.name, + logo: network.logo, + } + : { name: "loading..." } const stepId = chain === "source" ? "sourceChain" : "destinationChain" const getSubStepId = (subStep: string) => `${stepId}-${subStep}` @@ -163,6 +197,13 @@ export const DeployPoolStep = ({ chain }: DeployPoolStepProps) => { + + ) diff --git a/src/components/CCIP/TutorialBlockchainSelector/DeployTokenStep.module.css b/src/components/CCIP/TutorialBlockchainSelector/DeployTokenStep.module.css index a3802d16986..cf03c8ac49c 100644 --- a/src/components/CCIP/TutorialBlockchainSelector/DeployTokenStep.module.css +++ b/src/components/CCIP/TutorialBlockchainSelector/DeployTokenStep.module.css @@ -19,3 +19,36 @@ flex-direction: column; gap: var(--space-4x); } + +.verificationIntro { + margin-bottom: 1rem; +} + +.verificationSteps { + list-style-type: decimal; + padding-left: 1.5rem; + margin-bottom: 1.5rem; +} + +.verificationSteps li { + margin-bottom: 0.75rem; + line-height: 1.5; +} + +.explorerLink { + display: inline-flex; + align-items: center; + color: var(--primary-color); + text-decoration: none; + margin-left: 0.5rem; + font-size: 0.9em; +} + +.explorerLink:hover { + text-decoration: underline; +} + +.externalIcon { + margin-left: 0.25rem; + font-size: 0.8em; +} diff --git a/src/components/CCIP/TutorialBlockchainSelector/DeployTokenStep.tsx b/src/components/CCIP/TutorialBlockchainSelector/DeployTokenStep.tsx index 8f6a086a649..af5391c8c6c 100644 --- a/src/components/CCIP/TutorialBlockchainSelector/DeployTokenStep.tsx +++ b/src/components/CCIP/TutorialBlockchainSelector/DeployTokenStep.tsx @@ -6,6 +6,8 @@ import { TutorialStep } from "../TutorialSetup/TutorialStep" import { NetworkCheck } from "../TutorialSetup/NetworkCheck" import { SolidityParam } from "../TutorialSetup/SolidityParam" import { Callout } from "../TutorialSetup/Callout" +import { ContractVerificationStep } from "./ContractVerificationStep" +import type { LaneState, DeployedContracts } from "@stores/lanes" import styles from "./DeployTokenStep.module.css" interface DeployTokenStepProps { @@ -13,9 +15,32 @@ interface DeployTokenStepProps { isEnabled: boolean } +// Extend LaneState to include the properties we need +interface ExtendedLaneState extends Omit { + tokenAddress?: { + [key in "source" | "destination"]?: string + } + sourceContracts: DeployedContracts + destinationContracts: DeployedContracts +} + export const DeployTokenStep = ({ chain }: DeployTokenStepProps) => { - const state = useStore(laneStore) + const state = useStore(laneStore) as ExtendedLaneState + + // Debug store values + console.log("DeployTokenStep Store:", { + chain, + tokenAddress: state.tokenAddress, + sourceContract: state.sourceContracts?.token, + destContract: state.destinationContracts?.token, + chainTokenAddress: state.tokenAddress?.[chain], + network: state.sourceNetwork, + stateKeys: Object.keys(state), + }) + const network = chain === "source" ? state.sourceNetwork : state.destinationNetwork + const contractAddress = chain === "source" ? state.sourceContracts?.token : state.destinationContracts?.token + const networkInfo = network ? { name: network.name, @@ -106,6 +131,13 @@ export const DeployTokenStep = ({ chain }: DeployTokenStepProps) => { + + > )
+ Official guide for verifying contracts using the Remix IDE verification plugin +
+ Step-by-step tutorial for contract verification on blockchain explorers +