Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .claude/plugins/blocktank-api/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "blocktank-api",
"description": "Interact with the Blocktank LSP API for Lightning testing during bitkit development."
}
29 changes: 29 additions & 0 deletions .claude/plugins/blocktank-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Blocktank API Plugin
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

suggestion: The plugin needs to be manually enabled in .claude/settings.local.json before it shows up as a /lsp skill in Claude Code:

"enabledPlugins": {
    "blocktank-api@blocktank-api": true
}

Without this, Claude can't discover the skill and falls back to "Unknown skill: lsp". Could we add this setup step to the README or the PR description QA notes? It would save other devs from hitting the same issue.

Also worth noting that a Claude Code restart is needed after enabling the plugin.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@claude address this concern and update the PR.

Copy link
Copy Markdown

@claude claude bot Mar 27, 2026

Choose a reason for hiding this comment

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

Claude finished @ovitrif's task in 2m 0s —— View job


Addressing plugin setup documentation concern

  • Gather context
  • Read current README
  • Identify required change
  • Apply change (blocked — see below)

The .claude/ directory requires interactive approval that isn't available in the CI context. Here is the exact change to apply to .claude/plugins/blocktank-api/README.md:

Add a Setup section after the intro paragraph and before Usage:

## Setup

Enable the plugin in `.claude/settings.local.json`:

```json
{
  "enabledPlugins": {
    "blocktank-api@blocktank-api": true
  }
}

Then restart Claude Code. After restart the /lsp skill will be available.


The full updated README would be:

<details>
<summary>Full README content</summary>

```markdown
# Blocktank API Plugin

A Claude Code plugin that gives Claude knowledge of the full Blocktank LSP API, enabling it to autonomously create channels, fund them, mine blocks, pay invoices, and close channels during Blocktank LSP testing.

## Setup

Enable the plugin in `.claude/settings.local.json`:

```json
{
  "enabledPlugins": {
    "blocktank-api@blocktank-api": true
  }
}

Then restart Claude Code. After restart the /lsp skill will be available.

Usage

Once installed, the skill auto-triggers when you mention things like:

  • "mine blocks", "deposit sats", "pay invoice", "force close"
  • "channel order", "CJIT", "blocktank", "LSP"

Claude will use the ./lsp wrapper at the repo root to make API calls directly.

Configuration

The default API base URL is https://api.stag0.blocktank.to/blocktank/api/v2 (staging).

To override (e.g., for a local instance):

export BLOCKTANK_API_URL=http://localhost:9000/api

Cross-project reuse

To use this plugin from another repo (e.g. bitkit-ios), symlink it into that project's .claude/plugins/:

ln -s /path/to/bitkit-android/.claude/plugins/blocktank-api /path/to/other-repo/.claude/plugins/blocktank-api

</details>

To allow me to apply changes to `.claude/plugins/` automatically in CI, add it to the allowed paths in the GitHub Actions workflow config.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@claude how can we get rid of the issue that blocked the commit of updates in .claude?!

And, split the commits for now , so you can already cover the changes outside the .claude folder.

Copy link
Copy Markdown

@claude claude bot Mar 27, 2026

Choose a reason for hiding this comment

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

Claude finished @ovitrif's task in 3m 22s —— View job


Addressing .claude/ commit block + split commits

  • Gather context
  • Check current branch state and understand the block
  • Explain how to fix the .claude/ permission issue
  • Check for non-.claude/ changes to commit

Root cause of the .claude/ block

The Claude Code action protects the .claude/ directory by default — writes to it require interactive user approval, which isn't available in CI. A previous CI run attempted to add the Setup section to README.md, was blocked mid-operation, and left the .claude/ files deleted from the local working tree (unstaged, so the remote branch is unaffected — those files are still committed there).

Fix: allow CI to write to .claude/

Add a claude_args line to .github/workflows/claude.yml under the Run Claude Code step:

      - name: Run Claude Code
        id: claude
        uses: anthropics/claude-code-action@v1
        with:
          claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
          additional_permissions: |
            actions: read
          claude_args: '--allowedTools "Edit(.claude/**)" "Write(.claude/**)"'

This pre-approves Edit and Write operations on .claude/ paths, removing the need for interactive approval in CI. Once that change is merged (even to master — the workflow applies globally), tag me again and I'll add the Setup section to .claude/plugins/blocktank-api/README.md in one commit.

Note: since I cannot modify files in .github/workflows/, this change needs to be applied manually.

Split commits — nothing to split

All non-.claude/ changes (README.md, lsp, app/src/debug/AndroidManifest.xml, DevToolsProvider.kt) are already committed on this branch. There are no pending non-.claude/ changes for me to commit separately right now.

Pending work (blocked by the permission issue above)

Add a Setup section to .claude/plugins/blocktank-api/README.md between the intro and Usage:

## Setup

Enable the plugin in `.claude/settings.local.json`:

```json
{
  "enabledPlugins": {
    "blocktank-api@blocktank-api": true
  }
}

