Contract Studio: IDE layout with file explorer, tabs, and multi-file compilation#36
Merged
Contract Studio: IDE layout with file explorer, tabs, and multi-file compilation#36
Conversation
Introduce chain-types.ts with GenericChainClient, AssetHubApi union type, isAssetHubGenesis() and hasReviveApi() type guard. Refactor ClientProvider to instantiate typed DedotClient based on genesis hash (PolkadotAssetHubApi, WestendAssetHubApi, PaseoAssetHubApi) and expose isAssetHub in context. Widen DedotClient<PolkadotApi> to GenericChainClient across downstream consumers (types.ts, parser.ts, hooks).
New useGasEstimation hook performs reviveApi.instantiate dry-runs with 10% safety buffer on weight/storage. Only populates estimate state on successful dry-runs to prevent consumers from acting on failed results. Add fee-display.ts for formatting planck amounts and weight values. Extract shared compile logic into compile-client.ts. Fix Struct component to sync local state from external value prop (needed for gas estimation auto-fill) and pass values to child inputs. Widen BuilderFormValues index signature to support object values.
New /studio route with CompilePanel (left), EditorPanel (center, Monaco + output), and DeployPanel (right, constructor form + gas estimation + deploy + transaction log). ContractProvider context replaces the global singleton for Studio state to avoid mount/unmount reset conflicts between panels. Constructor form validates all fields before encoding (matching builder behavior), resets state on ABI changes, and provides hex fallback input with validation for unsupported constructor types. Deploy panel clears stale constructor data on contract switches, logs estimation failures to the transaction log, and validates hex inputs at the form boundary. Upload handler routes .sol files to the editor and validates .bin/.hex uploads for even-length hex.
Show Estimate Gas button and Open in Contract Studio link when pallet=Revive, method=instantiate_with_code. Auto-fill weight_limit (using metadata-derived field names) and storage_deposit_limit (Charge only) from dry-run results. Fix information-pane argValuesKey to use JSON.stringify for object values so weight struct changes trigger re-encoding. Refactor contract-code.tsx to use shared compile-client.ts.
Hardcode Builder and Studio links in both desktop nav and mobile Sheet menu, with active-state highlighting based on layout segment.
New use-gas-estimation.test.ts: success path with 10% buffer, Refund no-buffer, dispatch error leaves estimate state null, RPC exceptions, guard checks for missing client/account/bytecode. Extend extrinsic-builder tests: Estimate Gas button visibility for Revive, Studio link presence, hidden for non-Revive pallets. Extend information-pane tests: object-valued arg changes trigger re-encoding via JSON.stringify serialization. Extend struct tests: external value hydration, no infinite loop on same-value rerender, object-valued onChange emission.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #36 +/- ##
==========================================
- Coverage 56.80% 50.49% -6.31%
==========================================
Files 155 178 +23
Lines 18907 22233 +3326
Branches 1158 1236 +78
==========================================
+ Hits 10740 11227 +487
- Misses 8121 10958 +2837
- Partials 46 48 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…hains Dedot's proxy chains execute API spec lookups on property access, so merely checking typeof client.call.reviveApi.instantiate throws UnknownApiError on chains without ReviveApi. Wrap in try/catch.
Use percentage strings for react-resizable-panels v2 defaultSize/minSize/ maxSize (plain numbers are treated as pixels in v2, not percentages). Remove footer from Studio layout for full-height IDE experience. Use flex-1 + min-h-0 for proper height propagation.
Add flex flex-col to main element so flex-1 on children propagates height correctly through the layout → page → studio component chain.
…king
- Add types/studio.ts with StudioFile, StudioState, StudioAction types,
content hash utility (djb2), and workspace helpers
- Add bytecodeSource ("compile" | "upload" | null) and nullable mode to
ContractCompilationState in contract-store and contract-provider
- Add StudioProvider with useReducer for file system, tabs, and UI state,
including debounced sessionStorage persistence
- Add shadcn accordion component for right sidebar sections
- Add crypto.randomUUID polyfill for jsdom test environment
- Add compileIdRef token pattern to prevent stale compile responses from
overwriting newer state after uploads or recompiles
- Set bytecodeSource on compile success ("compile") and bytecode upload
("upload" with full artifact reset)
- Preserve previous successful artifacts on compile failure instead of
calling resetCompilationState
- Clear local isCompiling spinner on bytecode upload to prevent stuck UI
- Reset file inputs after selection to allow re-uploading the same file
- Guard "Compiled" indicator with bytecodeSource === "compile" check
…debar - Add StudioLayout with resizable 3-panel layout (file explorer, editor, sidebar) and fixed status bar - Add FileExplorer with search, file tree, inline rename with duplicate rejection, delete with last-file guard, and .sol upload - Add EditorTabs with open/close/switch, dirty dot indicator, and new file button - Add EditorArea combining tabs, Monaco editor (keyed by file ID for model isolation), and collapsible OutputPanel - Add CompilerSection with EVM/PVM toggle, compile button with race protection (compileIdRef), contract selector with smart re-selection, bytecode/ABI upload with full artifact reset rules - Add DeploySection with deploy gates per bytecodeSource (compile vs upload), dirty/mode warnings, no-ABI hex fallback, unverified ABI warning, and transaction log - Add RightSidebar wrapping compile and deploy as accordion sections - Add StatusBar showing chain, address, artifact mode badge (from compilation.mode, not compile target), and compile status - Update page.tsx with StudioProvider in the provider hierarchy
- Add compileSoliditySources() client function with 450KB size preflight - Extend /api/compile to accept sources (multi-file) alongside source (single-file, backward compatible) - Validate flat namespace: reject source keys containing / or .. - Add flat-namespace error hint for relative imports (./Token.sol) when basename matches a user source file - Raise body size limit from 100KB to 500KB for multi-file workspaces - Add resolveAllImportsSources() with user-source authority and CDN shadowing prevention - Sort compiled contracts with user files first, dependencies last
- Add studio-reducer.test.ts (23 tests): file ops (create, rename with duplicate rejection, delete with last-file guard), dirty tracking (content hash changes on edit/rename/delete/create), tab management (open, close with neighbor focus, switch), content hash determinism - Add studio-integration.test.ts (12 tests): compile race protection (stale response discard, upload-during-compile cancellation), compile failure artifact preservation, mixed artifact transitions (EVM→ABI, PVM→upload, upload→ABI layering), deploy gate rules
Remove contract-studio.tsx, compile-panel.tsx, and editor-panel.tsx. These are fully replaced by the new studio-layout.tsx, file-explorer.tsx, editor-area.tsx, compiler-section.tsx, and deploy-section.tsx components.
- Invalidate weightRequired/storageDeposit when deploy inputs (value, code, data, salt) change, preventing deploy with stale gas limits - Narrow CDN shadowing check to exact key match only; basename collision was blocking legitimate dependencies like @openzeppelin/.../Context.sol when a user file shared the same basename - Reject filenames containing /, .., or \ in CREATE_FILE and RENAME_FILE reducer actions, matching the flat namespace rules enforced by /api/compile
… account change - Builder compile failure/error now clears hexValue and calls onChange(undefined) so the extrinsic form cannot submit outdated bytecode that no longer matches the editor source - Add origin (account address) to gas estimate invalidation effect so wallet switches clear stale dry-run results and deployed address
- Replace LunoKit's isPending with local isSubmitting state managed in try/finally, ensuring the button always resets even if the wallet interaction hangs or the extension crashes - Add spinner icon to submitting state for clearer feedback - Improve signing toast to prompt user to approve in wallet extension - Distinguish user rejection (cancelled/rejected) from actual errors with appropriate toast messages
- Check receipt.status === "failed" after block inclusion to surface on-chain dispatch errors (e.g., module errors from pallet-revive) instead of showing a false success toast - Add "Signing... approve in your wallet extension" log entry in Studio deploy section for intermediate feedback - Distinguish user wallet rejection from actual transaction errors in Studio deploy log (info vs error)
Replace the flex-based 50/50 split between Monaco editor and output panel with a vertical ResizablePanelGroup (75/25 default). Users can now drag the handle to resize the editor vs output area.
6 tasks
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Redesigns Contract Studio from a basic 3-panel form into a proper IDE experience for the Polkadot Solidity Hackathon:
.solfiles. Flat namespace with duplicate rejection and last-file guard./api/compileviasourcesparam. Flat namespace validation, import hint for relative paths, user files sorted first./builderupdated with compile race protection (compileIdRef), artifact preservation on compile failure,bytecodeSourcetracking, and upload input reset.Commits
StudioStatetypes,contentHashutility,StudioProviderwithuseReducer,bytecodeSource/nullablemodeinContractCompilationStatecontract-code.tsxStudioLayout,FileExplorer,FileTreeItem,EditorTabs,EditorArea,OutputPanel,CompilerSection,DeploySection,RightSidebar,StatusBarcompileSoliditySources(), extended/api/compileroute,resolveAllImportsSources()contract-studio.tsx,compile-panel.tsx,editor-panel.tsxTest plan
yarn buildpassesyarn testpasses (1020 tests, 91 suites).binupload resets artifacts;.jsonABI layers on top with "unverified" warning/builder→ Revive →instantiate_with_codestill works end-to-end