Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
2c7ef9a
fix(wallet-service): require explicit backend token
nicosampler Jun 8, 2026
690f7ae
chore(canton): require explicit localnet tokens
nicosampler Jun 9, 2026
24ea3a7
feat(canton): run barebones on splice localnet
nicosampler Jun 9, 2026
10ec438
chore(dev-stack): remove local stack helper
nicosampler Jun 9, 2026
4c67f44
docs: document splice localnet stack
nicosampler Jun 9, 2026
75c2ef5
feat(carpincho): derive network from wallet-service status
nicosampler Jun 9, 2026
ebe742d
feat(wallet-service): configure splice services
nicosampler Jun 9, 2026
e81d955
feat(wallet-service): expose cip56 transfer helpers
nicosampler Jun 9, 2026
f5c4a33
feat(carpincho): accept cip56 transfers through wallet-service
nicosampler Jun 9, 2026
4ad9cec
fix(canton-barebones): pass splice urls to wallet-service
nicosampler Jun 9, 2026
d79fe4e
feat(carpincho): show cip56 transfer details
nicosampler Jun 9, 2026
d4a9a44
feat(carpincho): badge assets tab for pending transfers
nicosampler Jun 9, 2026
a53ea0a
feat(wallet-service): expose cip56 holdings
nicosampler Jun 9, 2026
5fe8636
feat(carpincho): add tokens tab for holdings
nicosampler Jun 9, 2026
7e3d14f
fix(carpincho): hide inactive tab content
nicosampler Jun 9, 2026
67af280
feat(carpincho): remove assets tab
nicosampler Jun 9, 2026
a64a454
feat(carpincho): show incoming transfers in tokens
nicosampler Jun 9, 2026
0650a22
style(carpincho): separate holding utxo details
nicosampler Jun 9, 2026
5c201ee
fix(carpincho): badge tokens tab for incoming transfers
nicosampler Jun 9, 2026
0a12fa0
feat(wallet-service): expose cip56 transfer creation
nicosampler Jun 10, 2026
2233a9d
feat(carpincho): add cip56 transfer logic
nicosampler Jun 10, 2026
2494727
feat(carpincho): add send token tab
nicosampler Jun 10, 2026
4927fc2
fix(carpincho): scope token tabs to selected account
nicosampler Jun 10, 2026
b6fbfc9
chore(carpincho): add tanstack query provider
nicosampler Jun 10, 2026
ec7e295
refactor(carpincho): query token holdings with tanstack
nicosampler Jun 10, 2026
fcd2904
refactor(carpincho): query incoming transfers with tanstack
nicosampler Jun 10, 2026
16bfbb6
feat(wallet-service): add cip56 holding summary rpc
nicosampler Jun 10, 2026
427c52b
perf(carpincho): load token details on demand
nicosampler Jun 10, 2026
612dd7c
fix(carpincho): reuse fallback token holding details
nicosampler Jun 10, 2026
849fd4f
update package-lock.json
nicosampler Jun 10, 2026
aec8a89
feat(wallet-service): add amulet preapproval rpc
nicosampler Jun 10, 2026
eaf7117
fix(wallet-service): accept amulet preapproval proposals
nicosampler Jun 10, 2026
2cd464e
feat(carpincho): add amulet preapproval helpers
nicosampler Jun 10, 2026
2868e2d
feat(carpincho): add amulet preapproval controls
nicosampler Jun 10, 2026
88cf0de
fix(wallet-service): wait for amulet preapproval proposals
nicosampler Jun 10, 2026
d12972a
fix(wallet-service): read amulet preapproval proposals from ACS
nicosampler Jun 10, 2026
be3cc71
fix(wallet-service): include dso in amulet preapproval proposals
nicosampler Jun 10, 2026
b57474e
fix(carpincho): rely on splice preapproval trigger
nicosampler Jun 10, 2026
80ab969
fix(amulet): make preapproval disable idempotent
nicosampler Jun 10, 2026
dffe262
fix(carpincho): compact auto-accept contract id
nicosampler Jun 11, 2026
bbf9320
build: add mermaid cli
nicosampler Jun 11, 2026
752c1a4
docs: fix readme mermaid chart
nicosampler Jun 11, 2026
36a9285
Merge branch 'main' into canton-barebones-splice
gabitoesmiapodo Jun 11, 2026
354d08b
docs: add react-query to carpincho-wallet stack row
gabitoesmiapodo Jun 11, 2026
2bfdfc5
docs: sync subproject docs with cip56 token features
gabitoesmiapodo Jun 11, 2026
c985601
fix(carpincho): keep connect resilient when wallet-service is unreach…
gabitoesmiapodo Jun 11, 2026
211b988
test(wallet-service): pin clock in amulet preapproval status test
gabitoesmiapodo Jun 11, 2026
9eaf8ae
refactor(carpincho): dedupe command/status types and query-client setup
gabitoesmiapodo Jun 11, 2026
1dfa3ce
feat(dev-stack): restore helper script, adapt for Splice LocalNet
gabitoesmiapodo Jun 11, 2026
eee1ca6
chore: update dev-stack labels
gabitoesmiapodo Jun 12, 2026
8f86940
feat(carpincho): cap toast message height with vertical scroll
gabitoesmiapodo Jun 12, 2026
f7e9274
feat(carpincho): add copy button to error toasts
gabitoesmiapodo Jun 12, 2026
e1e82f4
feat(carpincho): auto-dismiss non-error toasts after 5s
gabitoesmiapodo Jun 12, 2026
a9944d8
feat(carpincho): reorganize home tabs into Assets, Transfers, Activit…
gabitoesmiapodo Jun 12, 2026
3937c53
docs(carpincho): describe the new home tab layout in AGENTS.md
gabitoesmiapodo Jun 12, 2026
b3949d8
chore(wallet-service): document standalone env config for Splice Loca…
gabitoesmiapodo Jun 12, 2026
bf125c5
feat(carpincho): make Amulet auto-accept a toggle in the Transfers tab
gabitoesmiapodo Jun 12, 2026
dbe2f02
docs(carpincho): reflect auto-accept toggle move and default Assets tab
gabitoesmiapodo Jun 12, 2026
ccbb810
refactor(carpincho): drop orphaned hideWhenEmpty branch from Transfer…
gabitoesmiapodo Jun 12, 2026
26d7252
fix(carpincho): keep auto-accept toggle enabled during background pol…
gabitoesmiapodo Jun 12, 2026
e5922e3
refactor(carpincho): scope preapproval busy to in-flight actions
gabitoesmiapodo Jun 12, 2026
0aa343b
test(carpincho): cover useAmuletPreapproval busy semantics
gabitoesmiapodo Jun 12, 2026
b3d0a19
fix(carpincho): stop background polling from blinking panel content
gabitoesmiapodo Jun 12, 2026
5fa0a97
fix(carpincho): flip auto-accept toggle optimistically
gabitoesmiapodo Jun 12, 2026
09b7945
style(carpincho): shorten verbose comments added this session
gabitoesmiapodo Jun 12, 2026
4dd8227
style(carpincho): refine auto-accept toggle and its spacing
gabitoesmiapodo Jun 12, 2026
c19afef
chore(carpincho): add react-qr-code and Canton coin asset
gabitoesmiapodo Jun 12, 2026
23ed337
feat(carpincho): add send and receive icons
gabitoesmiapodo Jun 12, 2026
33bd8eb
feat(carpincho): add TokenRow assets list item
gabitoesmiapodo Jun 12, 2026
6a9af6b
feat(carpincho): add TokenReceive QR screen
gabitoesmiapodo Jun 12, 2026
e595455
feat(carpincho): extract TokenHoldingDetail UTXO view
gabitoesmiapodo Jun 12, 2026
6d551f5
feat(carpincho): add SendTokenForm with preset token
gabitoesmiapodo Jun 12, 2026
a06dbe1
feat(carpincho): add TokenDetailSheet screen-stack modal
gabitoesmiapodo Jun 12, 2026
5ae0662
feat(carpincho): move sending into token modal, drop Send tab
gabitoesmiapodo Jun 12, 2026
b6d9aa8
feat(carpincho): format token amounts and refine token modal header
gabitoesmiapodo Jun 12, 2026
57410a9
fix(carpincho): focus new modal screen and drop redundant send banner
gabitoesmiapodo Jun 12, 2026
ab6d18d
refactor(carpincho): move amount formatter to cip56 and flatten modal…
gabitoesmiapodo Jun 12, 2026
5f9a342
docs(carpincho): sync token modal redesign in architecture and AGENTS
gabitoesmiapodo Jun 12, 2026
38853c6
feat(carpincho): use boring-avatars for account avatars
gabitoesmiapodo Jun 12, 2026
91563bd
feat(carpincho): switch account avatars to abstract variant
gabitoesmiapodo Jun 12, 2026
201258b
feat(carpincho): use beam face avatars with a multi-hue palette
gabitoesmiapodo Jun 12, 2026
3472823
chore(carpincho): add radix select dep and contacts icon
gabitoesmiapodo Jun 12, 2026
ae84886
feat(carpincho): add exact decimal string comparison
gabitoesmiapodo Jun 12, 2026
24ad416
feat(carpincho): generate 256-color avatar palette keyed by full part…
gabitoesmiapodo Jun 12, 2026
72ad215
feat(carpincho): add crypto-standard amount field
gabitoesmiapodo Jun 12, 2026
74a6927
fix(carpincho): hide decorative avatar from a11y tree and correct pal…
gabitoesmiapodo Jun 12, 2026
615c0c6
refactor(carpincho): replace hsl sextant ternary with lookup table
gabitoesmiapodo Jun 12, 2026
81b4f2c
feat(carpincho): add contacts and confirmation steps to send flow
gabitoesmiapodo Jun 12, 2026
df4308f
feat(carpincho): icon-only contacts, fixed 4-row list, grouped amount…
gabitoesmiapodo Jun 12, 2026
ac8e272
fix(carpincho): normalize leading-dot amounts and flag invalid amount…
gabitoesmiapodo Jun 12, 2026
d24a495
feat(carpincho): direction-aware transfers tab with merged history
gabitoesmiapodo Jun 12, 2026
9752377
refactor(carpincho): dedup send request build, balance check, and tit…
gabitoesmiapodo Jun 12, 2026
e98f0e4
docs(carpincho): document redesigned send flow, Select primitive, and…
gabitoesmiapodo Jun 12, 2026
d2eab93
feat(carpincho): keep only pending transfers in transfers tab, histor…
gabitoesmiapodo Jun 12, 2026
04e2c2b
fix(carpincho): keep self-transfers acceptable in transfers tab
gabitoesmiapodo Jun 12, 2026
bb989ac
fix(carpincho): hide the active account from the account switcher
gabitoesmiapodo Jun 12, 2026
529cd7e
refactor(carpincho): extract transfer direction helper and tidy trans…
gabitoesmiapodo Jun 12, 2026
7128061
docs(carpincho): document direction-aware transfers and account switc…
gabitoesmiapodo Jun 12, 2026
39683a7
feat(carpincho): show a loading spinner while tab data is fetching
gabitoesmiapodo Jun 12, 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: 0 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ Subproject docs must not restate root rules. They should describe only their loc
- `npm run build-dar -- <daml-project>` / `npm run deploy-dar -- <dar>`
- `npm run carpincho:build:extension`
- `npm run app:dev`
- For local-stack convenience, [`scripts/dev-stack.sh`](scripts/dev-stack.sh) wraps the shortcuts above behind an interactive menu (run with no args) or direct subcommands (`install`, `docker-up`, `up`, `down`, `docker-down`, `mock-up`, `mock-down`, `extension`, `status`). The `npm` scripts remain canonical; the helper just orchestrates them. See [`README.md`](README.md).
- Local ports are intentionally assigned in the `3010+` range (see table above). Do not change them without updating every subproject's defaults.
- Treat the single root `package-lock.json` as authoritative. Do not regenerate it as part of unrelated changes, and do not reintroduce per-package lockfiles.
- The root `package.json` pins `@canton-network/dapp-sdk` to `1.1.0` via `overrides`: consumers declare `^1.1.0`, but `1.2.0` is intentionally held back. npm 11 does not persist `overrides` into `package-lock.json`, so the pin is enforced by the override on every relock and by the resolved `1.1.0` entry in the lock on every plain install. Do not bump it without testing the dApp flow against the newer SDK.
Expand Down
181 changes: 106 additions & 75 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,135 +1,166 @@
# Canton dApp Booster