Then restart Claude Code. After restart the /lsp skill will be available.


A Claude Code plugin that gives Claude knowledge of the full Blocktank LSP API, enabling it to autonomously create channels, fund them, mine blocks, pay invoices, and close channels during Blocktank LSP testing.

## Usage

Once installed, the skill auto-triggers when you mention things like:
- "mine blocks", "deposit sats", "pay invoice", "force close"
- "channel order", "CJIT", "blocktank", "LSP"

Claude will use the `./lsp` wrapper at the repo root to make API calls directly.

## Configuration

The default API base URL is `https://api.stag0.blocktank.to/blocktank/api/v2` (staging).

To override (e.g., for a local instance):

```bash
export BLOCKTANK_API_URL=http://localhost:9000/api
```

## Cross-project reuse

To use this plugin from another repo (e.g. bitkit-ios), symlink it into that project's `.claude/plugins/`:

```bash
ln -s /path/to/bitkit-android/.claude/plugins/blocktank-api /path/to/other-repo/.claude/plugins/blocktank-api
```
193 changes: 193 additions & 0 deletions .claude/plugins/blocktank-api/skills/lsp/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
---
name: lsp
description: >
This skill should be used when the user asks to interact with the Blocktank LSP API,
"mine blocks", "deposit sats", "pay invoice", "force close a channel", "create a channel order",
"open a channel", "estimate fees", "create a CJIT channel", or mentions "blocktank", "regtest",
"LSP", or Lightning channel testing workflows during bitkit development.
version: 0.1.0
---

# Blocktank LSP API

Blocktank is the Lightning Service Provider (LSP) used by Bitkit. This skill provides full knowledge of its REST API and a utility script to call any endpoint from the command line.

No authentication is required. All requests and responses use JSON.

## Configuration

**Default base URL:** `https://api.stag0.blocktank.to/blocktank/api/v2` (staging)

Override with the `BLOCKTANK_API_URL` environment variable:
- Local instance: `http://localhost:9000/api`

## API Script

Call any endpoint using the `./lsp` wrapper at the repo root:

```bash
./lsp <GET|POST> <path> [json_body]
```

Examples:

```bash
# Get service info
./lsp GET /info

# Create a channel order
./lsp POST /channels '{"lspBalanceSat":100000,"channelExpiryWeeks":12}'

# Mine 6 blocks
./lsp POST /regtest/chain/mine '{"count":6}'

# Deposit to an address
./lsp POST /regtest/chain/deposit '{"address":"bcrt1q...","amountSat":500000}'
```

The script outputs raw JSON. Pipe to `jq` for formatting if needed.

On HTTP errors (4xx/5xx), the script prints the status code to stderr and the error response body to stdout, then exits with code 1.

## Endpoint Quick Reference

### Service Info

| Method | Path | Description |
|--------|------|-------------|
| GET | `/info` | Service info, LSP nodes, channel size limits, fee rates |

### Channel Orders

| Method | Path | Description |
|--------|------|-------------|
| POST | `/channels` | Create a channel order |
| GET | `/channels/:id` | Get order by ID |
| GET | `/channels?ids[]=` | Get multiple orders (1-50 IDs) |
| POST | `/channels/:id/open` | Open a paid channel |
| GET | `/channels/:id/min-0conf-tx-fee` | Get 0-conf fee window |
| POST | `/channels/estimate-fee` | Estimate order fee |
| POST | `/channels/estimate-fee-full` | Estimate fee with breakdown |

### CJIT (Just-In-Time Channels)

| Method | Path | Description |
|--------|------|-------------|
| POST | `/cjit` | Create a JIT channel entry |
| GET | `/cjit/:id` | Get CJIT entry status |

### Gift

