Skip to content

feat: add fund platform address mode#9

Closed
thepastaclaw wants to merge 1 commit intoPastaPastaPasta:mainfrom
thepastaclaw:feat/fund-platform-address
Closed

feat: add fund platform address mode#9
thepastaclaw wants to merge 1 commit intoPastaPastaPasta:mainfrom
thepastaclaw:feat/fund-platform-address

Conversation

@thepastaclaw
Copy link
Contributor

@thepastaclaw thepastaclaw commented Feb 18, 2026

Summary

Adds a new Fund Platform Address mode to the bridge, allowing users to send L1 DASH directly to a Platform address (bech32m).

Requested by thephez.

Flow

  1. User selects "Fund Platform Address" mode
  2. User enters the private key (WIF) for their platform address
  3. Bridge derives and displays the bech32m platform address for confirmation
  4. Identical L1 deposit → asset lock flow as the existing top-up mode
  5. Calls sdk.addresses.fundFromAssetLock() instead of sdk.identities.topUp()

Files Changed

  • src/platform/address.ts (new) — fundPlatformAddress() implementation using sdk.addresses.fundFromAssetLock()
  • src/ui/fund-address.ts (new) — enter_platform_address step UI (key input + derived address display)
  • src/types.ts — added fund_address to BridgeMode, enter_platform_address to BridgeStep, new state fields
  • src/ui/state.tssetMode() handler, setPlatformAddressKey(), setFundAddressComplete()
  • src/ui/components.ts — mode button + fund-address step rendering
  • src/main.tsstartFundAddress() function + event handlers + step routing

Build

npm run build passes with zero TypeScript errors.

Summary by CodeRabbit

  • New Features
    • Added a new "Fund Platform Address" mode to the bridge interface.
    • Introduced user interface for entering platform address private keys with validation and display.
    • Implemented automated key backup and download functionality for fund operations.
    • Added processing flow with deposit address display and real-time transaction status updates.

Add new 'fund_address' mode to the bridge that lets users send L1 DASH
directly to a Platform address (bech32m) using an asset lock.

Flow:
1. User enters their platform address private key (WIF)
2. Bridge derives and displays the bech32m platform address for confirmation
3. Same L1 deposit → asset lock flow as topup mode
4. Calls sdk.addresses.fundFromAssetLock() instead of sdk.identities.topUp()

New files:
- src/platform/address.ts — fundPlatformAddress() implementation
- src/ui/fund-address.ts — enter_platform_address step UI

Updated:
- src/types.ts — added fund_address mode + enter_platform_address step + state fields
- src/ui/state.ts — setMode(), setPlatformAddressKey(), setFundAddressComplete()
- src/ui/components.ts — mode button + fund-address step rendering
- src/main.ts — startFundAddress(), event handlers, step routing
@coderabbitai
Copy link

coderabbitai bot commented Feb 18, 2026

📝 Walkthrough

Walkthrough

This pull request adds a complete fund-address flow to the Dash bridge, enabling users to fund a platform address from an asset lock. New UI components capture the platform address private key, render progress through deposit waiting and funding steps, and expose state management functions. A new fundPlatformAddress SDK function handles the platform-side operation.

Changes

Cohort / File(s) Summary
Platform Address Funding
src/platform/identity.ts, src/platform/index.ts
New fundPlatformAddress function establishes SDK connection, constructs AssetLockProof, PlatformAddressSigner, and PlatformAddressOutput, then invokes sdk.addresses.fundFromAssetLock; re-exported from platform module.
Type Definitions
src/types.ts
Extended BridgeMode to include 'fund_address'; added BridgeStep entries 'enter_platform_address' and 'funding_address'; expanded BridgeState with platformAddressPrivateKeyWif and platformAddress fields.
UI Components & State
src/ui/components.ts, src/ui/state.ts, src/ui/index.ts
New renderEnterPlatformAddressStep component for private key input; updated deposit/processing/complete flows to handle fund_address mode with adjusted headlines and address display; added setPlatformAddress and setFundAddressComplete state management functions; adjusted key backup filenames to prefix with dash-fund-address when applicable.
Main Orchestration
src/main.ts
Implemented startFundAddress end-to-end flow: generates one-time asset-lock key pair, auto-downloads key backup, waits for deposit via Insight, broadcasts asset-lock transaction with InstantSend confirmation, builds proof, invokes fundPlatformAddress, and marks completion; integrated into UI with mode button and continue handler; added validation and error handling throughout.

Sequence Diagram

