|
| 1 | +# Stellar Lab Integration Documentation |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +This document describes the implementation of the "Open in Stellar Lab" button feature for the Escrow Viewer. The button allows users to open escrow contracts directly in Stellar Lab (lab.stellar.org) for advanced contract inspection and interaction. |
| 6 | + |
| 7 | +## Stellar Lab URL Structure |
| 8 | + |
| 9 | +Stellar Lab uses a complex URL structure with multiple query parameters to configure the network and pre-fill the contract explorer. The URL format is: |
| 10 | + |
| 11 | +``` |
| 12 | +https://lab.stellar.org/smart-contracts/contract-explorer? |
| 13 | + $=network$id={network} |
| 14 | + &label={networkLabel} |
| 15 | + &horizonUrl={horizonUrl} |
| 16 | + &rpcUrl={rpcUrl} |
| 17 | + &passphrase={urlEncodedPassphrase} |
| 18 | + &smartContracts$explorer$contractId={contractId};; |
| 19 | +``` |
| 20 | + |
| 21 | +**Key Format Requirements:** |
| 22 | +1. Network parameter: `$=network$id={network}` - **No `&` separator** between `$=network` and `id` |
| 23 | +2. URLs use **double slashes**: `https:////horizon.stellar.org` (not `https://`) |
| 24 | +3. Passphrase format: Includes `/;` before the date and trailing semicolon: `"Public Global Stellar Network /; September 2015;"` |
| 25 | +4. URL ends with **trailing `;;`** |
| 26 | +5. Dollar signs in parameter names remain **unencoded** (e.g., `smartContracts$explorer$contractId`) |
| 27 | + |
| 28 | +## URL Parameters |
| 29 | + |
| 30 | +### Required Parameters |
| 31 | + |
| 32 | +1. **`$`** - Fixed value: `"network"` - Indicates network configuration mode |
| 33 | +2. **`id`** - Network identifier: `"testnet"` or `"mainnet"` |
| 34 | +3. **`label`** - Human-readable network name: `"Testnet"` or `"Mainnet"` |
| 35 | +4. **`horizonUrl`** - Horizon API endpoint URL |
| 36 | +5. **`rpcUrl`** - Soroban RPC endpoint URL |
| 37 | +6. **`passphrase`** - Network passphrase (URL encoded) |
| 38 | +7. **`smartContracts$explorer$contractId`** - The contract ID to open in the explorer |
| 39 | + |
| 40 | +## Network Configuration |
| 41 | + |
| 42 | +### Testnet Configuration |
| 43 | + |
| 44 | +- **Network ID**: `testnet` |
| 45 | +- **Network Label**: `Testnet` |
| 46 | +- **Horizon URL**: `https:////horizon-testnet.stellar.org` (double slashes) |
| 47 | +- **RPC URL**: `https:////soroban-testnet.stellar.org` (double slashes) |
| 48 | +- **Passphrase**: `Test SDF Network /; September 2015;` (with `/;` before date and trailing `;`) |
| 49 | + |
| 50 | +### Mainnet Configuration |
| 51 | + |
| 52 | +- **Network ID**: `mainnet` |
| 53 | +- **Network Label**: `Mainnet` |
| 54 | +- **Horizon URL**: `https:////horizon.stellar.org` (double slashes) |
| 55 | +- **RPC URL**: `https:////rpc.ankr.com//stellar_soroban` (double slashes, Ankr RPC) |
| 56 | +- **Passphrase**: `Public Global Stellar Network /; September 2015;` (with `/;` before date and trailing `;`) |
| 57 | + |
| 58 | +**Note**: Mainnet uses Ankr RPC endpoint (`rpc.ankr.com//stellar_soroban`) instead of the official Stellar endpoint. This is the correct endpoint as verified by working Stellar Lab URLs. |
| 59 | + |
| 60 | +## Implementation Details |
| 61 | + |
| 62 | +### Helper Function |
| 63 | + |
| 64 | +The URL generation is handled by `getStellarLabUrl()` in `src/lib/network-config.ts`. This function: |
| 65 | + |
| 66 | +1. Takes the network type and contract ID as parameters |
| 67 | +2. Retrieves network configuration from `NETWORK_CONFIGS` |
| 68 | +3. Uses official Stellar RPC endpoints (which may differ from the Escrow Viewer's RPC configuration) |
| 69 | +4. URL-encodes the network passphrase |
| 70 | +5. Constructs the complete Stellar Lab URL with all required parameters |
| 71 | + |
| 72 | +### Key Implementation Notes |
| 73 | + |
| 74 | +1. **RPC URL Selection**: Stellar Lab requires official Stellar RPC endpoints. The Escrow Viewer may use different RPC providers (e.g., OnFinality for mainnet) for performance reasons, but Stellar Lab URLs must use the official endpoints. |
| 75 | + - Testnet: `https://soroban-testnet.stellar.org` ✅ |
| 76 | + - Mainnet: `https://soroban-mainnet.stellar.org` ✅ |
| 77 | + |
| 78 | +2. **URL Encoding**: |
| 79 | + - The network passphrase contains special characters (semicolons, spaces) that must be properly URL-encoded using `encodeURIComponent()`. |
| 80 | + - **Important**: We manually construct the URL string instead of using `URLSearchParams` because: |
| 81 | + - Dollar signs (`$`) in parameter names (like `smartContracts$explorer$contractId`) must remain unencoded |
| 82 | + - `URLSearchParams` would encode `$` to `%24`, breaking the parameter name |
| 83 | + - The passphrase should only be encoded once, not double-encoded |
| 84 | + - **Passphrase Format**: Must include `/;` before the date and trailing semicolon: |
| 85 | + - Mainnet: `"Public Global Stellar Network /; September 2015;"` |
| 86 | + - Testnet: `"Test SDF Network /; September 2015;"` |
| 87 | + - **URL Format**: URLs use double slashes (`https:////`) and are NOT encoded |
| 88 | + - **Trailing Semicolons**: URL must end with `;;` |
| 89 | + |
| 90 | +3. **Parameter Format**: The contract ID parameter uses a special format: `smartContracts$explorer$contractId` with dollar signs as separators. These dollar signs must remain as literal `$` characters in the URL, not encoded as `%24`. |
| 91 | + |
| 92 | +## Example URLs |
| 93 | + |
| 94 | +### Testnet Example |
| 95 | + |
| 96 | +``` |
| 97 | +https://lab.stellar.org/smart-contracts/contract-explorer?$=network$id=testnet&label=Testnet&horizonUrl=https:////horizon-testnet.stellar.org&rpcUrl=https:////soroban-testnet.stellar.org&passphrase=Test%20SDF%20Network%20/%3B%20September%202015%3B&smartContracts$explorer$contractId=CDD3CLASPMKZ6ZYBMJDOGIUHZDVKPN6PF6RH7TXKRCYUVPA3BULSOJIE;; |
| 98 | +``` |
| 99 | + |
| 100 | +### Mainnet Example |
| 101 | + |
| 102 | +``` |
| 103 | +https://lab.stellar.org/smart-contracts/contract-explorer?$=network$id=mainnet&label=Mainnet&horizonUrl=https:////horizon.stellar.org&rpcUrl=https:////rpc.ankr.com//stellar_soroban&passphrase=Public%20Global%20Stellar%20Network%20/%3B%20September%202015%3B&smartContracts$explorer$contractId=CCQXWMZVM3KRTXTUPTN53YHL272QGKF32L7XEDNZ2S6OSUFK3NFBGG5M;; |
| 104 | +``` |
| 105 | + |
| 106 | +**Note**: Notice the key differences: |
| 107 | +- `$=network$id=mainnet` (no `&` between `$=network` and `id`) |
| 108 | +- Double slashes in URLs: `https:////` |
| 109 | +- Passphrase includes `/;` and trailing `;`: `/%3B%20September%202015%3B` |
| 110 | +- Trailing `;;` at the end of the URL |
| 111 | + |
| 112 | +## Button Implementation |
| 113 | + |
| 114 | +The "Open in Stellar Lab" button: |
| 115 | + |
| 116 | +- **Location**: Appears below the "View Transaction History" button when an escrow contract is loaded |
| 117 | +- **Visibility**: Only shown when `raw` escrow data is available |
| 118 | +- **Styling**: Uses the `outline` variant of the Button component to match other external tool buttons |
| 119 | +- **Icon**: Includes an `ExternalLink` icon from lucide-react |
| 120 | +- **Behavior**: Opens Stellar Lab in a new tab with `rel="noopener noreferrer"` for security |
| 121 | +- **Tooltip**: Includes a title attribute with "Open contract in Stellar Lab" |
| 122 | + |
| 123 | +## Testing |
| 124 | + |
| 125 | +### Testnet Testing |
| 126 | + |
| 127 | +1. Load a testnet escrow contract |
| 128 | +2. Click "Open in Stellar Lab" |
| 129 | +3. Verify the URL opens correctly in Stellar Lab |
| 130 | +4. Confirm the contract is pre-loaded in the explorer |
| 131 | +5. Verify network is set to Testnet |
| 132 | + |
| 133 | +### Mainnet Testing |
| 134 | + |
| 135 | +1. Switch to mainnet network |
| 136 | +2. Load a mainnet escrow contract |
| 137 | +3. Click "Open in Stellar Lab" |
| 138 | +4. Verify the URL opens correctly in Stellar Lab |
| 139 | +5. Confirm the contract is pre-loaded in the explorer |
| 140 | +6. Verify network is set to Mainnet |
| 141 | + |
| 142 | +## Research Findings |
| 143 | + |
| 144 | +### URL Parameter Discovery |
| 145 | + |
| 146 | +The reference URL provided in the task description showed: |
| 147 | +- Double slashes in URLs (`https:////horizon-testnet.stellar.org`) - This appears to be a typo or artifact. The implementation uses single slashes. |
| 148 | +- Complex parameter naming with dollar signs (`smartContracts$explorer$contractId`) |
| 149 | +- All parameters appear to be required for proper functionality |
| 150 | + |
| 151 | +### RPC URL Differences |
| 152 | + |
| 153 | +The Escrow Viewer's `NETWORK_CONFIGS` uses: |
| 154 | +- Testnet: `https://soroban-testnet.stellar.org` (matches Stellar Lab) |
| 155 | +- Mainnet: `https://stellar.api.onfinality.io/public` (different from Stellar Lab) |
| 156 | + |
| 157 | +Stellar Lab requires official Stellar RPC endpoints, so the implementation uses: |
| 158 | +- Testnet: `https://soroban-testnet.stellar.org` ✅ (Confirmed working from task example) |
| 159 | +- Mainnet: `https://soroban-mainnet.stellar.org` ⚠️ (Needs verification - follows pattern but not explicitly confirmed) |
| 160 | + |
| 161 | +**Research Finding**: According to [Stellar Lab documentation](https://developers.stellar.org/docs/tools/lab), the Lab is designed to let users configure RPC URLs through the network selector rather than requiring them in URL parameters. However, the task description provided a working testnet example with the full URL format including RPC URL, so we follow that pattern. The mainnet RPC URL follows the logical naming pattern but should be verified with actual testing. |
| 162 | + |
| 163 | +This ensures compatibility with Stellar Lab's requirements while allowing the Escrow Viewer to use optimized RPC providers for its own operations. |
| 164 | + |
| 165 | +## Files Modified |
| 166 | + |
| 167 | +1. **src/lib/network-config.ts** |
| 168 | + - Added `getStellarLabUrl()` function |
| 169 | + |
| 170 | +2. **src/components/escrow/EscrowDetails.tsx** |
| 171 | + - Added imports for `getStellarLabUrl`, `ExternalLink`, and `Button` |
| 172 | + - Added "Open in Stellar Lab" button in the action buttons section |
| 173 | + |
| 174 | +## Future Enhancements |
| 175 | + |
| 176 | +Potential improvements: |
| 177 | +- Add a tooltip component (beyond the title attribute) for better UX |
| 178 | +- Consider adding the button to other locations (e.g., transaction detail modal) |
| 179 | +- Add analytics tracking for button clicks |
| 180 | +- Consider caching generated URLs for performance |
0 commit comments