Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c081bf3
Add Contract ABI Documentation for Token Factory
ComputerOracle Mar 28, 2026
ba794c5
Merge pull request #1 from ComputerOracle/docs/507-contract-abi
ComputerOracle Mar 28, 2026
d933acf
feat(contract): add treasury fee split mechanism (#485)
Emmyt24 Mar 29, 2026
0777d93
feat(ux): insufficient balance warning before transaction submission …
popsman01 Mar 29, 2026
b50b182
feat(contract): add batch token creation (#487)
Emmyt24 Mar 29, 2026
f432620
docs: add Vercel deployment guide (#505)
popsman01 Mar 29, 2026
d83fe50
feat: implement global error boundary (#473)
temma02 Mar 29, 2026
73b04c9
feat: toast notification system already implemented (#474)
temma02 Mar 29, 2026
5db1fe4
feat: add update_admin function to token factory contract (#479)
temma02 Mar 29, 2026
4dd54ca
feat: pause/unpause factory already implemented; add burn-while-pause…
temma02 Mar 29, 2026
5e7ae49
Merge branch 'main' into feat/485-treasury-fee-split
Ejirowebfi Mar 29, 2026
0dffec8
Merge pull request #657 from Emmyt24/feat/485-treasury-fee-split
Ejirowebfi Mar 29, 2026
2a013b7
Merge branch 'main' into feature/496-insufficient-balance-warning
Ejirowebfi Mar 29, 2026
7d318ab
Merge pull request #658 from popsman01/feature/496-insufficient-balan…
Ejirowebfi Mar 29, 2026
aa4d778
Merge pull request #659 from Emmyt24/feat/487-batch-token-creation
Ejirowebfi Mar 29, 2026
abeddfe
Merge pull request #660 from popsman01/docs/505-vercel-deployment-guide
Ejirowebfi Mar 29, 2026
ac419a8
Merge branch 'main' into feat/473-global-error-boundary
Ejirowebfi Mar 29, 2026
ac721d2
Merge pull request #661 from temma02/feat/473-global-error-boundary
Ejirowebfi Mar 29, 2026
4c0474e
Merge pull request #662 from temma02/feat/474-toast-notification-system
Ejirowebfi Mar 29, 2026
3594e83
Merge pull request #663 from temma02/feat/479-update-admin
Ejirowebfi Mar 29, 2026
6cccbac
Merge pull request #664 from temma02/feat/480-pause-unpause-factory
Ejirowebfi Mar 29, 2026
ed8af1d
docs: add detailed contract ABI documentation
ComputerOracle Mar 29, 2026
c334a30
Merge pull request #665 from ComputerOracle/docs/contract-abi
Ejirowebfi Mar 29, 2026
cee6369
feat(monitoring): add Sentry, uptime monitoring, and health endpoint
Olisachukwuma1 Mar 29, 2026
e0c24c0
feat: enhance token factory with DataKey enum and update storage access
Folex1275 Mar 29, 2026
403745c
Add Monitoring and Alerting for Production Deployment
Olisachukwuma1 Mar 29, 2026
a7b1b01
Merge branch 'main' into contract
Folex1275 Mar 29, 2026
e043a5c
feat(monitoring): add monitoring docs and sentry dependency
Olisachukwuma1 Mar 29, 2026
a625191
feat(security): add strict CSP, X-Frame-Options, and X-Content-Type-O…
Olisachukwuma1 Mar 29, 2026
19f0f1f
feat(security): add Content Security Policy and security headers
Olisachukwuma1 Mar 29, 2026
ee84a63
Implement formatting tests and image preview
teslims2 Mar 29, 2026
96cabf4
Fix formatting tests for issue #610
teslims2 Mar 29, 2026
e4d8902
feat: add analytics integration spec and scaffolding (#522)
marvs8 Mar 29, 2026
4c837b6
Merge branch 'main' into feature/all-issues-610-497-515-523
teslims2 Mar 29, 2026
5952c01
feat: add contract event indexing spec (#612)
marvs8 Mar 29, 2026
f88ec3c
feat: add decimals validation for create_token (0-18 inclusive)
teslims2 Mar 29, 2026
149f770
Merge pull request #690 from Folex1275/contract
Ejirowebfi Mar 29, 2026
01b8d58
Merge branch 'main' into alert
Ejirowebfi Mar 29, 2026
f1ef0c3
Merge pull request #692 from lemarjohnny781/alert
Ejirowebfi Mar 29, 2026
11ca0a0
Merge pull request #693 from lemarjohnny781/security
Ejirowebfi Mar 29, 2026
726559e
Merge branch 'main' into feature/522-analytics-integration
Ejirowebfi Mar 29, 2026
f7241ba
Merge pull request #694 from marvs8/feature/522-analytics-integration
Ejirowebfi Mar 29, 2026
7e82375
Merge branch 'main' into feature/all-issues-610-497-515-523
Ejirowebfi Mar 29, 2026
c7736d1
Merge pull request #695 from teslims2/feature/all-issues-610-497-515-523
Ejirowebfi Mar 29, 2026
3174451
Merge pull request #696 from marvs8/feature/612-contract-event-indexing
Ejirowebfi Mar 29, 2026
120d95d
Merge pull request #697 from teslims2/feature/issue-610-formatting-tests
Ejirowebfi Mar 29, 2026
5f98e3c
Merge branch 'main' into feature/issue-515-decimals-validation
Ejirowebfi Mar 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .kiro/specs/analytics-integration/.config.kiro
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"specId": "c32919a5-fe46-4bc6-984f-f99cbbd4a134", "workflowType": "requirements-first", "specType": "feature"}
122 changes: 122 additions & 0 deletions .kiro/specs/analytics-integration/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Requirements Document

## Introduction

StellarForge currently has no visibility into how users interact with the application. This feature adds a privacy-respecting analytics integration (Plausible) to track key user actions and page views, enabling the team to prioritize features and identify drop-off points in the token creation flow — without collecting any personally identifiable information or wallet addresses.

The analytics infrastructure is partially scaffolded in the codebase (`frontend/src/services/analytics.ts`, `frontend/src/hooks/useAnalytics.ts`, `frontend/src/components/AnalyticsOptOut.tsx`). This spec covers completing and hardening that implementation.

## Glossary

- **Analytics_Service**: The `analytics.ts` module responsible for sending events and page views to Plausible.
- **Plausible**: The privacy-respecting, cookieless analytics provider used for event and page view tracking.
- **Opt_Out_Store**: The `localStorage` key (`analytics_opt_out`) that persists the user's opt-out preference.
- **Token_Creation_Flow**: The multi-step user journey from navigating to `/create`, submitting the token form, and receiving a success or failure result.
- **PII**: Personally Identifiable Information — includes wallet addresses, names, email addresses, and any data that can identify an individual.
- **CSP**: Content Security Policy — the HTTP header or meta tag that restricts which external resources the browser may load.

## Requirements

### Requirement 1: Plausible Script Injection

**User Story:** As a developer, I want the Plausible analytics script to be loaded only when configured, so that the app works correctly in environments without analytics credentials.

#### Acceptance Criteria

1. WHEN `VITE_PLAUSIBLE_DOMAIN` is set in the environment, THE Analytics_Service SHALL load the Plausible script by injecting a `<script>` tag with `defer` and `data-domain` attributes into the document `<head>`.
2. WHEN `VITE_PLAUSIBLE_DOMAIN` is not set, THE Analytics_Service SHALL not inject any external script tags.
3. THE Analytics_Service SHALL set the `data-api` attribute on the injected script to the Plausible API endpoint so that the CSP `connect-src` directive can be scoped to that origin.
4. IF the Plausible script fails to load, THEN THE Analytics_Service SHALL silently suppress the error and continue normal application operation.

---

### Requirement 2: Page View Tracking

**User Story:** As a product owner, I want page views tracked for each route, so that I can understand which parts of the app users visit most.

#### Acceptance Criteria

1. WHEN the active route changes, THE Analytics_Service SHALL call `trackPageView` with the new pathname.
2. THE Analytics_Service SHALL send the page view only when `VITE_PLAUSIBLE_DOMAIN` is configured and the user has not opted out.
3. THE Analytics_Service SHALL never include query parameters or hash fragments that could contain wallet addresses or other PII in the tracked URL path.
4. IF `trackPageView` throws an exception, THEN THE Analytics_Service SHALL catch the exception and not propagate it to the caller.

---

### Requirement 3: Wallet Connected Event

**User Story:** As a product owner, I want to know when users successfully connect their wallet, so that I can measure wallet adoption and connection success rates.

#### Acceptance Criteria

1. WHEN a wallet connection succeeds, THE Analytics_Service SHALL emit a `wallet_connected` event.
2. THE Analytics_Service SHALL not include the wallet address or any wallet-derived identifier in the event properties.
3. IF the wallet connection fails, THEN THE Analytics_Service SHALL not emit a `wallet_connected` event.

---

### Requirement 4: Token Creation Flow Events

**User Story:** As a product owner, I want to track the token creation funnel, so that I can identify where users drop off and improve the flow.

#### Acceptance Criteria

1. WHEN a user submits the token creation form, THE Analytics_Service SHALL emit a `token_creation_started` event.
2. WHEN token deployment completes successfully, THE Analytics_Service SHALL emit a `token_creation_succeeded` event.
3. WHEN token deployment fails, THE Analytics_Service SHALL emit a `token_creation_failed` event.
4. THE Analytics_Service SHALL not include the token address, creator wallet address, or any user-identifying data in any token creation event properties.
5. WHERE the network is available as a non-identifying property (e.g., `"testnet"` or `"mainnet"`), THE Analytics_Service SHALL include it as an event property to allow funnel analysis by network.

---

### Requirement 5: PII and Wallet Address Exclusion

**User Story:** As a user, I want assurance that my wallet address and personal data are never sent to third-party analytics, so that my privacy is protected.

#### Acceptance Criteria

1. THE Analytics_Service SHALL never include wallet addresses in any tracked event or page view.
2. THE Analytics_Service SHALL never include token contract addresses in any tracked event or page view.
3. THE Analytics_Service SHALL never include user-supplied token names, symbols, or metadata in any tracked event or page view.
4. WHEN constructing event properties, THE Analytics_Service SHALL only permit properties of type `string`, `number`, or `boolean` that are drawn from a predefined allowlist of safe property keys.

---

### Requirement 6: Analytics Opt-Out Mechanism

**User Story:** As a user, I want to opt out of analytics tracking, so that I can use the app without any data being sent to third parties.

#### Acceptance Criteria

1. THE Analytics_Service SHALL expose an `isOptedOut` function that reads the opt-out preference from the Opt_Out_Store.
2. THE Analytics_Service SHALL expose a `setOptOut(value: boolean)` function that persists the preference to the Opt_Out_Store.
3. WHEN `isOptedOut` returns `true`, THE Analytics_Service SHALL skip all `trackEvent` and `trackPageView` calls without throwing an error.
4. THE AnalyticsOptOut component SHALL render a visible checkbox control that reflects the current opt-out state.
5. WHEN the user toggles the opt-out checkbox, THE AnalyticsOptOut component SHALL call `setOptOut` with the new value and immediately stop or resume tracking.
6. WHEN `VITE_PLAUSIBLE_DOMAIN` is not configured, THE AnalyticsOptOut component SHALL not render.
7. IF `localStorage` is unavailable, THEN THE Analytics_Service SHALL treat the user as opted in and silently suppress the storage error.

---

### Requirement 7: Content Security Policy Compatibility

**User Story:** As a security-conscious developer, I want the analytics integration to be compatible with the existing CSP, so that no CSP violations are introduced.

#### Acceptance Criteria

1. THE Analytics_Service SHALL only make network requests to `https://plausible.io` (or the configured `data-api` endpoint).
2. WHEN the Plausible domain is configured, THE application CSP `connect-src` directive SHALL include `https://plausible.io` to permit analytics requests.
3. WHEN the Plausible domain is configured, THE application CSP `script-src` directive SHALL include `https://plausible.io` to permit the analytics script.
4. THE Analytics_Service SHALL not use `eval`, inline scripts, or any mechanism that would require `unsafe-inline` or `unsafe-eval` in the CSP.

---

### Requirement 8: Analytics Initialization

**User Story:** As a developer, I want analytics to be initialized once at application startup, so that page views and events are captured from the first interaction.

#### Acceptance Criteria

1. WHEN the application mounts, THE Analytics_Service SHALL be initialized before any route rendering occurs.
2. THE Analytics_Service SHALL be initialized at most once per application lifecycle, even if the initialization function is called multiple times (idempotent).
3. WHEN analytics is already initialized, THE Analytics_Service SHALL skip re-injection of the Plausible script.
1 change: 1 addition & 0 deletions .kiro/specs/contract-event-indexing/.config.kiro
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"specId": "c32919a5-fe46-4bc6-984f-f99cbbd4a134", "workflowType": "requirements-first", "specType": "feature"}
108 changes: 108 additions & 0 deletions .kiro/specs/contract-event-indexing/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Requirements Document

## Introduction

This feature adds contract event indexing and transaction history display to the StellarForge token factory frontend. The factory contract emits events (`token_created`, `tokens_minted`, `tokens_burned`, `metadata_set`) via Soroban's event system. Currently, `StellarService` can fetch these events via the Soroban RPC `getEvents` method, but there is no UI to display them as a transaction history. This feature surfaces that data on the token detail page, showing each event as a history entry with type, amount, date, and a link to Stellar Expert explorer. It also wires up the partially-scaffolded `TransactionHistory` component and introduces a `useTransactionHistory` hook to drive it.

## Glossary

- **StellarService**: The frontend service class in `frontend/src/services/stellar.ts` that communicates with the Soroban RPC and Horizon API.
- **TransactionHistory**: The React component in `frontend/src/components/TransactionHistory.tsx` that renders the list of contract events as a table.
- **useTransactionHistory**: A React hook that fetches and manages contract event data for a given token address.
- **TokenDetail**: The React component in `frontend/src/components/TokenDetail.tsx` that renders the token detail page.
- **ContractEvent**: The existing TypeScript type representing a parsed Soroban contract event (`token_created`, `tokens_minted`, `tokens_burned`, `metadata_set`, `fees_updated`).
- **TransactionEntry**: A display-oriented type derived from `ContractEvent`, containing `id`, `type`, `amount`, `date`, `hash`, and `token` fields for rendering.
- **Soroban RPC**: The JSON-RPC endpoint used to query contract events via the `getEvents` method.
- **Horizon API**: The Stellar Horizon REST API, already used by `StellarService.getTransaction()`.
- **NetworkContext**: The existing React context that exposes the active network (`testnet` | `mainnet`).
- **Stellar Expert**: The block explorer at `https://stellar.expert/explorer/{network}/tx/{hash}`.
- **Factory Contract**: The deployed Soroban token factory contract identified by `STELLAR_CONFIG.factoryContractId`.

---

## Requirements

### Requirement 1: Fetch Contract Events for a Token Address

**User Story:** As a user viewing a token detail page, I want to see the transaction history for that token, so that I can understand what operations have been performed on it.

#### Acceptance Criteria

1. WHEN `getContractEvents` is called with the factory contract ID, THE `StellarService` SHALL filter the returned `ContractEvent` list to only those events whose `data.tokenAddress` matches the requested token address.
2. THE `StellarService` SHALL expose a `getTokenEvents(tokenAddress: string, limit?: number, cursor?: string)` method that returns a `GetEventsResult` containing only events relevant to the given token address.
3. WHEN the Soroban RPC returns no events for the factory contract, THE `StellarService` SHALL return an empty `events` array and a `null` cursor.
4. IF the Soroban RPC call fails, THEN THE `StellarService` SHALL propagate the error so the caller can handle it.
5. THE `StellarService` SHALL support pagination by accepting an optional `cursor` parameter and returning the next cursor in `GetEventsResult`.

---

### Requirement 2: useTransactionHistory Hook

**User Story:** As a developer integrating transaction history into the UI, I want a React hook that manages fetching and pagination of contract events, so that the component stays free of data-fetching logic.

#### Acceptance Criteria

1. THE `useTransactionHistory` hook SHALL accept a `tokenAddress` string and an optional options object with `pageSize` (default 20).
2. WHEN the hook mounts or `tokenAddress` changes, THE `useTransactionHistory` hook SHALL fetch the initial page of `TransactionEntry` items for that token address.
3. THE `useTransactionHistory` hook SHALL expose `{ transactions, loading, error, hasMore, loadMore }` to consumers.
4. WHEN `loadMore` is called and `hasMore` is `true`, THE `useTransactionHistory` hook SHALL append the next page of results to `transactions` without replacing existing entries.
5. WHILE a fetch is in progress, THE `useTransactionHistory` hook SHALL set `loading` to `true`.
6. IF a fetch fails, THEN THE `useTransactionHistory` hook SHALL set `error` to a non-empty string and set `loading` to `false`.
7. WHEN `tokenAddress` is an empty string, THE `useTransactionHistory` hook SHALL return an empty `transactions` array without making a network request.
8. THE `useTransactionHistory` hook SHALL map each `ContractEvent` to a `TransactionEntry` with: `id` from `event.id`, `type` derived from `event.type` (e.g. `token_created` → `create`, `tokens_minted` → `mint`, `tokens_burned` → `burn`, `metadata_set` → `metadata`), `amount` from `event.data.amount` (or `'—'` when absent), `date` as an ISO string derived from `event.timestamp`, `hash` from `event.txHash`, and `token` from `event.data.tokenAddress`.

---

### Requirement 3: TransactionHistory Component

**User Story:** As a user on the token detail page, I want to see a table of transaction history entries, so that I can review past operations at a glance.

#### Acceptance Criteria

1. THE `TransactionHistory` component SHALL accept a `tokenAddress` string prop and use `useTransactionHistory` to load data.
2. WHILE `loading` is `true` and no transactions have been loaded yet, THE `TransactionHistory` component SHALL render a skeleton/loading placeholder.
3. WHEN `transactions` is empty and `loading` is `false` and `error` is absent, THE `TransactionHistory` component SHALL render a localised empty-state message using the `t('transactionHistory.noEvents')` key.
4. WHEN `error` is non-empty, THE `TransactionHistory` component SHALL render the error message in a visible error state.
5. WHEN `transactions` is non-empty, THE `TransactionHistory` component SHALL render a table with columns: Type, Amount, Date, and Transaction Hash.
6. FOR EACH transaction entry, THE `TransactionHistory` component SHALL render the `type` as a colour-coded badge using the existing `badgeColors` map.
7. FOR EACH transaction entry, THE `TransactionHistory` component SHALL render the `date` using the existing `formatTimestamp` utility.
8. FOR EACH transaction entry, THE `TransactionHistory` component SHALL render the `hash` as a link to `https://stellar.expert/explorer/{network}/tx/{hash}` that opens in a new tab, where `{network}` is derived from `NetworkContext`.
9. FOR EACH transaction entry, THE `TransactionHistory` component SHALL render a `CopyButton` next to the transaction hash.
10. WHEN the user scrolls to within 200px of the bottom of the page and `hasMore` is `true`, THE `TransactionHistory` component SHALL call `loadMore` to fetch the next page.
11. THE `TransactionHistory` component SHALL import and use `useTranslation` from `react-i18next` for all user-visible strings.

---

### Requirement 4: Token Detail Page Integration

**User Story:** As a user on the token detail page, I want the transaction history to appear below the token info card, so that I can see all relevant activity in one place.

#### Acceptance Criteria

1. THE `TokenDetail` component SHALL render the `TransactionHistory` component below the existing token info card, passing the current `address` as the `tokenAddress` prop.
2. WHEN `address` is defined and valid, THE `TokenDetail` component SHALL always render the `TransactionHistory` component regardless of whether the connected wallet is the token creator.
3. THE `TokenDetail` component SHALL wrap the `TransactionHistory` component in a `Card` with the title derived from `t('transactionHistory.title')`.

---

### Requirement 5: Explorer Link Correctness

**User Story:** As a user, I want transaction hash links to point to the correct network's Stellar Expert explorer, so that I can verify transactions on the right network.

#### Acceptance Criteria

1. WHEN the active network is `testnet`, THE `TransactionHistory` component SHALL construct explorer URLs using `https://stellar.expert/explorer/testnet/tx/{hash}`.
2. WHEN the active network is `mainnet`, THE `TransactionHistory` component SHALL construct explorer URLs using `https://stellar.expert/explorer/public/tx/{hash}`.
3. THE `TransactionHistory` component SHALL read the active network from `NetworkContext` via the `useNetwork` hook.

---

### Requirement 6: History Refresh After New Transactions

**User Story:** As a user who just minted or burned tokens, I want the transaction history to update automatically, so that I can confirm my action appeared in the list.

#### Acceptance Criteria

1. THE `TokenDetail` component SHALL pass an `onSuccess` callback to `MintForm`, `BurnForm`, and `SetMetadataForm` that triggers a refresh of the `TransactionHistory` component.
2. WHEN a mint, burn, or metadata operation completes successfully, THE `TransactionHistory` component SHALL re-fetch the first page of events from the beginning (resetting pagination state).
3. THE `useTransactionHistory` hook SHALL expose a `refresh` function that resets `transactions`, `cursor`, and `hasMore` to their initial state and re-fetches the first page.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# StellarForge - Stellar Token Deployer

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/Ejirowebfi/Stellar-forge&root=frontend&env=VITE_FACTORY_CONTRACT_ID,VITE_TOKEN_WASM_HASH,VITE_IPFS_API_KEY,VITE_IPFS_API_SECRET&envDescription=Required%20environment%20variables%20for%20StellarForge&envLink=https://github.com/Ejirowebfi/Stellar-forge/blob/main/docs/deployment-vercel.md)

StellarForge is a user-friendly decentralized application (dApp) that enables creators, entrepreneurs, and businesses in emerging markets to deploy custom tokens on the Stellar blockchain without writing a single line of code.

## Features
Expand Down Expand Up @@ -197,6 +199,8 @@ npm run build
# Deploy the dist/ folder to your hosting service (Vercel, Netlify, etc.)
```

For a full step-by-step Vercel deployment guide see [docs/deployment-vercel.md](./docs/deployment-vercel.md).

## Project Structure

```
Expand Down
Loading