sequenceDiagram
    participant User
    participant UI
    participant State
    participant Main as Main<br/>(startFundAddress)
    participant SDK as Dash SDK
    participant Insight
    participant Platform as Platform<br/>fundPlatformAddress

    User->>UI: Select "Fund Platform Address"
    UI->>State: setMode('fund_address')
    State-->>UI: Enter platform private key step
    User->>UI: Input platform address private key
    UI->>State: setPlatformAddress(privateKeyWif, address)
    User->>UI: Click Continue
    UI->>Main: Trigger fund process
    Main->>SDK: Generate one-time asset-lock key pair
    SDK-->>Main: keyPair, depositAddress
    State->>State: Update with depositAddress
    Main->>Main: Auto-download key backup
    Main->>Insight: Poll for deposit
    Insight-->>Main: Deposit detected
    Main->>SDK: Build asset-lock transaction
    SDK-->>Main: Transaction built
    Main->>SDK: Broadcast transaction
    Insight->>Insight: InstantSend confirmation
    Main->>SDK: Build asset-lock proof
    SDK-->>Main: Proof hex
    Main->>Platform: fundPlatformAddress(platformKey, proof)
    Platform->>SDK: Call sdk.addresses.fundFromAssetLock
    SDK-->>Platform: Platform address funded
    Platform-->>Main: { success: true, address }
    State->>State: setFundAddressComplete
    UI-->>User: Show completion screen
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A platform address to fund, so bright,
With keys and proofs we set things right,
Through deposits deep and SDK calls,
Our flow now answers funding's calls! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add fund platform address mode' accurately and concisely describes the main change: introducing a new mode for funding platform addresses, which is the primary objective of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/main.ts (2)

245-279: Platform key validation on blur/paste — consider also triggering on input or Enter key.

Currently the key is only validated on blur (focus lost) or paste. If a user types a WIF key manually and then clicks "Continue" without tabbing away, the key won't be validated and the button will remain disabled. This is a minor UX gap since most users will paste, but adding an input event (debounced) or validating on Enter would improve the experience.

That said, this is consistent with how DPNS and manage identity key inputs work in this file (also blur/paste only), so this can be deferred.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main.ts` around lines 245 - 279, The current validation only runs on
blur/paste for platformAddressKeyInput; extend it to also validate on user
typing and when they press Enter by wiring validatePlatformKey to a debounced
input event handler on platformAddressKeyInput (use a short debounce, e.g.,
200–300ms) and add a keydown listener that calls validatePlatformKey when the
Enter key is pressed; keep the existing error handling and state updates via
updateState(setPlatformAddress(...)) and ensure you reference the existing
validatePlatformKey, platformAddressKeyInput, updateState, and
setPlatformAddress symbols when adding these listeners.

1114-1211: startFundAddress() largely duplicates startTopUp() (steps 1–6 are identical).

The deposit → build → sign → broadcast → ISLock flow (lines 1118–1188) is a near-verbatim copy of startTopUp() (lines 1006–1086). Only step 7 (the SDK call) differs. Consider extracting the shared deposit-to-proof pipeline into a helper to reduce ~70 lines of duplication.

This is a pre-existing pattern (also shared with startBridge and recheckDeposit), so it's not new to this PR — deferring is reasonable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main.ts` around lines 1114 - 1211, startFundAddress duplicates the
deposit→build→sign→broadcast→ISLock pipeline found in startTopUp (and similar
logic in startBridge/recheckDeposit); extract that shared flow into a single
helper (e.g., createAssetLockFlow or getAssetLockProof) that accepts parameters
like depositAddress/privateKey or one-time keypair and returns {signedTxHex,
txid, islockBytes, assetLockProof, utxo} (or throws on timeout), then update
startFundAddress, startTopUp, startBridge and recheckDeposit to call this helper
and only perform their unique final steps (e.g., fundPlatformAddress) using the
returned proof; ensure the helper encapsulates steps: generate/wire one-time
keypair (or accept it), waitForUtxo (insightClient.waitForUtxo),
createAssetLockTransaction, signTransaction, serialize/hex conversion,
broadcastTransaction, waitForInstantSendLock
(dapiClient.waitForInstantSendLock), and buildInstantAssetLockProof so state
updates and error handling in callers are simplified.
src/ui/components.ts (1)

355-431: renderEnterPlatformAddressStep — consider escaping platformAddressPrivateKeyWif and platformAddress before interpolation into innerHTML.

Static analysis flags XSS risk on lines 369–396 where state.platformAddressPrivateKeyWif and state.platformAddress are interpolated directly into innerHTML. In practice these are Base58Check/bech32m strings with restricted character sets (only stored after SDK validation succeeds), so the actual risk is very low. However, the codebase already has an escapeHtml helper — using it here would be a consistent defensive measure.

This is the same pattern used elsewhere in the file for identity IDs and addresses, so it's not a regression.