Minimal local stack:
Local Canton Network stack for wallet-first dApp experiments.

```mermaid
flowchart TD
fe["dapp/frontend<br/>dApp frontend<br/>http://localhost:3012"]
wallet["carpincho-wallet<br/>Vault + signer<br/>http://localhost:3011"]
ws["canton-barebones/wallet-service<br/>Canton bridge<br/>http://localhost:3010"]
cb["canton-barebones<br/>Participant JSON API http://localhost:3013<br/>Ledger/Admin gRPC localhost:3014 / 3015"]
dar["dapp/daml<br/>quickstart-tally DAR<br/>.daml/dist/*.dar"]
ws["canton-barebones/wallet-service<br/>External-party bridge<br/>http://localhost:3010"]
au["Splice app-user<br/>primary local validator<br/>JSON API http://localhost:2975"]
sv["Splice sv<br/>SV / DSO / synchronizer side"]
scan["Scan<br/>Splice read model<br/>http://scan.localhost:4000"]
dar["dapp/daml<br/>quickstart-tally DAR"]

fe <-->|"Injected CIP-0103 provider<br/>optional WalletConnect"| wallet
wallet -->|"JSON-RPC /rpc<br/>prepare, execute, read, onboard"| ws
ws -->|"Canton JSON API<br/>self-minted JWT"| cb
dar -->|"deploy DAR package"| cb
wallet -->|"external-party onboarding"| ws
wallet -->|"Scan API / token metadata"| scan
ws -->|"Bearer CANTON_BACKEND_TOKEN"| au
au <--> sv
sv -->|"indexed Splice read model"| scan
dar -->|"deploy package"| au
```