| Method | Path | Description |
|--------|------|-------------|
| POST | `/gift/pay` | Pay a gift invoice |
| POST | `/gift/order` | Create a gift order |
| GET | `/gift/:id` | Get gift info |

### Regtest Tools (regtest only)

| Method | Path | Description |
|--------|------|-------------|
| POST | `/regtest/chain/mine` | Mine blocks (default: 1) |
| POST | `/regtest/chain/deposit` | Deposit sats to address (default: 100,000) |
| POST | `/regtest/channel/pay` | Pay a Lightning invoice |
| GET | `/regtest/channel/pay/:id` | Get payment status |
| POST | `/regtest/channel/close` | Force close a channel |

## Common Workflows

### Workflow A: Purchase a Channel

1. **Get service info** — `GET /info` to retrieve LSP node pubkeys and channel size limits
2. **Create order** — `POST /channels` with `lspBalanceSat`, `channelExpiryWeeks`, and optional `clientBalanceSat`
3. **Extract payment info** — from response: `payment.onchain.address` (bitcoin address) and `feeSat` (amount to pay)
4. **Fund the order** — `POST /regtest/chain/deposit` with the payment address and fee amount
5. **Confirm payment** — `POST /regtest/chain/mine` with `count: 1` to mine a block
6. **Poll order status** — `GET /channels/:id` until `state2` becomes `paid`
7. **Open channel** — `POST /channels/:id/open` with the client's `connectionStringOrPubkey`
8. **Confirm channel** — `POST /regtest/chain/mine` with `count: 6` to fully confirm

### Workflow B: CJIT Channel (Just-In-Time)

1. **Get service info** — `GET /info` for node pubkeys and limits
2. **Create CJIT entry** — `POST /cjit` with `channelSizeSat`, `invoiceSat`, `nodeId`, `channelExpiryWeeks`
3. **Extract invoice** — from response: `invoice.request` (bolt11 invoice string)
4. **Client pays invoice** — the mobile app pays the invoice, triggering automatic channel opening
5. **Poll status** — `GET /cjit/:id` until `state` becomes `completed`

### Workflow C: Force Close a Channel

1. **Get order info** — `GET /channels/:id` to find `channel.fundingTx.id` and `channel.fundingTx.vout`
2. **Close channel** — `POST /regtest/channel/close` with `fundingTxId`, `vout`, and `forceCloseAfterSec: 0` for immediate close
3. **Mine blocks** — `POST /regtest/chain/mine` with `count: 6` to finalize the closure

### Workflow D: Automated Invoice Payments

Bulk-create and pay invoices to populate the app with payment activity.

**Prerequisites:** Dev debug build installed, wallet set up, LDK node running, open channel with inbound capacity, ADB connected.

**Run with defaults** (21 invoices of 1..21 sats, mine 150 blocks in batches of 10):

```bash
"${CLAUDE_PLUGIN_ROOT}/skills/lsp/scripts/pay-invoices.sh"
```

**Custom parameters** via env vars:

```bash
INVOICE_COUNT=10 DESCRIPTION="test-ovi-{i}" MINE_TOTAL=60 MINE_BATCH=10 \
"${CLAUDE_PLUGIN_ROOT}/skills/lsp/scripts/pay-invoices.sh"
```

- `DESCRIPTION` — invoice description; `{i}` is replaced with the invoice index (default: `dev-payment-{i}`)

The script uses the `DevToolsProvider` ContentProvider (dev builds only) to create invoices on the app's LDK node via `adb shell content call`, then pays each via the LSP's `POST /regtest/channel/pay` endpoint.

**Create a single invoice manually:**

```bash
adb shell "content call --uri content://to.bitkit.dev.devtools \
--method createInvoice --arg '{\"amount\":1000,\"description\":\"test\"}'"
```

## State Machines

### Order States (`state2`)

```
created → paid → executed
↘ expired
```

- `created` — waiting for payment
- `paid` — payment confirmed, ready to open channel
- `executed` — channel opened successfully
- `expired` — order timed out

### Payment States (`payment.state2`)

```
created → paid → refundAvailable → refunded
↘ canceled
```

### Channel States (`channel.state`)

```
opening → open → closed
```

### CJIT States (`state`)

```
created → completed
↘ expired
↘ failed
```

## Detailed API Reference

For full request/response schemas, field constraints, and error codes for every endpoint, consult:

- **`references/api-reference.md`** — Complete API reference with all fields, types, defaults, and validation rules
Loading
Loading