Defensive escaping example for the WIF value attribute
         placeholder="Enter your platform address private key in WIF format..."
-        value="${state.platformAddressPrivateKeyWif || ''}"
+        value="${escapeHtml(state.platformAddressPrivateKeyWif || '')}"
       />

And similarly for state.platformAddress in the address display and data-copy attribute.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/components.ts` around lines 355 - 431, renderEnterPlatformAddressStep
currently interpolates state.platformAddressPrivateKeyWif and
state.platformAddress directly into innerHTML which can trigger static-analysis
XSS warnings; update the function to pass those values through the existing
escapeHtml helper before interpolation (apply to the input value attribute, the
<code class="address"> content, and the data-copy attribute on the copy button)
so all dynamic HTML fragments use escaped strings (refer to escapeHtml,
platformAddressPrivateKeyWif, platformAddress, renderEnterPlatformAddressStep).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main.ts`:
- Line 1191: The current call to updateState(setStep(state, 'topping_up')) uses
the wrong step identifier; replace the 'topping_up' step with the dedicated
'funding_address' step so the step metadata (used by getStepDescription and
progress) matches the flow—locate the invocation of updateState and setStep in
main.ts and change the second argument from 'topping_up' to 'funding_address' so
renderProcessingStep and getStepDescription reflect the correct "Funding
address..." semantics.

---

Nitpick comments:
In `@src/main.ts`:
- Around line 245-279: The current validation only runs on blur/paste for
platformAddressKeyInput; extend it to also validate on user typing and when they
press Enter by wiring validatePlatformKey to a debounced input event handler on
platformAddressKeyInput (use a short debounce, e.g., 200–300ms) and add a
keydown listener that calls validatePlatformKey when the Enter key is pressed;
keep the existing error handling and state updates via
updateState(setPlatformAddress(...)) and ensure you reference the existing
validatePlatformKey, platformAddressKeyInput, updateState, and
setPlatformAddress symbols when adding these listeners.
- Around line 1114-1211: startFundAddress duplicates the
deposit→build→sign→broadcast→ISLock pipeline found in startTopUp (and similar
logic in startBridge/recheckDeposit); extract that shared flow into a single
helper (e.g., createAssetLockFlow or getAssetLockProof) that accepts parameters
like depositAddress/privateKey or one-time keypair and returns {signedTxHex,
txid, islockBytes, assetLockProof, utxo} (or throws on timeout), then update
startFundAddress, startTopUp, startBridge and recheckDeposit to call this helper
and only perform their unique final steps (e.g., fundPlatformAddress) using the
returned proof; ensure the helper encapsulates steps: generate/wire one-time
keypair (or accept it), waitForUtxo (insightClient.waitForUtxo),
createAssetLockTransaction, signTransaction, serialize/hex conversion,
broadcastTransaction, waitForInstantSendLock
(dapiClient.waitForInstantSendLock), and buildInstantAssetLockProof so state
updates and error handling in callers are simplified.

In `@src/ui/components.ts`:
- Around line 355-431: renderEnterPlatformAddressStep currently interpolates
state.platformAddressPrivateKeyWif and state.platformAddress directly into
innerHTML which can trigger static-analysis XSS warnings; update the function to
pass those values through the existing escapeHtml helper before interpolation
(apply to the input value attribute, the <code class="address"> content, and the
data-copy attribute on the copy button) so all dynamic HTML fragments use
escaped strings (refer to escapeHtml, platformAddressPrivateKeyWif,
platformAddress, renderEnterPlatformAddressStep).

updateState(setInstantLockReceived(state, islockBytes, assetLockProof));

// Step 7: Fund the platform address
updateState(setStep(state, 'topping_up'));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Bug: Step should be 'funding_address', not 'topping_up'.

The types define a dedicated 'funding_address' step with its own description ("Funding address...") and progress value. Using 'topping_up' here means getStepDescription returns "Adding credits..." instead of "Funding address...", and the step semantics don't match the flow.

The rendering still works because renderProcessingStep checks state.mode === 'fund_address' for headlines, but the step metadata is wrong.

🐛 Proposed fix
-    updateState(setStep(state, 'topping_up'));
+    updateState(setStep(state, 'funding_address'));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main.ts` at line 1191, The current call to updateState(setStep(state,
'topping_up')) uses the wrong step identifier; replace the 'topping_up' step
with the dedicated 'funding_address' step so the step metadata (used by
getStepDescription and progress) matches the flow—locate the invocation of
updateState and setStep in main.ts and change the second argument from
'topping_up' to 'funding_address' so renderProcessingStep and getStepDescription
reflect the correct "Funding address..." semantics.

@thepastaclaw
Copy link
Contributor Author

Superseded by #10 which has a more complete implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant