feat: add Transaction Composer - GUI builder for multi-op Stellar transactions#23
Open
bytebinders wants to merge 9 commits into
Open
feat: add Transaction Composer - GUI builder for multi-op Stellar transactions#23bytebinders wants to merge 9 commits into
bytebinders wants to merge 9 commits into
Conversation
Introduces BuildTransactionDto and SimulateTransactionDto with full class-validator and class-transformer decorators. Supported op types: payment, create_account, change_trust, manage_sell_offer, manage_buy_offer, create_passive_sell_offer, set_options, account_merge, allow_trust, path_payment_strict_send, path_payment_strict_receive, manage_data. Each DTO uses @isin for type discrimination, @ValidateNested for nested asset/price sub-objects, and @ApiProperty for Swagger docs.
…mulation
Adds ComposerService with three methods:
- getOperations(): returns static manifest of all 12 op types with
per-field schemas (name, label, type, required, placeholder) for
the UI to render dynamic forms.
- buildTransaction(dto): loads source account from Horizon, constructs
a TransactionBuilder, appends each op via a type-switch dispatch,
applies optional memo, and returns the unsigned XDR envelope + hash.
- simulateTransaction(dto): parses the XDR envelope, submits to Horizon,
and returns { success, fee, resultCodes, operationResults }. Horizon
error responses are decoded to extract result_codes for the UI.
Uses @stellar/stellar-sdk (already in deps) for all Stellar primitives.
Supports both testnet and mainnet via network passphrase selection.
ComposerController exposes three endpoints under /v1/composer: GET /operations - returns full op-type manifest with field schemas POST /build - accepts ordered op array, returns unsigned XDR POST /simulate - dry-runs XDR on Horizon, returns fee + result codes ComposerModule wires controller and service with standard NestJS pattern. ComposerModule imported into AppModule alongside existing feature modules.
network-context.tsx: React context providing useNetwork() hook with testnet/mainnet toggle. State is persisted to localStorage under the key 'savitools:network' and defaults to 'testnet'. composer-api.ts: Typed fetch wrappers (using existing apiFetch helper) for all three composer endpoints. Also exports submitToHorizon() which posts directly to Horizon /transactions as application/x-www-form-urlencoded for final signed submission.
Imports NetworkProvider from lib/network-context and wraps the AuthProvider subtree so every page (including /composer) can access the testnet/mainnet toggle via useNetwork() without prop-drilling.
Adds six focused components under src/components/tools/composer/: operation-palette.tsx Left panel with 12 color-coded op-type cards. Each card shows an icon, label, and hover-reveal plus icon. Click appends op to list. operation-list.tsx Center drag-to-reorder list using @hello-pangea/dnd DragDropContext. Each item shows index, op type, destination preview, grip handle, and hover-reveal trash button. Re-index is guaranteed by splice/insert on drag result indices. operation-form.tsx Right dynamic form driven by the op schema manifest fetched from the API. Supports dotted field paths (asset.code), boolean radio pairs, and text/number inputs. Fires onChange with deep-merged field state. xdr-preview.tsx Bottom monospace panel. Green dot when XDR is present. One-click copy with 2s confirmation state. simulate-result.tsx Inline result panel showing success/failure badge, fee in stroops, tx result code, per-operation result codes, and tx hash. composer-toolbar.tsx Testnet/mainnet toggle (reads/writes useNetwork context), op count badge, Simulate and Submit to Horizon buttons with loading spinners, inline submit result with Stellar Expert explorer link. index.tsx (root ComposerTool) Manages all composer state. Fetches op manifest on mount. Auto-builds XDR 600ms after any change (debounced, avoids excess Horizon calls). Resets simulate/submit results on each rebuild.
other-tools.tsx: replace the ComposerTool placeholder stub with a re-export from the new ./composer module. WebhooksTool and MonitorTool stubs are preserved unchanged. package.json: formally declare @hello-pangea/dnd ^17.0.0 as a dependency (package was already installed to node_modules during development setup).
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
Implements a full-stack, GUI-based Transaction Composer that lets developers visually assemble, preview, and submit multi-operation Stellar transactions without writing raw SDK code.
Closes #[issue_number]
What Was Built
API —
apps/api/src/modules/composer/Three new endpoints under
/v1/composer:GET /operationsPOST /buildPOST /simulateWeb —
/composerrouteFull replacement of the placeholder stub with a three-panel composer:
@hello-pangea/dnd; each item shows index, type, destination preview, and a hover-reveal delete buttonasset.code), boolean radio pairs, and text/number inputsSupported Operation Types (12)
payment·create_account·change_trust·manage_sell_offer·manage_buy_offer·create_passive_sell_offer·set_options·account_merge·allow_trust·path_payment_strict_send·path_payment_strict_receive·manage_dataKey Design Decisions
useNetwork()React context (testnet/mainnet) is persisted tolocalStorageand available app-wide viaNetworkProvideradded to the root layout.splice(source.index, 1)+splice(destination.index, 0, moved)to guarantee correct re-indexing.How to Test
Closes #15