The dApp frontend knows the Tally DAML signature and talks to Carpincho through the injected CIP-0103 browser provider. Carpincho owns the local signing key and uses the wallet service to prepare, read, and execute against the Canton participant. WalletConnect remains available as an optional fallback path.
`canton:up` activates the official Splice LocalNet `sv` and `app-user` Docker
profiles, then starts wallet-service. It does not start Keycloak or OIDC.
The app-provider UI containers are not started; a local compose override
disables their Nginx routes. The official shared Canton/Splice containers still
expose app-provider backend ports because the bundle bakes that config in.
Splice and wallet-service share the `canton-barebones` Docker Compose project,
so Docker groups the full local stack together.
`app-user` is Splice's technical name for the primary local validator; it is not
the Carpincho user.

## Installation

Prerequisites:

- Node.js 24
- npm
- Docker
- npm `>=7`
- Docker with about 8 GB memory available
- `dpm` on `PATH` (DAML SDK 3.4.11), required for building DARs

### Recommended
Install workspace dependencies:

```bash
npx dappbooster --canton
npm install
```

### Manual
Create the local env file:

```bash
npm install
cp canton-barebones/.env.example canton-barebones/.env
```

### Environment files

#### Mandatory
Generate the backend token and paste the printed `CANTON_BACKEND_TOKEN=...`
line into `canton-barebones/.env`:

```bash
cp canton-barebones/.env.example canton-barebones/.env
npm run canton:token -- ledger-api-user
```

#### Optional
Token configuration:

| Name | What It Is | Who Uses It |
| --- | --- | --- |
| `CANTON_AUTH_AUDIENCE` | JWT audience recipe value | token script |
| `CANTON_AUTH_SECRET` | local unsafe JWT signing secret | token script only |
| `CANTON_BACKEND_TOKEN` | generated JWT pasted into `.env` | wallet-service |
| Carpincho LocalNet token | generated JWT pasted into Carpincho settings | Carpincho |

The token script uses `ledger-api-user` as the default JWT subject. Generate
another token with the same script or reuse the backend token locally. Do not
copy `CANTON_AUTH_SECRET` into Carpincho.

Only for the WalletConnect fallback. Copy each and set `VITE_WC_PROJECT_ID` (see the dApp frontend [WalletConnect setup](dapp/frontend/README.md#walletconnect-fallback)):
Optional WalletConnect fallback:

```bash
cp carpincho-wallet/.env.local.example carpincho-wallet/.env.local
cp dapp/frontend/.env.local.example dapp/frontend/.env.local
```

## Dev stack script
Set `VITE_WC_PROJECT_ID` in both files only if you use WalletConnect.

[`scripts/dev-stack.sh`](scripts/dev-stack.sh) automates the manual Quick Start below. Run it with no arguments for an interactive menu.
## Quick Start

Start the stack:

```bash
./scripts/dev-stack.sh
npm run canton:up
npm run canton:health
```

Or call an action directly:
Build and deploy the sample DAR:

```bash
./scripts/dev-stack.sh <action>
npm run build-dar -- dapp/daml
npm run deploy-dar -- dapp/daml/.daml/dist/quickstart-tally-0.0.1.dar
```

| Menu item | Action | What it does |
|-----------|--------|--------------|
| Install | `install` | Install and link every workspace from the repo root (`npm install`). |
| Docker up | `docker-up` | Launch Docker Desktop (macOS only). |
| Docker down | `docker-down` | Quit Docker Desktop (macOS only). |
| Stack up | `up` | Bring up containers, build + deploy the DAR, start the wallet and dApp dev servers, build the extension. |
| Stack down | `down` | Stop the dev servers and tear down the containers. |
| Wallet up | `mock-up` | Start the mocked wallet-service + Carpincho web app with no Docker. |
| Wallet down | `mock-down` | Stop the mocked wallet-service + Carpincho web app. |
| Build extension | `extension` | Build the Chrome extension and copy it to your desktop. |
| (CLI only) | `status` | Show running containers and listening ports. |

Notes:
Verify wallet-service:

- Docker lifecycle is managed separately from the stack: `up` and `down` assume Docker is already running and never start or quit it. Start/quit Docker with `docker-up` / `docker-down`, the Docker app, or your own CLI.
- `up` requires Docker running and `dpm` on `PATH` (for the DAR build).

## Quick Start (manual)
```bash
npm run wallet-service:health
```

1. **Start Canton + wallet-service** ([`canton-barebones`](canton-barebones/README.md)):
Start Carpincho and the dApp:

```bash
npm run canton:up
npm run canton:health
```
```bash
npm run wallet:dev
npm run app:dev
```

2. **Build and deploy the Tally DAR** ([`dapp/daml`](dapp/daml/README.md) builds, [`canton-barebones`](canton-barebones/README.md#deploy-a-dar) deploys):
Open the dApp:

```bash
npm run build-dar -- dapp/daml
npm run deploy-dar -- dapp/daml/.daml/dist/quickstart-tally-0.0.1.dar
```
```text
http://localhost:3012
```

3. **Build and load the Carpincho extension** ([`carpincho-wallet`](carpincho-wallet/README.md#browser-extension)):
In the frontend:

```bash
npm run carpincho:build:extension
```
1. Keep `canton:localnet` in settings.
2. Click `Connect with Carpincho`.
3. Approve the request in Carpincho.

4. **Start the dApp frontend** ([`dapp/frontend`](dapp/frontend/README.md)):
## Extension

```bash
npm run app:dev
```

For host-side iteration without Docker, see the wallet-service [mock mode](canton-barebones/wallet-service/README.md#mock-mode). For the WalletConnect fallback, see the dApp frontend [WalletConnect setup](dapp/frontend/README.md#walletconnect-fallback).
Build the extension:

## Ports
```bash
npm run carpincho:build:extension
```

| Component | URL / Port |
| --------------------------- | ----------------------- |
| Wallet service | `http://localhost:3010` |
| Carpincho wallet | `http://localhost:3011` |
| dApp frontend | `http://localhost:3012` |
| Canton JSON API | `http://localhost:3013` |
| Canton Ledger API | `grpc://localhost:3014` |
| Canton Admin API | `grpc://localhost:3015` |
| Canton health | `http://localhost:3016` |
| Canton sequencer public API | `localhost:3017` |
| Canton Postgres | `localhost:3018` |
Load `carpincho-wallet/dist-extension` from `chrome://extensions` with
Developer mode enabled.

## Services And Ports

| Service | What It Is | URL / Port | Who Uses It |
| --- | --- | --- | --- |
| wallet-service | Carpincho bridge for external-party onboarding | `http://localhost:3010` | Carpincho |
| Carpincho wallet | Browser wallet UI/provider | `http://localhost:3011` | user/dApp |
| dApp frontend | Example dApp | `http://localhost:3012` | user |
| app-user Wallet UI | Official Splice wallet UI for app-user | `http://wallet.localhost:2000` | optional/manual |
| app-user Ledger API | gRPC Ledger API | `grpc://localhost:2901` | SDK/tools |
| app-user Admin API | gRPC Admin API | `grpc://localhost:2902` | wallet-service/tools |
| app-user Validator API | Splice validator readiness/API | `http://localhost:2903` | health/tools |
| app-user JSON API | JSON Ledger API | `http://localhost:2975` | wallet-service/tools |
| app-user Validator proxy | wallet-sdk validator route | `http://localhost:2000/api/validator` | Carpincho |
| app-provider backend APIs | Official bundle backend wiring, unused here | `grpc://localhost:3901`, `grpc://localhost:3902`, `http://localhost:3903`, `http://localhost:3975` | not used |
| app-provider UI port | Nginx port exposed by the bundle; routes disabled here | `http://localhost:3000` | not used |
| Scan UI | Splice explorer/read model UI | `http://scan.localhost:4000` | optional/manual |
| Scan API | Splice indexed API | `http://scan.localhost:4000/api/scan` | Carpincho/tools |
| Amulet Registry | token metadata via scan proxy | `http://localhost:2000/api/validator/v0/scan-proxy` | Carpincho/tools |
| SV UI | Super Validator operations UI | `http://sv.localhost:4000` | optional/manual |
| sv Ledger/Admin/JSON APIs | Official SV participant APIs | `grpc://localhost:4901`, `grpc://localhost:4902`, `http://localhost:4975` | Splice internals/tools |
| sv Validator API | SV readiness/admin surface | `http://localhost:4903` | health checks |
| PostgreSQL | Splice LocalNet DB | `localhost:5432` | LocalNet containers/tools |

If `wallet.localhost`, `scan.localhost`, or `sv.localhost` do not resolve, add:

```text
127.0.0.1 wallet.localhost scan.localhost sv.localhost
```

## Releasing

Expand All @@ -149,4 +180,4 @@ The root `package.json` `version` is the single source of truth for the release.
git push --follow-tags
```

3. Publish a GitHub Release for that tag (the GitHub UI, or `gh release create v<x.y.z>`).
3. Publish a GitHub Release for that tag (the GitHub UI, or `gh release create v<x.y.z>`).
Loading